bluetoothengine/btaudioman/src/btaudiomanplugin.cpp
changeset 0 f63038272f30
child 6 6a29d5ad0713
child 15 00f9ee97d895
equal deleted inserted replaced
-1:000000000000 0:f63038272f30
       
     1 /*
       
     2 * Copyright (c) 2006 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:  Bluetooth Audio Manager ECom plug-in class definition.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <ecom/ecom.h>
       
    20 #include <bttypes.h>
       
    21 #include "btaudiomanplugin.h"
       
    22 #include "btaccTypes.h"
       
    23 #include "debug.h"
       
    24 
       
    25 enum TRequestId
       
    26     {
       
    27     ERequestConnect = 1,
       
    28     ERequestDisconnect = 2,
       
    29     ENotifyProfileStatusChange = 3,
       
    30     ERequestDisconnectAll,
       
    31     };
       
    32 
       
    33 CBtAudioManPlugin* CBtAudioManPlugin::NewL()
       
    34     {
       
    35     CBtAudioManPlugin* self = new (ELeave) CBtAudioManPlugin();
       
    36     CleanupStack::PushL(self);
       
    37     self->ConstructL();
       
    38     CleanupStack::Pop(self);
       
    39     return self;
       
    40     }
       
    41 
       
    42 CBtAudioManPlugin::~CBtAudioManPlugin()
       
    43     {
       
    44     delete iActive4ClientReq;
       
    45     delete iActive4ProfileStatus;
       
    46     iClient.Close();
       
    47     TRACE_FUNC
       
    48     }
       
    49 
       
    50 void CBtAudioManPlugin::SetObserver( MBTEngPluginObserver* aObserver )
       
    51     {
       
    52     iObserver = aObserver;
       
    53     }
       
    54 
       
    55 void CBtAudioManPlugin::GetSupportedProfiles( RProfileArray& aProfiles )
       
    56     {
       
    57     aProfiles.Reset();
       
    58     aProfiles.Append(EBTProfileHSP);
       
    59     aProfiles.Append(EBTProfileHFP);
       
    60     aProfiles.Append(EBTProfileA2DP);
       
    61     }
       
    62 
       
    63 TBool CBtAudioManPlugin::IsProfileSupported(const TBTProfile aProfile ) const
       
    64     {
       
    65     return (aProfile == EBTProfileHSP ||
       
    66         aProfile == EBTProfileHFP  ||
       
    67         aProfile == EBTProfileA2DP);
       
    68     }
       
    69 
       
    70 TInt CBtAudioManPlugin::Connect( const TBTDevAddr& aAddr )
       
    71     {
       
    72     TRACE_FUNC
       
    73     return HandleAsyncRequest(aAddr, ERequestConnect);    
       
    74     }
       
    75 
       
    76 void CBtAudioManPlugin::CancelConnect( const TBTDevAddr& aAddr )
       
    77     {
       
    78     if (iBTDevAddrPckgBuf() == aAddr &&
       
    79         iActive4ClientReq &&
       
    80         iActive4ClientReq->IsActive() &&
       
    81         iActive4ClientReq->RequestId() == ERequestConnect )
       
    82         {
       
    83         TRACE_INFO(_L("CBtAudioManPlugin::CancelConnect KErrCancel"))
       
    84         delete iActive4ClientReq;
       
    85         iActive4ClientReq = NULL;
       
    86         if (iObserver)
       
    87             {
       
    88             iObserver->ConnectComplete(iBTDevAddrPckgBuf(), 
       
    89                 EBTProfileHFP, KErrCancel);
       
    90             }
       
    91         }
       
    92     else
       
    93         {
       
    94         TRACE_INFO(_L("CBtAudioManPlugin::CancelConnect KErrNotFound"))
       
    95         if (iObserver)
       
    96             {
       
    97             iObserver->ConnectComplete(aAddr , 
       
    98                 EBTProfileHFP, KErrNotFound);
       
    99             }
       
   100         }
       
   101 
       
   102     }
       
   103 
       
   104 TInt CBtAudioManPlugin::Disconnect( const TBTDevAddr& aAddr, TBTDisconnectType /*aDiscType*/ )
       
   105     {
       
   106     TInt req = ERequestDisconnect;
       
   107     if (aAddr == TBTDevAddr())
       
   108         {
       
   109         req = ERequestDisconnectAll;
       
   110         }    
       
   111     return HandleAsyncRequest(aAddr, req);
       
   112     }
       
   113 
       
   114 void CBtAudioManPlugin::GetConnections( RBTDevAddrArray& aAddrArray, TBTProfile aConnectedProfile )
       
   115     {
       
   116     aAddrArray.Reset();
       
   117     TProfiles profile = EUnknownProfile;
       
   118     
       
   119     if (aConnectedProfile == EBTProfileHSP || aConnectedProfile == EBTProfileHFP)
       
   120         {
       
   121         profile = EAnyMonoAudioProfiles;
       
   122         }
       
   123     else if (aConnectedProfile == EBTProfileA2DP)
       
   124         {
       
   125         profile = EStereo;
       
   126         }
       
   127     else
       
   128         {
       
   129         return;
       
   130         }
       
   131     
       
   132     //guess there are 2 addresses as a 'best guess'
       
   133     TInt numAddresses = 2;
       
   134     TInt count = numAddresses;
       
   135     RBuf8 addrbuf;
       
   136     TPtrC8 ptr(addrbuf);
       
   137     
       
   138     do
       
   139         {
       
   140         //if this is > 1st time round, the buffer must be deleted and the
       
   141         //count might have changed
       
   142         addrbuf.Close();
       
   143         numAddresses = count;
       
   144         
       
   145         //create a buffer using the 'best guess' size
       
   146         TInt err = addrbuf.Create(KBTDevAddrSize * numAddresses);
       
   147         
       
   148         if (err != KErrNone)
       
   149             {
       
   150             //we can't do anything if the buffer fails to create, just return
       
   151             //and ignore the error as there is no error path (maybe this will
       
   152             //change in the future)
       
   153             return;
       
   154             }
       
   155         
       
   156         //get the number of connections and the addresses. count can be either
       
   157         //the number of connections or a system-wide error code
       
   158         count = iClient.GetConnections(addrbuf, profile);
       
   159         
       
   160         if (count < KErrNone)
       
   161             {
       
   162             //error occurred so we're finished with the buffer
       
   163             addrbuf.Close();
       
   164             
       
   165             //ignore the error as there is no error path (maybe this will
       
   166             //change in the future)
       
   167             return;
       
   168             }
       
   169         }
       
   170     //iterate if the number of connections is greater than our 'best guess' or
       
   171     //maybe another connection was established while this was taking place
       
   172     while (count > numAddresses);
       
   173     
       
   174     //iterate through the addresses buffer
       
   175     while (ptr.Length() >= KBTDevAddrSize)
       
   176         {
       
   177         //append each address to the device address array
       
   178         TInt err = aAddrArray.Append(TBTDevAddr(ptr.Left(KBTDevAddrSize)));
       
   179         
       
   180         if (err == KErrNone)
       
   181             {
       
   182             //shift the pointer along to the next address  
       
   183             ptr.Set(ptr.Mid(KBTDevAddrSize));
       
   184             }
       
   185         else
       
   186             {
       
   187             //error occurred so we're finished with the buffer
       
   188             addrbuf.Close();
       
   189             
       
   190             //ignore the error as there is no error path (maybe this will
       
   191             //change in the future)
       
   192             return;
       
   193             }
       
   194         }
       
   195     
       
   196     //now finished with the address buffer
       
   197     addrbuf.Close();
       
   198     }
       
   199 
       
   200 TBTEngConnectionStatus CBtAudioManPlugin::IsConnected( const TBTDevAddr& aAddr )
       
   201     {
       
   202     TBTEngConnectionStatus stat = (TBTEngConnectionStatus) iClient.IsConnected(aAddr);
       
   203     TRACE_INFO((_L("IsConnected %d"), stat))
       
   204     return stat;
       
   205     }
       
   206 
       
   207 void CBtAudioManPlugin::RequestCompletedL(CBasrvActive& aActive)
       
   208     {
       
   209     TRACE_FUNC
       
   210     switch (aActive.RequestId())
       
   211         {
       
   212         case ENotifyProfileStatusChange:
       
   213             {
       
   214             if (aActive.iStatus == KErrNone && iObserver)
       
   215                 {
       
   216                 ReportProfileConnectionEvents(iProfileStatus.iAddr, iProfileStatus.iProfiles,
       
   217                     iProfileStatus.iConnected);
       
   218                 iClient.NotifyConnectionStatus(iProfileStatusPckg, aActive.iStatus);
       
   219                 aActive.GoActive();
       
   220                 }
       
   221             break;
       
   222             }
       
   223         case ERequestConnect:
       
   224             {
       
   225             if (iActive4ClientReq->iStatus.Int() != KErrNone) // might have conflicts, decode iDiagnostic
       
   226                 {
       
   227                 if (iDiagnostic.Length() >= KBTDevAddrSize)
       
   228                     {
       
   229                     RBTDevAddrArray array;
       
   230                     CleanupClosePushL(array);
       
   231                     TPtrC8 ptr(iDiagnostic);
       
   232                     while (ptr.Length() >= KBTDevAddrSize)
       
   233                         {
       
   234                         array.AppendL(TBTDevAddr(ptr.Left(KBTDevAddrSize)));
       
   235                         #ifdef _DEBUG
       
   236                         const TPtrC8 myPtr(array[array.Count() - 1].Des());
       
   237                         #endif
       
   238                         TRACE_INFO((_L8("conflict <%S>"), &myPtr))
       
   239                         ptr.Set(ptr.Mid(KBTDevAddrSize));
       
   240                         }
       
   241                     iObserver->ConnectComplete(iBTDevAddrPckgBuf(), 
       
   242                         EBTProfileHFP, iActive4ClientReq->iStatus.Int(), &array);
       
   243                     CleanupStack::PopAndDestroy(&array);
       
   244                     }
       
   245                 else
       
   246                     {
       
   247                     iObserver->ConnectComplete(iBTDevAddrPckgBuf(), 
       
   248                         EBTProfileHFP, iActive4ClientReq->iStatus.Int());
       
   249                     }
       
   250                 }
       
   251             else
       
   252                 {
       
   253                 TInt profile = 0;
       
   254                 if (iDiagnostic.Length() >= sizeof(TInt))
       
   255                     {
       
   256                     TPckg<TInt> pckg(profile);
       
   257                     pckg.Copy(iDiagnostic.Mid(0, sizeof(TInt))); 
       
   258                     }
       
   259                 ReportProfileConnectionEvents(iBTDevAddrPckgBuf(), profile, ETrue);
       
   260                 }
       
   261             delete iActive4ClientReq;
       
   262             iActive4ClientReq = NULL;
       
   263             break;
       
   264             }
       
   265         case ERequestDisconnect:
       
   266             {
       
   267             if (iActive4ClientReq->iStatus.Int() != KErrNone)
       
   268                 {
       
   269                 iObserver->DisconnectComplete(iBTDevAddrPckgBuf(), 
       
   270                         EBTProfileHFP, iActive4ClientReq->iStatus.Int());
       
   271                 }
       
   272             else
       
   273                 {
       
   274                 TInt profile = 0;
       
   275                 if (iDiagnostic.Length() >= sizeof(TInt))
       
   276                     {
       
   277                     TPckg<TInt> pckg(profile);
       
   278                     pckg.Copy(iDiagnostic.Mid(0, sizeof(TInt))); 
       
   279                     }
       
   280                 ReportProfileConnectionEvents(iBTDevAddrPckgBuf(), profile, EFalse);
       
   281                 }            
       
   282             delete iActive4ClientReq;
       
   283             iActive4ClientReq = NULL;
       
   284             break;
       
   285             }
       
   286         case ERequestDisconnectAll:
       
   287             {
       
   288             iObserver->DisconnectComplete(iBTDevAddrPckgBuf(), 
       
   289                         EBTProfileHFP, iActive4ClientReq->iStatus.Int());
       
   290 			break;
       
   291             }
       
   292         }
       
   293     }
       
   294     
       
   295 void CBtAudioManPlugin::CancelRequest(CBasrvActive& aActive)
       
   296     {
       
   297     if (aActive.RequestId() == ENotifyProfileStatusChange )
       
   298         {
       
   299         iClient.CancelNotifyConnectionStatus();
       
   300         }
       
   301     else if (aActive.RequestId() == ERequestConnect )
       
   302         {
       
   303         iClient.CancelConnectToAccessory();
       
   304         }
       
   305     }
       
   306 
       
   307 CBtAudioManPlugin::CBtAudioManPlugin() : iProfileStatusPckg(iProfileStatus)
       
   308     {
       
   309     TRACE_FUNC
       
   310     }
       
   311 
       
   312 void CBtAudioManPlugin::ConstructL()
       
   313     {
       
   314     LEAVE_IF_ERROR(iClient.Connect());
       
   315     iActive4ProfileStatus = CBasrvActive::NewL(*this, CActive::EPriorityStandard, ENotifyProfileStatusChange);
       
   316     iClient.NotifyConnectionStatus(iProfileStatusPckg, iActive4ProfileStatus->iStatus);
       
   317     iActive4ProfileStatus->GoActive();
       
   318     }
       
   319 
       
   320 TInt CBtAudioManPlugin::HandleAsyncRequest(const TBTDevAddr& aAddr, TInt aRequestId)
       
   321     {
       
   322     TInt err = KErrNone;
       
   323     if (! iClient.Handle() )
       
   324         {
       
   325         err = iClient.Connect();
       
   326         }
       
   327     if ( err )
       
   328         {
       
   329         return err;
       
   330         }
       
   331     if ( iActive4ClientReq )
       
   332         {
       
   333         err = KErrServerBusy;
       
   334         }
       
   335     if (!err)
       
   336         {
       
   337         iActive4ClientReq = CBasrvActive::New(*this, CActive::EPriorityStandard, aRequestId);
       
   338         if (iActive4ClientReq)
       
   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         }
       
   361     return err;    
       
   362     }
       
   363 
       
   364 void CBtAudioManPlugin::ReportProfileConnectionEvents(const TBTDevAddr& aAddr, const TInt aProfiles, TBool aConnected)
       
   365     {
       
   366     TRACE_FUNC
       
   367     TRACE_INFO((_L("status %d profiles 0x%04X"), aConnected, aProfiles))
       
   368 	TBTEngConnectionStatus status = IsConnected(aAddr);
       
   369     if (iObserver)
       
   370         {
       
   371         if (aConnected)
       
   372             {
       
   373             if (aProfiles & EHFP)
       
   374                 {
       
   375                 iObserver->ConnectComplete(aAddr, EBTProfileHFP, KErrNone);
       
   376                 }
       
   377             if (aProfiles & EHSP)
       
   378                 {
       
   379                 iObserver->ConnectComplete(aAddr, EBTProfileHSP, KErrNone);
       
   380                 }
       
   381             if (aProfiles & EStereo)
       
   382                 {
       
   383                 iObserver->ConnectComplete(aAddr, EBTProfileA2DP, KErrNone);
       
   384                 }
       
   385             }
       
   386         else
       
   387             {
       
   388 			if(	status != EBTEngConnected )
       
   389 				{
       
   390 	            if (aProfiles & EHFP)
       
   391 	                {
       
   392 	                iObserver->DisconnectComplete(aAddr, EBTProfileHFP, KErrNone);
       
   393 	                }
       
   394 	            if (aProfiles & EHSP)
       
   395 	                {
       
   396 	                iObserver->DisconnectComplete(aAddr, EBTProfileHSP, KErrNone);
       
   397 	                }
       
   398 	            if (aProfiles & EStereo)
       
   399 	                {
       
   400 	                iObserver->DisconnectComplete(aAddr, EBTProfileA2DP, KErrNone);
       
   401 	                }
       
   402 				}
       
   403             }
       
   404         }
       
   405     }
       
   406 
       
   407 //