satengine/SatServer/Commands/SendDtmfCmd/src/CSendDtmfHandler.cpp
changeset 46 2fa1fa551b0b
parent 42 35488577e233
child 48 78df25012fda
equal deleted inserted replaced
42:35488577e233 46:2fa1fa551b0b
     1 /*
       
     2 * Copyright (c) 2002-2008 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:  Handles SendDtmf command
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include    "MSatApi.h"
       
    20 #include    "MSatUtils.h"
       
    21 #include    "MSatSystemState.h"
       
    22 #include    "MSatUiSession.h"
       
    23 #include    "SatSOpcodes.h"
       
    24 #include    "MSatSUiClientHandler.h"
       
    25 #include    "CSendDtmfHandler.h"
       
    26 #include    "csatdtmfsender.h"
       
    27 #include    "msatmultimodeapi.h"
       
    28 #include    "SatLog.h"
       
    29 
       
    30 const TUint KBcdZero      = 0x00;
       
    31 const TUint KBcdOne       = 0x01;
       
    32 const TUint KBcdTwo       = 0x02;
       
    33 const TUint KBcdThree     = 0x03;
       
    34 const TUint KBcdFour      = 0x04;
       
    35 const TUint KBcdFive      = 0x05;
       
    36 const TUint KBcdSix       = 0x06;
       
    37 const TUint KBcdSeven     = 0x07;
       
    38 const TUint KBcdEight     = 0x08;
       
    39 const TUint KBcdNine      = 0x09;
       
    40 const TUint KBcdStar      = 0x0A;
       
    41 const TUint KBcdHash      = 0x0B;
       
    42 const TUint KBcdPause     = 0x0C;
       
    43 const TUint KBcdWild      = 0x0D;
       
    44 const TUint KBcdExpansion = 0x0E;
       
    45 const TUint KBcdEnd       = 0x0F;
       
    46 
       
    47 const TUint KUcs2Zero     = 0x30; // '0'
       
    48 const TUint KUcs2Star     = 0x2A; // '*'
       
    49 const TUint KUcs2Hash     = 0x23; // '#'
       
    50 const TUint KUcs2Pause    = 0x70; // 'p'
       
    51 
       
    52 const TUint KHighNibble   = 0xF0;
       
    53 const TUint KLowNibble    = 0x0F;
       
    54 const TUint KBitsInNibble = 4;
       
    55 
       
    56 // ======== MEMBER FUNCTIONS ========
       
    57 
       
    58 // -----------------------------------------------------------------------------
       
    59 // Two-phased constructor.
       
    60 // -----------------------------------------------------------------------------
       
    61 //
       
    62 CSendDtmfHandler* CSendDtmfHandler::NewL( MSatUtils* aUtils )
       
    63     {
       
    64     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::NewL calling" )
       
    65 
       
    66     CSendDtmfHandler* self = new( ELeave ) CSendDtmfHandler;
       
    67 
       
    68     CleanupStack::PushL( self );
       
    69     self->BaseConstructL( aUtils );
       
    70     self->ConstructL();
       
    71     CleanupStack::Pop( self );
       
    72 
       
    73     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::NewL exiting" )
       
    74     return self;
       
    75     }
       
    76 
       
    77 
       
    78 // -----------------------------------------------------------------------------
       
    79 // Destructor.
       
    80 // -----------------------------------------------------------------------------
       
    81 //
       
    82 CSendDtmfHandler::~CSendDtmfHandler()
       
    83     {
       
    84     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::~CSendDtmfHandler calling" )
       
    85 
       
    86     Cancel();
       
    87 
       
    88     if ( iDtmfSender )
       
    89         {
       
    90         delete iDtmfSender;
       
    91         }
       
    92 
       
    93     if ( iDtmfStringUcs2 )
       
    94         {
       
    95         delete iDtmfStringUcs2;
       
    96         iDtmfStringUcs2 = NULL;
       
    97         }
       
    98 
       
    99     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::~CSendDtmfHandler exiting" )
       
   100     }
       
   101 
       
   102 // -----------------------------------------------------------------------------
       
   103 // Gets the result of DTMF sending.
       
   104 // -----------------------------------------------------------------------------
       
   105 //
       
   106 void CSendDtmfHandler::SendDtmfComplete( const TInt aErrCode )
       
   107     {
       
   108     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::SendDtmfComplete calling" )
       
   109 
       
   110     iDtmfResult = aErrCode;
       
   111     // Handles result and sends terminal response.
       
   112     HandleResult();
       
   113 
       
   114     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::SendDtmfComplete exiting" )
       
   115     }
       
   116 
       
   117 // -----------------------------------------------------------------------------
       
   118 // From class MSatCommand.
       
   119 // Response from the client
       
   120 // -----------------------------------------------------------------------------
       
   121 //
       
   122 void CSendDtmfHandler::ClientResponse()
       
   123     {
       
   124     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::ClientResponse calling" )
       
   125 
       
   126     iClientResponseReceived = ETrue;
       
   127     if( iWait.IsStarted() )
       
   128         {
       
   129         iWait.AsyncStop();
       
   130         }
       
   131 
       
   132     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::ClientResponse exiting" )
       
   133     }
       
   134 
       
   135 // -----------------------------------------------------------------------------
       
   136 // From class CSatCommandHandler.
       
   137 // Waits for indication of user rejection
       
   138 // -----------------------------------------------------------------------------
       
   139 //
       
   140 void CSendDtmfHandler::Event( TInt aEvent )
       
   141     {
       
   142     LOG2( SIMPLE,
       
   143         "SENDTMF: CSendDtmfHandler::Event calling, aEvent:%d", aEvent )
       
   144 
       
   145     switch ( aEvent )
       
   146         {
       
   147         case MSatUtils::ECommandCancelled:
       
   148             {
       
   149             // Cancel DTMF sending
       
   150             if ( iDtmfSender )
       
   151                 {
       
   152                 LOG( SIMPLE, 
       
   153                 "SENDTMF: CSendDtmfHandler::Event Cancel DTMF sending" )
       
   154                 iDtmfSender->Cancel();
       
   155                 }
       
   156 
       
   157             // Cancel key pressed. Send terminal response.
       
   158             iSendDtmfRsp.iGeneralResult = RSat::KPSessionTerminatedByUser;
       
   159             iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo;
       
   160             iSendDtmfRsp.iAdditionalInfo.Zero();
       
   161 
       
   162             SendTerminalResponse();
       
   163             break;
       
   164             }
       
   165 
       
   166         case MSatUtils::ECancelledUsingEndKey:
       
   167             {
       
   168             // Cancel DTMF sending
       
   169             if ( iDtmfSender )
       
   170                 {
       
   171                 LOG( SIMPLE, 
       
   172                 "CSendDtmfHandler::Event Cancel DTMF sending by endkey" )
       
   173                 iDtmfSender->Cancel();
       
   174                 }
       
   175 
       
   176             // End key pressed. Send terminal response.
       
   177             iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd;
       
   178             iSendDtmfRsp.iInfoType = RSat::KMeProblem;
       
   179             iSendDtmfRsp.iAdditionalInfo.Zero();
       
   180             iSendDtmfRsp.iAdditionalInfo.Append( RSat::KNotInSpeechCall );
       
   181 
       
   182             // Next SimSession end will close the ui session
       
   183             iUtils->NotifyEvent( MSatUtils::ESessionTerminatedByUser );
       
   184             SendTerminalResponse();
       
   185             break;
       
   186             }
       
   187 
       
   188         default:
       
   189             {
       
   190             // Move event to base class
       
   191             CSatCommandHandler::Event( aEvent );
       
   192             }
       
   193         }
       
   194 
       
   195     LOG( SIMPLE, "SENDTMF: CSendDtmfHandler::Event exiting" )
       
   196     }
       
   197 
       
   198 // -----------------------------------------------------------------------------
       
   199 // From class CActive.
       
   200 // Cancels the sat request.
       
   201 // -----------------------------------------------------------------------------
       
   202 //
       
   203 void CSendDtmfHandler::DoCancel()
       
   204     {
       
   205     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::DoCancel calling" )
       
   206 
       
   207     iUtils->USatAPI().NotifySendDtmfCancel();
       
   208 
       
   209     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::DoCancel exiting" )
       
   210     }
       
   211 
       
   212 // -----------------------------------------------------------------------------
       
   213 // From class CSatCommandHandler.
       
   214 // Requests the command notification.
       
   215 // -----------------------------------------------------------------------------
       
   216 //
       
   217 void CSendDtmfHandler::IssueUSATRequest( TRequestStatus& aStatus )
       
   218     {
       
   219     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::IssueUSATRequest calling" )
       
   220 
       
   221     // Clear the IPC package.
       
   222     new (&iSendDtmfData) RSat::TSendDtmfV1();
       
   223 
       
   224     if ( iDtmfStringUcs2 )
       
   225         {
       
   226         LOG( SIMPLE, 
       
   227         "CSendDtmfHandler::IssueUSATRequest iDtmfStringUcs2 true" )
       
   228         delete iDtmfStringUcs2;
       
   229         iDtmfStringUcs2 = NULL;
       
   230         }
       
   231 
       
   232     iUtils->USatAPI().NotifySendDtmf( aStatus, iSendDtmfPckg );
       
   233 
       
   234     // Unregister from events
       
   235     iUtils->UnregisterEvent( this, MSatUtils::ECommandCancelled );
       
   236     iUtils->UnregisterEvent( this, MSatUtils::ECancelledUsingEndKey );
       
   237 
       
   238     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::IssueUSATRequest exiting" )
       
   239     }
       
   240 
       
   241 // -----------------------------------------------------------------------------
       
   242 // From class CSatCommandHandler.
       
   243 // SendDtmf command is not allowed if there is not active speech call.
       
   244 // -----------------------------------------------------------------------------
       
   245 //
       
   246 TBool CSendDtmfHandler::CommandAllowed()
       
   247     {
       
   248     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::CommandAllowed calling" )
       
   249 
       
   250     // By default, this is true
       
   251     TBool commandAllowed( ETrue );
       
   252 
       
   253     // Allow next terminal response to be sent
       
   254     iTerminalRespSent = EFalse;
       
   255 
       
   256     // This is needed every time
       
   257     iSendDtmfRsp.SetPCmdNumber( iSendDtmfData.PCmdNumber() );
       
   258 
       
   259     // Call has to be established, otherwise DTMF cannot be sent.
       
   260 #ifdef SAT_USE_DUMMY_TSY
       
   261     TInt firstChar( ' ' );
       
   262     if ( iSendDtmfData.iAlphaId.iStatus == RSat::EAlphaIdProvided )
       
   263         {
       
   264         firstChar = iSendDtmfData.iAlphaId.iAlphaId[0];
       
   265         }
       
   266     const TBool callIsOngoing( firstChar != 'T' );
       
   267 #else
       
   268     const TBool callIsOngoing( iUtils->SystemState().IsCallActive() );
       
   269 #endif
       
   270 
       
   271     const TInt dtmfLength( iSendDtmfData.iDtmfString.Length() );
       
   272 
       
   273     // DTMF string shall have at least one BCD character.
       
   274     // Otherwise, minimum set of data objects is not complete,
       
   275     // and command has to be rejected with 'Error, required
       
   276     // values are missing'.
       
   277     const TBool dtmfStringHasContent( dtmfLength > 0 );
       
   278 
       
   279     // DTMF string shall not be longer than is possible
       
   280     // according to TS 11.14, clause 6.6.24. If the string is
       
   281     // longer than this, the DTMF String data object is not valid,
       
   282     // which means that the minimum set of data objects
       
   283     // is not complete, and the command has to be rejected
       
   284     // with 'Error, required values are missing'.
       
   285     const TBool dtmfStringNotTooLong( dtmfLength <= RSat::KDtmfStringMaxSize );
       
   286 
       
   287     // If icon data without alpha id.
       
   288     if ( ( RSat::EAlphaIdProvided != iSendDtmfData.iAlphaId.iStatus ) &&
       
   289         ( ( RSat::ESelfExplanatory == iSendDtmfData.iIconId.iQualifier ) ||
       
   290         ( RSat::ENotSelfExplanatory == iSendDtmfData.iIconId.iQualifier ) ) )
       
   291         {
       
   292         commandAllowed = EFalse;
       
   293         iSendDtmfRsp.iGeneralResult = RSat::KCmdDataNotUnderstood;
       
   294         iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo;
       
   295         iSendDtmfRsp.iAdditionalInfo.Zero();
       
   296         LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::CommandAllowed data not \
       
   297             understood" )
       
   298         }
       
   299     else if ( !( dtmfStringHasContent && callIsOngoing && dtmfStringNotTooLong ) )
       
   300         { // Handle the error cases.
       
   301 
       
   302         if ( !dtmfStringHasContent || !dtmfStringNotTooLong )
       
   303             {
       
   304             LOG( SIMPLE,
       
   305                 "SENDDTMF: !dtmfStringHasContent || !dtmfStringNotTooLong" )
       
   306             iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo;
       
   307             iSendDtmfRsp.iAdditionalInfo.Zero();
       
   308             iSendDtmfRsp.iGeneralResult = RSat::KErrorRequiredValuesMissing;
       
   309             }
       
   310         else // No callIsOngoing
       
   311             {
       
   312             LOG( SIMPLE, "SENDDTMF: !callIsOngoing" )
       
   313             // ME is not in speech call and dtmf string cannot be sent.
       
   314             iSendDtmfRsp.iInfoType = RSat::KMeProblem;
       
   315             iSendDtmfRsp.iAdditionalInfo.Zero();
       
   316             iSendDtmfRsp.iAdditionalInfo.Append( RSat::KNotInSpeechCall );
       
   317             iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd;
       
   318             }
       
   319         // Command is not allowed
       
   320         commandAllowed = EFalse;
       
   321         }
       
   322     else
       
   323         {
       
   324         // Convert DTMF string. This is done here, so UI is not launched.
       
   325         // for no reason.
       
   326 
       
   327         // At the ETel interface level, the DTMF string uses a TBuf where each
       
   328         // buffer character represents two DTMF digits coded as BCD characters.
       
   329         const TUint KDtmfStringETelNumberOfBcdPerBufferCharacter = 2;
       
   330 
       
   331         // The DTMF string uses a TBuf where each buffer character represents
       
   332         // one DTMF digit.
       
   333         const TUint KDtmfStringMaxLength =
       
   334             KDtmfStringETelNumberOfBcdPerBufferCharacter *
       
   335                 RSat::KDtmfStringMaxSize;
       
   336 
       
   337         TRAPD( noMemory, iDtmfStringUcs2 =
       
   338             HBufC16::NewL( KDtmfStringMaxLength ) )
       
   339 
       
   340         if ( KErrNone != noMemory )
       
   341             {
       
   342             LOG( SIMPLE, 
       
   343             "SENDDTMF: CSendDtmfHandler::CommandAllowed KErrNone != noMemory" )
       
   344             iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo;
       
   345             iSendDtmfRsp.iAdditionalInfo.Zero();
       
   346             iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd;
       
   347             // Command is not allowed
       
   348             commandAllowed = EFalse;
       
   349             }
       
   350         else
       
   351             {
       
   352 
       
   353             TPtr ptr = iDtmfStringUcs2->Des();
       
   354 
       
   355             if ( ! ConvertDtmfStringToUcs2( ptr ) )
       
   356                 {
       
   357                 LOG( SIMPLE, 
       
   358                 "CSendDtmfHandler::CommandAllowed not allowed" )
       
   359                 // DTMF string contains illegal characters
       
   360                 iSendDtmfRsp.iGeneralResult = RSat::KCmdDataNotUnderstood;
       
   361                 iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo;
       
   362                 iSendDtmfRsp.iAdditionalInfo.Zero();
       
   363                 // Command is not allowed
       
   364                 commandAllowed = EFalse;
       
   365                 }
       
   366             }
       
   367         }
       
   368 
       
   369     if ( !commandAllowed )
       
   370         {
       
   371         LOG( SIMPLE, 
       
   372         "CSendDtmfHandler::CommandAllowed commandAllowed false" )
       
   373         SendTerminalResponse();
       
   374         }
       
   375     // Set icon command flag whether icon data was received and set qualifier
       
   376     // to no icon id
       
   377     // To be removed when icons are allowed in this command
       
   378     else if ( ( RSat::ESelfExplanatory ==
       
   379         iSendDtmfData.iIconId.iQualifier ) ||
       
   380         ( RSat::ENotSelfExplanatory ==
       
   381         iSendDtmfData.iIconId.iQualifier ) )
       
   382         {
       
   383         LOG( SIMPLE, 
       
   384         "CSendDtmfHandler::CommandAllowed ENoIconId" )
       
   385         iIconCommand = ETrue;
       
   386         iSendDtmfData.iIconId.iQualifier = RSat::ENoIconId;
       
   387         }
       
   388     else
       
   389         {
       
   390         iIconCommand = EFalse;
       
   391         }
       
   392 
       
   393     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::CommandAllowed exiting" )
       
   394     return commandAllowed;
       
   395     }
       
   396 
       
   397 // -----------------------------------------------------------------------------
       
   398 // From class CSatCommandHandler.
       
   399 // Need for ui session.
       
   400 // -----------------------------------------------------------------------------
       
   401 //
       
   402 TBool CSendDtmfHandler::NeedUiSession()
       
   403     {
       
   404     LOG( NORMAL, "SENDDTMF: CSendDtmfHandler::NeedUiSession calling" )
       
   405     iNeedUiSession = ETrue;
       
   406 
       
   407     if ( RSat::EAlphaIdNull == iSendDtmfData.iAlphaId.iStatus )
       
   408         {
       
   409         LOG( NORMAL, "SENDDTMF: CSendDtmfHandler::NeedUiSession EAlphaIdNull" )
       
   410         iNeedUiSession = EFalse;
       
   411         }
       
   412 
       
   413     // Notify Cover UI if it's supported
       
   414     if ( iNeedUiSession && iUtils->CoverUiSupported() )
       
   415         {
       
   416         LOG( NORMAL, 
       
   417         "SENDDTMF: CSendDtmfHandler::NeedUiSession CoverUiSupported" )
       
   418         TSatCommandData medEventData;
       
   419         medEventData.iPCmdNumber = RSat::ESendDtmf;
       
   420         medEventData.iAlphaId =  iSendDtmfData.iAlphaId;
       
   421         medEventData.iDuration.iNumOfUnits = KSatDefaultDuration;
       
   422         medEventData.iDuration.iTimeUnit = RSat::ESeconds;
       
   423         medEventData.iIconID = iSendDtmfData.iIconId;
       
   424         TSatCommandPckg tPckg( medEventData );
       
   425         iUtils->RaiseSatEvent( tPckg );
       
   426         }
       
   427 
       
   428     LOG2( NORMAL, 
       
   429     "SENDDTMF: CSendDtmfHandler::NeedUiSession exiting,iNeedUiSession: %d",
       
   430     iNeedUiSession )
       
   431     return iNeedUiSession;
       
   432     }
       
   433 
       
   434 // -----------------------------------------------------------------------------
       
   435 // From class CSatCommandHandler.
       
   436 // Called when USAT API notifies that command.
       
   437 // -----------------------------------------------------------------------------
       
   438 //
       
   439 void CSendDtmfHandler::HandleCommand()
       
   440     {
       
   441     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::HandleCommand calling" )
       
   442 
       
   443     iUtils->NotifyEvent( MSatUtils::ESendDtmfExecuting );
       
   444 
       
   445     // Lower error granularity. This helps for mapping error cases
       
   446     iUtils->MultiModeApi().LowerErrorGranularity();
       
   447 
       
   448     // Pointer to converted DTMF string
       
   449     TPtr ptr = iDtmfStringUcs2->Des();
       
   450 
       
   451     iClientResponseReceived = EFalse;
       
   452     
       
   453     // First, send DTMF string
       
   454     iDtmfSender->SendToneString( ptr );
       
   455 
       
   456     if ( iNeedUiSession )
       
   457         {
       
   458         TRAPD( regErr,
       
   459         // Register to listen user cancel events:
       
   460         // Cancel key event from dialog
       
   461         iUtils->RegisterL( this, MSatUtils::ECommandCancelled );
       
   462         // End key from dialog
       
   463         iUtils->RegisterL( this, MSatUtils::ECancelledUsingEndKey );
       
   464 
       
   465         // Then send notification to UI
       
   466         // Register notification observer
       
   467         iUtils->RegisterServiceRequestL(
       
   468             ESatSProactiveNotification,
       
   469             ESatSProactiveNotificationResponse,
       
   470             this )
       
   471             ); // TRAPD
       
   472         LOG2( NORMAL, 
       
   473         "CSendDtmfHandler::HandleCommand regErr: %d", regErr )
       
   474         if ( KErrNone != regErr )
       
   475             {
       
   476             iDtmfSender->Cancel();
       
   477             // Raise error granularity back to extended errors
       
   478             iUtils->MultiModeApi().RaiseErrorGranularity();
       
   479 
       
   480             iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd;
       
   481             iSendDtmfRsp.iInfoType = RSat::KMeProblem;
       
   482             iSendDtmfRsp.iAdditionalInfo.Zero();
       
   483             iSendDtmfRsp.iAdditionalInfo.Append( RSat::KNoSpecificMeProblem );
       
   484             SendTerminalResponse();
       
   485             }
       
   486         else
       
   487             {
       
   488             TSatAlphaIdStatus alphaIdStatus;
       
   489             if ( iSendDtmfData.iAlphaId.iStatus == RSat::EAlphaIdNotPresent )
       
   490                 {
       
   491                 LOG( SIMPLE, 
       
   492                 "SENDDTMF: CSendDtmfHandler::HandleCommand EAlphaIdNotPresent" )
       
   493                 // If AlphaID is not provided, show DTMF string in note.
       
   494                 // Deliver empty text if DTMF string is bigger than it is
       
   495                 // capable to deliver to SAT UI.
       
   496                 alphaIdStatus = ESatAlphaIdNotProvided;
       
   497                 LOG2( NORMAL, 
       
   498                 "SENDDTMF: CSendDtmfHandler::HandleCommand ptr.Length: %d", 
       
   499                 ptr.Length() )
       
   500                 if ( RSat::KAlphaIdMaxSize >= ptr.Length() )
       
   501                     {
       
   502                     iNotificationData.iText = ptr;
       
   503                     }
       
   504                 else
       
   505                     {
       
   506                     iNotificationData.iText.Zero();
       
   507                     }
       
   508                 }
       
   509             else if ( iSendDtmfData.iAlphaId.iStatus == RSat::EAlphaIdProvided )
       
   510                 {
       
   511                 LOG( SIMPLE, 
       
   512                 "SENDDTMF: CSendDtmfHandler::HandleCommand EAlphaIdProvided" )
       
   513                 alphaIdStatus = ESatAlphaIdNotNull;
       
   514                 iNotificationData.iText = iSendDtmfData.iAlphaId.iAlphaId;
       
   515                 }
       
   516             else
       
   517                 {
       
   518                 LOG( SIMPLE, 
       
   519                 "SENDDTMF: CSendDtmfHandler::HandleCommand others" )
       
   520                 alphaIdStatus = ESatAlphaIdNull;
       
   521                 iNotificationData.iText.Zero();
       
   522                 }
       
   523 
       
   524             // Build notification data
       
   525             iNotificationData.iAlphaIdStatus = alphaIdStatus;
       
   526             iNotificationData.iCommand = ESatSSendDtmfNotify;
       
   527 
       
   528             // Has to be casted to TInt before casting to TSatIconQualifier,
       
   529             // because GCC warns about the direct cast.
       
   530             const struct TSatIconId iconId =
       
   531                 { iSendDtmfData.iIconId.iIdentifier,
       
   532                   static_cast<TSatIconQualifier>(
       
   533                     static_cast<TInt>( iSendDtmfData.iIconId.iQualifier ) ) };
       
   534 
       
   535             iNotificationData.iIconId = iconId;
       
   536 
       
   537             // Send notification
       
   538             iUtils->SatUiHandler().UiSession()->SendCommand(
       
   539                 &iNotificationDataPckg,
       
   540                 &iNotificationRspPckg,
       
   541                 ESatSProactiveNotification );
       
   542 
       
   543             // DTMF String sent, wait for completion
       
   544             }
       
   545         }
       
   546 
       
   547     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::HandleCommand exiting" )
       
   548     }
       
   549 
       
   550 // -----------------------------------------------------------------------------
       
   551 // From class CSatCommandHandler.
       
   552 // Called when UI launch fails.
       
   553 // -----------------------------------------------------------------------------
       
   554 //
       
   555 void CSendDtmfHandler::UiLaunchFailed()
       
   556     {
       
   557     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::UiLaunchFailed calling" )
       
   558 
       
   559     iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd;
       
   560     iSendDtmfRsp.iInfoType = RSat::KMeProblem;
       
   561     iSendDtmfRsp.iAdditionalInfo.Append( RSat::KNoSpecificMeProblem );
       
   562     iSendDtmfRsp.SetPCmdNumber( iSendDtmfData.PCmdNumber() );
       
   563     SendTerminalResponse();
       
   564 
       
   565     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::UiLaunchFailed exiting" )
       
   566     }
       
   567 
       
   568 // -----------------------------------------------------------------------------
       
   569 // C++ default constructor can NOT contain any code, that
       
   570 // might leave.
       
   571 // -----------------------------------------------------------------------------
       
   572 //
       
   573 //lint -e{1403, 1769} Can not be initialized, harmless.
       
   574 CSendDtmfHandler::CSendDtmfHandler() :
       
   575     CSatCommandHandler(),
       
   576     iSendDtmfData(),
       
   577     iSendDtmfPckg( iSendDtmfData ),
       
   578     iSendDtmfRsp(),
       
   579     iSendDtmfRspPckg( iSendDtmfRsp ),
       
   580     iNotificationData(),
       
   581     iNotificationDataPckg( iNotificationData ),
       
   582     iNotificationRsp(),
       
   583     iNotificationRspPckg( iNotificationRsp ),
       
   584     // To be removed when icons are allowed in this command
       
   585     iIconCommand( EFalse )
       
   586     {
       
   587     LOG( SIMPLE,
       
   588         "SENDDTMF: CSendDtmfHandler::CSendDtmfHandler calling - exiting" )
       
   589     }
       
   590 
       
   591 // -----------------------------------------------------------------------------
       
   592 // Symbian 2nd phase constructor can leave.
       
   593 // -----------------------------------------------------------------------------
       
   594 //
       
   595 void CSendDtmfHandler::ConstructL()
       
   596     {
       
   597     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::ConstructL calling" )
       
   598 
       
   599     // Register notification observer
       
   600     iUtils->RegisterServiceRequestL(
       
   601         ESatSProactiveNotification,
       
   602         ESatSProactiveNotificationResponse,
       
   603         this );
       
   604 
       
   605     // DTMF Sender
       
   606     iDtmfSender = 
       
   607         new ( ELeave ) CSatDtmfSender( *this, iUtils->MultiModeApi() );
       
   608 
       
   609     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::ConstructL exiting" )
       
   610     }
       
   611 
       
   612 
       
   613 // -----------------------------------------------------------------------------
       
   614 // Converts DTMF string from extended BCD to UCS2.
       
   615 // -----------------------------------------------------------------------------
       
   616 //
       
   617 TBool CSendDtmfHandler::ConvertDtmfStringToUcs2( TDes& aDtmfString )
       
   618     {
       
   619     LOG( SIMPLE,
       
   620         "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 calling" )
       
   621     aDtmfString.Zero();
       
   622 
       
   623     const TInt bcdLength = iSendDtmfData.iDtmfString.Length();
       
   624     TInt i( 0 );
       
   625     TBool retVal( ETrue );
       
   626     TBool continueLoop( ETrue );
       
   627 
       
   628     for ( i = 0; i < bcdLength && continueLoop; i++ )
       
   629         {
       
   630         // each 16 bit DTMF character of SAT ETel API holds two nibbles,
       
   631         // high byte always being 0
       
   632         TChar twoBcd = iSendDtmfData.iDtmfString[i];
       
   633 
       
   634         // low nibble yields first BCD in semi-octet representation
       
   635         TChar firstBcd = twoBcd & KLowNibble;
       
   636 
       
   637         // high nibble yields second BCD in semi-octet representation
       
   638         TChar secondBcd = ( twoBcd & KHighNibble ) >> KBitsInNibble;
       
   639 
       
   640         TChar destChar;
       
   641         TBool endOfString;
       
   642         TBool dtmfCharacter;
       
   643 
       
   644         // convert first extended BCD character
       
   645         ConvertDtmfCharacterToUcs2(
       
   646             firstBcd, endOfString, dtmfCharacter, destChar );
       
   647 
       
   648         if ( endOfString )
       
   649             {
       
   650             LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 \
       
   651                 (End of string in first BCD)" )
       
   652             retVal = ETrue; // completed string (F digit)
       
   653             continueLoop = EFalse;
       
   654             }
       
   655         else if ( !dtmfCharacter )
       
   656             {
       
   657             LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 \
       
   658                 (not dtmfCharacter in first BCD)" )
       
   659             retVal = EFalse;
       
   660             continueLoop = EFalse;
       
   661             }
       
   662         else
       
   663             {
       
   664             aDtmfString.Append( destChar );
       
   665 
       
   666             // convert second extended BCD character
       
   667             ConvertDtmfCharacterToUcs2(
       
   668                 secondBcd, endOfString, dtmfCharacter, destChar );
       
   669 
       
   670             if ( endOfString )
       
   671                 {
       
   672                 LOG( SIMPLE,
       
   673                     "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 \
       
   674                     (End of string in second BCD)" )
       
   675                 retVal = ETrue; // completed string (F digit)
       
   676                 continueLoop = EFalse;
       
   677                 }
       
   678             else if ( !dtmfCharacter )
       
   679                 {
       
   680                 LOG( SIMPLE,
       
   681                     "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 \
       
   682                     (not dtmfCharacter in second BCD)" )
       
   683                 retVal = EFalse;
       
   684                 continueLoop = EFalse;
       
   685                 }
       
   686             else
       
   687                 {
       
   688                 LOG( SIMPLE,
       
   689                     "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 \
       
   690                     others" )
       
   691                 aDtmfString.Append( destChar );
       
   692                 }
       
   693             }
       
   694         }
       
   695     LOG2( NORMAL, 
       
   696         "CSendDtmfHandler::ConvertDtmfStringToUcs2 i: %d", i )
       
   697     LOG2( SIMPLE,
       
   698         "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 exiting,\
       
   699         retVal: %d", retVal )
       
   700     return retVal; // completed string (all bytes converted)
       
   701     }
       
   702 
       
   703 // -----------------------------------------------------------------------------
       
   704 // Converts character from extended BCD to UCS2.
       
   705 // -----------------------------------------------------------------------------
       
   706 //
       
   707 void CSendDtmfHandler::ConvertDtmfCharacterToUcs2(
       
   708     const TChar& aExtBcd,
       
   709     TBool& aEndOfString,
       
   710     TBool& aDtmfCharacter,
       
   711     TChar& aUcs2Char ) const
       
   712     {
       
   713     LOG( SIMPLE,
       
   714         "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 calling" )
       
   715 
       
   716     aEndOfString = EFalse;
       
   717     aDtmfCharacter = ETrue;
       
   718 
       
   719     switch ( aExtBcd )
       
   720         {
       
   721         case KBcdZero:
       
   722         case KBcdOne:
       
   723         case KBcdTwo:
       
   724         case KBcdThree:
       
   725         case KBcdFour:
       
   726         case KBcdFive:
       
   727         case KBcdSix:
       
   728         case KBcdSeven:
       
   729         case KBcdEight:
       
   730         case KBcdNine:
       
   731             {
       
   732             LOG( SIMPLE,
       
   733             "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 Digit" )
       
   734             aUcs2Char = KUcs2Zero + aExtBcd;
       
   735             break;
       
   736             }
       
   737 
       
   738         case KBcdStar:
       
   739             {
       
   740             LOG( SIMPLE,
       
   741             "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 KBcdStar" )
       
   742             aUcs2Char = KUcs2Star;
       
   743             break;
       
   744             }
       
   745 
       
   746         case KBcdHash:
       
   747             {
       
   748             LOG( SIMPLE,
       
   749             "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 KBcdHash" )
       
   750             aUcs2Char = KUcs2Hash;
       
   751             break;
       
   752             }
       
   753 
       
   754         case KBcdPause:
       
   755             {
       
   756             LOG( SIMPLE,
       
   757             "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 KBcdPause" )
       
   758             aUcs2Char = KUcs2Pause;
       
   759             break;
       
   760             }
       
   761 
       
   762         case KBcdEnd:
       
   763             {
       
   764             LOG( SIMPLE,
       
   765             "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 KBcdEnd" )
       
   766             aEndOfString = ETrue;
       
   767             break;
       
   768             }
       
   769 
       
   770         case KBcdWild:
       
   771         case KBcdExpansion:
       
   772         default:
       
   773             {
       
   774             LOG( SIMPLE,
       
   775             "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 unknown" )
       
   776             aDtmfCharacter = EFalse;
       
   777             }
       
   778         }
       
   779 
       
   780     LOG( SIMPLE,
       
   781         "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 exiting" )
       
   782     }
       
   783 
       
   784 // -----------------------------------------------------------------------------
       
   785 // Handles the result of DTMF sending and sends terminal response.
       
   786 // -----------------------------------------------------------------------------
       
   787 //
       
   788 void CSendDtmfHandler::HandleResult()
       
   789     {
       
   790     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::HandleResult calling" )
       
   791 
       
   792     // If UI is needed, send DTMF Done event to close any progress bar
       
   793     if ( iNeedUiSession )
       
   794         {
       
   795         LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::HandleResult NeedUiSession" )
       
   796         // To prevent client traffic jamming.
       
   797         // Send UI event only when client response is received.
       
   798         if ( !iClientResponseReceived && !iWait.IsStarted() )
       
   799             {
       
   800             LOG( SIMPLE, 
       
   801             "SENDDTMF: CSendDtmfHandler::HandleResult start iwait" )
       
   802             iWait.Start();
       
   803             }
       
   804         // No need to send command result since this only removes any
       
   805         // existing wait notes...
       
   806         iUtils->NotifyUiEvent( ESatSDtmfEndEvent, ESatEventNone, KErrNone );
       
   807         }
       
   808 
       
   809     // Raise error granularity back to extended errors
       
   810     iUtils->MultiModeApi().RaiseErrorGranularity();
       
   811 
       
   812 #ifdef __WINS__
       
   813     if ( KErrTimedOut == iDtmfResult )
       
   814         {
       
   815         iDtmfResult = KErrNone;
       
   816         }
       
   817 #endif
       
   818 
       
   819     LOG2( NORMAL, 
       
   820     "SENDDTMF: CSendDtmfHandler::HandleResult Send DTMF result: %i", 
       
   821     iDtmfResult )
       
   822 
       
   823     switch ( iDtmfResult )
       
   824         {
       
   825         case KErrNone:
       
   826             {
       
   827             // No errors in DTMF sending. But cases like user termination and
       
   828             // icons are handled here.
       
   829             if ( iNotificationRsp.iSessionTerminatedByUser )
       
   830                 {
       
   831                 LOG( DETAILED,
       
   832                 "SENDDTMF: CSendDtmfHandler::HandleResult session terminated \
       
   833                 by user" )
       
   834                 iSendDtmfRsp.iGeneralResult = RSat::KPSessionTerminatedByUser;
       
   835                 iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo;
       
   836                 iSendDtmfRsp.iAdditionalInfo.Zero();
       
   837                 }
       
   838             else
       
   839                 {
       
   840                 iSendDtmfRsp.iGeneralResult = RSat::KSuccess;
       
   841                 iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo;
       
   842                 iSendDtmfRsp.iAdditionalInfo.Zero();
       
   843 
       
   844                 // If command had icon data and was done succesfully,
       
   845                 // report that icon was not shown.
       
   846                 // To be removed and correct handling (i.e. ClientResponse to
       
   847                 // notification is received) for general result
       
   848                 // KSuccessRequestedIconNotDisplayed must be added when icons
       
   849                 // are allowed in this command.
       
   850                 if ( iIconCommand )
       
   851                     {
       
   852                     LOG( DETAILED,
       
   853                     "SENDDTMF: CSendDtmfHandler::HandleResult iIconCommand \
       
   854                     true" )
       
   855                     iSendDtmfRsp.iGeneralResult =
       
   856                         RSat::KSuccessRequestedIconNotDisplayed;
       
   857                     }
       
   858                 }
       
   859 
       
   860             break;
       
   861             }
       
   862         case KErrCancel:
       
   863         case KErrEtelNoCarrier:
       
   864             {
       
   865             // Problems in communicating with receiving device are handled here
       
   866             // e.g. call was unexpectedly dropped.
       
   867             iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd;
       
   868             iSendDtmfRsp.iInfoType = RSat::KMeProblem;
       
   869             iSendDtmfRsp.iAdditionalInfo.Zero();
       
   870             iSendDtmfRsp.iAdditionalInfo.Append( RSat::KNoSpecificMeProblem );
       
   871             break;
       
   872             }
       
   873         case KErrArgument:
       
   874             {
       
   875             // Maximum length of DTMF string reached.
       
   876             LOG( DETAILED,
       
   877                  "SENDDTMF: CSendDtmfHandler  Over maximum DTMF length" )
       
   878             iSendDtmfRsp.iGeneralResult = RSat::KErrorRequiredValuesMissing;
       
   879             iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo;
       
   880             iSendDtmfRsp.iAdditionalInfo.Zero();
       
   881             break;
       
   882             }
       
   883         default:
       
   884             {
       
   885             // By default for other errors.
       
   886             iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd;
       
   887             iSendDtmfRsp.iInfoType = RSat::KMeProblem;
       
   888             iSendDtmfRsp.iAdditionalInfo.Zero();
       
   889             iSendDtmfRsp.iAdditionalInfo.Append( RSat::KNotInSpeechCall );
       
   890             break;
       
   891             }
       
   892         }
       
   893 
       
   894     // Cancel DTMF sending if it is running.
       
   895     iDtmfSender->Cancel();
       
   896     SendTerminalResponse();
       
   897 
       
   898     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::HandleResult exiting" )
       
   899     }
       
   900 
       
   901 // -----------------------------------------------------------------------------
       
   902 // Sends terminal response. Makes sure that terminal response
       
   903 // is not send more that once / command.
       
   904 // -----------------------------------------------------------------------------
       
   905 //
       
   906 void CSendDtmfHandler::SendTerminalResponse()
       
   907     {
       
   908     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::SendTerminalResponse calling" )
       
   909 
       
   910     if ( !iTerminalRespSent )
       
   911         {
       
   912         LOG( SIMPLE, 
       
   913         "CSendDtmfHandler::SendTerminalResponse iTerminalRespSent false" )
       
   914         iTerminalRespSent = ETrue;
       
   915         TerminalRsp( RSat::ESendDtmf, iSendDtmfRspPckg );
       
   916         }
       
   917 
       
   918     LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::SendTerminalResponse exiting" )
       
   919     }
       
   920