dbgagents/trkagent/engine/TrkBtSocketCommPort.cpp
changeset 0 c6b0df440bee
--- /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 <e32cons.h>
+#include <f32file.h>
+// Notifier to select a device
+#include <btextnotifiers.h>
+
+#ifdef __UIQ_BUILD__
+#include <QBTselectdlg.h>
+#include <btsdp.h>          // 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<CBTDevice>(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()
+{
+}