/*
* Copyright (c) 2004-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: Generic hid implementation
*
*/
#include <etel3rdparty.h>
#include <e32std.h>
#include <e32svr.h>
#include <coedef.h>
#include <eiksvdef.h>
#include <apgcli.h>
#include <apgtask.h>
#include <e32property.h>
#include <alarmuidomainpskeys.h>
#include <mpxplaybackmessage.h>
#include <mpxmessagegeneraldefs.h>
#include <mpxplaybackmessagedefs.h>
#include "hidremconbearerinternalpskeys.h"
#include "hidremconbearerscancodes.h"
#include "headset.h"
#include "finder.h"
#include "debug.h"
const TInt KHidUndefinedKeyCode = 0;
const TInt KHidNotSetKeyValue = 0;
const TInt KDoubleClickTimeout = 900000; // 0,9 seconds
const TInt KDoubleClickTimeoutRing = 500000; // 0,5 seconds
const TInt KScanClickTimeout = 500000; // 0,5 seconds
const TInt KLongClickTimeout = 3000000; // 3 seconds
// ======== MEMBER FUNCTIONS ========
// ---------------------------------------------------------------------------
// CHidHeadsetDriver()
// ---------------------------------------------------------------------------
//
CHidHeadsetDriver::CHidHeadsetDriver( MDriverAccess* aGenericHid ) :
iGenericHid( aGenericHid ), iFieldList(), iDriverState( EUninitialised ),
iConnectionId( 0 ), iSupportedFieldCount( 0 ), iForwardStatus(
EScanNotPressed ), iBackwardStatus( EScanNotPressed )
{
TRACE_FUNC_ENTRY_THIS
TRACE_FUNC_EXIT
}
// ---------------------------------------------------------------------------
// NewLC
// ---------------------------------------------------------------------------
//
CHidHeadsetDriver* CHidHeadsetDriver::NewLC( MDriverAccess* aGenericHid )
{
TRACE_INFO((_L("[HID]\tCHidHeadsetDriver::NewLC(0x%08x)"), aGenericHid));
CHidHeadsetDriver* self = new ( ELeave ) CHidHeadsetDriver( aGenericHid );
CleanupStack::PushL( self );
self->ConstructL();
return self;
}
// ---------------------------------------------------------------------------
// NewL
// ---------------------------------------------------------------------------
//
CHidHeadsetDriver* CHidHeadsetDriver::NewL( MDriverAccess* aGenericHid )
{
CHidHeadsetDriver* self = CHidHeadsetDriver::NewLC( aGenericHid );
CleanupStack::Pop();
return self;
}
// ---------------------------------------------------------------------------
// ConstructL()
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::ConstructL()
{
TRACE_FUNC_THIS
iTelephony = CTelephony::NewL();
User::LeaveIfError( iAlarmServerSession.Connect() );
iMusicPlayer = MMPXPlaybackUtility::UtilityL( KPbModeActivePlayer );
iMusicPlayer->AddObserverL( *this );
}
// ---------------------------------------------------------------------------
// Destructor
// ---------------------------------------------------------------------------
//
CHidHeadsetDriver::~CHidHeadsetDriver()
{
TRACE_FUNC_THIS
iAlarmServerSession.Close();
delete iTelephony;
iFieldList.Reset();
iFieldList.Close();
delete iDoubleClicktimer;
if ( iMusicPlayer )
{
iMusicPlayer->Close();
}
delete iScanPreviousTimer;
delete iScanNextTimer;
delete iLongClicktimer;
}
// ---------------------------------------------------------------------------
// From class CHidDriver
// StartL()
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::StartL( TInt /*aConnectionId*/)
{
TRACE_FUNC
// Ready to process headset events:
iDriverState = EInitialised;
}
// ---------------------------------------------------------------------------
// From class CHidDriver
// InitialiseL()
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::InitialiseL( TInt aConnectionId )
{
TRACE_FUNC
TRACE_INFO((_L("[HID]\tCHidHeadsetDriver::InitialiseL(%d)"),
aConnectionId));
// Store the connection ID:
iConnectionId = aConnectionId;
}
// ---------------------------------------------------------------------------
// From class CHidDriver
// Stop()
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::Stop()
{
TRACE_FUNC
iDriverState = EDisabled;
}
// ---------------------------------------------------------------------------
// From class CHidDriver
// DataIn()
// ---------------------------------------------------------------------------
//
TInt CHidHeadsetDriver::DataIn( CHidTransport::THidChannelType aChannel,
const TDesC8& aPayload )
{
// validate input data
if (0 >= aPayload.Length())
{
return KErrArgument;
}
TInt retVal = KErrNone;
switch ( aChannel )
{
case CHidTransport::EHidChannelInt:
if ( EInitialised == iDriverState )
{
retVal = InterruptData( aPayload );
}
break;
case CHidTransport::EHidChannelCtrl:
retVal = KErrNotSupported;
break;
default:
retVal = KErrNotSupported;
break;
}
return retVal;
}
// ---------------------------------------------------------------------------
// From class CHidDriver
// CommandResult()
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::CommandResult( TInt /*aCmdAck*/)
{
// No implementation as we don't issue any requests to be acknowledged
}
// ---------------------------------------------------------------------------
// From class CHidDriver
// Disconnected()
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::Disconnected( TInt aReason )
{
TRACE_INFO((_L("[HID]\tCHidHeadsetDriver::Disconnected(%d)"), aReason));
aReason = aReason;
Stop();
}
// ---------------------------------------------------------------------------
// From class CHidDriver
// SetInputHandlingReg()
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::SetInputHandlingReg(
CHidInputDataHandlingReg* aHandlingReg )
{
iInputHandlingReg = aHandlingReg;
}
// ---------------------------------------------------------------------------
// From class CHidDriver
// InterruptData()
// ---------------------------------------------------------------------------
//
TInt CHidHeadsetDriver::InterruptData( const TDesC8& aPayload )
{
// If the report has a report ID, it is in the first byte.
// If not, this value is ignored (see CField::IsInReport()).
//
TInt retVal = KErrNone;
TInt ret = KErrNotSupported;
TInt firstByte = aPayload[0];
TRACE_INFO((_L("[HID]\tCHidHeadsetDriver::InterruptData(), report \
0x%x (%d), length %d"),firstByte, firstByte, aPayload.Length()));
if ( iFieldList.Count() == 0 )
{
retVal = KErrNotSupported;
}
for ( TInt i = 0; i < iFieldList.Count(); i++ )
{
if ( iFieldList[i]->IsInReport( firstByte ) )
{
ret = HandleReport( aPayload, iFieldList[i] );
if ( ret == KErrNone )
{
retVal = KErrNone;
}
}
else
{
retVal = KErrNotSupported;
}
}
return retVal;
}
// ---------------------------------------------------------------------------
// HandleReport()
// ---------------------------------------------------------------------------
//
TInt CHidHeadsetDriver::HandleReport( const TDesC8& aReport,
const CField* aField )
{
TRACE_FUNC_ENTRY
TReportTranslator report( aReport, aField );
TInt retVal = KErrNotSupported;
// release if key if it pressed and relased
ReleasePressedKeys( report );
if ( HandleTelephonyUsage( report ) == KErrNone )
{
retVal = KErrNone;
}
if ( HandleControlUsage( report ) == KErrNone )
{
retVal = KErrNone;
}
if ( HandleVolumeUsage( report ) == KErrNone )
{
retVal = KErrNone;
}
TRACE_FUNC_EXIT
return retVal;
}
// ---------------------------------------------------------------------------
// HandleTelephonyUsage()
// ---------------------------------------------------------------------------
//
TInt CHidHeadsetDriver::HandleTelephonyUsage( TReportTranslator& aReport )
{
TRACE_FUNC_ENTRY
TInt retVal = KErrNotSupported;
TInt hookSwitch = 0;
TInt mute = 0;
TInt poc = 0;
// P&S key variables
TUint key = KHidUndefinedKeyCode;
TInt value = KHidNotSetKeyValue;
if ( aReport.GetValue( mute, ETelephonyUsagePhoneMute ) == KErrNone
&& mute == 1 )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver::HandleReport(): Send mute \
command"));
if ( iInputHandlingReg->AllowedToHandleEvent( EUsagePageTelephony,
ETelephonyUsagePhoneMute ) )
{
key = KHidMuteKeyEvent;
value = KPSMuteClicked;
iInputHandlingReg->AddHandledEvent( EUsagePageTelephony,
ETelephonyUsagePhoneMute );
}
}
else if ( aReport.GetValue( hookSwitch, ETelephonyUsageHookSwitch )
== KErrNone && hookSwitch == 1 )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver::HandleReport(): Send hook \
switch command (disabled)"));
if ( iInputHandlingReg->AllowedToHandleEvent( EUsagePageTelephony,
ETelephonyUsageHookSwitch ) )
{
HookKeyPres( ETrue );
iInputHandlingReg->AddHandledEvent( EUsagePageTelephony,
ETelephonyUsageHookSwitch );
}
}
else if ( aReport.GetValue( poc, ETelephonyUsagePoC ) == KErrNone && poc
== 1 )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver::HandleReport(): Send PoC \
command (disabled)"));
if ( iInputHandlingReg->AllowedToHandleEvent( EUsagePageTelephony,
ETelephonyUsagePoC ) )
{
key = KHidMuteKeyEvent;
value = KPSMuteClicked;
iInputHandlingReg->AddHandledEvent( EUsagePageTelephony,
ETelephonyUsagePoC );
}
}
if ( key != KHidUndefinedKeyCode && value != KHidNotSetKeyValue )
{
TInt err = RProperty::Set( KPSUidHidEventNotifier, key, value );
retVal = KErrNone;
}
TRACE_FUNC_EXIT
return retVal;
}
// ---------------------------------------------------------------------------
// HandleTelephonyUsage()
// ---------------------------------------------------------------------------
//
TInt CHidHeadsetDriver::HandleControlUsage( TReportTranslator& aReport )
{
TRACE_FUNC_ENTRY
TInt retVal = KErrNotSupported;
TInt playPause = 0;
TInt scanNext = 0;
TInt scanPrev = 0;
TInt stop = 0;
// P&S key variables
TUint key = KHidUndefinedKeyCode;
TInt value = KHidNotSetKeyValue;
if ( aReport.GetValue( playPause, EConsumerUsagePlayPause ) == KErrNone
&& playPause )
{
if ( iInputHandlingReg->AllowedToHandleEvent( EUsagePageConsumer,
EConsumerUsagePlayPause ) )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver::HandleReport(): Send \
play/pause command (currently only play)"));
key = KHidControlKeyEvent;
value = EPlayClicked;
iInputHandlingReg->AddHandledEvent( EUsagePageConsumer,
EConsumerUsagePlayPause );
}
}
else if ( aReport.GetValue( scanNext, EConsumerUsageScanNext )
== KErrNone && scanNext )
{
if ( iInputHandlingReg->AllowedToHandleEvent( EUsagePageConsumer,
EConsumerUsageScanNext ) )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver::HandleReport(): Send \
scan next command"));
TRAP_IGNORE( HandleScanNextPressL() );
iInputHandlingReg->AddHandledEvent( EUsagePageConsumer,
EConsumerUsageScanNext );
}
}
else if ( aReport.GetValue( scanPrev, EConsumerUsageScanPrev )
== KErrNone && scanPrev )
{
if ( iInputHandlingReg->AllowedToHandleEvent( EUsagePageConsumer,
EConsumerUsageScanPrev ) )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver::HandleReport(): Scan \
prev command"));
TRAP_IGNORE( HandleScanPrevPressL());
iInputHandlingReg->AddHandledEvent( EUsagePageConsumer,
EConsumerUsageScanPrev );
}
}
else if ( aReport.GetValue( stop, EConsumerUsageStop ) == KErrNone
&& stop )
{
if ( iInputHandlingReg->AllowedToHandleEvent( EUsagePageConsumer,
EConsumerUsageStop ) )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver::HandleReport(): Send \
stop command"));
key = KHidControlKeyEvent;
value = EStopClicked;
iInputHandlingReg->AddHandledEvent( EUsagePageConsumer,
EConsumerUsageScanPrev );
}
}
if ( key != KHidUndefinedKeyCode && value != KHidNotSetKeyValue )
{
TInt err = RProperty::Set( KPSUidHidEventNotifier, key, value );
retVal = KErrNone;
}
TRACE_FUNC_EXIT
return retVal;
}
// ---------------------------------------------------------------------------
// HandleVolumeUsage()
// ---------------------------------------------------------------------------
//
TInt CHidHeadsetDriver::HandleVolumeUsage( TReportTranslator& aReport )
{
TRACE_FUNC_ENTRY
TInt retVal = KErrNotSupported;
TInt volUp = 0;
TInt volDown = 0;
TInt speakermute = 0;
// P&S key variables
TUint key = KHidUndefinedKeyCode;
TInt value = KHidNotSetKeyValue;
if ( aReport.GetValue( volUp, EConsumerUsageVolumeInc ) == KErrNone
&& volUp )
{
if ( iInputHandlingReg->AllowedToHandleEvent( EUsagePageConsumer,
EConsumerUsageVolumeInc ) )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver::HandleReport(): \
Send volume up command"));
key = KHidAccessoryVolumeEvent;
iVolumeUpPressed = ETrue;
value = KPSVolumeUpPressed;
iInputHandlingReg->AddHandledEvent( EUsagePageConsumer,
EConsumerUsageScanPrev );
}
}
else if ( aReport.GetValue( volDown, EConsumerUsageVolumeDec )
== KErrNone && volDown )
{
if ( iInputHandlingReg->AllowedToHandleEvent( EUsagePageConsumer,
EConsumerUsageVolumeDec ) )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver::HandleReport(): Send \
volume down command"));
key = KHidAccessoryVolumeEvent;
iVolumeDownPressed = ETrue;
value = KPSVolumeDownPressed;
iInputHandlingReg->AddHandledEvent( EUsagePageConsumer,
EConsumerUsageVolumeDec );
}
}
else if ( ( aReport.GetValue( speakermute, EConsumerUsageMute )
== KErrNone && speakermute == 1 ) )
{
if ( iInputHandlingReg->AllowedToHandleEvent( EUsagePageConsumer,
EConsumerUsageMute ) )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver::HandleReport(): Send \
mute command"));
key = KHidMuteKeyEvent;
value = KPSMuteClicked;
iInputHandlingReg->AddHandledEvent( EUsagePageConsumer,
EConsumerUsageMute );
}
}
if ( key != KHidUndefinedKeyCode && value != KHidNotSetKeyValue )
{
TInt err = RProperty::Set( KPSUidHidEventNotifier, key, value );
retVal = KErrNone;
}
TRACE_FUNC_EXIT
return retVal;
}
// ---------------------------------------------------------------------------
// HandleScanNextPressL()
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::HandleScanNextPressL()
{
TRACE_FUNC_ENTRY
iForwardStatus = EScanPressed;
delete iScanNextTimer;
iScanNextTimer = NULL;
/**
* Scan key has two different behaviour if you are short click buttun or long
* click button. In short press next track command is sent and whit long press
* is sending seek forward command. iScanNextTimer is used to detect if click
* is long click or short click.
*/
iScanNextTimer = CKeyPressTimer::NewL( this, TTimeIntervalMicroSeconds32(
KScanClickTimeout ), EScanNextPressTimer );
TRACE_FUNC_EXIT
}
// ---------------------------------------------------------------------------
// HandleScanNextPressL()
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::HandleScanPrevPressL()
{
TRACE_FUNC_ENTRY
iBackwardStatus = EScanPressed;
delete iScanPreviousTimer;
iScanPreviousTimer = NULL;
/**
* Scan key has two different behaviour if you are short click buttun or
* long click button. In short press previous track command is sent and
* whit long press is sending seek forward command. iScanPreviousTimer
* is used to detect if click is long click or short click.
*/
iScanPreviousTimer = CKeyPressTimer::NewL( this,
TTimeIntervalMicroSeconds32( KScanClickTimeout ),
EScanPrevPressTimer );
TRACE_FUNC_EXIT
}
// ---------------------------------------------------------------------------
// ReleasePressedVolumeKeys
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::ReleasePressedVolumeKeys(
TReportTranslator& aReportTranslator )
{
TInt volUp = 0;
TInt volDown = 0;
TUint key = KHidUndefinedKeyCode;
TInt value = KHidNotSetKeyValue;
if ( iVolumeUpPressed )
{
if ( aReportTranslator.GetValue( volUp, EConsumerUsageVolumeInc )
== KErrNone && volDown == 0 )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver::ReleasepressedKeys(): \
Volume up released"));
key = KHidAccessoryVolumeEvent;
iVolumeUpPressed = EFalse;
value = KPSVolumeUpReleased;
}
}
else if ( iVolumeDownPressed )
{
if ( aReportTranslator.GetValue( volDown, EConsumerUsageVolumeDec )
== KErrNone && volDown == 0 )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver::ReleasepressedKeys(): \
Volume downkey realeased"));
key = KHidAccessoryVolumeEvent;
iVolumeDownPressed = EFalse;
value = KPSVolumeDownReleased;
}
}
if ( key != KHidUndefinedKeyCode && value != KHidNotSetKeyValue )
{
TInt err = RProperty::Set( KPSUidHidEventNotifier, key, value );
}
}
// ---------------------------------------------------------------------------
// ReleasePressedScanKeys()
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::ReleasePressedScanKeys(
TReportTranslator& aReportTranslator )
{
TInt scanNext = 0;
TInt scanPrev = 0;
TUint key = KHidUndefinedKeyCode;
TInt value = KHidNotSetKeyValue;
if ( iForwardStatus != EScanNotPressed )
{
if ( aReportTranslator.GetValue( scanNext, EConsumerUsageScanNext )
== KErrNone && scanNext == 0 )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver::HandleReport(): Scan \
next command released"));
HandleScanNextRelease( key, value );
}
}
else if ( iBackwardStatus != EScanNotPressed )
{
if ( aReportTranslator.GetValue( scanPrev, EConsumerUsageScanPrev )
== KErrNone && scanPrev == 0 )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver::HandleReport(): Scan \
prev command released"));
HandleScanPreviousRelease( key, value );
}
}
if ( key != KHidUndefinedKeyCode && value != KHidNotSetKeyValue )
{
TInt err = RProperty::Set( KPSUidHidEventNotifier, key, value );
}
}
// ---------------------------------------------------------------------------
// ReleasePressedKeys()
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::ReleasePressedKeys(
TReportTranslator& aReportTranslator )
{
TRACE_FUNC_ENTRY
TInt hookSwitch = 0;
/*
* Check hook key release here, because hook key long press
* is handled different way.
*/
if ( iOnHookPressed || iOffHookPressed || iNoneHookPressed )
{
if ( aReportTranslator.GetValue( hookSwitch,
ETelephonyUsageHookSwitch ) == KErrNone && hookSwitch == 0 )
{
ReleaseHookKey();
}
}
ReleasePressedVolumeKeys( aReportTranslator );
ReleasePressedScanKeys( aReportTranslator );
TRACE_FUNC_EXIT
}
// ---------------------------------------------------------------------------
// HandleScanNextRelease()
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::HandleScanNextRelease( TUint& aKeyCode, TInt& aValue )
{
TRACE_FUNC_ENTRY
aKeyCode = KHidControlKeyEvent;
if ( iForwardStatus == EScanPressed )
{
aValue = EForwardClicked;
}
else //long press
{
aValue = EFastForwardReleased;
}
iForwardStatus = EScanNotPressed;
delete iScanNextTimer;
iScanNextTimer = NULL;
TRACE_FUNC_EXIT
}
// ---------------------------------------------------------------------------
// HandleScanPreviousRelease()
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::HandleScanPreviousRelease( TUint& aKeyCode,
TInt& aValue )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver::HandleReport(): Scan prev \
command released"));
aKeyCode = KHidControlKeyEvent;
if ( iBackwardStatus == EScanPressed )
{
aValue = EBackwardClicked;
}
else //long press
{
aValue = ERewindReleased;
}
iBackwardStatus = EScanNotPressed;
delete iScanPreviousTimer;
iScanPreviousTimer = NULL;
TRACE_FUNC_EXIT
}
// ---------------------------------------------------------------------------
// HookKeyPres()
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::HookKeyPres( TBool aStatus )
{
TRACE_FUNC_ENTRY
THookHandling hookStatus = HookStatus();
if ( !iAlarmStatus )
{
iAlarmStatus = AlarmStatus();
}
iPlayingStatus = MusicPlayingStatus();
if ( aStatus )
{
switch ( hookStatus )
{
case EOnHook:
if ( !iIncomingCallStatus )
{
// For the first click, trigger the timer
// single click is handled in ExpiredDoubleClickTimer
if ( iDoubleClicktimer )
{
delete iDoubleClicktimer;
iDoubleClicktimer = NULL;
}
TRAP_IGNORE( iDoubleClicktimer = CKeyPressTimer::NewL( this,
TTimeIntervalMicroSeconds32( KDoubleClickTimeoutRing ),
EDoubleClickTimer ) );
if ( iDoubleClicktimer )
{
iIncomingCallStatus = ETrue;
}
else // If fail to create timer, handle as single click,
// for double click case, the next click will hang off
{
iIncomingCallStatus = EFalse;
iOnHookPressed = ETrue;
}
break; // switch
}
else
{
iIncomingCallStatus = EFalse;
if ( iDoubleClicktimer )
{
delete iDoubleClicktimer;
iDoubleClicktimer = NULL;
}
// This is the double click case, handle as EOffHook
}
// No break here
case EOffHook:
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver Hook Off Pressed"));
iOffHookPressed = ETrue;
break;
case ENoHook:
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver Hook None Pressed"));
TRAP_IGNORE( HandleNoneHookPressL() );
break;
default:
TRACE_INFO(_L("CHidHeadsetDriver::HookKeyPres : Not \
supported"));
}
}
else
{
ReleaseHookKey();
}
TRACE_FUNC_EXIT
}
// ---------------------------------------------------------------------------
// ReleaseHookKey()
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::ReleaseHookKey()
{
TRACE_FUNC_ENTRY
if ( iOnHookPressed )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver Hook On released"));
iOnHookPressed = EFalse;
// Incoming call
RProperty::Set( KPSUidHidEventNotifier, KHidHookKeyEvent,
KPSAnsweClicked );
}
if ( iOffHookPressed )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver Hook Off released"));
iOffHookPressed = EFalse;
// Disconnect connected call
RProperty::Set( KPSUidHidEventNotifier, KHidHookKeyEvent,
KPSHangUpClicked );
}
if ( iNoneHookPressed && !iAlarmStatus )
{
TRAP_IGNORE( HandleIdleHookReleaseL() );
}
if ( iNoneHookPressed && iAlarmStatus )
{
TRAP_IGNORE( HandleAlarmHookReleaseL() );
}
if ( iLongClicktimer )
{
iLongPress = EFalse;
}
delete iLongClicktimer;
iLongClicktimer = NULL;
TRACE_FUNC_EXIT
}
// ---------------------------------------------------------------------------
// HandleNoneHook()
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::HandleNoneHookPressL()
{
TRACE_FUNC_ENTRY
/** Start long press timer is alarm is ongoing, or phone
* is not alarming and thre are no hook key press whitout
* release
*/
if ( iAlarmStatus || ( !iNoneHookPressed && !iAlarmStatus ) )
{
iNoneHookPressed = ETrue;
iLongPress = EFalse;
delete iLongClicktimer;
iLongClicktimer = NULL;
iLongClicktimer = CKeyPressTimer::NewL( this,
TTimeIntervalMicroSeconds32( KLongClickTimeout ),
ELongPressTimer );
}
TRACE_FUNC_EXIT
}
// ---------------------------------------------------------------------------
// HandleAlarmHookReleaseL()
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::HandleAlarmHookReleaseL()
{
TRACE_FUNC_ENTRY
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver Hook None released"));
/**
* Hook key is released when there is active alarm. Start double
* click timer for monitoring double click.
*/
if ( !iDoubleClicktimer && !iLongPress )
{
iDoubleClicktimer = CKeyPressTimer::NewL( this,
TTimeIntervalMicroSeconds32( KDoubleClickTimeout ),
EDoubleClickTimer );
}
/**
* Stot alar when hook key is pressed long time during alarm.
*/
else if ( iLongPress )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver Stop alarm"));
RProperty::Set( KPSUidAlarmExtCntl, KAlarmStopKey,
EAlarmUIStopAlarm );
iAlarmStatus = EFalse;
iLongPress = EFalse;
}
/**
* Double click timer exsist and is it not long press, so
* this is double click release. Then snooze alarm.
*/
else if ( !iLongPress )
{
delete iDoubleClicktimer;
iDoubleClicktimer = NULL;
iAlarmStatus = EFalse;
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver Snooze"));
RProperty::Set( KPSUidAlarmExtCntl, KAlarmSnoozeKey,
EAlarmUISnoozeAlarm );
}
TRACE_FUNC_EXIT
}
// ---------------------------------------------------------------------------
// HandleIdleHookReleaseL
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::HandleIdleHookReleaseL()
{
TRACE_FUNC_ENTRY
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver Hook None released"));
iNoneHookPressed = EFalse;
/**
* Hook key is released when there is music playing ongoing. Start double
* click timer for monitoring double click.
*/
if ( !iDoubleClicktimer && !iLongPress )
{
iDoubleClicktimer = CKeyPressTimer::NewL( this,
TTimeIntervalMicroSeconds32( KDoubleClickTimeout ),
EDoubleClickTimer );
}
/**
* Hook key is released when there is not music playing ongoing.
* Because double click timer is active this is second release in
* short beriod and redial needs to be issued.
*/
else if ( !iLongPress && !iPlayingStatus )
{
delete iDoubleClicktimer;
iDoubleClicktimer = NULL;
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver Redial"));
RProperty::Set( KPSUidHidEventNotifier, KHidHookKeyEvent,
KPSRedial );
}
/**
* Hook key is released when there is music playing ongoing.
* Because double click timer is active, is send forward command sent
* and DoubleNextClick set to true for sending next command.
*/
else if ( iPlayingStatus && !iLongPress )
{
delete iDoubleClicktimer;
iDoubleClicktimer = NULL;
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver next after next"));
if ( !iLongPress )
{
iDoubleNextClick = ETrue; //set to true and when player change
//track press next again
}
RProperty::Set( KPSUidHidEventNotifier, KHidControlKeyEvent,
EForwardClicked ); //next after next
}
/**
* Long press release when there are no actie calls, alarms, and music
* playing is stopped, activates voice dialing.
*/
else if ( iLongPress )
{
delete iDoubleClicktimer;
iDoubleClicktimer = NULL;
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver VoiceDial"));
RProperty::Set( KPSUidHidEventNotifier, KHidHookKeyEvent,
KPSVoiceDial );
iLongPress = EFalse;
}
TRACE_FUNC_EXIT
}
// ---------------------------------------------------------------------------
// GetHookStatus()
// ---------------------------------------------------------------------------
//
CHidHeadsetDriver::THookHandling CHidHeadsetDriver::HookStatus()
{
TRACE_FUNC_ENTRY
THookHandling retVal = EOffHook;
TInt ret = KErrNone;
CTelephony::TCallStatusV1 callStatusV1;
CTelephony::TCallStatusV1Pckg callStatusV1Pckg( callStatusV1 );
ret = iTelephony->GetLineStatus( CTelephony::EVoiceLine,
callStatusV1Pckg );
if ( ret != KErrNone )
{
retVal = ENoHook;
}
CTelephony::TCallStatus voiceLineStatus = callStatusV1.iStatus;
TRACE_INFO((_L("[HID]\tCHidHeadsetDriver GetHookStatus voiceline \
status %d"), voiceLineStatus));
if ( voiceLineStatus == CTelephony::EStatusHold || voiceLineStatus
== CTelephony::EStatusRinging )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver GetHookStatus on hook"));
retVal = EOnHook;
}
else if ( voiceLineStatus == CTelephony::EStatusUnknown
|| voiceLineStatus == CTelephony::EStatusIdle )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver GetHookStatus no hook"));
retVal = ENoHook;
}
TRACE_FUNC_EXIT
return retVal;
}
// ---------------------------------------------------------------------------
// From class CHidDriver
// CanHandleReportL()
// ---------------------------------------------------------------------------
//
TInt CHidHeadsetDriver::CanHandleReportL( CReportRoot* aReportRoot )
{
TRACE_INFO((_L("[HID]\tCHidHeadsetDriver::CanHandleReport(0x%08x)"),
aReportRoot));
THidFieldSearch search;
THeadsetFinder headsetFinder;
search.SearchL( aReportRoot, &headsetFinder );
iSupportedFieldCount = headsetFinder.FieldCount();
for ( TInt i = 0; i < headsetFinder.FieldCount(); i++ )
{
User::LeaveIfError( iFieldList.Append( headsetFinder.GetFieldAtIndex(
i ) ) );
TRACE_INFO((_L("[HID]\tCHidHeadsetDriver::CanHandleReportL, field \
pointer: 0x%08x"), iFieldList[i]));
}
TInt valid = KErrHidUnrecognised;
if ( headsetFinder.Found() )
{
valid = KErrNone;
}
// empty finder's field list before going out of scope.
headsetFinder.EmptyList();
TRACE_INFO((_L("[HID]\tCHidHeadsetDriver::CanHandleReport() returning \
%d"), valid));
return valid;
}
// ---------------------------------------------------------------------------
// From class CHidDriver
// SupportedFieldCount
// ---------------------------------------------------------------------------
//
TInt CHidHeadsetDriver::SupportedFieldCount()
{
return iSupportedFieldCount;
}
// ---------------------------------------------------------------------------
// From class MTimerNotifier
// TimerExpired()
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::TimerExpired( TTimerType aTimerType )
{
TRACE_FUNC_ENTRY
switch ( aTimerType )
{
case EDoubleClickTimer:
ExpiredDoubleClickTimer();
break;
case ELongPressTimer:
ExpiredLongClickTimer();
break;
case EScanNextPressTimer:
iForwardStatus = EScanLongPress;
RProperty::Set( KPSUidHidEventNotifier, KHidControlKeyEvent,
EFastForwardPressed );
break;
case EScanPrevPressTimer:
iBackwardStatus = EScanLongPress;
RProperty::Set( KPSUidHidEventNotifier, KHidControlKeyEvent,
ERewindPressed );
break;
default:
TRACE_INFO(_L("CHidHeadsetDriver::TimerExpired : Not supported"))
;
}
TRACE_FUNC_EXIT
}
// ---------------------------------------------------------------------------
// ExpiredDoubleClickTimer()
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::ExpiredDoubleClickTimer()
{
TRACE_FUNC_ENTRY
if ( iDoubleClicktimer )
{
delete iDoubleClicktimer;
iDoubleClicktimer = NULL;
if ( iIncomingCallStatus )
{
iIncomingCallStatus = EFalse;
iOnHookPressed = ETrue;
ReleaseHookKey();
}
if ( iAlarmStatus )
{
RProperty::Set( KPSUidAlarmExtCntl, KAlarmStopKey,
EAlarmUIStopAlarm );
iAlarmStatus = EFalse;
}
if ( iPlayingStatus )
{
RProperty::Set( KPSUidHidEventNotifier, KHidControlKeyEvent,
EForwardClicked );
iPlayingStatus = EFalse;
}
}
TRACE_FUNC_EXIT
}
// ---------------------------------------------------------------------------
// ExpiredLongClickTimer()
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::ExpiredLongClickTimer()
{
TRACE_FUNC_ENTRY
if ( iLongClicktimer )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver::TimerExpired long click"));
delete iLongClicktimer;
iLongClicktimer = NULL;
iLongPress = ETrue;
ReleaseHookKey();
}
TRACE_FUNC_EXIT
}
// ---------------------------------------------------------------------------
// AlarmStatus()
// ---------------------------------------------------------------------------
//
TBool CHidHeadsetDriver::AlarmStatus()
{
TRACE_FUNC_ENTRY
TInt activealarmcount = 0;
TBool retVal = EFalse;
activealarmcount = iAlarmServerSession.AlarmCountByState(
EAlarmStateNotifying );
if ( activealarmcount > 0 )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver::AlarmStatus active alarms"));
retVal = ETrue;
}
else
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver::AlarmStatus no active \
alarms"));
retVal = EFalse;
}
TRACE_FUNC_EXIT
return retVal;
}
// ---------------------------------------------------------------------------
// AlarmStatus()
// ---------------------------------------------------------------------------
//
TBool CHidHeadsetDriver::MusicPlayingStatus()
{
TRACE_FUNC_ENTRY
TBool retVal = EFalse;
TMPXPlaybackState state = EPbStateNotInitialised;
TRAPD( err, state = iMusicPlayer->StateL() );
if ( state == EPbStatePlaying && err == KErrNone )
{
TRACE_INFO(_L("[HID]\tCHidHeadsetDriver::MusicPlayingStatus play \
active"));
retVal = ETrue;
}
TRACE_FUNC_EXIT
return retVal;
}
// ---------------------------------------------------------------------------
// HandlePlaybackMessage
// ---------------------------------------------------------------------------
//
void CHidHeadsetDriver::HandlePlaybackMessage( CMPXMessage* aMsg, TInt /*aErr*/)
{
TRACE_FUNC_ENTRY
TMPXMessageId id( aMsg->ValueTObjectL<TMPXMessageId> (
KMPXMessageGeneralId ) );
// send nect track whit double hook click when track is changed
if ( id == KMPXMessagePbMediaChanged && iDoubleNextClick )
{
TRACE_INFO(_L("[HID]\tHandlePlaybackMessage: PbMediaChangeg"));
RProperty::Set( KPSUidHidEventNotifier, KHidControlKeyEvent,
EForwardClicked );
iDoubleNextClick = EFalse;
}
TRACE_FUNC_EXIT
}