diff -r 000000000000 -r c6b0df440bee dbgagents/trkagent/engine/TrkBtSocketCommPort.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dbgagents/trkagent/engine/TrkBtSocketCommPort.cpp Tue Mar 02 10:33:16 2010 +0530 @@ -0,0 +1,575 @@ +/* +* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + +#include +#include +// Notifier to select a device +#include + +#ifdef __UIQ_BUILD__ +#include +#include // CSdpAgent +#endif + +#include "TrkBtSocketCommPort.h" +#include "TrkFramingLayer.h" +#include "TrkConnData.h" + + +// +// Static helper functions +// + +// +// +// CTrkBtSocketCommPort implementation +// +// + +// +// CTrkBtSocketCommPort constructor +// +CTrkBtSocketCommPort::CTrkBtSocketCommPort() + : CTrkCommPort(CActive::EPriorityStandard, ETrkNotConnected), + iServerStarted(EFalse), + iConnected(EFalse), + iListening(EFalse), + iCurrUUID(0), + iPortValid(EFalse), + iDiscovering(EFalse), + iSearchPattern(NULL), + iAgent(NULL), + iConnectionListener(NULL) +{ + iAddr.Reset(); +} + +// +// CTrkBtSocketCommPort::ConstructL +// +void CTrkBtSocketCommPort::ConstructL(TTrkConnData aTrkConnData, TDes& /*aErrorMessage*/, MTrkConnectionListener* aCallback) +{ + iUnitNumber = aTrkConnData.iPortNumber; + iUpdatedPort = iUnitNumber; + + CActiveScheduler::Add(this); + + iConnectionListener = aCallback; + +} + +// +// CTrkBtSocketCommPort destructor +// +CTrkBtSocketCommPort::~CTrkBtSocketCommPort() +{ + // make sure we cancel the request for data before shutting down + Cancel(); + StopDiscovery(); + + if (iConnected) + { + iSock.Close(); + iConnected = EFalse; + } + + if (iServerStarted) + { + iSocketServ.Close(); + iServerStarted = EFalse; + } + + +} + +// +// CTrkBtSocketCommPort::NewL +// +CTrkBtSocketCommPort* CTrkBtSocketCommPort::NewL(TTrkConnData aTrkConnData, TDes& aErrorMessage, MTrkConnectionListener* aCallback) +{ + CTrkBtSocketCommPort* self = new(ELeave) CTrkBtSocketCommPort; + CleanupStack::PushL(self); + self->ConstructL(aTrkConnData, aErrorMessage, aCallback); + CleanupStack::Pop(self); + return self; +} + +// +// CTrkBtSocketCommPort::OpenPortL +// +// Open the bluetooth selection dialog and connect to the selected device. +// +void CTrkBtSocketCommPort::OpenPortL() +{ + if (!iServerStarted) + { + StartC32(); + ReportAndLeaveIfErrorL(iSocketServ.Connect(), _L("Failed to connect to socketserver.")); + iServerStarted = ETrue; + } + +#ifdef __UIQ_BUILD__ + CBTDeviceArray* aSelectedDeviceArray = new (ELeave) CArrayPtrFlat(4); + CleanupStack::PushL(aSelectedDeviceArray); + CQBTUISelectDialog* dialog = CQBTUISelectDialog::NewL(aSelectedDeviceArray); + TInt err = dialog->RunDlgLD(KQBTUISelectDlgFlagNone); + if (err == KErrNone) + { + CBTDevice* ptrBTDev = aSelectedDeviceArray->operator[](0); + + TBTDeviceResponseParamsPckg devRespParamsPckg; + devRespParamsPckg().SetDeviceAddress(ptrBTDev->BDAddr()); + devRespParamsPckg().SetDeviceName(ptrBTDev->FriendlyName()); + devRespParamsPckg().SetDeviceClass(ptrBTDev->DeviceClass()); + + TBuf8<100> tmpName = ptrBTDev->DeviceName(); + iName.Copy(tmpName); + iAddr = devRespParamsPckg().BDAddr(); + } + else + { + ReportAndLeaveIfErrorL(err, _L("Failed to get device list.")); + } + CleanupStack::Pop(aSelectedDeviceArray); +#else + // Try to open bluetooth selection dialog to get the name and address of the device + TBTDeviceResponseParamsPckg aResponse; + + RNotifier notifier; + User::LeaveIfError(notifier.Connect()); + + TBTDeviceSelectionParamsPckg selectionFilter; + + TRequestStatus status; + notifier.StartNotifierAndGetResponse( + status, + KDeviceSelectionNotifierUid, + selectionFilter, + aResponse + ); + + User::WaitForRequest(status); + + if (status.Int() != KErrNone) + { + notifier.CancelNotifier(KDeviceSelectionNotifierUid); + notifier.Close(); + + ReportAndLeaveIfErrorL(status.Int(), _L("Failed to get device list.")); + } + + notifier.CancelNotifier(KDeviceSelectionNotifierUid); + notifier.Close(); + + iName = aResponse().DeviceName(); + iAddr = aResponse().BDAddr(); +#endif + + // load protocol, RFCOMM + TProtocolDesc pdesc; + ReportAndLeaveIfErrorL(iSocketServ.FindProtocol(_L("RFCOMM"), pdesc),_L("Unable to find protocol.")); + + // open socket + ReportAndLeaveIfErrorL(iSock.Open(iSocketServ, _L("RFCOMM")),_L("Unable to open socket.")); + // set address and port + iState = EDiscovering; + DiscoverPortL(); + iConnectionStatus = ETrkConnecting; +} + +/* + * To connect to BT socket after getting appropriate port + * + */ +void CTrkBtSocketCommPort::ConnectToPortL() +{ + TBTSockAddr addr; + addr.SetBTAddr(iAddr); + addr.SetPort(iUpdatedPort); + + TRequestStatus cstatus; + iSock.Connect(addr, cstatus); + User::WaitForRequest(cstatus); + + TInt err = cstatus.Int(); + if (err != KErrNone) + { + iErrorMessage.Format(_L("Error connecting socket\r\nError Code: %d\r\n"),err); + iConnectionStatus = ETrkConnectionError; + iConnectionListener->AsyncConnectionFailed(); + return; + } + + iConnected = ETrue; + iConnectionMessage.Format(_L("BT Dev Name: %S\r\nBT Port number: %d\r\n"), &iName, iUpdatedPort); + + iConnectionStatus = ETrkConnected; + iConnectionListener->AsyncConnectionSuccessfulL(); +} + +// +// CTrkBtSocketCommPort::ClosePort +// +// Close the communications port +// +void CTrkBtSocketCommPort::ClosePort() +{ + Cancel(); + + if (iConnected) + { + iSock.Close(); + iConnected = EFalse; + } + + if (iServerStarted) + { + iSocketServ.Close(); + iServerStarted = EFalse; + } +} + +// +// CTrkBtSocketCommPort::SendDataL +// +// Write data to the serial type port +// +void CTrkBtSocketCommPort::SendDataL(const TDesC8& aBuffer) +{ + iSock.CancelRead(); + iState = ESending; + + iSock.Write(aBuffer, iStatus); + User::WaitForRequest(iStatus); + + if (iStatus!=KErrNone) + { + ReportAndLeaveIfErrorL(iStatus.Int(), _L("Error sending data.")); + } +} + +// +// CTrkBtSocketCommPort::Listen +// +// Start listening for data coming into the serial type communications port +// +void CTrkBtSocketCommPort::Listen(CTrkFramingLayer *aFramingLayer) +{ + iFramingLayer = aFramingLayer; + iListening = ETrue; +} + +// +// CTrkBtSocketCommPort::StopListening +// +// Stop listening for data coming into the serial type communications port +// +void CTrkBtSocketCommPort::StopListening() +{ + if (iListening) + { + iSock.CancelRead(); + Cancel(); + Deque(); + } + + iListening = EFalse; +} + +// +// CTrkBtSocketCommPort::ReportAndLeaveIfErrorL +// +// If an error occurred, print the error information to the screen and bail out +// +void CTrkBtSocketCommPort::ReportAndLeaveIfErrorL(TInt aError, const TDesC& aDesc) +{ + if (KErrNone != aError) + { + iErrorMessage.Format(_L("%S\r\nError Code: %d\r\n"), &aDesc, aError); + User::Leave(aError); + } +} + + +// +// CTrkBtSocketCommPort::IssueReadRequest +// +// Wait for data to come into the communications port +// +void CTrkBtSocketCommPort::IssueReadRequest() +{ + iSock.CancelRead(); + iNextReadChar = 0; + iState = EWaiting; + iReceivedChars.Zero(); + iSock.RecvOneOrMore(iReceivedChars, 0, iStatus, iLen); + SetActive(); +} + +// +// CTrkBtSocketCommPort::DoCancel +// +// Cancel the request for data from the communications port +// +void CTrkBtSocketCommPort::DoCancel() +{ + //iSock.CancelRead(); + //iPort.ReadCancel(); +} + +// +// CTrkBtSocketCommPort::RunL +// +// Called when data comes into the communications port +// +void CTrkBtSocketCommPort::RunL() +{ + if (iStatus != KErrNone) + { + switch(iState) + { + case EDiscovering: + { + iConnectionListener->AsyncConnectionFailed(); + break; + } + default: + break; + } + } + else + { + switch (iState) + { + + case EWaiting: + { + if (iStatus.Int() == KErrNone) + { + while (iNextReadChar < iReceivedChars.Length()) + iFramingLayer->HandleByte(iReceivedChars[iNextReadChar++]); + } + break; + } + case ESending: + { + break; + } + case EDiscovering: + { + ConnectToPortL(); + break; + } + case EConnecting: + { + break; + } + default: + break; + } + IssueReadRequest(); + } + +} + +// +// CTrkBtSocketCommPort::DiscoverPortL +// +// Called to figure out the port number for serial profile +// +void CTrkBtSocketCommPort::DiscoverPortL() +{ + StopDiscovery(); // to avoid conflicts if called several times before the old discovery is finished + + const TInt BT_UUID_SPP_SP = 0x1101; // SPP (Serial Port) UUID + + // Init new service discovery agent + iAgent = CSdpAgent::NewL( *this, iAddr); + + // Set search properties for agent (use SPP service-UUID to filter the services discovered) + iSearchPattern = CSdpSearchPattern::NewL(); + + iSearchPattern->AddL(BT_UUID_SPP_SP); + iAgent->SetRecordFilterL(*iSearchPattern); + iDiscovering = ETrue; + + // Initiate search, result will be received with call of NextRecordRequestComplete() + iAgent->NextRecordRequestL(); + iStatus = KRequestPending; + SetActive(); +} + +// +//CTrkBtSocketCommPort::StopDiscovery() +// +//Called to stop the discovery services +// +void CTrkBtSocketCommPort::StopDiscovery() +{ + iDiscovering = EFalse; + + if (iAgent) + { + iAgent->Cancel(); + delete iAgent; + iAgent = NULL; + } + + if (iSearchPattern) + { + iSearchPattern->Reset(); + delete iSearchPattern; + iSearchPattern = NULL; + } +} + + +// +// CTrkBtSocketCommPort::NextRecordRequestComplete +// +// called when the service discovery agent has completed discovering services on device (i.e. if next service found or not) +// +void CTrkBtSocketCommPort::NextRecordRequestComplete(TInt aError, TSdpServRecordHandle aHandle, TInt aTotalRecordsCount) +{ + if ( (KErrNone == aError) && (0 < aTotalRecordsCount) ) + { + // We got next service record, request protocol descriptor to retrieve remote port + // (it calls later the AttributeRequestResult() when the answer is ready) + TRAPD(err, iAgent->AttributeRequestL(aHandle, KSdpAttrIdProtocolDescriptorList)); + if( err ) + { + iErrorMessage.Format(_L("Error in finding the serial port record\r\nError Code: %d\r\n"),err); + iConnectionStatus = ETrkConnectionError; + StopDiscovery(); + TRequestStatus *status = &iStatus; + User::RequestComplete(status, aError); + } + } + else + { + // no any services found or error occures (probably the device is not present or SPP service is not present) + iErrorMessage.Format(_L("Error in finding the serial port record\r\nError Code: %d\r\n"),aError); + iConnectionStatus = ETrkConnectionError; + StopDiscovery(); + TRequestStatus *status = &iStatus; + User::RequestComplete(status, aError); + } + +} + + +// +//CTrkBtSocketCommPort::AttributeRequestResult +// +// Called when the service attributes for the service record have been retrieved. +// +void CTrkBtSocketCommPort::AttributeRequestResult(TSdpServRecordHandle, TSdpAttributeID, CSdpAttrValue* aAttrValue) +{ + // can't ignore the call of this function because we need take care about aAttrValue + // Parse attributes, it will return results by several calls of VisitAttributeValue() + TRAPD(err, aAttrValue->AcceptVisitorL(*this)); + if( err ) + { + iErrorMessage.Format(_L("Error in finding the serial port record \r\nError Code: %d"),err); + iConnectionStatus = ETrkConnectionError; + StopDiscovery(); + TRequestStatus *status = &iStatus; + User::RequestComplete(status, err); + } + delete aAttrValue; +} + +// +// CTrkBtSocketCommPort::AttributeRequestComplete +// +// Called when the request to resolve the service attributes for the service record completes. +// +void CTrkBtSocketCommPort::AttributeRequestComplete(TSdpServRecordHandle, TInt aError) +{ + // if KErrNone ==aError and we need not just the first SPP service but check several services, + // can call for iAgent->NextRecordRequestL() here (and add corresponded processing in + // NextRecordRequestComplete() ) + if (KErrNone != aError) + { + iErrorMessage.Format(_L("Error in finding the serial port record\r\nError Code: %d"),aError); + iConnectionStatus = ETrkConnectionError; + StopDiscovery(); + TRequestStatus *status = &iStatus; + User::RequestComplete(status, aError); + } + else + { + StopDiscovery(); + TRequestStatus *status = &iStatus; + User::RequestComplete(status, KErrNone); + } +} + +// +// CTrkBtSocketCommPort::VisitAttributeValueL +// +// Called for processing of each service attribute. +// +void CTrkBtSocketCommPort::VisitAttributeValueL(CSdpAttrValue &aValue, TSdpElementType aType) +{ + if (!iDiscovering) + { + return; // ignore calls to that function if not discovering currently + } + + // Check for attributes of UUID type. + // If the UUID is RFCOMM UUID, resolve the value for this attribute, + // which will be the channel number. + switch (aType) + { + case ETypeUUID: // UUID of attribute, store it + { + TPtrC8 uuid(aValue.UUID().ShortestForm()); + iCurrUUID.SetL(uuid); + break; + } + case ETypeUint: // uint value, check if the current attribute type is KRFCOMM, store the port value if "yes" + { + if (iCurrUUID == KRFCOMM) + { + iUpdatedPort = aValue.Uint(); + iPortValid = TRUE; + iDiscovering = EFalse; + } + break; + } + default: + // other attributes are not interesting for processing... + break; + } +} + +/* + * This method should be overridden + */ +void CTrkBtSocketCommPort::StartListL(CSdpAttrValueList&) +{ +} + +/* + * This method should be overridden + * + */ +void CTrkBtSocketCommPort::EndListL() +{ +}