dbgagents/trkagent/engine/TrkBtSocketCommPort.cpp
changeset 0 c6b0df440bee
equal deleted inserted replaced
-1:000000000000 0:c6b0df440bee
       
     1 /*
       
     2 * Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32cons.h>
       
    20 #include <f32file.h>
       
    21 // Notifier to select a device
       
    22 #include <btextnotifiers.h>
       
    23 
       
    24 #ifdef __UIQ_BUILD__
       
    25 #include <QBTselectdlg.h>
       
    26 #include <btsdp.h>          // CSdpAgent
       
    27 #endif
       
    28 
       
    29 #include "TrkBtSocketCommPort.h"
       
    30 #include "TrkFramingLayer.h"
       
    31 #include "TrkConnData.h"
       
    32 
       
    33 
       
    34 //
       
    35 // Static helper functions
       
    36 //
       
    37 
       
    38 //
       
    39 //
       
    40 // CTrkBtSocketCommPort implementation
       
    41 //
       
    42 //
       
    43 
       
    44 //
       
    45 // CTrkBtSocketCommPort constructor
       
    46 //
       
    47 CTrkBtSocketCommPort::CTrkBtSocketCommPort()
       
    48 	: CTrkCommPort(CActive::EPriorityStandard, ETrkNotConnected),
       
    49 	  iServerStarted(EFalse),
       
    50 	  iConnected(EFalse),
       
    51 	  iListening(EFalse),
       
    52 	  iCurrUUID(0),
       
    53 	  iPortValid(EFalse),
       
    54 	  iDiscovering(EFalse),
       
    55 	  iSearchPattern(NULL),
       
    56 	  iAgent(NULL),
       
    57 	  iConnectionListener(NULL)
       
    58 {
       
    59    iAddr.Reset();
       
    60 }
       
    61 
       
    62 //
       
    63 // CTrkBtSocketCommPort::ConstructL
       
    64 //
       
    65 void CTrkBtSocketCommPort::ConstructL(TTrkConnData aTrkConnData, TDes& /*aErrorMessage*/, MTrkConnectionListener* aCallback)
       
    66 {
       
    67 	iUnitNumber = aTrkConnData.iPortNumber;
       
    68 	iUpdatedPort = iUnitNumber;
       
    69 
       
    70 	CActiveScheduler::Add(this);		
       
    71 	
       
    72 	iConnectionListener = aCallback;
       
    73 	
       
    74 }
       
    75 
       
    76 //
       
    77 // CTrkBtSocketCommPort destructor
       
    78 //
       
    79 CTrkBtSocketCommPort::~CTrkBtSocketCommPort()
       
    80 {
       
    81 	// make sure we cancel the request for data before shutting down
       
    82 	Cancel();
       
    83 	StopDiscovery();
       
    84 	
       
    85 	if (iConnected)
       
    86 	{
       
    87 		iSock.Close();
       
    88 		iConnected = EFalse;
       
    89 	}
       
    90 	
       
    91 	if (iServerStarted)
       
    92 	{
       
    93 		iSocketServ.Close();
       
    94 		iServerStarted = EFalse;
       
    95 	}	
       
    96 	
       
    97 
       
    98 }
       
    99 
       
   100 //
       
   101 // CTrkBtSocketCommPort::NewL
       
   102 //
       
   103 CTrkBtSocketCommPort* CTrkBtSocketCommPort::NewL(TTrkConnData aTrkConnData, TDes& aErrorMessage, MTrkConnectionListener* aCallback)
       
   104 {
       
   105 	CTrkBtSocketCommPort* self = new(ELeave) CTrkBtSocketCommPort;
       
   106 	CleanupStack::PushL(self);
       
   107 	self->ConstructL(aTrkConnData, aErrorMessage, aCallback);
       
   108 	CleanupStack::Pop(self);
       
   109 	return self;
       
   110 }
       
   111 
       
   112 //
       
   113 // CTrkBtSocketCommPort::OpenPortL
       
   114 //
       
   115 // Open the bluetooth selection dialog and connect to the selected device.
       
   116 //
       
   117 void CTrkBtSocketCommPort::OpenPortL()
       
   118 {
       
   119 	if (!iServerStarted)
       
   120 	{
       
   121 		StartC32();
       
   122 		ReportAndLeaveIfErrorL(iSocketServ.Connect(), _L("Failed to connect to socketserver."));
       
   123 		iServerStarted = ETrue;
       
   124 	}
       
   125 
       
   126 #ifdef __UIQ_BUILD__
       
   127 	CBTDeviceArray* aSelectedDeviceArray = new (ELeave) CArrayPtrFlat<CBTDevice>(4); 
       
   128 	CleanupStack::PushL(aSelectedDeviceArray); 
       
   129 	CQBTUISelectDialog* dialog = CQBTUISelectDialog::NewL(aSelectedDeviceArray); 
       
   130 	TInt err = dialog->RunDlgLD(KQBTUISelectDlgFlagNone);
       
   131 	if (err == KErrNone)
       
   132 	{ 
       
   133 		CBTDevice* ptrBTDev = aSelectedDeviceArray->operator[](0); 
       
   134 
       
   135 	  	TBTDeviceResponseParamsPckg devRespParamsPckg;
       
   136 		devRespParamsPckg().SetDeviceAddress(ptrBTDev->BDAddr()); 
       
   137 		devRespParamsPckg().SetDeviceName(ptrBTDev->FriendlyName()); 
       
   138 		devRespParamsPckg().SetDeviceClass(ptrBTDev->DeviceClass()); 
       
   139 
       
   140 		TBuf8<100> tmpName = ptrBTDev->DeviceName();
       
   141 		iName.Copy(tmpName);
       
   142 		iAddr = devRespParamsPckg().BDAddr();
       
   143 	}
       
   144 	else
       
   145 	{ 
       
   146 		ReportAndLeaveIfErrorL(err, _L("Failed to get device list."));
       
   147 	}
       
   148 	CleanupStack::Pop(aSelectedDeviceArray); 
       
   149 #else
       
   150 	// Try to open bluetooth selection dialog to get the name and address of the device
       
   151 	TBTDeviceResponseParamsPckg aResponse;
       
   152     
       
   153     RNotifier notifier;
       
   154     User::LeaveIfError(notifier.Connect());
       
   155   
       
   156     TBTDeviceSelectionParamsPckg selectionFilter;
       
   157 
       
   158     TRequestStatus status;
       
   159     notifier.StartNotifierAndGetResponse(
       
   160         status,
       
   161         KDeviceSelectionNotifierUid,
       
   162         selectionFilter,
       
   163         aResponse
       
   164     );
       
   165 
       
   166     User::WaitForRequest(status);
       
   167 
       
   168     if (status.Int() != KErrNone)
       
   169     {
       
   170         notifier.CancelNotifier(KDeviceSelectionNotifierUid);
       
   171 	    notifier.Close();
       
   172 	
       
   173      	ReportAndLeaveIfErrorL(status.Int(), _L("Failed to get device list."));
       
   174     }
       
   175 
       
   176     notifier.CancelNotifier(KDeviceSelectionNotifierUid);
       
   177     notifier.Close();
       
   178     
       
   179     iName = aResponse().DeviceName();
       
   180     iAddr = aResponse().BDAddr();
       
   181 #endif
       
   182 
       
   183 	// load protocol, RFCOMM
       
   184 	TProtocolDesc pdesc;
       
   185 	ReportAndLeaveIfErrorL(iSocketServ.FindProtocol(_L("RFCOMM"), pdesc),_L("Unable to find protocol."));
       
   186 
       
   187 	// open socket
       
   188 	ReportAndLeaveIfErrorL(iSock.Open(iSocketServ, _L("RFCOMM")),_L("Unable to open socket."));
       
   189 	// set address and port
       
   190     iState = EDiscovering;
       
   191     DiscoverPortL();
       
   192     iConnectionStatus = ETrkConnecting;
       
   193 }
       
   194 
       
   195 /*
       
   196  * To connect to BT socket after getting appropriate port
       
   197  * 
       
   198  */
       
   199 void CTrkBtSocketCommPort::ConnectToPortL()
       
   200 {
       
   201 	TBTSockAddr addr;
       
   202 	addr.SetBTAddr(iAddr);
       
   203     addr.SetPort(iUpdatedPort);
       
   204 
       
   205 	TRequestStatus cstatus;
       
   206 	iSock.Connect(addr, cstatus);
       
   207 	User::WaitForRequest(cstatus);
       
   208 
       
   209     TInt err = cstatus.Int();    
       
   210     if (err != KErrNone)
       
   211     {
       
   212         iErrorMessage.Format(_L("Error connecting socket\r\nError Code: %d\r\n"),err);
       
   213         iConnectionStatus = ETrkConnectionError;
       
   214         iConnectionListener->AsyncConnectionFailed();
       
   215         return;
       
   216 	}
       
   217 		
       
   218 	iConnected = ETrue;
       
   219     iConnectionMessage.Format(_L("BT Dev Name: %S\r\nBT Port number: %d\r\n"), &iName, iUpdatedPort);
       
   220 		
       
   221     iConnectionStatus = ETrkConnected;
       
   222     iConnectionListener->AsyncConnectionSuccessfulL();    
       
   223 }
       
   224 
       
   225 //
       
   226 // CTrkBtSocketCommPort::ClosePort
       
   227 //
       
   228 // Close the communications port
       
   229 //
       
   230 void CTrkBtSocketCommPort::ClosePort()
       
   231 {
       
   232 	Cancel();
       
   233 	
       
   234 	if (iConnected)
       
   235 	{
       
   236 		iSock.Close();
       
   237 		iConnected = EFalse;
       
   238 	}
       
   239 
       
   240 	if (iServerStarted)
       
   241 	{
       
   242 		iSocketServ.Close();
       
   243 		iServerStarted = EFalse;
       
   244 	}
       
   245 }
       
   246 
       
   247 //
       
   248 // CTrkBtSocketCommPort::SendDataL
       
   249 //
       
   250 // Write data to the serial type port
       
   251 //
       
   252 void CTrkBtSocketCommPort::SendDataL(const TDesC8& aBuffer)
       
   253 {
       
   254 	iSock.CancelRead();
       
   255 	iState = ESending;
       
   256 
       
   257 	iSock.Write(aBuffer, iStatus);
       
   258 	User::WaitForRequest(iStatus);
       
   259 	
       
   260 	if (iStatus!=KErrNone)
       
   261 	{
       
   262 		ReportAndLeaveIfErrorL(iStatus.Int(), _L("Error sending data."));
       
   263 	}	
       
   264 }
       
   265 
       
   266 //
       
   267 // CTrkBtSocketCommPort::Listen
       
   268 //
       
   269 // Start listening for data coming into the serial type communications port
       
   270 //
       
   271 void CTrkBtSocketCommPort::Listen(CTrkFramingLayer *aFramingLayer)
       
   272 {
       
   273 	iFramingLayer = aFramingLayer;
       
   274 	iListening = ETrue;
       
   275 }
       
   276 
       
   277 //
       
   278 // CTrkBtSocketCommPort::StopListening
       
   279 //
       
   280 // Stop listening for data coming into the serial type communications port
       
   281 //
       
   282 void CTrkBtSocketCommPort::StopListening()
       
   283 {
       
   284 	if (iListening)
       
   285 	{
       
   286 		iSock.CancelRead();
       
   287 		Cancel();
       
   288 		Deque();
       
   289 	}
       
   290 	
       
   291 	iListening = EFalse;
       
   292 }
       
   293 
       
   294 //
       
   295 // CTrkBtSocketCommPort::ReportAndLeaveIfErrorL
       
   296 //
       
   297 // If an error occurred, print the error information to the screen and bail out
       
   298 //
       
   299 void CTrkBtSocketCommPort::ReportAndLeaveIfErrorL(TInt aError, const TDesC& aDesc)
       
   300 {
       
   301 	if (KErrNone != aError)
       
   302 	{
       
   303 		iErrorMessage.Format(_L("%S\r\nError Code: %d\r\n"), &aDesc, aError);
       
   304 		User::Leave(aError);
       
   305 	}
       
   306 }
       
   307 
       
   308 
       
   309 //
       
   310 // CTrkBtSocketCommPort::IssueReadRequest
       
   311 //
       
   312 // Wait for data to come into the communications port
       
   313 //
       
   314 void CTrkBtSocketCommPort::IssueReadRequest()
       
   315 {
       
   316 	iSock.CancelRead();
       
   317 	iNextReadChar = 0;
       
   318 	iState = EWaiting;
       
   319 	iReceivedChars.Zero();
       
   320 	iSock.RecvOneOrMore(iReceivedChars, 0, iStatus, iLen);
       
   321 	SetActive();
       
   322 }
       
   323 
       
   324 //
       
   325 // CTrkBtSocketCommPort::DoCancel
       
   326 //
       
   327 // Cancel the request for data from the communications port
       
   328 //
       
   329 void CTrkBtSocketCommPort::DoCancel()
       
   330 {
       
   331 	//iSock.CancelRead();
       
   332 	//iPort.ReadCancel();
       
   333 }
       
   334 
       
   335 //
       
   336 // CTrkBtSocketCommPort::RunL
       
   337 //
       
   338 // Called when data comes into the communications port
       
   339 //
       
   340 void CTrkBtSocketCommPort::RunL()
       
   341 {
       
   342 	if (iStatus != KErrNone)
       
   343 	{
       
   344 		switch(iState)
       
   345 		{
       
   346 		   case EDiscovering:
       
   347 		   {
       
   348 		       iConnectionListener->AsyncConnectionFailed();
       
   349 		       break;	       
       
   350 		   }	       
       
   351 		   default:
       
   352 		 	  break;
       
   353 		}
       
   354 	}
       
   355 	else
       
   356 	{
       
   357 		switch (iState)
       
   358 		{
       
   359 	
       
   360 			case EWaiting:
       
   361 			{
       
   362 				if (iStatus.Int() == KErrNone)
       
   363 				{
       
   364 					while (iNextReadChar < iReceivedChars.Length())
       
   365 						iFramingLayer->HandleByte(iReceivedChars[iNextReadChar++]);
       
   366 				}
       
   367 				break;
       
   368 			}
       
   369 			case ESending:
       
   370 			{
       
   371 				break;
       
   372 			}
       
   373 			case EDiscovering:
       
   374 			{
       
   375 				ConnectToPortL();
       
   376 				break;
       
   377 			}
       
   378 			case EConnecting:
       
   379 			{
       
   380 				break;
       
   381 			}
       
   382 			default:
       
   383 				break;
       
   384 		}
       
   385 		IssueReadRequest();
       
   386 	}
       
   387 
       
   388 }
       
   389 
       
   390 //
       
   391 // CTrkBtSocketCommPort::DiscoverPortL
       
   392 //
       
   393 // Called to figure out the port number for serial profile
       
   394 //
       
   395 void CTrkBtSocketCommPort::DiscoverPortL()
       
   396 {
       
   397     StopDiscovery(); // to avoid conflicts if called several times before the old discovery is finished
       
   398    
       
   399     const TInt BT_UUID_SPP_SP = 0x1101; // SPP (Serial Port) UUID
       
   400     
       
   401     // Init new service discovery agent
       
   402     iAgent = CSdpAgent::NewL( *this, iAddr);
       
   403     
       
   404     // Set search properties for agent (use SPP service-UUID to filter the services discovered)
       
   405     iSearchPattern = CSdpSearchPattern::NewL();
       
   406     
       
   407     iSearchPattern->AddL(BT_UUID_SPP_SP);
       
   408     iAgent->SetRecordFilterL(*iSearchPattern);
       
   409     iDiscovering = ETrue;
       
   410    
       
   411     // Initiate search, result will be received with call of NextRecordRequestComplete()
       
   412     iAgent->NextRecordRequestL();
       
   413     iStatus = KRequestPending;
       
   414     SetActive();       
       
   415 }
       
   416 
       
   417 //
       
   418 //CTrkBtSocketCommPort::StopDiscovery()
       
   419 //
       
   420 //Called to stop the discovery services
       
   421 //
       
   422 void CTrkBtSocketCommPort::StopDiscovery()
       
   423 {
       
   424     iDiscovering = EFalse;
       
   425     
       
   426     if (iAgent)
       
   427     {
       
   428         iAgent->Cancel();
       
   429         delete iAgent;
       
   430         iAgent = NULL;
       
   431     }
       
   432     
       
   433     if (iSearchPattern)
       
   434     {
       
   435         iSearchPattern->Reset();
       
   436         delete iSearchPattern;
       
   437         iSearchPattern = NULL;
       
   438     }
       
   439 }
       
   440 
       
   441 
       
   442 //
       
   443 // CTrkBtSocketCommPort::NextRecordRequestComplete
       
   444 //
       
   445 // called when the service discovery agent has completed discovering services on device (i.e. if next service found or not)
       
   446 //
       
   447 void CTrkBtSocketCommPort::NextRecordRequestComplete(TInt aError, TSdpServRecordHandle aHandle, TInt aTotalRecordsCount)
       
   448 {
       
   449     if ( (KErrNone == aError) && (0 < aTotalRecordsCount) )
       
   450     {
       
   451         // We got next service record, request protocol descriptor to retrieve remote port
       
   452         // (it calls later the AttributeRequestResult() when the answer is ready)
       
   453         TRAPD(err, iAgent->AttributeRequestL(aHandle, KSdpAttrIdProtocolDescriptorList));
       
   454         if( err )
       
   455         {
       
   456 	        iErrorMessage.Format(_L("Error in finding the serial port record\r\nError Code: %d\r\n"),err);
       
   457 	        iConnectionStatus = ETrkConnectionError;
       
   458 	        StopDiscovery();
       
   459 	        TRequestStatus *status = &iStatus;
       
   460 	        User::RequestComplete(status, aError);
       
   461         }
       
   462     }
       
   463     else
       
   464     {
       
   465 	    // no any services found or error occures (probably the device is not present or SPP service is not present)
       
   466 	    iErrorMessage.Format(_L("Error in finding the serial port record\r\nError Code: %d\r\n"),aError);
       
   467 	    iConnectionStatus = ETrkConnectionError;
       
   468 	    StopDiscovery();
       
   469 	    TRequestStatus *status = &iStatus;
       
   470 	    User::RequestComplete(status, aError);  
       
   471     }    
       
   472 
       
   473 }
       
   474 
       
   475 
       
   476 //
       
   477 //CTrkBtSocketCommPort::AttributeRequestResult
       
   478 //
       
   479 // Called when the service attributes for the service record have been retrieved.
       
   480 //
       
   481 void CTrkBtSocketCommPort::AttributeRequestResult(TSdpServRecordHandle, TSdpAttributeID, CSdpAttrValue* aAttrValue)
       
   482 {
       
   483     // can't ignore the call of this function because we need take care about aAttrValue
       
   484     // Parse attributes, it will return results by several calls of VisitAttributeValue()
       
   485     TRAPD(err, aAttrValue->AcceptVisitorL(*this));
       
   486     if( err )
       
   487     {   
       
   488 	    iErrorMessage.Format(_L("Error in finding the serial port record \r\nError Code: %d"),err);
       
   489 	    iConnectionStatus = ETrkConnectionError;
       
   490 	    StopDiscovery();
       
   491 	    TRequestStatus *status = &iStatus;
       
   492 	    User::RequestComplete(status, err);
       
   493     }
       
   494     delete aAttrValue;
       
   495 }
       
   496 
       
   497 //
       
   498 // CTrkBtSocketCommPort::AttributeRequestComplete
       
   499 //
       
   500 // Called when the request to resolve the service attributes for the service record completes.
       
   501 //
       
   502 void CTrkBtSocketCommPort::AttributeRequestComplete(TSdpServRecordHandle, TInt aError)
       
   503 {
       
   504     // if KErrNone ==aError and we need not just the first SPP service but check several services,
       
   505     // can call for iAgent->NextRecordRequestL() here (and add corresponded processing in
       
   506     // NextRecordRequestComplete() )
       
   507     if (KErrNone != aError)
       
   508     {
       
   509         iErrorMessage.Format(_L("Error in finding the serial port record\r\nError Code: %d"),aError);
       
   510         iConnectionStatus = ETrkConnectionError;
       
   511         StopDiscovery();
       
   512         TRequestStatus *status = &iStatus;
       
   513         User::RequestComplete(status, aError);
       
   514     }
       
   515     else
       
   516     {
       
   517         StopDiscovery();
       
   518         TRequestStatus *status = &iStatus;
       
   519         User::RequestComplete(status, KErrNone);  
       
   520     }
       
   521 }
       
   522     
       
   523 //
       
   524 // CTrkBtSocketCommPort::VisitAttributeValueL
       
   525 //    
       
   526 // Called for processing of each service attribute.
       
   527 //
       
   528 void CTrkBtSocketCommPort::VisitAttributeValueL(CSdpAttrValue &aValue, TSdpElementType aType)
       
   529 {
       
   530     if (!iDiscovering)
       
   531     {
       
   532         return; // ignore calls to that function if not discovering currently
       
   533     }
       
   534     
       
   535     // Check for attributes of UUID type. 
       
   536     // If the UUID is RFCOMM UUID, resolve the value for this attribute,
       
   537     // which will be the channel number.
       
   538     switch (aType)
       
   539     {
       
   540         case ETypeUUID: // UUID of attribute, store it 
       
   541         {
       
   542             TPtrC8 uuid(aValue.UUID().ShortestForm());
       
   543             iCurrUUID.SetL(uuid);
       
   544             break;
       
   545         }
       
   546         case ETypeUint: // uint value, check if the current attribute type is KRFCOMM, store the port value if "yes"
       
   547         {
       
   548             if (iCurrUUID == KRFCOMM)
       
   549             {
       
   550                 iUpdatedPort = aValue.Uint();
       
   551                 iPortValid = TRUE;
       
   552                 iDiscovering = EFalse;
       
   553             }
       
   554             break;
       
   555         }
       
   556         default:
       
   557             // other attributes are not interesting for processing...
       
   558             break;
       
   559     }   
       
   560 }
       
   561 
       
   562 /*
       
   563  * This method should be overridden
       
   564  */
       
   565 void CTrkBtSocketCommPort::StartListL(CSdpAttrValueList&)
       
   566 {
       
   567 }
       
   568 
       
   569 /*
       
   570  * This method should be overridden 
       
   571  * 
       
   572  */
       
   573 void CTrkBtSocketCommPort::EndListL()
       
   574 {
       
   575 }