diff -r 000000000000 -r 4e1aa6a622a0 accessoryservices/accessoryserver/src/Server/AccSrvConnectionHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/accessoryservices/accessoryserver/src/Server/AccSrvConnectionHandler.cpp Tue Feb 02 00:53:00 2010 +0200 @@ -0,0 +1,1223 @@ +/* +* Copyright (c) 2002-2009 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: Connection Handler +* +*/ + + + +// INCLUDE FILES +#include "AccSrvConnectionHandler.h" +#include "AccSrvConnectionController.h" //MAccSrvConnectionControllerObserver +#include "AccPolSubblockNameArrayAccessor.h" +#include "AccPolAccessoryPolicy.h" +#include "AccSrvASYProxyHandler.h" +#include "AccSrvServerModel.h" +#include "AccPolGenericIDAccessor.h" +#include "AccPolicyDB.h" +#include "acc_debug.h" + +// EXTERNAL DATA STRUCTURES + +// EXTERNAL FUNCTION PROTOTYPES + +// CONSTANTS + +const TUid KAccFwUiDialogNotifierUid = { 0x10205062 }; + +// MACROS + +// LOCAL CONSTANTS AND MACROS + +// MODULE DATA STRUCTURES + +// LOCAL FUNCTION PROTOTYPES + +// FORWARD DECLARATIONS + +// ============================= LOCAL FUNCTIONS =============================== + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::CAccSrvConnectionHandler +// ----------------------------------------------------------------------------- +// +CAccSrvConnectionHandler::CAccSrvConnectionHandler( + MAccSrvConnectionControllerObserver* aCallback, + CAccSrvServerModel * aModel, + CAccPolAccessoryPolicy* aPolicy ) + : CAccSrvHandlerBase (aCallback), + iPolicy( aPolicy ), + iModel( aModel), + iReplyValue(0), + iReplyPck( iReplyValue) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::CAccSrvConnectionHandler()" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::ConstructL() + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::ConstructL()" ); + } + + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CAccSrvConnectionHandler* CAccSrvConnectionHandler::NewL( + MAccSrvConnectionControllerObserver* aCallback, + CAccSrvServerModel* aModel, + CAccPolAccessoryPolicy* aPolicy ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::NewL()" ); + + CAccSrvConnectionHandler* self = new( ELeave ) CAccSrvConnectionHandler( + aCallback, aModel, aPolicy ); + + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::NewL - return self" ); + return self; + } + +// Destructor +CAccSrvConnectionHandler::~CAccSrvConnectionHandler() + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::~CAccSrvConnectionHandler()" ); + + //closes notfier connection + iNotifier.Close(); + iRequestDataArray.Close(); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::RunL +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::RunL() + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::RunL()" ); + + switch ( iState ) + { + /* + Get response from the user (the notifier completes asyncronous command). Send + accessory update command to ASY. + */ + + case EGetSelectionFromUser: + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::RunL() - Get selection from user" ); + + if ( iReplyValue ) + { + COM_TRACE_1( "[AccFW:AccServer] CAccSrvConnectionHandler::RunL() - User selection %d", iReplyValue ); + + //update generic id + iPolicy->UpdateGenericIDL( iGenericID, iReplyValue); + + TASYCommandParamRecord asyCommandParamRecord; + asyCommandParamRecord.iCmdValue = 0;//Not used in update command + asyCommandParamRecord.iGenericID = iGenericID; + + //Send request to ASY Proxy Handler + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::RunL() - Send update request"); + TInt trId = iCallback->HandleASYCommsL( ECmdAccessoryUpdated, + asyCommandParamRecord ); + + //Stored request data is used when response is received from ASY + //(i.e. HandleValueMessageL) + StoreRequestData( asyCommandParamRecord.iNameRecord, trId, ETrue ); + + //Store this object to queue to be able to receive response from ASY + iCallback->RegisterControlMessageL( ESetValue, this ); + + //closes notfier connection + iNotifier.Close(); + } + else + { + // If this is KErrCancel, cancel is already done. Handle only if user has cancelled the dialog + if ( KErrNone == iStatus.Int() ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::RunL() - User cancel"); + iCallback->ConnectionHandlingCancel( this); + } + } + + } + break; + + case EInitializeConnection: + { + if( iCallback->ServerModelHandle().ASYsLoadCompleted() ) + { + if ( iConnectionUpdate ) + { + //get new capabilities to use + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::RunL() - Connection update, set new capabilities"); + iModel->CapabilityStorage().UseUpdatedGenericIDL( iGenericID); + } + + if ( InitializeCriticalCapsL() ) + { + //ASY query started + } + else + { + if ( iConnectionUpdate ) + { + //No critical caps, continue connection handling + TAccPolGenericID oldGenericId; + iModel->FindWithUniqueIDL( iGenericID.UniqueID(), oldGenericId); + iCallback->HandleConnectionUpdateValidationL( + iGenericID, oldGenericId, this, KErrNone ); + } + else + { + //No critical caps, continue connection handling + iCallback->HandleConnectValidationL( iGenericID, this, KErrNone ); + } + } + } + else + { + //ASY is not ready yet, wait for an another RunL-loop + CAccSrvHandlerBase::IssueRequest(); + } + } + break; + + case EWaitForUINotifier: + { + // If cancelled, do not show dialog + if ( KErrCancel != iStatus.Int() ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::RunL() - Change in boot state, try again open selection dialog" ); + OpenSelectionDialogL(); + } + } + break; + + default: + TRACE_ASSERT_ALWAYS; + break; + } + + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::RunL - return void" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::StartConnectionHandling +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::StartConnectionHandlingL( + TAccPolGenericID& aGenericID, + TBool aEvaluateConnectionRules, + TBool aUpdatedConnection ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::StartConnectionHandling()" ); + + iGenericID = aGenericID; + iConnectionUpdate = aUpdatedConnection; + + //evaluate connection rules + if ( aEvaluateConnectionRules ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::StartConnectionHandling() - Evaluate connection rules" ); + + //check rules + TUint32 selectionListBitmask( 0 ); + iPolicy->EvaluateConnectionRulesL( iGenericID, selectionListBitmask ); + + if ( selectionListBitmask ) + { + COM_TRACE_1( "[AccFW:AccServer] CAccSrvConnectionHandler::StartConnectionHandling() - Selection bitmask: 0x%bb", selectionListBitmask); + + //remove not supported items... + selectionListBitmask = selectionListBitmask & iModel->SupportedDevicesL(); + + //Check default selection + TInt defaultSelection( iModel->DeviceType() ); + + if ( selectionListBitmask == ( KASTTY | KASHeadset ) ) + { + if ( defaultSelection != KASTTY ) + { + defaultSelection = KASHeadset; + } + else + { + defaultSelection = KASTTY; + } + } + else + { + if ( defaultSelection == KASHeadset ) + { + defaultSelection = 0; + } + + defaultSelection = selectionListBitmask & defaultSelection; + } + + if ( defaultSelection ) + { + iReplyValue = defaultSelection; + iCallback->SetDefaultAccessoryInformation( iGenericID, defaultSelection ); + CAccSrvHandlerBase::IssueRequest(); + } + else + { + //check that more than one accessories in the selection list + TUint32 bitmask( 1 ); + TInt accCount( 0 ); + for ( TInt i( 0 ); i < 32; i++ ) + { + if ( selectionListBitmask & bitmask ) + { + if ( ++accCount > 1 ) + { + //more than one accessories, stop the loop + break; + } + } + bitmask <<= 1; + } + + if ( accCount > 1 ) + { + //if there is possible selection show UI + SetupSelectionDialogL( selectionListBitmask ); + } + else + { + //only one selection, don't show selection dialog + iState = EGetSelectionFromUser; + iReplyValue = selectionListBitmask; + iCallback->SetDefaultAccessoryInformation( iGenericID, selectionListBitmask ); + CAccSrvHandlerBase::IssueRequest(); + } + } + + } + else + { + iState = EInitializeConnection; + } + + } + else + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::StartConnectionHandling() - No connection rules" ); + iState = EInitializeConnection; + } + + + // Atleas one Asynchronous request is made for ourselves, + // clients ConnectAccessory asynchronous request will be completed + // during it. + if ( iState == EInitializeConnection ) + { + CAccSrvHandlerBase::IssueRequest(); + } + + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::StartConnectionHandling- return void" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::OpenSelectionDialogL +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::OpenSelectionDialogL() + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::OpenSelectionDialogL() - start" ); + + + if ( !iModel->IdleDetected() ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::OpenSelectionDialogL() - Idle is not detected" ); + + //boot is ongoing, wait for that ui notifier is ready + iState = EWaitForUINotifier; + + //wait for idle + Cancel(); + iStatus = KRequestPending; + iModel->WaitForIdle( &iStatus ); + SetActive(); + } + else + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::OpenSelectionDialogL() - Boot ok, connect notifier" ); + + iState = EGetSelectionFromUser; + + //selection bit mask package + TPckg selectionBitmaskPackage( iSelectionListBitmask ); + + //activate active object + Cancel(); + iStatus = KRequestPending; + + //open ui + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::OpenSelectionDialogL() - Open selection dialog" ); + User::LeaveIfError( iNotifier.Connect() ); + iNotifier.StartNotifierAndGetResponse( + iStatus, + KAccFwUiDialogNotifierUid, + selectionBitmaskPackage, + iReplyPck); + SetActive(); + } + + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::OpenSelectionDialogL() - end" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::OpenSelectionDialogL +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::SetupSelectionDialogL( TUint32 aSelectionListBitmask ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::SetupSelectionDialogL() - start" ); + iSelectionListBitmask = aSelectionListBitmask; + //open dialog + OpenSelectionDialogL(); + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::SetupSelectionDialogL() - end" ); + } + + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::UniqueIDForConnectionHandler +// ----------------------------------------------------------------------------- +// +TInt CAccSrvConnectionHandler::UniqueIDForConnectionHandler() + { + return iGenericID.UniqueID(); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::CancelConnectionHandling +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::CancelConnectionHandling() + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::CancelConnectionHandling() - start" ); + + if ( iNotifier.Handle() ) + { + // If notifier exists, it must be cancelled + iNotifier.CancelNotifier( KAccFwUiDialogNotifierUid ); + iNotifier.Close(); + // No need to cancel notifier request, cancel comes from notifier + } + + else if ( IsActive() ) + { + if ( EWaitForUINotifier == iState ) + { + // Internal request, cancel in different way + iModel->CancelWaitForIdle(); + } + else + { + Cancel(); + } + } + + // remove this from NotificationQueue + iCallback->CancelControlMessage( ESetValue, this ); + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::CancelConnectionHandling() - end" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::ResetHandler +// Resets member variables and is free to handle next connection +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::ResetHandler() + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::ResetHandler() - start" ); + // Reset member variables related to connection + iSelectionListBitmask = 0; + iReplyValue = 0; + iState = EGetSelectionFromUser; + iRequestDataArray.Reset(); + // Reset generic id. This also indicates that this hander has no connection + TAccPolGenericID temp; + iGenericID = temp; + // No need to reset iPolicy, iModel or iGenericID + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::ResetHandler() - end" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::IsFree +// ----------------------------------------------------------------------------- +// +TBool CAccSrvConnectionHandler::IsFree() + { + COM_TRACE_1( "[AccFW:AccServer] CAccSrvConnectionHandler::IsFree() - UniqueID(%i)", iGenericID.UniqueID() ); + return ( KErrNotFound == iGenericID.UniqueID() ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::InitializeCriticalCapsL +// ----------------------------------------------------------------------------- +// +TBool CAccSrvConnectionHandler::InitializeCriticalCapsL() + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::InitializeCriticalCapsL()" ); + + TBool ASYqueryStarted( EFalse ); + TAccPolNameRecord nameRecord; + TUint32 name( 0 ); + TASYCommandParamRecord asyCommandParamRecord; + + CAccPolSubblockNameArray* criticalCapabilities = CAccPolSubblockNameArray::NewL(); + CleanupStack::PushL( criticalCapabilities ); + + //After this query, criticalCapabilities contains all critical capabilities from iGenericID + iPolicy->ResolveCriticalCapabilitiesL( iGenericID, *criticalCapabilities ); + + TInt nameCount( TAccPolSubblockNameArrayAccessor::GetCount( *criticalCapabilities ) ); + + for ( TInt i( 0 ) ; iCapabilityStorage().GetCapability( iGenericID, name ); + + if ( !capValue) + { + User::Leave( KErrArgument ); + } + + if ( capValue->Type() == EAPVBool || + capValue->Type() == EAPVUInt || + capValue->Type() == EAPVInt ) + { + TInt32 value( 0 ); + TInt err( capValue->ValueInt( value ) ); + + if ( value == KErrUnknown && err == KErrNone ) + { + StartASYCommandHandlingL( capValue->Type(), asyCommandParamRecord ); + ASYqueryStarted = ETrue; + } + } + else + { + StartASYCommandHandlingL( capValue->Type(), asyCommandParamRecord ); + ASYqueryStarted = ETrue; + } + } + + CleanupStack::PopAndDestroy( criticalCapabilities ); + + //In case of BT, query supported BT-profiles from BT-ASY + if ( iGenericID.PhysicalConnectionCaps( KPCBluetooth ) ) + { + TAccPolNameRecord emptyNameRecord; + + asyCommandParamRecord.iNameRecord = emptyNameRecord; + asyCommandParamRecord.iCmdValue = iGenericID.DeviceAddress(); + asyCommandParamRecord.iGenericID = iGenericID; + + StartASYCommandHandlingL( EAPVDes8, asyCommandParamRecord ); + + ASYqueryStarted = ETrue; + } + + COM_TRACE_1( "[AccFW:AccServer] CAccSrvConnectionHandler::InitializeCriticalCapsL - return %d", ASYqueryStarted ); + return ( ASYqueryStarted ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::StartASYCommandHandlingL +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::StartASYCommandHandlingL( + TAccPolValueType aValueType, + TASYCommandParamRecord& aASYCommandParam ) + { + TProcessCmdId command( ECmdBadFunction ); + TInt trId( 0 ); + + switch ( aValueType ) + { + case EAPVBool: + { + command = ECmdGetValueBool; + } + break; + + case EAPVInt: + { + command = ECmdGetValueTInt; + } + break; + + case EAPVDes8: + { + if ( aASYCommandParam.iGenericID.PhysicalConnectionCaps( KPCBluetooth ) ) + { + //Supported profiles are queried from BT-ASY + command = ECmdGetSupportedBTProfiles; + } + else + { + command = ECmdGetValueTDes8; + } + } + break; + + default: + { + TRACE_ASSERT_ALWAYS; + } + break; + } + + //Send request to ASY Proxy Handler + trId = iCallback->HandleASYCommsL( command, aASYCommandParam ); + + //Stored request data is used when response is received from ASY + //(i.e. HandleValueMessageL) + StoreRequestData( aASYCommandParam.iNameRecord, trId, EFalse ); + + //Store this object to queue to be able to receive response from ASY + iCallback-> RegisterControlMessageL( EGetValue, this ); + + } +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::StoreRequestData +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::StoreRequestData( TAccPolNameRecord aName, + TInt aTrId, + TBool aUpdateConnectionNotification ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::StoreRequestData()" ); + + TAccSrvRequestData requestData; + requestData.iName = aName; + requestData.iTrId = aTrId; + requestData.iUpdateNotification = aUpdateConnectionNotification; + + iRequestDataArray.Append( requestData ); + + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::StoreRequestData - return void" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::FindRequestData +// +// Find the location of aTrId from iRequestDataArray +// ----------------------------------------------------------------------------- +// +TInt CAccSrvConnectionHandler::FindRequestData( TInt aTrId ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::FindRequestData()" ); + + TInt index( KErrNotFound ); + TInt count( iRequestDataArray.Count() ); + + for ( TInt i( 0 ); i < count ; ++i ) + { + if( iRequestDataArray.operator[]( i ).iTrId == aTrId ) + { + index = i;//match found + } + } + + COM_TRACE_1( "[AccFW:AccServer] CAccSrvConnectionHandler::FindRequestData - return %d", index ); + return index; + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::HandleValueMessageL (From MQueueObserver) +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::HandleValueMessageL( TMsgID aMsgID, + TAccValueTypeTBool aValue, + TInt aErrorCode, + TInt aTrId ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::HandleValueMessageL() - TBool" ); + + HandleValueMessagesL( aMsgID, aValue.iValue, aErrorCode, aTrId ); + + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::HandleValueMessageL - TBool - return void" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::HandleValueMessageL (From MQueueObserver) +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::HandleValueMessageL( TMsgID aMsgID, + TAccValueTypeTInt aValue, + TInt aErrorCode, + TInt aTrId ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::HandleValueMessageL() - TInt" ); + + HandleValueMessagesL( aMsgID, aValue.iValue, aErrorCode, aTrId ); + + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::HandleValueMessageL - TInt - return void" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::HandleValueMessagesL +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::HandleValueMessagesL( TMsgID /*aMsgID*/, + TInt aValue, + TInt aErrorCode, + TInt aTrId ) + { + COM_TRACE_1( "[AccFW:AccServer] CAccSrvConnectionHandler::HandleValueMessagesL(value=%d)", aValue ); + + TInt index( FindRequestData( aTrId ) ); + TAccSrvRequestData requestData; + TBool isUpdate( EFalse ); + + if ( KErrNotFound != index ) + { + requestData.iName = iRequestDataArray.operator[]( index ).iName; + requestData.iTrId = iRequestDataArray.operator[]( index ).iTrId; + requestData.iUpdateNotification = + iRequestDataArray.operator[]( index ).iUpdateNotification; + + if ( KErrNone == aErrorCode ) + { + + if ( requestData.iUpdateNotification ) + { + //ASY response to accessory update command, continue connection process.... + iState = EInitializeConnection; + IssueRequest(); + isUpdate = ETrue; + } + else + { + //Store value to capability storage + TUint32 name; + requestData.iName.GetName( name ); + + CCapValue* value = iModel->CapabilityStorage().GetCapability( iGenericID, name ); + + if ( !value) + { + User::Leave( KErrArgument ); + } + value->SetValueL( aValue ); + } + } + else + { + COM_TRACE_1( "[AccFW:AccServer] CAccSrvConnectionHandler::HandleValueMessagesL - Error response received(err=%d)", aErrorCode ); + } + + iRequestDataArray.Remove( index );//Remove this request from iRequestDataArray + } + else + { + COM_TRACE_1( "[AccFW:AccServer] CAccSrvConnectionHandler::HandleValueMessagesL - Unidentified response received(TrID=%d)", aTrId ); + TRACE_ASSERT_ALWAYS; + } + + if ( 0 == iRequestDataArray.Count() && !isUpdate ) + { + //No more pending requests + iCallback->HandleConnectValidationL( iGenericID, this, KErrNone ); + } + else + { + //Wait next response + } + + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::HandleValueMessagesL - return void " ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::HandleValueMessageL (From MQueueObserver) +// +// Resolve the Generic ID according to the profile information +// received from BT-ASY. +// +// TASYBTAccInfo type is only supported object in aValue. Its assumed that ASY +// uses package buffer to make type safe transfer for that object i.e. +// TASYBTAccInfo btInfo +// TASYBTAccInfoPckgC btInfoPckgC( btInfo ) +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::HandleValueMessageL( TMsgID /*aMsgID*/, + TDesC8& aValue, + TInt aErrorCode, + TInt aTrId ) + { + COM_TRACE_1( "[AccFW:AccServer] CAccSrvConnectionHandler::HandleValueMessageL(err=%d) - TDesC8", aErrorCode ); + + TInt index( FindRequestData( aTrId ) ); + + if ( KErrNotFound != index) + { + iRequestDataArray.Remove( index );//Remove this request from iRequestDataArray + //RequestData was not used in this case + } + else + { + TRACE_ASSERT_ALWAYS;//iRequestDataArray is out of sync + } + + if ( KErrNone == aErrorCode ) + { + ResolveGenericIDL( aValue ); + } + + if ( 0 == iRequestDataArray.Count() ) + { + //No more pending requests + iCallback->HandleConnectValidationL( iGenericID, this, aErrorCode ); + } + else + { + //Wait next response + } + + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::HandleValueMessageL - TDesC8 - return void" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::HandleValueMessagesL +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::HandleValueMessageL( TMsgID /*aMsgID*/, + TInt /*aTrId*/, + TPtr8* /*aPtrBuf*/, + TInt /*aErrorCode*/ ) + { + User::Leave( KErrNotSupported ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::ResolveGenericIDL +// +// Fill Generic ID according supported profiles received from BT-ASY. +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::ResolveGenericIDL( TDesC8& aValue ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::ResolveGenericIDL()" ); + + TPckg btInfoPckg( *static_cast *>( &aValue ) ); + + COM_TRACE_3( "[AccFW:AccServer] CAccSrvConnectionHandler::ResolveGenericIDL - model=%d type=%d prof=%d", btInfoPckg().iDeviceInfo, btInfoPckg().iDeviceType, btInfoPckg().iProfiles ); + COM_TRACE_4( "[AccFW:AccServer] CAccSrvConnectionHandler::ResolveGenericIDL - HSP=%d HFP=%d AVRCP=%d A2DP=%d", btInfoPckg().iSupportedFeatures[0], btInfoPckg().iSupportedFeatures[1], btInfoPckg().iSupportedFeatures[2], btInfoPckg().iSupportedFeatures[3]); + + TAccPolGenericIDAccessor::SetHWDeviceID( iGenericID, + btInfoPckg().iDeviceInfo ); + TAccPolGenericIDAccessor::SetFeatureAttributeL( iGenericID, + KAccPolDTDeviceType, + btInfoPckg().iDeviceType ); + + if ( btInfoPckg().iReserved & KAccInfoDRM ) + { + //If accessory have recording possibility, KAccNoDRMOutput capability is set. + //i.e. Capturing Major Service Class is indicated by accessory. + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::ResolveGenericIDL - DRM output not allowed" ); + iModel->CapabilityStorage().SetCapabilityL( iGenericID, KAccNoDRMOutput ); + } + + if ( btInfoPckg().iReserved & KAccInfoLatency ) + { + //If accessory provides latency information, KAccAudioLatency capability is set. + //Initialize capability value as 0. Will be updated via notification. + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::ResolveGenericIDL - Latency set" ); + iModel->CapabilityStorage().SetCapabilityL( iGenericID, KAccAudioLatency, EAPVAccessory, EAPVInt, 0 ); + } + + ResolveGidL(); + + // Fill the Audio subblock and Bluetooth subblock + if ( KAccInfoHSP & btInfoPckg().iProfiles )//Headset Profile (HSP) + { + ResolveHSPSpecificGidL( btInfoPckg().iSupportedFeatures.At( EAccInfoHSPIndex ) ); + } + + if ( KAccInfoHFP & btInfoPckg().iProfiles )//Handsfree Profile (HFP) + { + ResolveHFPSpecificGidL( btInfoPckg().iSupportedFeatures.At( EAccInfoHFPIndex ) ); + } + + if ( KAccInfoAVRCP & btInfoPckg().iProfiles )//Audio Video Remote Control Profile (AVRCP) + { + ResolveAVRCPSpecificGidL( btInfoPckg().iSupportedFeatures.At( EAccInfoAVRCPIndex ) ); + } + + if ( KAccInfoA2DP & btInfoPckg().iProfiles )//Advanced Audio Distribution Profile (A2DP) + { + ResolveA2DPSpecificGidL( btInfoPckg().iSupportedFeatures.At( EAccInfoA2DPIndex ) ); + } + + //Update GenericID to CapabilityStorage + iModel->CapabilityStorage().SetGenericIDHeaderL( + *( reinterpret_cast( &iGenericID ) ) ); + + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::ResolveGenericIDL - return void" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::ResolveGidL +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::ResolveGidL() + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::ResolveGidL()" ); + TInt value; + + //Set Audio Output Type capability. For CarKits its public, otherwise private. + if ( iGenericID.DeviceTypeCaps( KDTCarKit ) ) + { + value = EAccAudioOutPutTypePublic; + } + else + { + value = EAccAudioOutPutTypePrivate; + } + + //Set KAccAudioOutputType capability + iModel->CapabilityStorage().SetCapabilityL( + iGenericID, KAccAudioOutputType, EAPVPolicy, EAPVInt, value ); + + //Set KAccSetVolumeLevel capability with zero value. + //Real values are filled according to supported features. + iModel->CapabilityStorage().SetCapabilityL( + iGenericID, KAccSetVolumeLevel, EAPVPolicy, EAPVInt, 0 ); + + //Set KSBAudioSubblock capability group + TAccPolGenericIDAccessor::SetFeatureAttributeL( iGenericID, + KAccPolSBCapabilities, + iGenericID.SubblockCaps() | + KSBAudioSubblock ); + + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::ResolveGidL - return void" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::ResolveHSPSpecificGidL +// +// HEADSET PROFILE 1.1 / supported features: +// Remote audio volume control +// -Boolean +// -Optional +// -Default=False +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::ResolveHSPSpecificGidL( TUint16 aSupportedFeatures ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::ResolveHSPSpecificGidL()" ); + + /****************** + * Audio subblock * + ******************/ + //following capabilities are fixed (because of Headset profile is supported) + iModel->CapabilityStorage().SetCapabilityL( iGenericID, KAccMonoAudio ); + iModel->CapabilityStorage().SetCapabilityL( iGenericID, KAccIntegratedAudioInput );//i.e. all HSP accessories has microphone + + if ( aSupportedFeatures ) + { + //Remote audio volume control is supported. + UpdateSetVolumeLevelCapabilityL( KAccSetVolumeLevelHSP ); + } + + //KSBAudioSubblock capability group is allready set in CAccSrvConnectionHandler::ResolveGidL() + + /********************** + * Bluetooth subblock * + **********************/ + //Set KAccBTHSP capability and KSBBluetoothSubblock capability group + iModel->CapabilityStorage().SetCapabilityL( iGenericID, KAccBTHSP); + TAccPolGenericIDAccessor::SetFeatureAttributeL( iGenericID, + KAccPolSBCapabilities, + iGenericID.SubblockCaps() | + KSBBluetoothSubblock ); + + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::ResolveHSPSpecificGidL - return void" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::ResolveHFPSpecificGidL +// +// Accessory device type is resolved according to this table: +// Profile supported Accessory type +// ----------------- -------------- +// both headset and handsfree headset +// headset headset +// handsfree carkit +// +// Hands-Free Profile 1.0 / supported features bitmap: +// 000000 +// ^^^^^^ +// |||||| +// ||||||--Bit 0----- EC and/or NR function +// |||||---Bit 1----- Call waiting and 3-way calling +// ||||----Bit 2----- CLI presentation capability +// |||-----Bit 3----- Voice recognition activation +// ||------Bit 4----- Remote volume control +// |-------Bit 5-31-- Unused (available for PAP and other extensibility) +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::ResolveHFPSpecificGidL( TUint16 aSupportedFeatures ) + { + COM_TRACE_( "[AccFW:AccServer] CAccBTConnectionHandler::ResolveHFPSpecificGidL()" ); + + /****************** + * Audio subblock * + ******************/ + // The default value for supported features of a HF device according to the + // HF profile specification is 0. + if ( aSupportedFeatures & 0x1 )//Bit 0 -> EC and/or NR function + { + iModel->CapabilityStorage().SetCapabilityL( iGenericID, + KAccAcousticEchoControl, + EAPVAccessory, + EAPVBool, + EFalse ); + iModel->CapabilityStorage().SetCapabilityL( iGenericID, + KAccNoiseReduction, + EAPVAccessory, + EAPVBool, + EFalse ); + } + + + if ( aSupportedFeatures & 0x8 )//Bit 3 -> Voice recognition + { + iModel->CapabilityStorage().SetCapabilityL( iGenericID, + KAccBTVoiceRecognition ); + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::ResolveHFPSpecificGidL - KAccVoiceRecognition supported." ); + } + else + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::ResolveHFPSpecificGidL - KAccVoiceRecognition not supported." ); + } + + + if ( aSupportedFeatures & 0x10 )//Bit 4 -> Remote volume control + { + //Remote audio volume control is supported. + UpdateSetVolumeLevelCapabilityL( KAccSetVolumeLevelHFP ); + } + + //following capabilities are fixed (because of Handsfree profile is supported) + iModel->CapabilityStorage().SetCapabilityL( iGenericID, KAccMonoAudio ); + iModel->CapabilityStorage().SetCapabilityL( iGenericID, KAccIntegratedAudioInput );//i.e. all HFP accessories has microphone + + //KSBAudioSubblock capability group is allready set in CAccSrvConnectionHandler::ResolveGidL() + + /********************** + * Bluetooth subblock * + **********************/ + //Set KAccBTHSP capability and KSBBluetoothSubblock capability group + iModel->CapabilityStorage().SetCapabilityL( iGenericID, KAccBTHFP ); + TAccPolGenericIDAccessor::SetFeatureAttributeL( iGenericID, + KAccPolSBCapabilities, + iGenericID.SubblockCaps() | + KSBBluetoothSubblock ); + + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::ResolveHFPSpecificGidL - return void" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::ResolveAVRCPSpecificGidL +// +// AUDIO/VIDEO REMOTE CONTROL PROFILE 1.0 / supported features bitmap: +// AVRCP +// Service Record for TG (Accessory is TG) +// Bit 0 = Category 1 +// Bit 1 = Category 2 +// Bit 2 = Category 3 +// Bit 3 = Category 4 +// Bit 4-15 = Reserved for Future Additions +// +// Service Record for CT +// Bit 0 = Category 1 +// Bit 1 = Category 2 +// Bit 2 = Category 3 +// Bit 3 = Category 4 +// Bit 4-15 = Reserved for Future Additions +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::ResolveAVRCPSpecificGidL( + TUint16 /*aSupportedFeatures*/ ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::ResolveAVRCPSpecificGidL()" ); + + /****************** + * Audio subblock * + ******************/ + //AVRCP doesn't support remote audio volume control. + + /********************** + * Bluetooth subblock * + **********************/ + //Set KAccBTAVRCP capability and KSBBluetoothSubblock capability group + iModel->CapabilityStorage().SetCapabilityL( iGenericID, KAccBTAVRCP ); + TAccPolGenericIDAccessor::SetFeatureAttributeL( iGenericID, + KAccPolSBCapabilities, + iGenericID.SubblockCaps() | + KSBBluetoothSubblock ); + + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::ResolveAVRCPSpecificGidL - return void" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::ResolveA2DPSpecificGidL +// +// ADVANCED AUDIO DISTRIBUTION PROFILE SPECIFICATION 1.0 / supported features bitmap: +// A2DP +// +// Service Record for Sink (Accessory is sink) +// Bit 0 = Headphone +// Bit 1 = Speaker +// Bit 2 = Recorder +// Bit 3 = Amplifier +// Bit 4-15 = Reserved for Future Additions +// +// Service Record for Source +// Bit 0 = Player +// Bit 1 = Microphone +// Bit 2 = Tuner +// Bit 3 = Mixer +// Bit 4-15 = Reserved for Future Additions +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::ResolveA2DPSpecificGidL( TUint16 /*aSupportedFeatures*/ ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::ResolveA2DPSpecificGidL()" ); + + /****************** + * Audio subblock * + ******************/ + iModel->CapabilityStorage().SetCapabilityL( iGenericID, KAccStereoAudio ); + //KSBAudioSubblock capability group is allready set in CAccSrvConnectionHandler::ResolveGidL() + + /********************** + * Bluetooth subblock * + **********************/ + //Set KAccBTA2DP capability and KSBBluetoothSubblock capability group + iModel->CapabilityStorage().SetCapabilityL( iGenericID, KAccBTA2DP ); + TAccPolGenericIDAccessor::SetFeatureAttributeL( iGenericID, + KAccPolSBCapabilities, + iGenericID.SubblockCaps() | + KSBBluetoothSubblock ); + + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::ResolveA2DPSpecificGidL - return void" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::UpdateSetVolumeLevelCapabilityL +// +// Read the existing KAccSetVolumeLevel capability value and update it +// according to the aCapability parameter. +// ----------------------------------------------------------------------------- +// +void CAccSrvConnectionHandler::UpdateSetVolumeLevelCapabilityL( TInt32 aCapability ) + { + COM_TRACE_1( "[AccFW:AccServer] CAccSrvConnectionHandler::UpdateSetVolumeLevelCapabilityL(%d)", aCapability ); + + CCapValue* capValue = iModel->CapabilityStorage().GetCapability( + iGenericID, KAccSetVolumeLevel ); + + if ( capValue ) + { + TInt32 currentValue( 0 ); + if( KErrNone == capValue->ValueInt( currentValue ) ) + { + currentValue = currentValue | aCapability; + iModel->CapabilityStorage().SetCapabilityL( + iGenericID, + KAccSetVolumeLevel, + EAPVPolicy, + EAPVInt, + currentValue ); + } + } + + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::UpdateSetVolumeLevelCapabilityL - return void" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::RunError +// +// Called if RunL Leaves +// ----------------------------------------------------------------------------- +// +TInt CAccSrvConnectionHandler::RunError( TInt aError ) + { + COM_TRACE_1( "[AccFW:AccServer] CAccSrvConnectionHandler::RunError(%d)", aError ); + + aError = KErrNone;// Avoid Panic in CActiveScheduler + + COM_TRACE_( "[AccFW:AccServer] CAccSrvConnectionHandler::RunError - return KErrNone" ); + + return aError; + } + +// ----------------------------------------------------------------------------- +// CAccSrvConnectionHandler::CompleteMessageL (From MQueueObserver) +// ----------------------------------------------------------------------------- +// +TBool CAccSrvConnectionHandler::CompleteMessageL( TMsgID /*aMsgID*/, + TInt /*aErrorCode*/, + TInt /*aUniqueID*/ ) + { + //Not used, must define it here because pure virtual in base class (MQueueObserver) + TRACE_ASSERT_ALWAYS; + return EFalse; + } + +// ----------------------------------------------------------------------------- +//CAccSrvConnectionHandler::CompleteProcessCommandL +// ----------------------------------------------------------------------------- +// +TBool CAccSrvConnectionHandler::CompleteProcessCommandL( + TProcessCmdId /*aCmdn*/, + TInt /*aTrId*/, + TASYCommandParamRecord& /*aASYCommandParamRecord*/, + TPtr8* /*aPtrBuf*/ ) + { + //Not used, must define it here because pure virtual in base class (MQueueObserver) + TRACE_ASSERT_ALWAYS; + return EFalse; + } +// End of File