accessoryservices/autoaudioasy/src/cautoaudioasyservice.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 06 Jul 2010 15:43:30 +0300
changeset 45 c6215323ad55
parent 35 f7565e9c9ce8
child 76 cb32bcc88bad
permissions -rw-r--r--
Revision: 201027 Kit: 2010127

/*
* Copyright (c) 2010 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:  This class handles connect and disconnect to AccFw.
*
*/

#include <acccongenericid.h>
#include <accpolobjectcon.h>
#include <accpolnamevaluerecord.h>
#include <accconfigfileparser.h>
#include <accpolcommonnamevaluepairs.h>
#include <accessoryservicesinternalpskeys.h>
#include <autoaudiopskeys.h>

#include "cautoaudioasyservice.h"
#include "cautoaudioasypropertyobserver.h"
#include "acc_debug.h"

#define SET_STATE(state) (iState=state)
 
// ----------------------------------------------------------------------------------
// CAutoAudioAsyService::CAutoAudioAsyService() 
// ----------------------------------------------------------------------------------
CAutoAudioAsyService::CAutoAudioAsyService ()
	: CActive ( EPriorityStandard )
    {
    CActiveScheduler::Add ( this );
    }

// ----------------------------------------------------------------------------------
// CAutoAudioAsyService::NewL ()
// ----------------------------------------------------------------------------------
CAutoAudioAsyService* CAutoAudioAsyService::NewL ()
    {
    COM_TRACE_ ( "[AccFW:AutoAudioAsy] CAutoAudioAsyService::NewL" );
    CAutoAudioAsyService* self = new ( ELeave ) CAutoAudioAsyService ();
    CleanupStack::PushL ( self );
    self->ConstructL ();
    CleanupStack::Pop ( self );
    return self;
    }

// ----------------------------------------------------------------------------------
// CAutoAudioAsyService::ConstructL ()
// ----------------------------------------------------------------------------------
void CAutoAudioAsyService::ConstructL ()
    {
    COM_TRACE_ ( "[AccFW:AutoAudioAsy] CAutoAudioAsyService::ConstructL" );
    User::LeaveIfError ( iAccessoryServer.Connect () );
    User::LeaveIfError ( iAccessoryControl.CreateSubSession ( iAccessoryServer ) );
    SET_STATE ( EServiceStateIdle );	
    }

// ----------------------------------------------------------------------------------
// CAutoAudioAsyService::~CAutoAudioAsyService()
// ----------------------------------------------------------------------------------
CAutoAudioAsyService::~CAutoAudioAsyService ()
    {
    COM_TRACE_ ( "[AccFW:AutoAudioAsy] CAutoAudioAsyService::~CAutoAudioAsyService" );
    Cancel ();
	
	delete iPropertyObserver;
    iAccessoryControl.CloseSubSession ();
    iAccessoryServer.Close ();
    
	FreeResources ();
    }
	
void CAutoAudioAsyService::StartL ()
	{
    COM_TRACE_ ( "[AccFW:AutoAudioAsy] CAutoAudioAsyService::StartL" );
	iPropertyObserver = CAutoAudioAsyPropertyObserver::NewL ( KPSUidAccessoryServices, KPSAutoKeyRTPStreamingConnectionStatus, *this );
	}

// ----------------------------------------------------------------------------------
// CAutoAudioAsyService::PropertyChange ()
// Defined in MAutoAudioAsyPropertyListener interface.
// Receives notifications about RTP Streaming channel property changes. Property changes occur
// when accessory is connected or disconnected or headunit attached or detached
// ----------------------------------------------------------------------------------
void CAutoAudioAsyService::PropertyChange ( RProperty& aProperty, TUid aUid, TUint aKey, TInt aStatus )
    {
    COM_TRACE_ ( "[AccFW:AutoAudioAsy] CAutoAudioAsyService::PropertyChange" );

    TInt propValue;
    TInt status = aProperty.Get ( propValue );
    COM_TRACE_1 ( "[AccFW:AutoAudioAsy] CAutoAudioAsyService::PropertyChange -- request property value %d", propValue );
    
    if ( aUid == KPSUidAccessoryServices && aKey == KPSAutoKeyRTPStreamingConnectionStatus )
        {
        // Check if audio accessory has been connected
        if ( ( status == KErrNone ) && ( aStatus == KErrNone ) )
            {
			if ( propValue == EAudioConnectionStatusUnidirectional ) // Current release supports only UniDirectional, so other key values ignored.
				{
				TInt err;
				switch ( iState )
					{
					case EServiceStateIdle:
						TRAP ( err, ConnectAccessoryL () );
						if ( err != KErrNone )
							{
							COM_TRACE_1 ("[AccFW:AutoAudioAsy] ConnectAccessoryL error %d", err );
							FreeResources (); // switch to EServiceStateIdle							
							}
						break;
						
					case EServiceStateConnecting:
					case EServiceStateConnected:
						// Nothing to do
						break;
					}
				return;
				}
            }
			
        // Otherwise assume that it's disconnected
        AccessoryDisconnected ();
        }
    }

// ----------------------------------------------------------------------------------
// CAutoAudioAsyService::AccessoryDisconnected ()
// Called when a disconnect notification is received
// ----------------------------------------------------------------------------------
void CAutoAudioAsyService::AccessoryDisconnected ()
    {
    COM_TRACE_ ( "[AccFW:AutoAudioAsy] CAutoAudioAsyService::AccessoryDisconnected" );
    TRequestStatus status;
    switch ( iState )
        {
        case EServiceStateConnected:
            iAccessoryControl.DisconnectAccessory ( status, iGenericId->GenericID () );
            User::WaitForRequest ( status );
            FreeResources (); // sets state to EServiceStateIdle
            break;

        case EServiceStateConnecting:
            Cancel ();
            break;

        default:
            // nothing to do in this case
            break;
        }
    }

