htiui/HtiServicePlugins/HtiKeyEventServicePlugin/src/KeyEventHandler.cpp
changeset 0 d6fe6244b863
child 3 2703485a934c
equal deleted inserted replaced
-1:000000000000 0:d6fe6244b863
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Functional implementation of key event service
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include "HtiKeyEventServiceplugin.h"
       
    21 #include "KeyEventHandler.h"
       
    22 
       
    23 #include <apgtask.h>
       
    24 #include <HtiDispatcherInterface.h>
       
    25 #include <HTILogging.h>
       
    26 
       
    27 
       
    28 // CONSTANTS
       
    29 _LIT8( KErrorServiceNotReady, "Service is busy - possibly executing long running typetext or long key press functionality" );
       
    30 _LIT8( KErrorUnrecognizedCommand, "Unrecognized command" );
       
    31 _LIT8( KErrorEmptyUnicodeArray, "Unicode char array was empty" );
       
    32 _LIT8( KErrorInvalidUnicodeCharArray, "Invalid unicode character array" );
       
    33 _LIT8( KErrorInvalidScancode, "Invalid scancode. Wrong length" );
       
    34 _LIT8( KErrorTypeTextFailure, "Internal typetext failure" );
       
    35 _LIT8( KErrorLongKeyPressFailure, "Internal long key press failure" );
       
    36 
       
    37 const TInt KKeyboardFuncDataLength = 2;  // scancode with 2 bytes
       
    38 const TInt KLongKeyPressDataLength = 4;  // scancode 2 bytes + time 2 bytes
       
    39 const TInt KPressKeySequenceMinDataLength = 6;  // hold time 2 bytes + key press interval 2 bytes + at least one scancode 2 bytes
       
    40 const TInt KTypeTextDelayBetweenCharsInMicroSeconds = 50000; // 50 milliseconds
       
    41 const TInt KTypeTextStartPausing = 200; // start pausing after this many characters
       
    42 const TInt KTypeTextPauseInterval = 50; // how many chars to type before pausing
       
    43 const TInt KTypeTextPauseInMicroSeconds = 800000; // 0.8 sec
       
    44 
       
    45 
       
    46 // ----------------------------------------------------------------------------
       
    47 // UintValue()
       
    48 // Helper: aPtr must point to 16 bits area where the value will be extracted
       
    49 // ----------------------------------------------------------------------------
       
    50 TUint UintValue( const TUint8* aPtr )
       
    51     {
       
    52     // This is short way to do it..
       
    53     //return (aPtr[1]<<8) + aPtr[0];
       
    54 
       
    55     TUint8 uInt8Low = *aPtr;
       
    56     TUint8 uInt8High = *(aPtr+1);
       
    57 
       
    58     HTI_LOG_FORMAT( "UintValue:: Low: %d", uInt8Low );
       
    59     HTI_LOG_FORMAT( "UintValue:: High: %d", uInt8High );
       
    60 
       
    61     TUint16 uInt16 = (TUint16)uInt8High;
       
    62     uInt16 = (uInt16 << 8);
       
    63     uInt16 = uInt16 + (TUint)uInt8Low;
       
    64 
       
    65     HTI_LOG_FORMAT( "UintValue:: 16-bit value: %d", uInt16 );
       
    66 
       
    67     TUint uInt = (TUint)uInt16;
       
    68     HTI_LOG_FORMAT( "UintValue:: 32-bit value: %d", uInt );
       
    69 
       
    70     return uInt;
       
    71     }
       
    72 
       
    73 // ----------------------------------------------------------------------------
       
    74 // CKeyEventHandler::NewL()
       
    75 // ----------------------------------------------------------------------------
       
    76 CKeyEventHandler* CKeyEventHandler::NewL()
       
    77     {
       
    78     HTI_LOG_FUNC_IN( "CKeyEventHandler::NewL" );
       
    79     CKeyEventHandler* self = new (ELeave) CKeyEventHandler();
       
    80     CleanupStack::PushL ( self );
       
    81     self->ConstructL();
       
    82     CleanupStack::Pop();
       
    83     HTI_LOG_FUNC_OUT( "CKeyEventHandler::Done" );
       
    84     return self;
       
    85     }
       
    86 
       
    87 // ----------------------------------------------------------------------------
       
    88 // CKeyEventHandler::CKeyEventHandler()
       
    89 // ----------------------------------------------------------------------------
       
    90 CKeyEventHandler::CKeyEventHandler()
       
    91     : CActive( CActive::EPriorityStandard ), iReady( ETrue ), iCommand( 0 ),
       
    92       iHoldingScanCode( 0 )
       
    93 
       
    94     {
       
    95     }
       
    96 
       
    97 // ----------------------------------------------------------------------------
       
    98 // CKeyEventHandler::~CKeyEventHandler()
       
    99 // ----------------------------------------------------------------------------
       
   100 CKeyEventHandler::~CKeyEventHandler()
       
   101     {
       
   102     HTI_LOG_TEXT( "CKeyEventHandler destroy" );
       
   103     Cancel();
       
   104     iTimer.Close();
       
   105     iWsSession.Close();
       
   106     delete iUnicodeChars;
       
   107     iUnicodeChars = NULL;
       
   108     }
       
   109 
       
   110 // ----------------------------------------------------------------------------
       
   111 // CKeyEventHandler::ConstructL()
       
   112 // ----------------------------------------------------------------------------
       
   113 void CKeyEventHandler::ConstructL()
       
   114     {
       
   115     HTI_LOG_TEXT( "CKeyEventHandler::ConstructL" );
       
   116     User::LeaveIfError( iWsSession.Connect() );
       
   117     User::LeaveIfError( iTimer.CreateLocal() );
       
   118     CActiveScheduler::Add( this );
       
   119     }
       
   120 
       
   121 // ----------------------------------------------------------------------------
       
   122 // CKeyEventHandler::SetDispatcher()
       
   123 // ----------------------------------------------------------------------------
       
   124 void CKeyEventHandler::SetDispatcher( MHtiDispatcher* aDispatcher )
       
   125     {
       
   126     iDispatcher = aDispatcher;
       
   127     }
       
   128 
       
   129 // ----------------------------------------------------------------------------
       
   130 // CKeyEventHandler::RunL()
       
   131 // ----------------------------------------------------------------------------
       
   132 void CKeyEventHandler::RunL()
       
   133     {
       
   134     HTI_LOG_FUNC_IN( "CKeyEventHandler::RunL" );
       
   135 
       
   136     if ( iCommand == ELongKeyPress )
       
   137         {
       
   138         KeyUp( iHoldingScanCode );
       
   139         SendOkMsgL();
       
   140         iReady = ETrue;
       
   141         HTI_LOG_TEXT( "CKeyEventHandler::RunL: LongKeyPress has finished" );
       
   142         }
       
   143 
       
   144     else if ( iCommand == ETypeText || iCommand == ETypeTextPassword )
       
   145         {
       
   146         SimulateKeyEventL( *iUnicodeChars, iUnicodeCharIndex );
       
   147 
       
   148         if ( iUnicodeCharIndex == iUnicodeChars->Length() / 2 - 1 )
       
   149             {
       
   150             delete iUnicodeChars;
       
   151             iUnicodeChars = NULL;
       
   152             SendOkMsgL();
       
   153             iReady = ETrue;
       
   154             HTI_LOG_TEXT( "CKeyEventHandler::RunL: TypeText has finished: OK" );
       
   155             }
       
   156         else
       
   157             {
       
   158             iUnicodeCharIndex++;
       
   159             TypeTextWithDelay( iUnicodeCharIndex );
       
   160             }
       
   161         }
       
   162 
       
   163     else if ( iCommand == EPressKeySequence )
       
   164         {
       
   165         PressKeySequenceKeyL();
       
   166         }
       
   167 
       
   168     HTI_LOG_FUNC_OUT( "CKeyEventHandler::RunL" );
       
   169     }
       
   170 
       
   171 // ----------------------------------------------------------------------------
       
   172 // CKeyEventHandler::RunError()
       
   173 // ----------------------------------------------------------------------------
       
   174 TInt CKeyEventHandler::RunError( TInt aError )
       
   175     {
       
   176     TInt dispatchResult = KErrNone;
       
   177 
       
   178     if ( iCommand == ELongKeyPress )
       
   179         {
       
   180         HTI_LOG_FORMAT( "CKeyEventHandler::RunError: LongKeyPress failure: %d.", aError );
       
   181         dispatchResult = iDispatcher->DispatchOutgoingErrorMessage( aError,
       
   182                 KErrorLongKeyPressFailure,  KKeyEventServiceUid );
       
   183         }
       
   184 
       
   185     else // it's TypeText
       
   186         {
       
   187         HTI_LOG_FORMAT( "CKeyEventHandler::RunError: TypeText failure: %d.", aError );
       
   188         dispatchResult = iDispatcher->DispatchOutgoingErrorMessage( aError,
       
   189                 KErrorTypeTextFailure,  KKeyEventServiceUid );
       
   190         }
       
   191 
       
   192     if ( dispatchResult != KErrNone )
       
   193         {
       
   194         HTI_LOG_FORMAT( "CKeyEventHandler::RunError: Failed to send error report to framework: %d.", dispatchResult );
       
   195         }
       
   196     iReady = ETrue;
       
   197     return KErrNone;
       
   198     }
       
   199 
       
   200 // ----------------------------------------------------------------------------
       
   201 // CKeyEventHandler::DoCancel()
       
   202 // ----------------------------------------------------------------------------
       
   203 void CKeyEventHandler::DoCancel()
       
   204     {
       
   205     iTimer.Cancel();
       
   206     delete iUnicodeChars;
       
   207     iUnicodeChars = NULL;
       
   208     }
       
   209 
       
   210 // ----------------------------------------------------------------------------
       
   211 // CKeyEventHandler::ProcessMessageL()
       
   212 // ----------------------------------------------------------------------------
       
   213 void CKeyEventHandler::ProcessMessageL( const TDesC8& aMessage,
       
   214     THtiMessagePriority /*aPriority*/ )
       
   215     {
       
   216     HTI_LOG_FUNC_IN("CKeyEventHandler::ProcessMessageL");
       
   217     HTI_LOG_FORMAT("Msg len: %d.", aMessage.Length());
       
   218 
       
   219     if ( !iReady )
       
   220         {
       
   221         SendErrorMessageL( ENotReadyCommand, KErrorServiceNotReady );
       
   222         return;
       
   223         }
       
   224 
       
   225     iCommand = aMessage.Ptr()[0];
       
   226     switch ( iCommand )
       
   227         {
       
   228         case EPressKey:
       
   229         case EKeyDown:
       
   230         case EKeyUp:
       
   231             HandleKeyboardFuncL( aMessage.Right( aMessage.Length() - 1 ) );
       
   232             break;
       
   233         case ETypeText:
       
   234         case ETypeTextPassword:
       
   235             HandleTypeTextFuncL( aMessage.Right( aMessage.Length() - 1 ) );
       
   236             break;
       
   237         case ELongKeyPress:
       
   238             HandleLongKeyPressFuncL( aMessage.Right( aMessage.Length() - 1 ) );
       
   239             break;
       
   240         case EPressKeySequence:
       
   241             HandlePressKeySequenceFuncL( aMessage.Right( aMessage.Length() - 1 ) );
       
   242             break;
       
   243         default:
       
   244             SendErrorMessageL( EUnrecognizedCommand,
       
   245                 KErrorUnrecognizedCommand );
       
   246         break;
       
   247         }
       
   248 
       
   249     HTI_LOG_FUNC_OUT( "CKeyEventHandler::ProcessMessageL: Done" );
       
   250     }
       
   251 
       
   252 // ----------------------------------------------------------------------------
       
   253 // CKeyEventHandler::HandleTypeTextFuncL()
       
   254 // Handle request to send one or more unicode characters to top most
       
   255 // focused UI application.
       
   256 // ----------------------------------------------------------------------------
       
   257 void CKeyEventHandler::HandleTypeTextFuncL(
       
   258     const TDesC8& aUnicodeChars )
       
   259     {
       
   260     HTI_LOG_FUNC_IN( "CKeyEventHandler::HandleTypeTextFunc" );
       
   261 
       
   262     // For UCS-2 and common unicode key code areas, see
       
   263     // http://czyborra.com/unicode/characters.html
       
   264     // "How are the Unicode characters numbered?"
       
   265 
       
   266     if ( aUnicodeChars.Size() == 0 )
       
   267         {
       
   268         SendErrorMessageL( EEmptyUnicodeCharArray, KErrorEmptyUnicodeArray );
       
   269         return;
       
   270         }
       
   271 
       
   272 #ifdef __ENABLE_LOGGING__
       
   273     CArrayFixFlat<TInt> *windowGroups = new (ELeave) CArrayFixFlat<TInt>(5);
       
   274     iWsSession.WindowGroupList(windowGroups);
       
   275     HTI_LOG_FORMAT("WindowGroupList, %d groups:",windowGroups->Count());
       
   276     for ( TInt i = 0; i < windowGroups->Count(); i++ )
       
   277     {
       
   278         TBuf<125> wgname; // max length for wg name?
       
   279         iWsSession.GetWindowGroupNameFromIdentifier((*windowGroups)[i], wgname);
       
   280 
       
   281         TBuf<145> logmsg;
       
   282         logmsg.AppendFormat(_L("WgId %3d - \""), (*windowGroups)[i]);
       
   283         logmsg.Append(wgname);
       
   284         logmsg.Append(_L("\""));
       
   285         HTI_LOG_DES(logmsg);
       
   286     }
       
   287     delete windowGroups;
       
   288 #endif
       
   289 
       
   290     // Get the front most focused window group. Note that this might
       
   291     // not necessarily be the front-most window group, as
       
   292     // window groups can disable keyboard focus.
       
   293     iFocusedWindowGroup = iWsSession.GetFocusWindowGroup();
       
   294 
       
   295     HTI_LOG_TEXT("FocusWindowGroup name :");
       
   296     TBuf<125> focusWindowGroupName; // max length for wg name?
       
   297     iWsSession.GetWindowGroupNameFromIdentifier(iFocusedWindowGroup, focusWindowGroupName);
       
   298     HTI_LOG_DES(focusWindowGroupName);
       
   299 
       
   300     // ...exception to above! (in EKA2) :
       
   301     // When we are in idle state the text must be sent to 'Telephone' task's
       
   302     // windowgroup because 'idle' windowgroup does not handle keyevents.
       
   303     //
       
   304     // Also when typing in idle state we need EKeyUp event to prevent the key
       
   305     // beeing stuck in the pressed position.
       
   306     //
       
   307     // Window group name contains UID - we are using UID to find the
       
   308     // 'Idle' window group so it will be found also with different
       
   309     // localizations. The name 'Idle' cannot be used since the name is
       
   310     // localized.
       
   311 
       
   312     if ( ( focusWindowGroupName.Find( _L( "101fd64c" ) ) != KErrNotFound ) ||
       
   313          ( focusWindowGroupName.Find( _L( "102750f0" ) ) != KErrNotFound ) )
       
   314         {
       
   315         HTI_LOG_TEXT( "FocusWindowGroup is \"Idle\". Sending text to \"Telephone\" task." );
       
   316         TApaTaskList taskList( iWsSession );
       
   317         TApaTask telephoneTask = taskList.FindApp( TUid::Uid( 0x100058b3 ) );
       
   318         if ( !telephoneTask.Exists() )
       
   319             {
       
   320             HTI_LOG_FUNC_OUT( "CKeyEventHandler::SimulateKeyEventL: \"Telephone\" task does not exist" );
       
   321             User::Leave( KErrNotFound );
       
   322             }
       
   323 
       
   324         iFocusedWindowGroup = telephoneTask.WgId();
       
   325 
       
   326         // We must also get focus to 'Telephone' task for it
       
   327         // to receive our text.
       
   328         TWsEvent event;
       
   329         event.SetType( EEventFocusGained );
       
   330         iWsSession.SendEventToWindowGroup( telephoneTask.WgId(), event );
       
   331         }
       
   332 
       
   333     if ( aUnicodeChars.Size() % 2 == 1 )
       
   334         {
       
   335         // aUnicodeChars descriptor must be divisible by two,
       
   336         // because expecting two-byte characters
       
   337         SendErrorMessageL( EInvalidUnicodeCharArray,
       
   338             KErrorInvalidUnicodeCharArray );
       
   339         return;
       
   340         }
       
   341 
       
   342     // Start work
       
   343     if ( iUnicodeChars )
       
   344         {
       
   345         delete iUnicodeChars;
       
   346         iUnicodeChars = NULL;
       
   347         }
       
   348 
       
   349     // If the string begins with unicode byte order mark 0xfffe, strip it away
       
   350     if ( ( aUnicodeChars[0] == 0xff && aUnicodeChars[1] == 0xfe ) )
       
   351         {
       
   352         HTI_LOG_TEXT( "Ignoring Unicode BOM (first 2 bytes) from the string" );
       
   353         iUnicodeChars = aUnicodeChars.Mid( 2 ).AllocL();
       
   354         }
       
   355     else // take the string as it is
       
   356         {
       
   357         iUnicodeChars = aUnicodeChars.AllocL();
       
   358         }
       
   359     iReady = EFalse;
       
   360 
       
   361     TypeTextWithDelay( 0 );
       
   362 
       
   363     HTI_LOG_FUNC_OUT("CKeyEventHandler::HandleTypeTextFunc: Done (operation started)");
       
   364     }
       
   365 
       
   366 // ----------------------------------------------------------------------------
       
   367 // CKeyEventHandler::TypeTextWithDelay()
       
   368 // ----------------------------------------------------------------------------
       
   369 void CKeyEventHandler::TypeTextWithDelay( TInt aNextIndex )
       
   370     {
       
   371     iUnicodeCharIndex = aNextIndex;
       
   372     // Keep a longer pause in some character intervals if the given text
       
   373     // is very long to avoid losing characters.
       
   374     if ( iUnicodeCharIndex > KTypeTextStartPausing &&
       
   375         iUnicodeCharIndex % KTypeTextPauseInterval == 0 )
       
   376         {
       
   377         iTimer.After( iStatus, KTypeTextPauseInMicroSeconds );
       
   378         }
       
   379     else
       
   380         {
       
   381         iTimer.After( iStatus, KTypeTextDelayBetweenCharsInMicroSeconds );
       
   382         }
       
   383     SetActive();
       
   384     }
       
   385 
       
   386 // ----------------------------------------------------------------------------
       
   387 // CKeyEventHandler::SimulateKeyEventL()
       
   388 // ----------------------------------------------------------------------------
       
   389 void CKeyEventHandler::SimulateKeyEventL( const TDesC8& aUnicodeChars,
       
   390     TInt aIndex )
       
   391     {
       
   392 
       
   393     // Expect aUnicodeChars to be Unicode characters (each two bytes)
       
   394     // Note: aIndex is within range of 0 to aUnicodeChars/2
       
   395 
       
   396     HTI_LOG_FUNC_IN("CKeyEventHandler::SimulateKeyEventL");
       
   397     TKeyEvent keyEvent;
       
   398     const TUint8* rawDataStart = aUnicodeChars.Ptr();
       
   399     keyEvent.iCode = *( (TUint16*) ( rawDataStart + aIndex * 2 ) );
       
   400     // Set modifier to treat key events as events from external keyboard
       
   401     // so that AknFep won't interfere with numbers and * and # characters.
       
   402     keyEvent.iModifiers = EModifierKeyboardExtend;
       
   403     keyEvent.iRepeats = 0;
       
   404     //keyEvent.iScanCode = EStdKeyNull;
       
   405     // change because FEP got confused about EStdKeyNull in key-up event and
       
   406     // opened the edit menu
       
   407     keyEvent.iScanCode = 255;
       
   408 
       
   409     TWsEvent event;
       
   410     *event.Key() = keyEvent;
       
   411 
       
   412     if ( iCommand == ETypeTextPassword )
       
   413         {
       
   414         // Typing a password needs only EEventKey.
       
   415         // Otherwise it will appear to be pressed twice.
       
   416         HTI_LOG_FORMAT( "EEventKey 0x%x", keyEvent.iCode );
       
   417         event.SetType( EEventKey );
       
   418         iWsSession.SendEventToWindowGroup( iFocusedWindowGroup, event );
       
   419         }
       
   420     else
       
   421         {
       
   422         // EEventKeyUp is needed when typing a SMS or MMS. Otherwise the
       
   423         // counters will not be updated and message will be corrupt.
       
   424         // Also typing in idle state requires EEventKeyUp for the key to be
       
   425         // released.
       
   426         HTI_LOG_FORMAT( "EEventKey&EEventKeyUp 0x%x", keyEvent.iCode );
       
   427         event.SetType( EEventKey );
       
   428         iWsSession.SendEventToWindowGroup( iFocusedWindowGroup, event );
       
   429 
       
   430         event.SetType( EEventKeyUp );
       
   431         iWsSession.SendEventToWindowGroup( iFocusedWindowGroup, event );
       
   432         }
       
   433 
       
   434     HTI_LOG_FUNC_OUT( "CKeyEventHandler::SimulateKeyEventL" );
       
   435     }
       
   436 
       
   437 // ----------------------------------------------------------------------------
       
   438 // CKeyEventHandler::KeyUp()
       
   439 // ----------------------------------------------------------------------------
       
   440 void CKeyEventHandler::KeyUp( TUint aCode )
       
   441     {
       
   442     HTI_LOG_FUNC_IN( "CKeyEventHandler::KeyUp: Starting" );
       
   443     TRawEvent rawEvent;
       
   444     rawEvent.Set( TRawEvent::EKeyUp, aCode );
       
   445     iWsSession.SimulateRawEvent( rawEvent );
       
   446     iWsSession.Flush();
       
   447     HTI_LOG_FUNC_OUT( "CKeyEventHandler::KeyUp: Done" );
       
   448     }
       
   449 
       
   450 // ----------------------------------------------------------------------------
       
   451 // CKeyEventHandler::KeyDown()
       
   452 // ----------------------------------------------------------------------------
       
   453 void CKeyEventHandler::KeyDown( TUint aCode )
       
   454     {
       
   455     HTI_LOG_FUNC_IN( "CKeyEventHandler::KeyDown: Starting" );
       
   456     User::ResetInactivityTime();
       
   457     TRawEvent rawEvent;
       
   458     rawEvent.Set( TRawEvent::EKeyDown, aCode );
       
   459     iWsSession.SimulateRawEvent( rawEvent );
       
   460     iWsSession.Flush();
       
   461     HTI_LOG_FUNC_OUT( "CKeyEventHandler::KeyDown: Done" );
       
   462     }
       
   463 
       
   464 // ----------------------------------------------------------------------------
       
   465 // CKeyEventHandler::HandleKeyboardFuncL()
       
   466 // Handle request to emulate pressing keyboard keys in sequence.
       
   467 // ----------------------------------------------------------------------------
       
   468 void CKeyEventHandler::HandleKeyboardFuncL( const TDesC8& aData )
       
   469     {
       
   470     HTI_LOG_FUNC_IN( "CKeyEventHandler::HandleKeyboardFuncL" );
       
   471 
       
   472     HTI_LOG_FORMAT( "CKeyEventHandler::HandleKeyboardFuncL: Size of data: %d", aData.Length() );
       
   473     HTI_LOG_TEXT( "CKeyEventHandler::HandleKeyboardFuncL: Data: " );
       
   474     HTI_LOG_DES( aData );
       
   475 
       
   476 //  <scancode> is unsigned short integer, a scancode of
       
   477 //  keyboard key. Theses are defined in E32KEYS.H. It depends on
       
   478 //  device how these are mapped to actual keyboard keys in the
       
   479 //  device.
       
   480 //
       
   481 //  Client note: each call to KEYDOWN should be followed by KEYUP
       
   482 //               with the same scancode at some point.
       
   483 
       
   484     if ( aData.Length() != KKeyboardFuncDataLength )
       
   485         {
       
   486 //        HTI_LOG_FORMAT( "PRESSKEY: Invalid scancode length: %d (expecting 2 bytes).", ptr.Length() - 1);
       
   487         SendErrorMessageL( EInvalidScancode, KErrorInvalidScancode );
       
   488         return;
       
   489         }
       
   490 
       
   491     iReady = EFalse;
       
   492 
       
   493     TUint scanCode = UintValue( aData.Ptr() );
       
   494 
       
   495     switch ( iCommand )
       
   496         {
       
   497         case EPressKey:
       
   498             KeyDown( scanCode );
       
   499             KeyUp( scanCode );
       
   500             break;
       
   501 
       
   502         case EKeyDown:
       
   503             KeyDown( scanCode );
       
   504             break;
       
   505 
       
   506         case EKeyUp:
       
   507             KeyUp( scanCode );
       
   508             break;
       
   509 
       
   510         default:
       
   511         break;
       
   512         }
       
   513     SendOkMsgL();
       
   514     iReady = ETrue;
       
   515     HTI_LOG_FUNC_OUT("CKeyEventHandler::HandleKeyboardFuncL: Done");
       
   516     }
       
   517 
       
   518 // ----------------------------------------------------------------------------
       
   519 // CKeyEventHandler::HandleLongKeyPressFuncL()
       
   520 // Handle request to emulate holding a key down for specified time.
       
   521 // ----------------------------------------------------------------------------
       
   522 void CKeyEventHandler::HandleLongKeyPressFuncL( const TDesC8& aData )
       
   523     {
       
   524     HTI_LOG_FUNC_IN( "CKeyEventHandler::HanldeLongKeyPressFuncL" );
       
   525 
       
   526     if ( aData.Length() != KLongKeyPressDataLength )
       
   527         {
       
   528         SendErrorMessageL( EInvalidScancode, KErrorInvalidScancode );
       
   529         return;
       
   530         }
       
   531 
       
   532     iReady = EFalse;
       
   533     iHoldingScanCode = UintValue( aData.Ptr() );
       
   534     TTimeIntervalMicroSeconds32 holdTime( UintValue( aData.Ptr() + 2 ) * 1000 );
       
   535     KeyDown( iHoldingScanCode );
       
   536     iTimer.After( iStatus, holdTime );
       
   537     SetActive();
       
   538 
       
   539     HTI_LOG_FUNC_OUT( "CKeyEventHandler::HanldeLongKeyPressFuncL" );
       
   540     }
       
   541 
       
   542 // ----------------------------------------------------------------------------
       
   543 // CKeyEventHandler::HandlePressKeySequenceFuncL()
       
   544 // Handle request to press keys in sequence.
       
   545 // ----------------------------------------------------------------------------
       
   546 void CKeyEventHandler::HandlePressKeySequenceFuncL( const TDesC8& aData )
       
   547     {
       
   548     HTI_LOG_FUNC_IN( "CKeyEventHandler::HandlePressKeySequenceFuncL" );
       
   549 
       
   550     if ( aData.Length() % 2 != 0 )
       
   551         {
       
   552         HTI_LOG_FORMAT( "Invalid data length: %d", aData.Length() );
       
   553         SendErrorMessageL( EInvalidUnicodeCharArray, KErrorInvalidUnicodeCharArray );
       
   554         return;
       
   555         }
       
   556 
       
   557     if ( aData.Length() < KPressKeySequenceMinDataLength )
       
   558         {
       
   559         HTI_LOG_FORMAT( "Too short data: %d", aData.Length() );
       
   560         SendErrorMessageL( EEmptyUnicodeCharArray, KErrorEmptyUnicodeArray );
       
   561         return;
       
   562         }
       
   563 
       
   564     iReady = EFalse;
       
   565 
       
   566     iKeySequenceHoldTime = UintValue( aData.Ptr() ) * 1000;
       
   567     iKeySequenceInterval = UintValue( aData.Ptr() + 2 ) * 1000;
       
   568     HTI_LOG_FORMAT( "Parsed key sequence hold time: %d", iKeySequenceHoldTime.Int() / 1000 );
       
   569     HTI_LOG_FORMAT( "Parsed key sequence interval: %d", iKeySequenceInterval.Int() / 1000 );
       
   570     if ( iKeySequenceInterval.Int() < KTypeTextDelayBetweenCharsInMicroSeconds )
       
   571         {
       
   572         HTI_LOG_TEXT( "Given key sequence interval too low, using the default value" );
       
   573         iKeySequenceInterval = KTypeTextDelayBetweenCharsInMicroSeconds;
       
   574         }
       
   575 
       
   576     if(iUnicodeChars)
       
   577 		{
       
   578 			delete iUnicodeChars;
       
   579 			iUnicodeChars = NULL;
       
   580 		}
       
   581 	
       
   582 	iUnicodeChars = aData.Mid( 4 ).AllocL();
       
   583     iUnicodeCharIndex = 0;
       
   584     iHoldingKey = EFalse;
       
   585 
       
   586     PressKeySequenceKeyL();
       
   587 
       
   588     HTI_LOG_FUNC_OUT( "CKeyEventHandler::HandlePressKeySequenceFuncL" );
       
   589     }
       
   590 
       
   591 // ----------------------------------------------------------------------------
       
   592 // CKeyEventHandler::PressKeySequenceKeyL()
       
   593 // Handle a single key press from press keys in sequence command.
       
   594 // ----------------------------------------------------------------------------
       
   595 void CKeyEventHandler::PressKeySequenceKeyL()
       
   596     {
       
   597     HTI_LOG_FUNC_IN( "CKeyEventHandler::PressKeySequenceKeyL" );
       
   598 
       
   599     if ( iHoldingKey )
       
   600         {
       
   601         KeyUp( iHoldingScanCode );
       
   602         iHoldingKey = EFalse;
       
   603 
       
   604         HTI_LOG_FORMAT( "Released key: %d", iHoldingScanCode );
       
   605 
       
   606         if ( iUnicodeChars->Length() > iUnicodeCharIndex )
       
   607             {
       
   608             iTimer.After( iStatus, iKeySequenceInterval );
       
   609             SetActive();
       
   610             }
       
   611         else
       
   612             {
       
   613             HTI_LOG_TEXT( "PressKeySequence has finished: OK" );
       
   614             SendOkMsgL();
       
   615             iReady = ETrue;
       
   616             }
       
   617         }
       
   618     else
       
   619         {
       
   620         iHoldingScanCode = UintValue( iUnicodeChars->Ptr() + iUnicodeCharIndex );
       
   621         iUnicodeCharIndex += 2;
       
   622 
       
   623         KeyDown( iHoldingScanCode );
       
   624         iHoldingKey = ETrue;
       
   625 
       
   626         HTI_LOG_FORMAT( "Holding down key: %d", iHoldingScanCode );
       
   627 
       
   628         iTimer.After( iStatus, iKeySequenceHoldTime );
       
   629         SetActive();
       
   630         }
       
   631 
       
   632     HTI_LOG_FUNC_OUT( "CKeyEventHandler::HandlePressKeySequenceFuncL" );
       
   633     }
       
   634 
       
   635 // ----------------------------------------------------------------------------
       
   636 // CKeyEventHandler::SendOkMsgL()
       
   637 // ----------------------------------------------------------------------------
       
   638 void CKeyEventHandler::SendOkMsgL()
       
   639     {
       
   640     HTI_LOG_FUNC_IN("CKeyEventHandler::SendOkMsgL: Starting");
       
   641 
       
   642     User::LeaveIfNull( iDispatcher );
       
   643     TBuf8<1> response;
       
   644     response.Append( EResultOk );
       
   645     HBufC8* respH8 = response.AllocL();
       
   646     User::LeaveIfError( iDispatcher->DispatchOutgoingMessage(
       
   647         respH8, KKeyEventServiceUid ) );
       
   648 
       
   649     HTI_LOG_FUNC_OUT("CKeyEventHandler::SendOkMsgL: Done");
       
   650     }
       
   651 
       
   652 // ----------------------------------------------------------------------------
       
   653 // CKeyEventHandler::SendErrorMessageL()
       
   654 // ----------------------------------------------------------------------------
       
   655 void CKeyEventHandler::SendErrorMessageL( TInt aError,
       
   656         const TDesC8& aDescription )
       
   657     {
       
   658     HTI_LOG_FUNC_IN("CKeyEventHandler::SendErrorMessageL: Starting");
       
   659     User::LeaveIfNull( iDispatcher );
       
   660     User::LeaveIfError( iDispatcher->DispatchOutgoingErrorMessage(
       
   661         aError, aDescription, KKeyEventServiceUid ) );
       
   662     HTI_LOG_FUNC_OUT("CKeyEventHandler::SendErrorMessageL: Done");
       
   663     }