/*
* 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<TUint32> 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 ) ; i<nameCount ; ++i )
{
TAccPolSubblockNameArrayAccessor::GetName( *criticalCapabilities,
i,
name );
nameRecord.SetName( name );
asyCommandParamRecord.iNameRecord = nameRecord;
asyCommandParamRecord.iCmdValue = 0;//Not used in Getters
asyCommandParamRecord.iGenericID = iGenericID;
CCapValue* capValue = iModel->CapabilityStorage().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<TASYBTAccInfo> btInfoPckg( *static_cast<TPckg<TASYBTAccInfo> *>( &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<TAccPolGIDHeader*>( &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