// ----------------------------------------------------------------------------------
// CAutoAudioAsyService::ConnectAccessoryL ()
// Notifies the accessory server and switches to EServiceStateConnecting state.
// ----------------------------------------------------------------------------------
void CAutoAudioAsyService::ConnectAccessoryL ()
    {
    COM_TRACE_ ( "[AccFW:AutoAudioAsy] CAutoAudioAsyService::ConnectAccessoryL" );

    RArray<TAccPolNameValueRecord> nameValueArray;
    CleanupClosePushL ( nameValueArray );

    // Set GenericID header
    COM_TRACE_ ( "[AccFW:AutoAudioAsy] Set generic header" );
    iGenericIDHeader.iAccessoryDeviceType   = KDTCarKit;
    iGenericIDHeader.iPhysicalConnection    = KPCUSB;
    iGenericIDHeader.iApplicationProtocol   = 0x0;
    iGenericIDHeader.iCapabilitiesSubblocks = KSBAudioSubblock;
    iGenericIDHeader.iHWDeviceID            = 0x0;
    iGenericIDHeader.iHWModelID				= KNullDesC;

    iGenericId = CAccConGenericID::NewL ();

    COM_TRACE_ ( "[AccFW:AutoAudioAsy] Set capabilities" );
    
    // Set "Audio Output Type" capability
	COM_TRACE_ ( "[AccFW:AutoAudioAsy] KAccAudioOutputType " );
    nameValueArray.AppendL ( TAccPolNameValueRecord ( KAccAudioOutputType,
        EAccAudioOutPutTypePublic, EAPVInt, EAPVPolicy ) );

    // Set "Audio stereo" capability
	COM_TRACE_ ( "[AccFW:AutoAudioAsy] KAccStereoAudio " );
	nameValueArray.AppendL ( TAccPolNameValueRecord ( KAccStereoAudio ) );

    // Set "Integrated audio output"
	COM_TRACE_ ( "[AccFW:AutoAudioAsy] KAccIntegratedAudioOutput " );
	nameValueArray.AppendL ( TAccPolNameValueRecord ( KAccIntegratedAudioOutput ) );

	// Set "RTP streaming"
	COM_TRACE_ ( "[AccFW:AutoAudioAsy] KAccRTPStreaming " );
	nameValueArray.AppendL ( TAccPolNameValueRecord ( KAccRTPStreaming ) );

    // Make generic id
    CAccConfigFileParser* accConfigFileParser = CAccConfigFileParser::NewL ( KNullDesC );
    CleanupStack::PushL ( accConfigFileParser );
    accConfigFileParser->ParseGenericIDL ( iGenericId, iGenericIDHeader, nameValueArray );

    // Connect accessory
    COM_TRACE_ ( "[AccFW:AutoAudioAsy] Connecting accessory..." );
    iAccessoryControl.ConnectAccessory ( iStatus, iGenericId, EFalse );
    SET_STATE ( EServiceStateConnecting );
    SetActive ();

    CleanupStack::PopAndDestroy ( accConfigFileParser );
    CleanupStack::PopAndDestroy ( &nameValueArray );
    }    

// ----------------------------------------------------------------------------------
// CActive methods
// ----------------------------------------------------------------------------------
void CAutoAudioAsyService::DoCancel ()
    {
    COM_TRACE_ ( "[AccFW:AutoAudioAsy] CAutoAudioAsyService::DoCancel" );
    iAccessoryControl.CancelConnectAccessory ();
    FreeResources ();
    }

TInt CAutoAudioAsyService::RunError ( TInt /*aError*/ )
    {
    COM_TRACE_ ( "[AccFW:AutoAudioAsy] CAutoAudioAsyService::RunError" );
    return KErrNone;
    }

void CAutoAudioAsyService::RunL ()
    {
    COM_TRACE_ ( "[AccFW:AutoAudioAsy] CAutoAudioAsyService::RunL" );
	TInt retVal ( iStatus.Int () );
	COM_TRACE_1 ( "[AccFW:AutoAudioAsy] Connected with return value %d", retVal );
	
    if ( KErrNone == retVal )
		{
			switch ( iState )
			{
			case EServiceStateConnecting:				
				SET_STATE ( EServiceStateConnected );
				break;
			
			case EServiceStateIdle:
			case EServiceStateConnected:
			default:
				COM_TRACE_ ( "State machine broken" );
				break;
			}
		}
	else
		{
		COM_TRACE_ ( "[AccFW:AutoAudioAsy] Accessory Server failed to accept connection, freeing up resources" );		
		FreeResources ();
		}
	}	
	
// ----------------------------------------------------------------------------------
// Frees resources and set state to EServiceStateIdle
// ----------------------------------------------------------------------------------
void CAutoAudioAsyService::FreeResources ()
    {
    COM_TRACE_ ( "[AccFW:AutoAudioAsy] CAutoAudioAsyService::FreeResources" );

    if ( iState != EServiceStateIdle )
        {
        SET_STATE ( EServiceStateIdle );
        }

    delete iGenericId;
    iGenericId = NULL;
    }