diff -r 000000000000 -r ff3b6d0fd310 satengine/SatServer/Commands/SendDtmfCmd/src/CSendDtmfHandler.cpp --- /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( + static_cast( 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" ) + } +