--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/satengine/SatServer/Commands/SendDtmfCmd/src/CSendDtmfHandler.cpp Tue Feb 02 01:11:09 2010 +0200
@@ -0,0 +1,920 @@
+/*
+* Copyright (c) 2002-2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Handles SendDtmf command
+*
+*/
+
+
+#include "MSatApi.h"
+#include "MSatUtils.h"
+#include "MSatSystemState.h"
+#include "MSatUiSession.h"
+#include "SatSOpcodes.h"
+#include "MSatSUiClientHandler.h"
+#include "CSendDtmfHandler.h"
+#include "csatdtmfsender.h"
+#include "msatmultimodeapi.h"
+#include "SatLog.h"
+
+const TUint KBcdZero = 0x00;
+const TUint KBcdOne = 0x01;
+const TUint KBcdTwo = 0x02;
+const TUint KBcdThree = 0x03;
+const TUint KBcdFour = 0x04;
+const TUint KBcdFive = 0x05;
+const TUint KBcdSix = 0x06;
+const TUint KBcdSeven = 0x07;
+const TUint KBcdEight = 0x08;
+const TUint KBcdNine = 0x09;
+const TUint KBcdStar = 0x0A;
+const TUint KBcdHash = 0x0B;
+const TUint KBcdPause = 0x0C;
+const TUint KBcdWild = 0x0D;
+const TUint KBcdExpansion = 0x0E;
+const TUint KBcdEnd = 0x0F;
+
+const TUint KUcs2Zero = 0x30; // '0'
+const TUint KUcs2Star = 0x2A; // '*'
+const TUint KUcs2Hash = 0x23; // '#'
+const TUint KUcs2Pause = 0x70; // 'p'
+
+const TUint KHighNibble = 0xF0;
+const TUint KLowNibble = 0x0F;
+const TUint KBitsInNibble = 4;
+
+// ======== MEMBER FUNCTIONS ========
+
+// -----------------------------------------------------------------------------
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CSendDtmfHandler* CSendDtmfHandler::NewL( MSatUtils* aUtils )
+ {
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::NewL calling" )
+
+ CSendDtmfHandler* self = new( ELeave ) CSendDtmfHandler;
+
+ CleanupStack::PushL( self );
+ self->BaseConstructL( aUtils );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::NewL exiting" )
+ return self;
+ }
+
+
+// -----------------------------------------------------------------------------
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CSendDtmfHandler::~CSendDtmfHandler()
+ {
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::~CSendDtmfHandler calling" )
+
+ Cancel();
+
+ if ( iDtmfSender )
+ {
+ delete iDtmfSender;
+ }
+
+ if ( iDtmfStringUcs2 )
+ {
+ delete iDtmfStringUcs2;
+ iDtmfStringUcs2 = NULL;
+ }
+
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::~CSendDtmfHandler exiting" )
+ }
+
+// -----------------------------------------------------------------------------
+// Gets the result of DTMF sending.
+// -----------------------------------------------------------------------------
+//
+void CSendDtmfHandler::SendDtmfComplete( const TInt aErrCode )
+ {
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::SendDtmfComplete calling" )
+
+ iDtmfResult = aErrCode;
+ // Handles result and sends terminal response.
+ HandleResult();
+
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::SendDtmfComplete exiting" )
+ }
+
+// -----------------------------------------------------------------------------
+// From class MSatCommand.
+// Response from the client
+// -----------------------------------------------------------------------------
+//
+void CSendDtmfHandler::ClientResponse()
+ {
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::ClientResponse calling" )
+
+ iClientResponseReceived = ETrue;
+ if( iWait.IsStarted() )
+ {
+ iWait.AsyncStop();
+ }
+
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::ClientResponse exiting" )
+ }
+
+// -----------------------------------------------------------------------------
+// From class CSatCommandHandler.
+// Waits for indication of user rejection
+// -----------------------------------------------------------------------------
+//
+void CSendDtmfHandler::Event( TInt aEvent )
+ {
+ LOG2( SIMPLE,
+ "SENDTMF: CSendDtmfHandler::Event calling, aEvent:%d", aEvent )
+
+ switch ( aEvent )
+ {
+ case MSatUtils::ECommandCancelled:
+ {
+ // Cancel DTMF sending
+ if ( iDtmfSender )
+ {
+ LOG( SIMPLE,
+ "SENDTMF: CSendDtmfHandler::Event Cancel DTMF sending" )
+ iDtmfSender->Cancel();
+ }
+
+ // Cancel key pressed. Send terminal response.
+ iSendDtmfRsp.iGeneralResult = RSat::KPSessionTerminatedByUser;
+ iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo;
+ iSendDtmfRsp.iAdditionalInfo.Zero();
+
+ SendTerminalResponse();
+ break;
+ }
+
+ case MSatUtils::ECancelledUsingEndKey:
+ {
+ // Cancel DTMF sending
+ if ( iDtmfSender )
+ {
+ LOG( SIMPLE,
+ "CSendDtmfHandler::Event Cancel DTMF sending by endkey" )
+ iDtmfSender->Cancel();
+ }
+
+ // End key pressed. Send terminal response.
+ iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd;
+ iSendDtmfRsp.iInfoType = RSat::KMeProblem;
+ iSendDtmfRsp.iAdditionalInfo.Zero();
+ iSendDtmfRsp.iAdditionalInfo.Append( RSat::KNotInSpeechCall );
+
+ // Next SimSession end will close the ui session
+ iUtils->NotifyEvent( MSatUtils::ESessionTerminatedByUser );
+ SendTerminalResponse();
+ break;
+ }
+
+ default:
+ {
+ // Move event to base class
+ CSatCommandHandler::Event( aEvent );
+ }
+ }
+
+ LOG( SIMPLE, "SENDTMF: CSendDtmfHandler::Event exiting" )
+ }
+
+// -----------------------------------------------------------------------------
+// From class CActive.
+// Cancels the sat request.
+// -----------------------------------------------------------------------------
+//
+void CSendDtmfHandler::DoCancel()
+ {
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::DoCancel calling" )
+
+ iUtils->USatAPI().NotifySendDtmfCancel();
+
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::DoCancel exiting" )
+ }
+
+// -----------------------------------------------------------------------------
+// From class CSatCommandHandler.
+// Requests the command notification.
+// -----------------------------------------------------------------------------
+//
+void CSendDtmfHandler::IssueUSATRequest( TRequestStatus& aStatus )
+ {
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::IssueUSATRequest calling" )
+
+ // Clear the IPC package.
+ new (&iSendDtmfData) RSat::TSendDtmfV1();
+
+ if ( iDtmfStringUcs2 )
+ {
+ LOG( SIMPLE,
+ "CSendDtmfHandler::IssueUSATRequest iDtmfStringUcs2 true" )
+ delete iDtmfStringUcs2;
+ iDtmfStringUcs2 = NULL;
+ }
+
+ iUtils->USatAPI().NotifySendDtmf( aStatus, iSendDtmfPckg );
+
+ // Unregister from events
+ iUtils->UnregisterEvent( this, MSatUtils::ECommandCancelled );
+ iUtils->UnregisterEvent( this, MSatUtils::ECancelledUsingEndKey );
+
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::IssueUSATRequest exiting" )
+ }
+
+// -----------------------------------------------------------------------------
+// From class CSatCommandHandler.
+// SendDtmf command is not allowed if there is not active speech call.
+// -----------------------------------------------------------------------------
+//
+TBool CSendDtmfHandler::CommandAllowed()
+ {
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::CommandAllowed calling" )
+
+ // By default, this is true
+ TBool commandAllowed( ETrue );
+
+ // Allow next terminal response to be sent
+ iTerminalRespSent = EFalse;
+
+ // This is needed every time
+ iSendDtmfRsp.SetPCmdNumber( iSendDtmfData.PCmdNumber() );
+
+ // Call has to be established, otherwise DTMF cannot be sent.
+#ifdef SAT_USE_DUMMY_TSY
+ TInt firstChar( ' ' );
+ if ( iSendDtmfData.iAlphaId.iStatus == RSat::EAlphaIdProvided )
+ {
+ firstChar = iSendDtmfData.iAlphaId.iAlphaId[0];
+ }
+ const TBool callIsOngoing( firstChar != 'T' );
+#else
+ const TBool callIsOngoing( iUtils->SystemState().IsCallActive() );
+#endif
+
+ const TInt dtmfLength( iSendDtmfData.iDtmfString.Length() );
+
+ // DTMF string shall have at least one BCD character.
+ // Otherwise, minimum set of data objects is not complete,
+ // and command has to be rejected with 'Error, required
+ // values are missing'.
+ const TBool dtmfStringHasContent( dtmfLength > 0 );
+
+ // DTMF string shall not be longer than is possible
+ // according to TS 11.14, clause 6.6.24. If the string is
+ // longer than this, the DTMF String data object is not valid,
+ // which means that the minimum set of data objects
+ // is not complete, and the command has to be rejected
+ // with 'Error, required values are missing'.
+ const TBool dtmfStringNotTooLong( dtmfLength <= RSat::KDtmfStringMaxSize );
+
+ // If icon data without alpha id.
+ if ( ( RSat::EAlphaIdProvided != iSendDtmfData.iAlphaId.iStatus ) &&
+ ( ( RSat::ESelfExplanatory == iSendDtmfData.iIconId.iQualifier ) ||
+ ( RSat::ENotSelfExplanatory == iSendDtmfData.iIconId.iQualifier ) ) )
+ {
+ commandAllowed = EFalse;
+ iSendDtmfRsp.iGeneralResult = RSat::KCmdDataNotUnderstood;
+ iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo;
+ iSendDtmfRsp.iAdditionalInfo.Zero();
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::CommandAllowed data not \
+ understood" )
+ }
+ else if ( !( dtmfStringHasContent && callIsOngoing && dtmfStringNotTooLong ) )
+ { // Handle the error cases.
+
+ if ( !dtmfStringHasContent || !dtmfStringNotTooLong )
+ {
+ LOG( SIMPLE,
+ "SENDDTMF: !dtmfStringHasContent || !dtmfStringNotTooLong" )
+ iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo;
+ iSendDtmfRsp.iAdditionalInfo.Zero();
+ iSendDtmfRsp.iGeneralResult = RSat::KErrorRequiredValuesMissing;
+ }
+ else // No callIsOngoing
+ {
+ LOG( SIMPLE, "SENDDTMF: !callIsOngoing" )
+ // ME is not in speech call and dtmf string cannot be sent.
+ iSendDtmfRsp.iInfoType = RSat::KMeProblem;
+ iSendDtmfRsp.iAdditionalInfo.Zero();
+ iSendDtmfRsp.iAdditionalInfo.Append( RSat::KNotInSpeechCall );
+ iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd;
+ }
+ // Command is not allowed
+ commandAllowed = EFalse;
+ }
+ else
+ {
+ // Convert DTMF string. This is done here, so UI is not launched.
+ // for no reason.
+
+ // At the ETel interface level, the DTMF string uses a TBuf where each
+ // buffer character represents two DTMF digits coded as BCD characters.
+ const TUint KDtmfStringETelNumberOfBcdPerBufferCharacter = 2;
+
+ // The DTMF string uses a TBuf where each buffer character represents
+ // one DTMF digit.
+ const TUint KDtmfStringMaxLength =
+ KDtmfStringETelNumberOfBcdPerBufferCharacter *
+ RSat::KDtmfStringMaxSize;
+
+ TRAPD( noMemory, iDtmfStringUcs2 =
+ HBufC16::NewL( KDtmfStringMaxLength ) )
+
+ if ( KErrNone != noMemory )
+ {
+ LOG( SIMPLE,
+ "SENDDTMF: CSendDtmfHandler::CommandAllowed KErrNone != noMemory" )
+ iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo;
+ iSendDtmfRsp.iAdditionalInfo.Zero();
+ iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd;
+ // Command is not allowed
+ commandAllowed = EFalse;
+ }
+ else
+ {
+
+ TPtr ptr = iDtmfStringUcs2->Des();
+
+ if ( ! ConvertDtmfStringToUcs2( ptr ) )
+ {
+ LOG( SIMPLE,
+ "CSendDtmfHandler::CommandAllowed not allowed" )
+ // DTMF string contains illegal characters
+ iSendDtmfRsp.iGeneralResult = RSat::KCmdDataNotUnderstood;
+ iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo;
+ iSendDtmfRsp.iAdditionalInfo.Zero();
+ // Command is not allowed
+ commandAllowed = EFalse;
+ }
+ }
+ }
+
+ if ( !commandAllowed )
+ {
+ LOG( SIMPLE,
+ "CSendDtmfHandler::CommandAllowed commandAllowed false" )
+ SendTerminalResponse();
+ }
+ // Set icon command flag whether icon data was received and set qualifier
+ // to no icon id
+ // To be removed when icons are allowed in this command
+ else if ( ( RSat::ESelfExplanatory ==
+ iSendDtmfData.iIconId.iQualifier ) ||
+ ( RSat::ENotSelfExplanatory ==
+ iSendDtmfData.iIconId.iQualifier ) )
+ {
+ LOG( SIMPLE,
+ "CSendDtmfHandler::CommandAllowed ENoIconId" )
+ iIconCommand = ETrue;
+ iSendDtmfData.iIconId.iQualifier = RSat::ENoIconId;
+ }
+ else
+ {
+ iIconCommand = EFalse;
+ }
+
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::CommandAllowed exiting" )
+ return commandAllowed;
+ }
+
+// -----------------------------------------------------------------------------
+// From class CSatCommandHandler.
+// Need for ui session.
+// -----------------------------------------------------------------------------
+//
+TBool CSendDtmfHandler::NeedUiSession()
+ {
+ LOG( NORMAL, "SENDDTMF: CSendDtmfHandler::NeedUiSession calling" )
+ iNeedUiSession = ETrue;
+
+ if ( RSat::EAlphaIdNull == iSendDtmfData.iAlphaId.iStatus )
+ {
+ LOG( NORMAL, "SENDDTMF: CSendDtmfHandler::NeedUiSession EAlphaIdNull" )
+ iNeedUiSession = EFalse;
+ }
+
+ // Notify Cover UI if it's supported
+ if ( iNeedUiSession && iUtils->CoverUiSupported() )
+ {
+ LOG( NORMAL,
+ "SENDDTMF: CSendDtmfHandler::NeedUiSession CoverUiSupported" )
+ TSatCommandData medEventData;
+ medEventData.iPCmdNumber = RSat::ESendDtmf;
+ medEventData.iAlphaId = iSendDtmfData.iAlphaId;
+ medEventData.iDuration.iNumOfUnits = KSatDefaultDuration;
+ medEventData.iDuration.iTimeUnit = RSat::ESeconds;
+ medEventData.iIconID = iSendDtmfData.iIconId;
+ TSatCommandPckg tPckg( medEventData );
+ iUtils->RaiseSatEvent( tPckg );
+ }
+
+ LOG2( NORMAL,
+ "SENDDTMF: CSendDtmfHandler::NeedUiSession exiting,iNeedUiSession: %d",
+ iNeedUiSession )
+ return iNeedUiSession;
+ }
+
+// -----------------------------------------------------------------------------
+// From class CSatCommandHandler.
+// Called when USAT API notifies that command.
+// -----------------------------------------------------------------------------
+//
+void CSendDtmfHandler::HandleCommand()
+ {
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::HandleCommand calling" )
+
+ iUtils->NotifyEvent( MSatUtils::ESendDtmfExecuting );
+
+ // Lower error granularity. This helps for mapping error cases
+ iUtils->MultiModeApi().LowerErrorGranularity();
+
+ // Pointer to converted DTMF string
+ TPtr ptr = iDtmfStringUcs2->Des();
+
+ iClientResponseReceived = EFalse;
+
+ // First, send DTMF string
+ iDtmfSender->SendToneString( ptr );
+
+ if ( iNeedUiSession )
+ {
+ TRAPD( regErr,
+ // Register to listen user cancel events:
+ // Cancel key event from dialog
+ iUtils->RegisterL( this, MSatUtils::ECommandCancelled );
+ // End key from dialog
+ iUtils->RegisterL( this, MSatUtils::ECancelledUsingEndKey );
+
+ // Then send notification to UI
+ // Register notification observer
+ iUtils->RegisterServiceRequestL(
+ ESatSProactiveNotification,
+ ESatSProactiveNotificationResponse,
+ this )
+ ); // TRAPD
+ LOG2( NORMAL,
+ "CSendDtmfHandler::HandleCommand regErr: %d", regErr )
+ if ( KErrNone != regErr )
+ {
+ iDtmfSender->Cancel();
+ // Raise error granularity back to extended errors
+ iUtils->MultiModeApi().RaiseErrorGranularity();
+
+ iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd;
+ iSendDtmfRsp.iInfoType = RSat::KMeProblem;
+ iSendDtmfRsp.iAdditionalInfo.Zero();
+ iSendDtmfRsp.iAdditionalInfo.Append( RSat::KNoSpecificMeProblem );
+ SendTerminalResponse();
+ }
+ else
+ {
+ TSatAlphaIdStatus alphaIdStatus;
+ if ( iSendDtmfData.iAlphaId.iStatus == RSat::EAlphaIdNotPresent )
+ {
+ LOG( SIMPLE,
+ "SENDDTMF: CSendDtmfHandler::HandleCommand EAlphaIdNotPresent" )
+ // If AlphaID is not provided, show DTMF string in note.
+ // Deliver empty text if DTMF string is bigger than it is
+ // capable to deliver to SAT UI.
+ alphaIdStatus = ESatAlphaIdNotProvided;
+ LOG2( NORMAL,
+ "SENDDTMF: CSendDtmfHandler::HandleCommand ptr.Length: %d",
+ ptr.Length() )
+ if ( RSat::KAlphaIdMaxSize >= ptr.Length() )
+ {
+ iNotificationData.iText = ptr;
+ }
+ else
+ {
+ iNotificationData.iText.Zero();
+ }
+ }
+ else if ( iSendDtmfData.iAlphaId.iStatus == RSat::EAlphaIdProvided )
+ {
+ LOG( SIMPLE,
+ "SENDDTMF: CSendDtmfHandler::HandleCommand EAlphaIdProvided" )
+ alphaIdStatus = ESatAlphaIdNotNull;
+ iNotificationData.iText = iSendDtmfData.iAlphaId.iAlphaId;
+ }
+ else
+ {
+ LOG( SIMPLE,
+ "SENDDTMF: CSendDtmfHandler::HandleCommand others" )
+ alphaIdStatus = ESatAlphaIdNull;
+ iNotificationData.iText.Zero();
+ }
+
+ // Build notification data
+ iNotificationData.iAlphaIdStatus = alphaIdStatus;
+ iNotificationData.iCommand = ESatSSendDtmfNotify;
+
+ // Has to be casted to TInt before casting to TSatIconQualifier,
+ // because GCC warns about the direct cast.
+ const struct TSatIconId iconId =
+ { iSendDtmfData.iIconId.iIdentifier,
+ static_cast<TSatIconQualifier>(
+ static_cast<TInt>( iSendDtmfData.iIconId.iQualifier ) ) };
+
+ iNotificationData.iIconId = iconId;
+
+ // Send notification
+ iUtils->SatUiHandler().UiSession()->SendCommand(
+ &iNotificationDataPckg,
+ &iNotificationRspPckg,
+ ESatSProactiveNotification );
+
+ // DTMF String sent, wait for completion
+ }
+ }
+
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::HandleCommand exiting" )
+ }
+
+// -----------------------------------------------------------------------------
+// From class CSatCommandHandler.
+// Called when UI launch fails.
+// -----------------------------------------------------------------------------
+//
+void CSendDtmfHandler::UiLaunchFailed()
+ {
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::UiLaunchFailed calling" )
+
+ iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd;
+ iSendDtmfRsp.iInfoType = RSat::KMeProblem;
+ iSendDtmfRsp.iAdditionalInfo.Append( RSat::KNoSpecificMeProblem );
+ iSendDtmfRsp.SetPCmdNumber( iSendDtmfData.PCmdNumber() );
+ SendTerminalResponse();
+
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::UiLaunchFailed exiting" )
+ }
+
+// -----------------------------------------------------------------------------
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+//lint -e{1403, 1769} Can not be initialized, harmless.
+CSendDtmfHandler::CSendDtmfHandler() :
+ CSatCommandHandler(),
+ iSendDtmfData(),
+ iSendDtmfPckg( iSendDtmfData ),
+ iSendDtmfRsp(),
+ iSendDtmfRspPckg( iSendDtmfRsp ),
+ iNotificationData(),
+ iNotificationDataPckg( iNotificationData ),
+ iNotificationRsp(),
+ iNotificationRspPckg( iNotificationRsp ),
+ // To be removed when icons are allowed in this command
+ iIconCommand( EFalse )
+ {
+ LOG( SIMPLE,
+ "SENDDTMF: CSendDtmfHandler::CSendDtmfHandler calling - exiting" )
+ }
+
+// -----------------------------------------------------------------------------
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CSendDtmfHandler::ConstructL()
+ {
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::ConstructL calling" )
+
+ // Register notification observer
+ iUtils->RegisterServiceRequestL(
+ ESatSProactiveNotification,
+ ESatSProactiveNotificationResponse,
+ this );
+
+ // DTMF Sender
+ iDtmfSender =
+ new ( ELeave ) CSatDtmfSender( *this, iUtils->MultiModeApi() );
+
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::ConstructL exiting" )
+ }
+
+
+// -----------------------------------------------------------------------------
+// Converts DTMF string from extended BCD to UCS2.
+// -----------------------------------------------------------------------------
+//
+TBool CSendDtmfHandler::ConvertDtmfStringToUcs2( TDes& aDtmfString )
+ {
+ LOG( SIMPLE,
+ "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 calling" )
+ aDtmfString.Zero();
+
+ const TInt bcdLength = iSendDtmfData.iDtmfString.Length();
+ TInt i( 0 );
+ TBool retVal( ETrue );
+ TBool continueLoop( ETrue );
+
+ for ( i = 0; i < bcdLength && continueLoop; i++ )
+ {
+ // each 16 bit DTMF character of SAT ETel API holds two nibbles,
+ // high byte always being 0
+ TChar twoBcd = iSendDtmfData.iDtmfString[i];
+
+ // low nibble yields first BCD in semi-octet representation
+ TChar firstBcd = twoBcd & KLowNibble;
+
+ // high nibble yields second BCD in semi-octet representation
+ TChar secondBcd = ( twoBcd & KHighNibble ) >> KBitsInNibble;
+
+ TChar destChar;
+ TBool endOfString;
+ TBool dtmfCharacter;
+
+ // convert first extended BCD character
+ ConvertDtmfCharacterToUcs2(
+ firstBcd, endOfString, dtmfCharacter, destChar );
+
+ if ( endOfString )
+ {
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 \
+ (End of string in first BCD)" )
+ retVal = ETrue; // completed string (F digit)
+ continueLoop = EFalse;
+ }
+ else if ( !dtmfCharacter )
+ {
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 \
+ (not dtmfCharacter in first BCD)" )
+ retVal = EFalse;
+ continueLoop = EFalse;
+ }
+ else
+ {
+ aDtmfString.Append( destChar );
+
+ // convert second extended BCD character
+ ConvertDtmfCharacterToUcs2(
+ secondBcd, endOfString, dtmfCharacter, destChar );
+
+ if ( endOfString )
+ {
+ LOG( SIMPLE,
+ "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 \
+ (End of string in second BCD)" )
+ retVal = ETrue; // completed string (F digit)
+ continueLoop = EFalse;
+ }
+ else if ( !dtmfCharacter )
+ {
+ LOG( SIMPLE,
+ "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 \
+ (not dtmfCharacter in second BCD)" )
+ retVal = EFalse;
+ continueLoop = EFalse;
+ }
+ else
+ {
+ LOG( SIMPLE,
+ "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 \
+ others" )
+ aDtmfString.Append( destChar );
+ }
+ }
+ }
+ LOG2( NORMAL,
+ "CSendDtmfHandler::ConvertDtmfStringToUcs2 i: %d", i )
+ LOG2( SIMPLE,
+ "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 exiting,\
+ retVal: %d", retVal )
+ return retVal; // completed string (all bytes converted)
+ }
+
+// -----------------------------------------------------------------------------
+// Converts character from extended BCD to UCS2.
+// -----------------------------------------------------------------------------
+//
+void CSendDtmfHandler::ConvertDtmfCharacterToUcs2(
+ const TChar& aExtBcd,
+ TBool& aEndOfString,
+ TBool& aDtmfCharacter,
+ TChar& aUcs2Char ) const
+ {
+ LOG( SIMPLE,
+ "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 calling" )
+
+ aEndOfString = EFalse;
+ aDtmfCharacter = ETrue;
+
+ switch ( aExtBcd )
+ {
+ case KBcdZero:
+ case KBcdOne:
+ case KBcdTwo:
+ case KBcdThree:
+ case KBcdFour:
+ case KBcdFive:
+ case KBcdSix:
+ case KBcdSeven:
+ case KBcdEight:
+ case KBcdNine:
+ {
+ LOG( SIMPLE,
+ "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 Digit" )
+ aUcs2Char = KUcs2Zero + aExtBcd;
+ break;
+ }
+
+ case KBcdStar:
+ {
+ LOG( SIMPLE,
+ "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 KBcdStar" )
+ aUcs2Char = KUcs2Star;
+ break;
+ }
+
+ case KBcdHash:
+ {
+ LOG( SIMPLE,
+ "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 KBcdHash" )
+ aUcs2Char = KUcs2Hash;
+ break;
+ }
+
+ case KBcdPause:
+ {
+ LOG( SIMPLE,
+ "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 KBcdPause" )
+ aUcs2Char = KUcs2Pause;
+ break;
+ }
+
+ case KBcdEnd:
+ {
+ LOG( SIMPLE,
+ "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 KBcdEnd" )
+ aEndOfString = ETrue;
+ break;
+ }
+
+ case KBcdWild:
+ case KBcdExpansion:
+ default:
+ {
+ LOG( SIMPLE,
+ "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 unknown" )
+ aDtmfCharacter = EFalse;
+ }
+ }
+
+ LOG( SIMPLE,
+ "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 exiting" )
+ }
+
+// -----------------------------------------------------------------------------
+// Handles the result of DTMF sending and sends terminal response.
+// -----------------------------------------------------------------------------
+//
+void CSendDtmfHandler::HandleResult()
+ {
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::HandleResult calling" )
+
+ // If UI is needed, send DTMF Done event to close any progress bar
+ if ( iNeedUiSession )
+ {
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::HandleResult NeedUiSession" )
+ // To prevent client traffic jamming.
+ // Send UI event only when client response is received.
+ if ( !iClientResponseReceived && !iWait.IsStarted() )
+ {
+ LOG( SIMPLE,
+ "SENDDTMF: CSendDtmfHandler::HandleResult start iwait" )
+ iWait.Start();
+ }
+ // No need to send command result since this only removes any
+ // existing wait notes...
+ iUtils->NotifyUiEvent( ESatSDtmfEndEvent, ESatEventNone, KErrNone );
+ }
+
+ // Raise error granularity back to extended errors
+ iUtils->MultiModeApi().RaiseErrorGranularity();
+
+#ifdef __WINS__
+ if ( KErrTimedOut == iDtmfResult )
+ {
+ iDtmfResult = KErrNone;
+ }
+#endif
+
+ LOG2( NORMAL,
+ "SENDDTMF: CSendDtmfHandler::HandleResult Send DTMF result: %i",
+ iDtmfResult )
+
+ switch ( iDtmfResult )
+ {
+ case KErrNone:
+ {
+ // No errors in DTMF sending. But cases like user termination and
+ // icons are handled here.
+ if ( iNotificationRsp.iSessionTerminatedByUser )
+ {
+ LOG( DETAILED,
+ "SENDDTMF: CSendDtmfHandler::HandleResult session terminated \
+ by user" )
+ iSendDtmfRsp.iGeneralResult = RSat::KPSessionTerminatedByUser;
+ iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo;
+ iSendDtmfRsp.iAdditionalInfo.Zero();
+ }
+ else
+ {
+ iSendDtmfRsp.iGeneralResult = RSat::KSuccess;
+ iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo;
+ iSendDtmfRsp.iAdditionalInfo.Zero();
+
+ // If command had icon data and was done succesfully,
+ // report that icon was not shown.
+ // To be removed and correct handling (i.e. ClientResponse to
+ // notification is received) for general result
+ // KSuccessRequestedIconNotDisplayed must be added when icons
+ // are allowed in this command.
+ if ( iIconCommand )
+ {
+ LOG( DETAILED,
+ "SENDDTMF: CSendDtmfHandler::HandleResult iIconCommand \
+ true" )
+ iSendDtmfRsp.iGeneralResult =
+ RSat::KSuccessRequestedIconNotDisplayed;
+ }
+ }
+
+ break;
+ }
+ case KErrCancel:
+ case KErrEtelNoCarrier:
+ {
+ // Problems in communicating with receiving device are handled here
+ // e.g. call was unexpectedly dropped.
+ iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd;
+ iSendDtmfRsp.iInfoType = RSat::KMeProblem;
+ iSendDtmfRsp.iAdditionalInfo.Zero();
+ iSendDtmfRsp.iAdditionalInfo.Append( RSat::KNoSpecificMeProblem );
+ break;
+ }
+ case KErrArgument:
+ {
+ // Maximum length of DTMF string reached.
+ LOG( DETAILED,
+ "SENDDTMF: CSendDtmfHandler Over maximum DTMF length" )
+ iSendDtmfRsp.iGeneralResult = RSat::KErrorRequiredValuesMissing;
+ iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo;
+ iSendDtmfRsp.iAdditionalInfo.Zero();
+ break;
+ }
+ default:
+ {
+ // By default for other errors.
+ iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd;
+ iSendDtmfRsp.iInfoType = RSat::KMeProblem;
+ iSendDtmfRsp.iAdditionalInfo.Zero();
+ iSendDtmfRsp.iAdditionalInfo.Append( RSat::KNotInSpeechCall );
+ break;
+ }
+ }
+
+ // Cancel DTMF sending if it is running.
+ iDtmfSender->Cancel();
+ SendTerminalResponse();
+
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::HandleResult exiting" )
+ }
+
+// -----------------------------------------------------------------------------
+// Sends terminal response. Makes sure that terminal response
+// is not send more that once / command.
+// -----------------------------------------------------------------------------
+//
+void CSendDtmfHandler::SendTerminalResponse()
+ {
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::SendTerminalResponse calling" )
+
+ if ( !iTerminalRespSent )
+ {
+ LOG( SIMPLE,
+ "CSendDtmfHandler::SendTerminalResponse iTerminalRespSent false" )
+ iTerminalRespSent = ETrue;
+ TerminalRsp( RSat::ESendDtmf, iSendDtmfRspPckg );
+ }
+
+ LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::SendTerminalResponse exiting" )
+ }
+