bluetoothengine/btaudioman/src/btaudiomanplugin.cpp
branchRCL_3
changeset 6 6a29d5ad0713
parent 0 f63038272f30
child 11 a42ed326b458
equal deleted inserted replaced
2:0b192a3a05a4 6:6a29d5ad0713
     1 /*
     1 /*
     2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
     2 * Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     4 * This component and the accompanying materials are made available
     5 * under the terms of "Eclipse Public License v1.0"
     5 * under the terms of "Eclipse Public License v1.0"
     6 * which accompanies this distribution, and is available
     6 * which accompanies this distribution, and is available
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
    68     }
    68     }
    69 
    69 
    70 TInt CBtAudioManPlugin::Connect( const TBTDevAddr& aAddr )
    70 TInt CBtAudioManPlugin::Connect( const TBTDevAddr& aAddr )
    71     {
    71     {
    72     TRACE_FUNC
    72     TRACE_FUNC
    73     return HandleAsyncRequest(aAddr, ERequestConnect);    
    73     TInt err = PrepareAsyncRequest(aAddr, ERequestConnect);
       
    74     if(!err)
       
    75         {
       
    76         iDiagnostic.Zero();
       
    77         iClient.ConnectToAccessory(iActive4ClientReq->iStatus, iBTDevAddrPckgBuf, iDiagnostic);
       
    78         iActive4ClientReq->GoActive();
       
    79         }
       
    80     return err;
    74     }
    81     }
    75 
    82 
    76 void CBtAudioManPlugin::CancelConnect( const TBTDevAddr& aAddr )
    83 void CBtAudioManPlugin::CancelConnect( const TBTDevAddr& aAddr )
    77     {
    84     {
    78     if (iBTDevAddrPckgBuf() == aAddr &&
    85     if (iBTDevAddrPckgBuf() == aAddr &&
    79         iActive4ClientReq &&
       
    80         iActive4ClientReq->IsActive() &&
    86         iActive4ClientReq->IsActive() &&
    81         iActive4ClientReq->RequestId() == ERequestConnect )
    87         iActive4ClientReq->RequestId() == ERequestConnect )
    82         {
    88         {
    83         TRACE_INFO(_L("CBtAudioManPlugin::CancelConnect KErrCancel"))
    89         TRACE_INFO(_L("CBtAudioManPlugin::CancelConnect KErrCancel"))
    84         delete iActive4ClientReq;
    90         iActive4ClientReq->Cancel();
    85         iActive4ClientReq = NULL;
       
    86         if (iObserver)
    91         if (iObserver)
    87             {
    92             {
    88             iObserver->ConnectComplete(iBTDevAddrPckgBuf(), 
    93             iObserver->ConnectComplete(aAddr, EBTProfileHFP, KErrCancel);
    89                 EBTProfileHFP, KErrCancel);
       
    90             }
    94             }
    91         }
    95         }
    92     else
    96     else
    93         {
    97         {
    94         TRACE_INFO(_L("CBtAudioManPlugin::CancelConnect KErrNotFound"))
    98         TRACE_INFO(_L("CBtAudioManPlugin::CancelConnect KErrNotFound"))
    95         if (iObserver)
    99         if (iObserver)
    96             {
   100             {
    97             iObserver->ConnectComplete(aAddr , 
   101             iObserver->ConnectComplete(aAddr, EBTProfileHFP, KErrNotFound);
    98                 EBTProfileHFP, KErrNotFound);
       
    99             }
   102             }
   100         }
   103         }
   101 
   104 
   102     }
   105     }
   103 
   106 
   105     {
   108     {
   106     TInt req = ERequestDisconnect;
   109     TInt req = ERequestDisconnect;
   107     if (aAddr == TBTDevAddr())
   110     if (aAddr == TBTDevAddr())
   108         {
   111         {
   109         req = ERequestDisconnectAll;
   112         req = ERequestDisconnectAll;
   110         }    
   113         }
   111     return HandleAsyncRequest(aAddr, req);
   114     TInt err = PrepareAsyncRequest(aAddr, req);
       
   115     if (!err)
       
   116         {
       
   117         if (req == ERequestDisconnect)
       
   118             {
       
   119             iClient.DisconnectAccessory(iActive4ClientReq->iStatus, iBTDevAddrPckgBuf, iDiagnostic);
       
   120             }
       
   121         else // if (req == ERequestDisconnectAll)
       
   122             {
       
   123             iClient.DisconnectAllGracefully(iActive4ClientReq->iStatus);
       
   124             }
       
   125         iActive4ClientReq->GoActive();
       
   126         }
       
   127     return err;
   112     }
   128     }
   113 
   129 
   114 void CBtAudioManPlugin::GetConnections( RBTDevAddrArray& aAddrArray, TBTProfile aConnectedProfile )
   130 void CBtAudioManPlugin::GetConnections( RBTDevAddrArray& aAddrArray, TBTProfile aConnectedProfile )
   115     {
   131     {
   116     aAddrArray.Reset();
   132     aAddrArray.Reset();
   205     }
   221     }
   206 
   222 
   207 void CBtAudioManPlugin::RequestCompletedL(CBasrvActive& aActive)
   223 void CBtAudioManPlugin::RequestCompletedL(CBasrvActive& aActive)
   208     {
   224     {
   209     TRACE_FUNC
   225     TRACE_FUNC
       
   226     TInt result = aActive.iStatus.Int();
   210     switch (aActive.RequestId())
   227     switch (aActive.RequestId())
   211         {
   228         {
   212         case ENotifyProfileStatusChange:
   229         case ENotifyProfileStatusChange:
   213             {
   230             {
   214             if (aActive.iStatus == KErrNone && iObserver)
   231             // Notify any observer if one is present, and we got valid data (i.e. no error)
   215                 {
   232             if (result == KErrNone && iObserver)
   216                 ReportProfileConnectionEvents(iProfileStatus.iAddr, iProfileStatus.iProfiles,
   233                 {
   217                     iProfileStatus.iConnected);
   234                 ReportProfileConnectionEvents(iProfileStatus.iAddr, iProfileStatus.iProfiles, iProfileStatus.iConnected);
   218                 iClient.NotifyConnectionStatus(iProfileStatusPckg, aActive.iStatus);
   235                 }
   219                 aActive.GoActive();
   236             // Handle resubscribing for future notifications
       
   237             static const TInt KMaxFailedNotifyConnectionStatusAttempts = 3;
       
   238             if (result == KErrNone)
       
   239                 {
       
   240                 iNotifyConnectionStatusFailure = 0; // reset failure count
       
   241                 NotifyConnectionStatus();
       
   242                 }
       
   243             else if (result != KErrServerTerminated && iNotifyConnectionStatusFailure < KMaxFailedNotifyConnectionStatusAttempts)
       
   244                 {
       
   245                 TRACE_ERROR((_L8("Connection Status Notification failed (transiently): %d"), result))
       
   246                 ++iNotifyConnectionStatusFailure;
       
   247                 NotifyConnectionStatus();
       
   248                 }
       
   249             else
       
   250                 {
       
   251                 // The server has died unexpectedly, or we've failed a number of times in succession so we cannot re-subscribe. 
       
   252                 // The lack of state here makes it diffcult to know how to report (handle?) this.  However, we are in
       
   253                 // no worse situation than before, plus the issue is now logged.
       
   254                 TRACE_ERROR((_L8("Connection Status Notification failed (terminally): %d"), result))
       
   255                 iClient.Close(); // clean the handle, this might kill outstanding disconnect/connect requests
       
   256                                  // but it looks like the server is hosed anyway...
       
   257                 // In keeping with the existing logic we don't attempt to re-start the server.  That will only happen when an
       
   258                 // active request is made.
   220                 }
   259                 }
   221             break;
   260             break;
   222             }
   261             }
   223         case ERequestConnect:
   262         case ERequestConnect:
   224             {
   263             {
   225             if (iActive4ClientReq->iStatus.Int() != KErrNone) // might have conflicts, decode iDiagnostic
   264             if (result != KErrNone) // might have conflicts, decode iDiagnostic
   226                 {
   265                 {
   227                 if (iDiagnostic.Length() >= KBTDevAddrSize)
   266                 if (iDiagnostic.Length() >= KBTDevAddrSize)
   228                     {
   267                     {
   229                     RBTDevAddrArray array;
   268                     RBTDevAddrArray array;
   230                     CleanupClosePushL(array);
   269                     CleanupClosePushL(array);
   236                         const TPtrC8 myPtr(array[array.Count() - 1].Des());
   275                         const TPtrC8 myPtr(array[array.Count() - 1].Des());
   237                         #endif
   276                         #endif
   238                         TRACE_INFO((_L8("conflict <%S>"), &myPtr))
   277                         TRACE_INFO((_L8("conflict <%S>"), &myPtr))
   239                         ptr.Set(ptr.Mid(KBTDevAddrSize));
   278                         ptr.Set(ptr.Mid(KBTDevAddrSize));
   240                         }
   279                         }
   241                     iObserver->ConnectComplete(iBTDevAddrPckgBuf(), 
   280                     iObserver->ConnectComplete(iBTDevAddrPckgBuf(), EBTProfileHFP, result, &array);
   242                         EBTProfileHFP, iActive4ClientReq->iStatus.Int(), &array);
       
   243                     CleanupStack::PopAndDestroy(&array);
   281                     CleanupStack::PopAndDestroy(&array);
   244                     }
   282                     }
   245                 else
   283                 else
   246                     {
   284                     {
   247                     iObserver->ConnectComplete(iBTDevAddrPckgBuf(), 
   285                     iObserver->ConnectComplete(iBTDevAddrPckgBuf(), EBTProfileHFP, result);
   248                         EBTProfileHFP, iActive4ClientReq->iStatus.Int());
       
   249                     }
   286                     }
   250                 }
   287                 }
   251             else
   288             else
   252                 {
   289                 {
   253                 TInt profile = 0;
   290                 TInt profile = 0;
   256                     TPckg<TInt> pckg(profile);
   293                     TPckg<TInt> pckg(profile);
   257                     pckg.Copy(iDiagnostic.Mid(0, sizeof(TInt))); 
   294                     pckg.Copy(iDiagnostic.Mid(0, sizeof(TInt))); 
   258                     }
   295                     }
   259                 ReportProfileConnectionEvents(iBTDevAddrPckgBuf(), profile, ETrue);
   296                 ReportProfileConnectionEvents(iBTDevAddrPckgBuf(), profile, ETrue);
   260                 }
   297                 }
   261             delete iActive4ClientReq;
       
   262             iActive4ClientReq = NULL;
       
   263             break;
   298             break;
   264             }
   299             }
   265         case ERequestDisconnect:
   300         case ERequestDisconnect:
   266             {
   301             {
   267             if (iActive4ClientReq->iStatus.Int() != KErrNone)
   302             if (result != KErrNone)
   268                 {
   303                 {
   269                 iObserver->DisconnectComplete(iBTDevAddrPckgBuf(), 
   304                 iObserver->DisconnectComplete(iBTDevAddrPckgBuf(), EBTProfileHFP, result);
   270                         EBTProfileHFP, iActive4ClientReq->iStatus.Int());
       
   271                 }
   305                 }
   272             else
   306             else
   273                 {
   307                 {
   274                 TInt profile = 0;
   308                 TInt profile = 0;
   275                 if (iDiagnostic.Length() >= sizeof(TInt))
   309                 if (iDiagnostic.Length() >= sizeof(TInt))
   276                     {
   310                     {
   277                     TPckg<TInt> pckg(profile);
   311                     TPckg<TInt> pckg(profile);
   278                     pckg.Copy(iDiagnostic.Mid(0, sizeof(TInt))); 
   312                     pckg.Copy(iDiagnostic.Mid(0, sizeof(TInt))); 
   279                     }
   313                     }
   280                 ReportProfileConnectionEvents(iBTDevAddrPckgBuf(), profile, EFalse);
   314                 ReportProfileConnectionEvents(iBTDevAddrPckgBuf(), profile, EFalse);
   281                 }            
   315                 }
   282             delete iActive4ClientReq;
       
   283             iActive4ClientReq = NULL;
       
   284             break;
   316             break;
   285             }
   317             }
   286         case ERequestDisconnectAll:
   318         case ERequestDisconnectAll:
   287             {
   319             {
   288             iObserver->DisconnectComplete(iBTDevAddrPckgBuf(), 
   320             iObserver->DisconnectComplete(iBTDevAddrPckgBuf(), EBTProfileHFP, result);
   289                         EBTProfileHFP, iActive4ClientReq->iStatus.Int());
   321             break;
   290 			break;
       
   291             }
   322             }
   292         }
   323         }
   293     }
   324     }
   294     
   325     
   295 void CBtAudioManPlugin::CancelRequest(CBasrvActive& aActive)
   326 void CBtAudioManPlugin::CancelRequest(CBasrvActive& aActive)
   296     {
   327     {
   297     if (aActive.RequestId() == ENotifyProfileStatusChange )
   328     if (aActive.RequestId() == ENotifyProfileStatusChange)
   298         {
   329         {
   299         iClient.CancelNotifyConnectionStatus();
   330         iClient.CancelNotifyConnectionStatus();
   300         }
   331         }
   301     else if (aActive.RequestId() == ERequestConnect )
   332     else if (aActive.RequestId() == ERequestConnect)
   302         {
   333         {
   303         iClient.CancelConnectToAccessory();
   334         iClient.CancelConnectToAccessory();
   304         }
   335         }
   305     }
   336     }
   306 
   337 
   310     }
   341     }
   311 
   342 
   312 void CBtAudioManPlugin::ConstructL()
   343 void CBtAudioManPlugin::ConstructL()
   313     {
   344     {
   314     LEAVE_IF_ERROR(iClient.Connect());
   345     LEAVE_IF_ERROR(iClient.Connect());
       
   346     // Create the handler for profile notifications
   315     iActive4ProfileStatus = CBasrvActive::NewL(*this, CActive::EPriorityStandard, ENotifyProfileStatusChange);
   347     iActive4ProfileStatus = CBasrvActive::NewL(*this, CActive::EPriorityStandard, ENotifyProfileStatusChange);
       
   348     NotifyConnectionStatus();
       
   349     // Create the handler for active requests (connect, disconnect, etc.)
       
   350     iActive4ClientReq = CBasrvActive::New(*this, CActive::EPriorityStandard, ERequestConnect);
       
   351     }
       
   352 
       
   353 void CBtAudioManPlugin::NotifyConnectionStatus()
       
   354     {
   316     iClient.NotifyConnectionStatus(iProfileStatusPckg, iActive4ProfileStatus->iStatus);
   355     iClient.NotifyConnectionStatus(iProfileStatusPckg, iActive4ProfileStatus->iStatus);
   317     iActive4ProfileStatus->GoActive();
   356     iActive4ProfileStatus->GoActive();
   318     }
   357     }
   319 
   358 
   320 TInt CBtAudioManPlugin::HandleAsyncRequest(const TBTDevAddr& aAddr, TInt aRequestId)
   359 TInt CBtAudioManPlugin::ReconnectIfNeccessary()
   321     {
   360     {
   322     TInt err = KErrNone;
   361     TInt err = KErrNone;
   323     if (! iClient.Handle() )
   362     if (iClient.Handle() == KNullHandle)
   324         {
   363         {
       
   364         TRACE_INFO((_L8("Handle to Audio Man Server is not valid, connecting again...")))
   325         err = iClient.Connect();
   365         err = iClient.Connect();
   326         }
   366         TRACE_INFO((_L8("... reconnection result = %d"), err))
   327     if ( err )
   367         if(!err)
   328         {
   368             {
   329         return err;
   369             // Now reconnected, we should start status notifications again...
   330         }
   370             NotifyConnectionStatus();
   331     if ( iActive4ClientReq )
   371             }
   332         {
   372         }
       
   373     return err;
       
   374     }
       
   375 
       
   376 TInt CBtAudioManPlugin::PrepareAsyncRequest(const TBTDevAddr& aAddr, TInt aRequestId)
       
   377     {
       
   378     TInt err = KErrNone;
       
   379     err = ReconnectIfNeccessary();
       
   380     if (!err && iActive4ClientReq->IsActive())
       
   381         {
       
   382         // I would normally expect KErrInUse, so as to distinguish this failure from running out of message slots
   333         err = KErrServerBusy;
   383         err = KErrServerBusy;
   334         }
   384         }
   335     if (!err)
   385     if (!err)
   336         {
   386         {
   337         iActive4ClientReq = CBasrvActive::New(*this, CActive::EPriorityStandard, aRequestId);
   387         iBTDevAddrPckgBuf() = aAddr;
   338         if (iActive4ClientReq)
   388         iActive4ClientReq->SetRequestId(aRequestId);
   339             {
       
   340             iBTDevAddrPckgBuf() = aAddr;
       
   341             if (aRequestId == ERequestConnect)
       
   342                 {
       
   343                 iDiagnostic.Zero();
       
   344                 iClient.ConnectToAccessory(iActive4ClientReq->iStatus, iBTDevAddrPckgBuf, iDiagnostic);
       
   345                 }
       
   346             else if (aRequestId == ERequestDisconnect)
       
   347                 {
       
   348                 iClient.DisconnectAccessory(iActive4ClientReq->iStatus, iBTDevAddrPckgBuf, iDiagnostic);
       
   349                 }
       
   350             else // if (aRequestId == ERequestDisconnectAll)
       
   351             	{
       
   352             	iClient.DisconnectAllGracefully(iActive4ClientReq->iStatus);
       
   353             	}
       
   354             iActive4ClientReq->GoActive();
       
   355             }
       
   356         else
       
   357             {
       
   358             err = KErrNoMemory;
       
   359             }
       
   360         }
   389         }
   361     return err;    
   390     return err;    
   362     }
   391     }
   363 
   392 
   364 void CBtAudioManPlugin::ReportProfileConnectionEvents(const TBTDevAddr& aAddr, const TInt aProfiles, TBool aConnected)
   393 void CBtAudioManPlugin::ReportProfileConnectionEvents(const TBTDevAddr& aAddr, const TInt aProfiles, TBool aConnected)
   365     {
   394     {
   366     TRACE_FUNC
   395     TRACE_FUNC
   367     TRACE_INFO((_L("status %d profiles 0x%04X"), aConnected, aProfiles))
   396     TRACE_INFO((_L("status %d profiles 0x%04X"), aConnected, aProfiles))
   368 	TBTEngConnectionStatus status = IsConnected(aAddr);
   397     TBTEngConnectionStatus status = IsConnected(aAddr);
   369     if (iObserver)
   398     if (iObserver)
   370         {
   399         {
   371         if (aConnected)
   400         if (aConnected)
   372             {
   401             {
   373             if (aProfiles & EHFP)
   402             if (aProfiles & EHFP)
   383                 iObserver->ConnectComplete(aAddr, EBTProfileA2DP, KErrNone);
   412                 iObserver->ConnectComplete(aAddr, EBTProfileA2DP, KErrNone);
   384                 }
   413                 }
   385             }
   414             }
   386         else
   415         else
   387             {
   416             {
   388 			if(	status != EBTEngConnected )
   417             if (status != EBTEngConnected)
   389 				{
   418                 {
   390 	            if (aProfiles & EHFP)
   419                 if (aProfiles & EHFP)
   391 	                {
   420                     {
   392 	                iObserver->DisconnectComplete(aAddr, EBTProfileHFP, KErrNone);
   421                     iObserver->DisconnectComplete(aAddr, EBTProfileHFP, KErrNone);
   393 	                }
   422                     }
   394 	            if (aProfiles & EHSP)
   423                 if (aProfiles & EHSP)
   395 	                {
   424                     {
   396 	                iObserver->DisconnectComplete(aAddr, EBTProfileHSP, KErrNone);
   425                     iObserver->DisconnectComplete(aAddr, EBTProfileHSP, KErrNone);
   397 	                }
   426                     }
   398 	            if (aProfiles & EStereo)
   427                 if (aProfiles & EStereo)
   399 	                {
   428                     {
   400 	                iObserver->DisconnectComplete(aAddr, EBTProfileA2DP, KErrNone);
   429                     iObserver->DisconnectComplete(aAddr, EBTProfileA2DP, KErrNone);
   401 	                }
   430                     }
   402 				}
   431                 }
   403             }
   432             }
   404         }
   433         }
   405     }
   434     }
   406 
   435 
   407 //
   436 //