breakdeps/AknEcs.cpp
changeset 62 d951a20326d6
child 63 ae68f05b0b2f
equal deleted inserted replaced
61:bdb0226b36a8 62:d951a20326d6
       
     1 /*
       
     2 * Copyright (c) 2002-2010 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:   Support for Emergency Calls. Class Implementations.
       
    15 *   Pressed keys are tracked in a buffer and CEmergencyNumberUtils
       
    16 *   is used to find out if the buffer matches to emergency number.
       
    17 *   Observers, if registered are called to notify them.
       
    18 *
       
    19 *
       
    20 */
       
    21 
       
    22 
       
    23 
       
    24 // INCLUDES
       
    25 #include <e32std.h>
       
    26 #include "aknenv.h"
       
    27 #include "aknappui.h"
       
    28 #include "AknEcs.h"
       
    29 #include <featmgr.h>
       
    30 #include "AknDebug.h"
       
    31 
       
    32 #include <CPhCltEmergencyCall.h>
       
    33 #include <MPhCltEmergencyCallObserver.h>
       
    34 #include <PhCltTypes.h>
       
    35 #include <AvkonInternalCRKeys.h>
       
    36 #include <PtiDefs.h>
       
    37 #include <e32property.h>
       
    38 #include <AiwCommon.hrh>
       
    39 #include <aiwdialdata.h>
       
    40 #include <AiwServiceHandler.h>
       
    41 #include <centralrepository.h>
       
    42 
       
    43 #include "akntrace.h"
       
    44 
       
    45 const TInt KAknKeyScanCodeBegin = 33;
       
    46 const TInt KAknKeyScanCodeEnd   = 126;
       
    47 
       
    48 // CLASS DECLARATIONS
       
    49 
       
    50 /** Class for getting emergency call events */
       
    51 NONSHARABLE_CLASS(CPhCltEmergencyCallObserver) : public CBase,
       
    52                                                  public MPhCltEmergencyCallObserver
       
    53     {
       
    54     public:
       
    55         /** Constructor */
       
    56         CPhCltEmergencyCallObserver(CAknEcsDetector* aParent);
       
    57         
       
    58         /** Destructor */
       
    59         ~CPhCltEmergencyCallObserver( );
       
    60         
       
    61        /**
       
    62          * This method is called when client's dial request is completed.
       
    63          *
       
    64          * @param aStatus error code of the success of the operation.
       
    65          */       
       
    66         virtual void HandleEmergencyDialL( const TInt aStatus );
       
    67     private:
       
    68         /** Pointer to the parent object that really handles the events. */
       
    69         CAknEcsDetector* iParent;
       
    70     };
       
    71     
       
    72     
       
    73 CPhCltEmergencyCallObserver::CPhCltEmergencyCallObserver(CAknEcsDetector* aParent)
       
    74     :iParent(aParent)
       
    75     {
       
    76     }
       
    77     
       
    78 CPhCltEmergencyCallObserver::~CPhCltEmergencyCallObserver()
       
    79     {
       
    80     }
       
    81     
       
    82 void CPhCltEmergencyCallObserver::HandleEmergencyDialL( const TInt /*aStatus*/ )
       
    83     {
       
    84 #ifdef AVKON_RDEBUG_INFO
       
    85     _LIT(KDebugDialRequestCompleted, "Dial request is completed");
       
    86     RDebug::Print(KDebugDialRequestCompleted);
       
    87 #endif
       
    88     iParent->CallAttemptedCallback( iParent );    
       
    89     }
       
    90        
       
    91 /**
       
    92 * Class to hold the queue of keys (TText characters) provided to the emergency call detector.
       
    93 *
       
    94 * Performs matching of an emergency number with the current queue.
       
    95 *
       
    96 * No memory is allocated after its complete construction
       
    97 *
       
    98 */
       
    99 NONSHARABLE_CLASS(CAknMatchingCharacterQueue) : public CBase
       
   100     {
       
   101     public:
       
   102         /**
       
   103         * These statuses are returned by MatchText
       
   104         */
       
   105         enum TStatus
       
   106             {
       
   107             ENoMatch,
       
   108             ECompleteMatch,
       
   109             EServiceNumMatch
       
   110             };
       
   111     public:
       
   112         /**
       
   113         * C++ constructor
       
   114         *
       
   115         * @param aPhCltEmergencyCall  Emergency call client
       
   116         * @param aServiceCallEnabled  Is service call feature enabled during device or key lock.
       
   117         */
       
   118         CAknMatchingCharacterQueue( CPhCltEmergencyCall* aPhCltEmergencyCall, TBool aServiceCallEnabled );
       
   119 
       
   120         /**
       
   121         * C++ destructor
       
   122         */
       
   123         ~CAknMatchingCharacterQueue( );
       
   124 
       
   125         /**
       
   126         * 2nd phase constructor
       
   127         */
       
   128         void ConstructL();
       
   129 
       
   130         /**
       
   131         * Method to reset the buffer by resetting the pointers.
       
   132         *
       
   133         */
       
   134         void Reset();
       
   135 
       
   136         /**
       
   137         * Adds the passed character code to the queue. All codes append to the queue;
       
   138         * none are ignored.
       
   139         *
       
   140         * @param aNewChar New char to the queue.
       
   141         */
       
   142         void AddChar( TText aNewChar );
       
   143 
       
   144 
       
   145         /**
       
   146         * Set the entire contents of the queue. If the new buffer is longer than
       
   147         * the queue, rest are stripped.
       
   148         *
       
   149         * @param aNewBuffer New content to the queue.
       
   150         */
       
   151         void SetBuffer( const TDesC& aNewBuffer );
       
   152 
       
   153         /**
       
   154         * The number of characters in the queue.  Resets to 0. Increases as characters are added
       
   155         * up to and equal to KAknEcsMaxMatchingLength
       
   156         *
       
   157         * @return   the number of characters queued and available for match.
       
   158         *
       
   159         */
       
   160         TInt Count() const;
       
   161 
       
   162         /**
       
   163         * Returns the status of the queue (which is automatically updated when AddChar and other non-const
       
   164         * API is called)
       
   165         * @return The status of the match. Nothing matching returns ENoMatch; 
       
   166         *         The whole sequence matching returns ECompleteMatch.
       
   167         */
       
   168         TStatus Status() const;
       
   169 
       
   170         /**
       
   171         * Returns a pointer to the current matching number. 
       
   172         *
       
   173         * @return A ptr descriptor into the currently matching text
       
   174         */
       
   175         TPtrC CurrentMatch() const;
       
   176 
       
   177         /**
       
   178         * Returns an index to the current character buffer where the emergency number
       
   179         * match begins.  This value is between 0 and KAknEcsMaxMatchingLength, even if
       
   180         * there have been a large number characters input to the FIFO. Thus, it does not
       
   181         * take account of characters that have fallen out of the FIFO.
       
   182         *
       
   183         * @return the index in the current buffer where the match starts
       
   184         */
       
   185         TInt IndexOfCurrentMatch() const;
       
   186 
       
   187         /**
       
   188         * Validates the service number.
       
   189         *
       
   190         * @param aNumber Service number to be validated from CenRep.
       
   191         *
       
   192         * @return Returns ETrue if aNumber is a service number, EFalse if not.
       
   193         */
       
   194         TBool ValidateServiceNumberL( const TDesC& aNumber );
       
   195 
       
   196     private:
       
   197         /**
       
   198         * Update the status of the queue
       
   199         */
       
   200         void UpdateStatus( TBool aBufferMode );
       
   201 
       
   202     private:
       
   203         // Emergency number buffer is as long as maximum sequence
       
   204         TBuf<KAknEcsMaxMatchingLength> iCharBuffer;
       
   205 
       
   206         /** Pointer to phone client interface of emergency call. Not owned */
       
   207         CPhCltEmergencyCall* iPhCltEmergencyCall; 
       
   208         TStatus iStatus;      // Holds the status;
       
   209         TInt iMatchPosition;  // Position in iCharBuffer from where the match starts.
       
   210         TBool iServiceCallFeature;  // True if service call feature is enabled.
       
   211 
       
   212         TAny* iSpare;
       
   213     };
       
   214 
       
   215 
       
   216 
       
   217 
       
   218 // CLASS IMPLEMENTATIONS
       
   219 
       
   220 /**
       
   221  * Local Panic Function and Panic Codes
       
   222  */
       
   223 
       
   224 enum TAknEcsPanicCodes
       
   225     {
       
   226     EAknEcsPanicDialLLeft = 1,
       
   227     EAknEcsPanicBadState
       
   228     };
       
   229 
       
   230 GLDEF_C void Panic(TAknEcsPanicCodes aPanic)
       
   231     {
       
   232     _LIT(KPanicCat,"AknEcs");
       
   233     User::Panic(KPanicCat, aPanic);
       
   234     }
       
   235 
       
   236 //
       
   237 // Queue used for storing and matching the keys used in emergency number detection
       
   238 //
       
   239 //
       
   240 
       
   241 
       
   242 CAknMatchingCharacterQueue::CAknMatchingCharacterQueue( CPhCltEmergencyCall* aPhCltEmergencyCall, TBool aServiceCallEnabled )
       
   243         : iPhCltEmergencyCall( aPhCltEmergencyCall ), iServiceCallFeature( aServiceCallEnabled )
       
   244     {
       
   245     _AKNTRACE_FUNC_ENTER;
       
   246     Reset();
       
   247     _AKNTRACE_FUNC_EXIT;
       
   248     }
       
   249 
       
   250 CAknMatchingCharacterQueue::~CAknMatchingCharacterQueue( )
       
   251     {
       
   252     }
       
   253 
       
   254 void CAknMatchingCharacterQueue::ConstructL()
       
   255     {
       
   256     }
       
   257 
       
   258 void CAknMatchingCharacterQueue::Reset()
       
   259     {
       
   260     _AKNTRACE_FUNC_ENTER;
       
   261     iMatchPosition = 0;
       
   262     iCharBuffer.Zero();
       
   263     _AKNTRACE_FUNC_EXIT;
       
   264     }
       
   265 
       
   266 void CAknMatchingCharacterQueue::AddChar( TText aNewChar )
       
   267     {    
       
   268     _AKNTRACE_FUNC_ENTER;
       
   269     _AKNTRACE( "[%s][%s] aNewChar: %s", "CAknMatchingCharacterQueue", 
       
   270         		__FUNCTION__,&aNewChar);
       
   271     
       
   272     TInt length = iCharBuffer.Length();
       
   273     TInt maxLenght = iCharBuffer.MaxLength();
       
   274     if (length >= maxLenght)
       
   275         {
       
   276         iCharBuffer = iCharBuffer.Right(length - 1);
       
   277         }
       
   278     iCharBuffer.Append( aNewChar );
       
   279     UpdateStatus( EFalse );
       
   280     _AKNTRACE_FUNC_EXIT;
       
   281     }
       
   282 
       
   283 void CAknMatchingCharacterQueue::SetBuffer( const TDesC& aNewBuffer )
       
   284     {    
       
   285     _AKNTRACE_FUNC_ENTER;
       
   286     _AKNTRACE( "[%s][%s] aNewBuffer: %s", "CAknMatchingCharacterQueue", 
       
   287             		__FUNCTION__,&aNewBuffer);
       
   288     
       
   289     TInt maxLenght = iCharBuffer.MaxLength();
       
   290     TInt length = aNewBuffer.Length();
       
   291     if ( length > maxLenght )
       
   292         {
       
   293         length = maxLenght;
       
   294         }
       
   295     iCharBuffer = aNewBuffer.Left( length );
       
   296     UpdateStatus( ETrue );
       
   297     _AKNTRACE_FUNC_EXIT;
       
   298     }
       
   299 
       
   300 TInt CAknMatchingCharacterQueue::Count() const
       
   301     {
       
   302     return iCharBuffer.Length();
       
   303     }
       
   304 
       
   305 CAknMatchingCharacterQueue::TStatus CAknMatchingCharacterQueue::Status() const
       
   306     {
       
   307     return iStatus;
       
   308     }
       
   309 
       
   310 TPtrC CAknMatchingCharacterQueue::CurrentMatch() const
       
   311     {
       
   312     return TPtrC(iCharBuffer.Right(iCharBuffer.Length() - iMatchPosition));
       
   313     }
       
   314 
       
   315 TInt CAknMatchingCharacterQueue::IndexOfCurrentMatch() const
       
   316     {
       
   317     return iMatchPosition;
       
   318     }
       
   319 
       
   320 void CAknMatchingCharacterQueue::UpdateStatus( TBool aBufferMode )
       
   321     {
       
   322     _AKNTRACE_FUNC_ENTER;
       
   323     TBool isEmergency = EFalse;
       
   324     TInt err = KErrNone;
       
   325     TPhCltTelephoneNumber buffer = iCharBuffer;
       
   326     if (iPhCltEmergencyCall)
       
   327         {
       
   328         err = iPhCltEmergencyCall->FindEmergencyPhoneNumber(buffer, isEmergency);        
       
   329         }
       
   330     if ( err != KErrNone )
       
   331         {
       
   332         isEmergency = EFalse;
       
   333         }
       
   334 
       
   335     TInt cbLength = iCharBuffer.Length();
       
   336     TInt bLength = buffer.Length();
       
   337 
       
   338     if ( aBufferMode && isEmergency && ( cbLength != bLength ) )
       
   339         {
       
   340         isEmergency = EFalse;
       
   341         }
       
   342 
       
   343     if ( isEmergency )
       
   344         {
       
   345         iMatchPosition = cbLength - bLength;
       
   346         iStatus = ECompleteMatch;
       
   347         }
       
   348     else if ( iServiceCallFeature && cbLength >= KAknServiceCallMinLength )
       
   349         {
       
   350         // Check if this is a service call
       
   351         TBool isServiceNum = EFalse;
       
   352         TRAP_IGNORE( isServiceNum = ValidateServiceNumberL( iCharBuffer ) );
       
   353 
       
   354         if ( isServiceNum )
       
   355             {
       
   356             iMatchPosition = 0;
       
   357             iStatus = EServiceNumMatch;
       
   358             }
       
   359         else
       
   360             {
       
   361             iMatchPosition = cbLength;
       
   362             iStatus = ENoMatch;
       
   363             }
       
   364         }
       
   365     else
       
   366         {
       
   367         iMatchPosition = cbLength;
       
   368         iStatus = ENoMatch;
       
   369         }
       
   370     _AKNTRACE( "[%s][%s] iStatus: %d", "CAknMatchingCharacterQueue", 
       
   371                 		__FUNCTION__,iStatus );
       
   372     _AKNTRACE_FUNC_EXIT;
       
   373     }
       
   374 
       
   375 // -----------------------------------------------------------------------------
       
   376 // CAknMatchingCharacterQueue::ValidateServiceNumber
       
   377 // 
       
   378 // Validates the service phone number.
       
   379 // -----------------------------------------------------------------------------
       
   380 //
       
   381 TBool CAknMatchingCharacterQueue::ValidateServiceNumberL( const TDesC& aNumber )
       
   382     {
       
   383     _AKNTRACE_FUNC_ENTER;
       
   384 	TBool isServiceNum = EFalse;
       
   385     HBufC* serviceNum = HBufC::NewLC( KAknEcsMaxMatchingLength );
       
   386     CRepository* cenRep = CRepository::NewLC( KCRUidAvkon );
       
   387     TPtr bufPtr = serviceNum->Des();
       
   388 
       
   389     if( cenRep->Get( KAknServiceCallNumber, bufPtr ) != KErrNone )
       
   390         {
       
   391         CleanupStack::PopAndDestroy( cenRep );
       
   392         CleanupStack::PopAndDestroy( serviceNum );
       
   393         return EFalse;
       
   394         }
       
   395 
       
   396     // Check if aNumber matches serviceNum
       
   397     if ( aNumber.Compare( *serviceNum ) == 0 )
       
   398         {
       
   399         isServiceNum = ETrue;
       
   400 		}
       
   401 
       
   402     CleanupStack::PopAndDestroy( cenRep );
       
   403     CleanupStack::PopAndDestroy( serviceNum );
       
   404     _AKNTRACE_FUNC_EXIT;
       
   405     return isServiceNum;
       
   406     }
       
   407 
       
   408 //
       
   409 //
       
   410 // Implementation of CAknEcsDetector
       
   411 //  (Emergency Call Support Detector)
       
   412 //
       
   413 //
       
   414 
       
   415 EXPORT_C CAknEcsDetector::CAknEcsDetector()
       
   416     {
       
   417     _AKNTRACE_FUNC_ENTER;
       
   418     iCoeEnv = CCoeEnv::Static();
       
   419     iState = ENotFullyConstructed;
       
   420     _AKNTRACE_FUNC_EXIT;
       
   421     }
       
   422 
       
   423 EXPORT_C CAknEcsDetector::~CAknEcsDetector()
       
   424     {
       
   425     _AKNTRACE_FUNC_ENTER;
       
   426     // Must close this in order to remove any observers from the AppUi's monitor
       
   427     CloseEventSource();
       
   428     delete iPhCltEmergencyCall;
       
   429     delete iEmergencyCallObserver;
       
   430     delete iQueue;
       
   431     delete iIdler;
       
   432     delete iKeyTimeoutTimer;
       
   433     _AKNTRACE_FUNC_EXIT;
       
   434     }
       
   435 
       
   436 EXPORT_C void CAknEcsDetector::ConstructL()
       
   437     {
       
   438     _AKNTRACE_FUNC_ENTER;
       
   439     iEmergencyCallObserver = new (ELeave) CPhCltEmergencyCallObserver( this );
       
   440     // Phone client interface
       
   441     iPhCltEmergencyCall = CPhCltEmergencyCall::NewL( iEmergencyCallObserver );
       
   442 
       
   443     // Check if service call is allowed during device and key lock
       
   444     iServiceCallEnabled = 
       
   445         FeatureManager::FeatureSupported( KFeatureIdFfServiceCallWhilePhoneLocked );
       
   446 
       
   447     iQueue = new (ELeave) CAknMatchingCharacterQueue( iPhCltEmergencyCall, iServiceCallEnabled );
       
   448     iQueue->ConstructL();
       
   449 
       
   450     DetermineState();
       
   451 
       
   452     // Idler for delaying the change of state to Call Attempted
       
   453     iIdler = CIdle::NewL( CActive::EPriorityLow );
       
   454 
       
   455     // Timer for timing the timeout between keys
       
   456     iKeyTimeoutTimer = CPeriodic::NewL( CActive::EPriorityLow);
       
   457     _AKNTRACE_FUNC_EXIT;
       
   458     }
       
   459 
       
   460 EXPORT_C CAknEcsDetector* CAknEcsDetector::NewL()
       
   461     { // static
       
   462     _AKNTRACE_FUNC_ENTER;
       
   463     CAknEcsDetector* self = new (ELeave) CAknEcsDetector();
       
   464     CleanupStack::PushL( self );
       
   465     self->ConstructL();
       
   466     CleanupStack::Pop(); //self
       
   467     _AKNTRACE_FUNC_EXIT;
       
   468     return self;
       
   469     }
       
   470 
       
   471 EXPORT_C TBool CAknEcsDetector::ConnectToEventSource()
       
   472     {
       
   473     if ( iFlags.IsClear( EEventSourceConnected ) )
       
   474         {
       
   475         TRAPD( err, iAvkonAppUi->EventMonitor()->AddObserverL(this) );
       
   476         iFlags.Assign( EEventSourceConnected, ( err == KErrNone ) );
       
   477         return ( err == KErrNone );
       
   478         }
       
   479     else
       
   480         {
       
   481         return ETrue;
       
   482         }
       
   483     }
       
   484 
       
   485 EXPORT_C void CAknEcsDetector::CloseEventSource()
       
   486     {
       
   487     if (iFlags.IsSet( EEventSourceConnected ) )
       
   488         {
       
   489         CAknWsEventMonitor* eventMonitor = iAvkonAppUi->EventMonitor();
       
   490         eventMonitor->RemoveObserver(this);
       
   491         iFlags.Clear( EEventSourceConnected );
       
   492         }
       
   493     }
       
   494 
       
   495 EXPORT_C void CAknEcsDetector::HandleWsEventL(const TWsEvent& aEvent, CCoeControl* /* aDestination  */)
       
   496     {
       
   497     _AKNTRACE_FUNC_ENTER;
       
   498     _AKNTRACE( "[%s][%s] aEvent.type(): %d, aEvent.Key()->iScanCode :%d", "CAknEcsDetector", 
       
   499                             		__FUNCTION__,aEvent.Type(),aEvent.Key()->iScanCode );
       
   500     if ( aEvent.Type() == EEventKeyDown || 
       
   501         // EKeyPhoneEnd/EKeyNo doesn't send EEVentKeyDown events, so EEventKey is used instead
       
   502        ( ( aEvent.Key()->iScanCode == EStdKeyNo ) && ( aEvent.Type() == EEventKey ) ) )
       
   503         {
       
   504         AddChar( (TText)(aEvent.Key()->iScanCode ) ); // top 16 ( in Unicode build) bits removed
       
   505         }
       
   506 
       
   507     if ( iServiceCallEnabled )
       
   508         {
       
   509         // When Cancel is pressed we need to clear the queue
       
   510         if ( iState == EServiceNumMatch && aEvent.Type() == EEventPointer && 
       
   511         	   aEvent.Pointer()->iType == TPointerEvent::EButton1Down )
       
   512             {
       
   513             // Clear the queue, set state to EEmpty, and cancel any pending timeout
       
   514             Reset();
       
   515             iKeyTimeoutTimer->Cancel();
       
   516             }
       
   517         }
       
   518     _AKNTRACE_FUNC_EXIT;
       
   519     }
       
   520 
       
   521 
       
   522 EXPORT_C void CAknEcsDetector::AddChar( TText aNewChar )
       
   523     {
       
   524     _AKNTRACE_FUNC_ENTER;
       
   525     _AKNTRACE( "[%s][%s] aNewChar: %s", "CAknEcsDetector", 
       
   526                                 		__FUNCTION__, &aNewChar );
       
   527 
       
   528     if (aNewChar == EKeyQwertyOn || aNewChar == EKeyQwertyOff)
       
   529         { 
       
   530         _AKNTRACE_FUNC_EXIT;
       
   531         return;   // return directly if the aNewChar is slide open/closed.
       
   532         }
       
   533 	
       
   534     iKeyTimeoutTimer->Cancel(); // there might be pending timeout; clear it
       
   535     if ( aNewChar == EStdKeyYes || aNewChar == EKeyPhoneSend )
       
   536         {
       
   537         if ( iServiceCallEnabled )
       
   538             {
       
   539             if ( iState == ECompleteMatch || iState == EServiceNumMatch )
       
   540                 {
       
   541                 _AKNTRACE( "[%s][%s] SetState( ECompleteMatchThenSendKey )", "CAknEcsDetector", 
       
   542                                             		    __FUNCTION__ );
       
   543                 SetState( ECompleteMatchThenSendKey );
       
   544                 }
       
   545             }
       
   546         else
       
   547             {
       
   548             if ( iState == ECompleteMatch )
       
   549                 {
       
   550                 _AKNTRACE( "[%s][%s] SetState( ECompleteMatchThenSendKey )", "CAknEcsDetector", 
       
   551                                                         __FUNCTION__ );
       
   552                 SetState( ECompleteMatchThenSendKey );
       
   553                 }
       
   554             }
       
   555         // else do nothing with it...
       
   556         }
       
   557     else
       
   558         {
       
   559         TText scanCode = aNewChar;
       
   560 
       
   561         if ( scanCode < KAknKeyScanCodeBegin || scanCode > KAknKeyScanCodeEnd )
       
   562             {
       
   563             // Just return since it is an invalid character
       
   564             return;
       
   565             }
       
   566 
       
   567 #ifdef RD_INTELLIGENT_TEXT_INPUT 
       
   568         // Convert scan code to number value here 
       
   569         // for 4*10, 3*11, half-qwerty key pad
       
   570         // The convert value is referenced from KeymapBuilder.pl in ptienginev2
       
   571         // Note: if the product change the scancode defintion,pls change the following 
       
   572         // map rules.
       
   573         TInt keyboardLayout = EPtiKeyboardNone;
       
   574         TInt errCode = RProperty::Get( KCRUidAvkon, KAknKeyBoardLayout, keyboardLayout );
       
   575         if ( errCode == KErrNone &&  ( keyboardLayout == EPtiKeyboardQwerty4x10 
       
   576             || keyboardLayout == EPtiKeyboardQwerty3x11 ) )
       
   577             {
       
   578             // using same conventor rule for 3x11 & 4x10
       
   579             if ( scanCode == EPtiKeyQwertyQ )
       
   580                 {
       
   581                 scanCode = EPtiKeyQwerty1;
       
   582                 }
       
   583             else if ( scanCode == EPtiKeyQwertyW )
       
   584                 {
       
   585                 scanCode = EPtiKeyQwerty2;
       
   586                 }
       
   587             else if ( scanCode == EPtiKeyQwertyE )
       
   588                 {
       
   589                 scanCode = EPtiKeyQwerty3;
       
   590                 }        
       
   591             else if ( scanCode == EPtiKeyQwertyR )
       
   592                 {
       
   593                 scanCode = EPtiKeyQwerty4;
       
   594                 }
       
   595             else if ( scanCode == EPtiKeyQwertyT )
       
   596                 {
       
   597                 scanCode = EPtiKeyQwerty5;
       
   598                 }
       
   599             else if ( scanCode == EPtiKeyQwertyY )
       
   600                 {
       
   601                 scanCode = EPtiKeyQwerty6;
       
   602                 }
       
   603             else if ( scanCode == EPtiKeyQwertyU )
       
   604                 {
       
   605                 scanCode = EPtiKeyQwerty7;
       
   606                 }
       
   607             else if ( scanCode == EPtiKeyQwertyI )
       
   608                 {
       
   609                 scanCode = EPtiKeyQwerty8;
       
   610                 }
       
   611             else if ( scanCode == EPtiKeyQwertyO )
       
   612                 {
       
   613                 scanCode = EPtiKeyQwerty9;
       
   614                 }
       
   615             else if ( scanCode == EPtiKeyQwertyP )
       
   616                 {
       
   617                 scanCode = EPtiKeyQwerty0;
       
   618                 }    
       
   619             }
       
   620         else if ( errCode == KErrNone && keyboardLayout == EPtiKeyboardHalfQwerty )
       
   621             {
       
   622             if ( scanCode == EPtiKeyQwertyE )
       
   623                 {
       
   624                 scanCode = EPtiKeyQwerty1;
       
   625                 }
       
   626             else if ( scanCode == EPtiKeyQwertyT )
       
   627                 {
       
   628                 scanCode = EPtiKeyQwerty2;
       
   629                 }
       
   630             else if ( scanCode == EPtiKeyQwertyU )
       
   631                 {
       
   632                 scanCode = EPtiKeyQwerty3;
       
   633                 }        
       
   634             else if ( scanCode == EPtiKeyQwertyD )
       
   635                 {
       
   636                 scanCode = EPtiKeyQwerty4;
       
   637                 }
       
   638             else if ( scanCode == EPtiKeyQwertyG )
       
   639                 {
       
   640                 scanCode = EPtiKeyQwerty5;
       
   641                 }
       
   642             else if ( scanCode == EPtiKeyQwertyJ )
       
   643                 {
       
   644                 scanCode = EPtiKeyQwerty6;
       
   645                 }
       
   646             else if ( scanCode == EPtiKeyQwertyU )
       
   647                 {
       
   648                 scanCode = EPtiKeyQwertyC;
       
   649                 }
       
   650             else if ( scanCode == EPtiKeyQwertyB )
       
   651                 {
       
   652                 scanCode = EPtiKeyQwerty8;
       
   653                 }
       
   654             else if ( scanCode == EPtiKeyQwertyM )
       
   655                 {
       
   656                 scanCode = EPtiKeyQwerty9;
       
   657                 }
       
   658             else if ( scanCode == EPtiKeyQwertySpace )
       
   659                 {
       
   660                 scanCode = EPtiKeyQwerty0;
       
   661                 }    
       
   662             }
       
   663 #endif   //RD_INTELLIGENT_TEXT_INPUT    
       
   664         
       
   665         iQueue->AddChar( scanCode );
       
   666         DetermineState();
       
   667         iKeyTimeoutTimer->Start( KEcsInterKeyTimeout, KEcsInterKeyTimeout, TCallBack( CancelMatch, this ) );
       
   668         }
       
   669     _AKNTRACE_FUNC_EXIT;
       
   670     }
       
   671 
       
   672 
       
   673 void CAknEcsDetector::DetermineState()
       
   674     {
       
   675     _AKNTRACE_FUNC_ENTER;
       
   676     TState bestState = ENoMatch;
       
   677 
       
   678     if ( iQueue->Count() == 0 )
       
   679         {
       
   680         bestState = EEmpty;
       
   681         }
       
   682     else
       
   683         {
       
   684         CAknMatchingCharacterQueue::TStatus matchStatus = iQueue->Status();
       
   685 
       
   686         switch ( matchStatus )
       
   687             {
       
   688             case CAknMatchingCharacterQueue::ENoMatch:
       
   689                 bestState = ENoMatch;
       
   690                 break;
       
   691             case CAknMatchingCharacterQueue::ECompleteMatch:
       
   692                 bestState = ECompleteMatch;
       
   693                 break;
       
   694             case CAknMatchingCharacterQueue::EServiceNumMatch:
       
   695                 if ( iServiceCallEnabled )
       
   696                     {
       
   697                     bestState = EServiceNumMatch;
       
   698                     break;
       
   699                     }
       
   700                 // Fall through to default case if service call feature is off
       
   701             default:
       
   702                 __ASSERT_DEBUG( 0, Panic(EAknEcsPanicBadState) );
       
   703                 break;
       
   704             }
       
   705         SetState(bestState);
       
   706         }
       
   707     _AKNTRACE( "[%s][%s] bestState: %d", "CAknEcsDetector", 
       
   708                                     		__FUNCTION__, bestState );
       
   709     _AKNTRACE_FUNC_EXIT;
       
   710     }
       
   711 
       
   712 EXPORT_C void CAknEcsDetector::ReportEvent(TState aNewState )
       
   713     {
       
   714     if (iObserver)
       
   715         {
       
   716         iObserver->HandleEcsEvent( this, aNewState );
       
   717         }
       
   718     }
       
   719 
       
   720 
       
   721 EXPORT_C TPtrC CAknEcsDetector::CurrentMatch() const
       
   722     {
       
   723     return iQueue->CurrentMatch();
       
   724     }
       
   725 
       
   726 TInt CAknEcsDetector::IndexOfCurrentMatch() const
       
   727     {
       
   728     return iQueue->IndexOfCurrentMatch();
       
   729     }
       
   730 
       
   731 EXPORT_C CAknEcsDetector::TState CAknEcsDetector::State()
       
   732     {
       
   733     return iState;
       
   734     }
       
   735 EXPORT_C void CAknEcsDetector::SetBuffer( const TDesC& aNewBuffer )
       
   736     {
       
   737     _AKNTRACE_FUNC_ENTER;
       
   738     _AKNTRACE( "[%s][%s] aNewBuffer: %s", "CAknEcsDetector", 
       
   739                                         		__FUNCTION__, &aNewBuffer );
       
   740         
       
   741     iKeyTimeoutTimer->Cancel(); // there might be pending timeout; clear it
       
   742     iQueue->Reset();
       
   743     iQueue->SetBuffer(aNewBuffer);
       
   744     DetermineState();
       
   745 
       
   746     if ( iServiceCallEnabled )
       
   747         {
       
   748         if ( iState == ECompleteMatch || iState == EServiceNumMatch )
       
   749             {
       
   750             iKeyTimeoutTimer->Start( KEcsInterKeyTimeout,
       
   751                 KEcsInterKeyTimeout, TCallBack( CancelMatch, this ) );
       
   752             }
       
   753         }
       
   754     else
       
   755         {
       
   756         if ( iState == ECompleteMatch )
       
   757             {
       
   758             _AKNTRACE( "[%s][%s] State() == ECompleteMatch ", "CAknEcsDetector", 
       
   759                                                 		    __FUNCTION__ );
       
   760             iKeyTimeoutTimer->Start( KEcsInterKeyTimeout,
       
   761                 KEcsInterKeyTimeout, TCallBack( CancelMatch, this ) );
       
   762             }
       
   763         }
       
   764     _AKNTRACE_FUNC_EXIT;
       
   765     }
       
   766 
       
   767 EXPORT_C void CAknEcsDetector::SetState( TState aNewState )
       
   768     {
       
   769     _AKNTRACE_FUNC_ENTER;
       
   770     _AKNTRACE( "[%s][%s] aNewState: %d", "CAknEcsDetector", 
       
   771                                             		__FUNCTION__, aNewState );
       
   772     ReportEvent( aNewState );
       
   773 
       
   774     TInt oldState = iState;
       
   775     iState = aNewState;
       
   776 
       
   777     switch ( oldState )
       
   778         {
       
   779         // All these are OK to go to the next state without transition action:
       
   780         case ENotFullyConstructed:
       
   781         case EEmpty:
       
   782         case ECallAttempted:
       
   783         case ENoMatch:
       
   784         case ECompleteMatchThenSendKey:
       
   785             break;
       
   786 
       
   787         case ECompleteMatch:
       
   788             if ( aNewState == ECompleteMatchThenSendKey )
       
   789                 {
       
   790                 RelinquishCapturedKeys();
       
   791 
       
   792                 TBool proceedWithCall = ETrue;
       
   793                 proceedWithCall = OfferEmergencyCall();
       
   794                 if ( proceedWithCall )
       
   795                     {
       
   796                     _AKNTRACE( "[%s][%s] Attempt Emergency Call", "CAknEcsDetector", 
       
   797                                                                 		__FUNCTION__);
       
   798                     AttemptEmergencyCall();
       
   799                     }
       
   800                 else
       
   801                     {  // Pass through this state immediately
       
   802                     _AKNTRACE( "[%s][%s] Reset", "CAknEcsDetector", __FUNCTION__);
       
   803                     iQueue->Reset();
       
   804                     SetState( EEmpty );
       
   805                     }
       
   806                 }
       
   807             break;
       
   808 
       
   809         case EServiceNumMatch:
       
   810             if ( iServiceCallEnabled )
       
   811                 {
       
   812                 if ( aNewState == ECompleteMatchThenSendKey )
       
   813                     {
       
   814                     RelinquishCapturedKeys();
       
   815                     _AKNTRACE( "[%s][%s] Make Service Call", "CAknEcsDetector", 
       
   816                                                                 		__FUNCTION__);
       
   817                     TRAP_IGNORE( MakeServiceCallL() );
       
   818                     }
       
   819                 }
       
   820             break;
       
   821 
       
   822         default:
       
   823             break;
       
   824 
       
   825         }
       
   826     _AKNTRACE_FUNC_EXIT;
       
   827     }
       
   828 
       
   829 EXPORT_C void CAknEcsDetector::Reset()
       
   830     {
       
   831     _AKNTRACE_FUNC_ENTER;
       
   832     iQueue->Reset();
       
   833     SetState( EEmpty );
       
   834     _AKNTRACE_FUNC_EXIT;
       
   835     }
       
   836 
       
   837 /**
       
   838 * This may be re-implemented to add a confirm query. Re-implementation must not leave
       
   839 *
       
   840 */
       
   841 EXPORT_C TBool CAknEcsDetector::OfferEmergencyCall()
       
   842     {
       
   843     return ETrue;
       
   844     }
       
   845 
       
   846 void CAknEcsDetector::CaptureKeys()
       
   847     {
       
   848     // Capture Send Key
       
   849     RWindowGroup& groupWin=iCoeEnv->RootWin();
       
   850     iCapturedKey=groupWin.CaptureKey( EStdKeyYes, 0, 0);
       
   851     }
       
   852 
       
   853 void CAknEcsDetector::RelinquishCapturedKeys()
       
   854     {
       
   855     RWindowGroup& groupWin=iCoeEnv->RootWin();
       
   856     groupWin.CancelCaptureKey( iCapturedKey );
       
   857     }
       
   858 
       
   859 void CAknEcsDetector::AttemptEmergencyCall()
       
   860     {
       
   861     _AKNTRACE_FUNC_ENTER;
       
   862 #ifdef AVKON_RDEBUG_INFO
       
   863     _LIT(KDebugAttemptEmergencyCall, "Attempt Emergency Call From Detector");
       
   864     RDebug::Print(KDebugAttemptEmergencyCall);
       
   865 #endif
       
   866 
       
   867     TRAPD( err, iPhCltEmergencyCall->DialEmergencyCallL( CurrentMatch() ) );
       
   868     __ASSERT_DEBUG( err==KErrNone, Panic( EAknEcsPanicDialLLeft ) );
       
   869     if(err != KErrNone)
       
   870         {
       
   871         err = KErrNone;
       
   872         }
       
   873     _AKNTRACE_FUNC_EXIT;
       
   874     }
       
   875 
       
   876 void CAknEcsDetector::MakeServiceCallL()
       
   877     {
       
   878     _AKNTRACE_FUNC_ENTER;
       
   879     if ( iServiceCallEnabled )
       
   880         {
       
   881         CAiwServiceHandler* aiwServiceHandler = CAiwServiceHandler::NewLC();
       
   882         RCriteriaArray interest;
       
   883         CleanupClosePushL( interest );
       
   884 
       
   885         CAiwCriteriaItem* criteria = CAiwCriteriaItem::NewLC( KAiwCmdCall,
       
   886                                          KAiwCmdCall, _L8( "*" ) );
       
   887         TUid base;
       
   888         base.iUid = KAiwClassBase;
       
   889         criteria->SetServiceClass( base );
       
   890         User::LeaveIfError( interest.Append( criteria ) );
       
   891         aiwServiceHandler->AttachL( interest );
       
   892 
       
   893         CAiwDialData* dialData = CAiwDialData::NewLC();
       
   894         dialData->SetCallType( CAiwDialData::EAIWForcedCS );
       
   895         dialData->SetPhoneNumberL( CurrentMatch() );
       
   896         dialData->SetWindowGroup( AIWDialData::KAiwGoToIdle );
       
   897 
       
   898         CAiwGenericParamList& paramList = aiwServiceHandler->InParamListL();
       
   899         dialData->FillInParamListL( paramList );
       
   900 
       
   901         TRAPD( err, aiwServiceHandler->ExecuteServiceCmdL( KAiwCmdCall, paramList,
       
   902                     aiwServiceHandler->OutParamListL(), 0, NULL ) );
       
   903         __ASSERT_DEBUG( err == KErrNone, Panic( EAknEcsPanicDialLLeft ) );
       
   904 
       
   905         //reset the queue
       
   906         iQueue->Reset();
       
   907 
       
   908         CleanupStack::PopAndDestroy( dialData );
       
   909         CleanupStack::PopAndDestroy( criteria );
       
   910         CleanupStack::PopAndDestroy( &interest );
       
   911         CleanupStack::PopAndDestroy( aiwServiceHandler );
       
   912 
       
   913         if( err != KErrNone )
       
   914             {
       
   915             User::Leave( err );
       
   916             }
       
   917         }
       
   918     _AKNTRACE_FUNC_EXIT;
       
   919     }
       
   920 
       
   921 EXPORT_C void CAknEcsDetector::SetObserver( MAknEcsObserver* aObserver )
       
   922     {
       
   923     iObserver = aObserver;
       
   924     }
       
   925 
       
   926     /**
       
   927      * It is called whenever status is retrieved (by the client).
       
   928      *
       
   929      * @param aStatus It is the status of the phone.
       
   930      */
       
   931 void CAknEcsDetector::HandlePhoneStatusL( const TInt /* aStatus */ )
       
   932     {
       
   933     }
       
   934 
       
   935     /**
       
   936     * This is meant to be called asynchronously in order for the Observer to destroy itself
       
   937     *
       
   938     */
       
   939 TInt CAknEcsDetector::CallAttemptedCallback(TAny* aSelf)
       
   940     { // static
       
   941     _AKNTRACE_FUNC_ENTER;
       
   942     REINTERPRET_CAST(CAknEcsDetector*,aSelf)->SetState( ECallAttempted );
       
   943 #ifdef AVKON_RDEBUG_INFO
       
   944     _LIT(KDebugCallAttemptedCallback, "CallAttemptedCallback");
       
   945     RDebug::Print(KDebugCallAttemptedCallback);
       
   946 #endif
       
   947     _AKNTRACE_FUNC_EXIT;
       
   948     return 0;
       
   949     }
       
   950 
       
   951 TInt CAknEcsDetector::CancelMatch(TAny* aThis)
       
   952     {
       
   953     _AKNTRACE_FUNC_ENTER;
       
   954     static_cast<CAknEcsDetector*>(aThis)->Reset();
       
   955     static_cast<CAknEcsDetector*>(aThis)->iKeyTimeoutTimer->Cancel();
       
   956     _AKNTRACE_FUNC_EXIT;
       
   957     return 0; // Do not repeat the operation
       
   958     }
       
   959 
       
   960 // End of File