--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cbsatplugin/atmisccmdplugin/src/cusdcommandhandler.cpp Tue Apr 27 16:49:44 2010 +0300
@@ -0,0 +1,460 @@
+/* Copyright (c) 2010 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 :
+ *
+ */
+#include "cusdcommandhandler.h"
+
+#include <exterror.h>
+
+#include "atmisccmdpluginconsts.h"
+#include "cusdreadwriteimp.h"
+#include "debug.h"
+
+const TUint8 KPhCltUssdCarriageReturn = 0x0d;
+const TUint8 KPhCltUssdDcsNotSet = 0x00; // not set
+
+const TUint8 KQuarterShift( 2 );
+const TUint8 KHighNibbleShift( 4 );
+const TUint8 KDcsCharacterSet7Bit( 0x00 );
+const TUint8 KDcsCharacterSet8Bit( 0x01 );
+const TUint8 KDcsCharacterSet16Bit( 0x02 );
+const TUint8 KDcsCharacterSet7Bit2( 0x00 );
+const TUint8 KDcsCharacterSet16Bit2( 0x01 );
+
+CCUSDCommandHandler* CCUSDCommandHandler::NewL(MATMiscCmdPlugin* aCallback, TAtCommandParser& aATCmdParser, RMobilePhone& aPhone)
+ {
+ TRACE_FUNC_ENTRY
+ CCUSDCommandHandler* self = new (ELeave) CCUSDCommandHandler(aCallback, aATCmdParser, aPhone);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ TRACE_FUNC_EXIT
+ return self;
+ }
+
+CCUSDCommandHandler::CCUSDCommandHandler(MATMiscCmdPlugin* aCallback, TAtCommandParser& aATCmdParser, RMobilePhone& aPhone) :
+ CATCmdAsyncBase(aCallback, aATCmdParser, aPhone)
+ {
+ TRACE_FUNC_ENTRY
+ iSendAttributes.iDcs = KPhCltUssdDcsNotSet;
+ iSendAttributes.iType = RMobileUssdMessaging::EUssdMORequest;
+ iSendAttributes.iFlags = RMobileUssdMessaging::KUssdMessageType | RMobileUssdMessaging::KUssdMessageDcs | RMobileUssdMessaging::KUssdDataFormat;
+ TRACE_FUNC_EXIT
+ }
+
+void CCUSDCommandHandler::ConstructL()
+ {
+ TRACE_FUNC_ENTRY
+ User::LeaveIfError(iUssdMessaging.Open(iPhone));
+
+ iUSSDSender = CCUSSDSendMessageImpl::NewL(this, iUssdMessaging);
+ iUSSDReader = CCUSSDReadMessageImpl::NewL(this, iUssdMessaging);
+
+ //start a read session for network based ussd requests
+ User::LeaveIfError(iUSSDReader->ReadUSSDMessage(iReceivedData, iReceiveAttributes));
+ TRACE_FUNC_EXIT
+ }
+
+CCUSDCommandHandler::~CCUSDCommandHandler()
+ {
+ TRACE_FUNC_ENTRY
+ delete iUSSDSender;
+ delete iUSSDReader;
+
+ iReply.Close();
+ iUssdMessaging.Close();
+ TRACE_FUNC_EXIT
+ }
+
+void CCUSDCommandHandler::DoCancel()
+ {
+ TRACE_FUNC_ENTRY
+ // This would never get called as the AO is never activated
+ TRACE_FUNC_EXIT
+ }
+
+void CCUSDCommandHandler::HandleCommand( const TDesC8& aCmd,
+ RBuf8& /*aReply*/,
+ TBool /*aReplyNeeded*/ )
+ {
+ TRACE_FUNC_ENTRY
+ TAtCommandParser::TCommandHandlerType cmdHandlerType = iATCmdParser.CommandHandlerType();
+
+ switch (cmdHandlerType)
+ {
+ case (TAtCommandParser::ECmdHandlerTypeTest):
+ {
+ iReply.Create(KDefaultCmdBufLength);
+ iReply.Append(KCRLF);
+ iReply.Append(KCUSDSupportedCmdsList);
+ iCallback->CreateReplyAndComplete( EReplyTypeOther, iReply );
+ break;
+ }
+ case (TAtCommandParser::ECmdHandlerTypeRead):
+ {
+ iReply.Create(KDefaultCmdBufLength);
+ iReply.Append(KCRLF);
+ iReply.Append(KAtCUSD);
+ iReply.AppendNum(iDisplayRetMessage);
+ iReply.Append(KCRLF);
+
+ iCallback->CreateReplyAndComplete( EReplyTypeOther, iReply );
+ break;
+ }
+ case (TAtCommandParser::ECmdHandlerTypeSet):
+ {
+ if(ParseCUSDCmd(aCmd) == KErrNone)
+ {
+ if(iUSSDCommand.Length() == 0)
+ {
+ Trace(KDebugPrintD, "No USSD command: ", iUSSDCommand.Length());
+
+ // the USSD command is not set then this is a set
+ iReply.Create(KDefaultCmdBufLength);
+ iReply.Append(KCRLF);
+ iReply.Append(KAtCUSD);
+ iReply.AppendNum(iDisplayRetMessage);
+ iReply.Append(KCRLF);
+
+ iCallback->CreateReplyAndComplete( EReplyTypeOther, iReply );
+ }
+ else
+ {
+ if(iUSSDSender->HandleSendUSSDCmd(iUSSDCommand, iSendAttributes) == KErrNone)
+ {
+ iSendCommandSent = ETrue;
+ }
+ else
+ {
+ iCallback->CreateReplyAndComplete(EReplyTypeError);
+ }
+ }
+ }
+ else
+ {
+ iCallback->CreateReplyAndComplete(EReplyTypeError);
+ }
+
+ break;
+ }
+ default:
+ {
+ iCallback->CreateReplyAndComplete(EReplyTypeError);
+ break;
+ }
+ }
+ TRACE_FUNC_EXIT
+ }
+
+void CCUSDCommandHandler::RunL()
+ {
+ TRACE_FUNC_ENTRY
+ // This would never get called as the AO is never activated
+ TRACE_FUNC_EXIT
+ }
+
+
+void CCUSDCommandHandler::HandleCommandCancel()
+ {
+ TRACE_FUNC_ENTRY
+ iUSSDSender->Cancel();
+ TRACE_FUNC_EXIT
+ }
+
+TInt CCUSDCommandHandler::ParseCUSDCmd(const TDesC8& aCmd)
+ {
+ TRACE_FUNC_ENTRY
+
+ iReply.Create(KDefaultCmdBufLength);
+ TBool tempRetMessage = EFalse;
+ TInt ret = iATCmdParser.NextIntParam(tempRetMessage);
+
+ if(ret == KErrNone)
+ {
+ if(tempRetMessage < 0 || tempRetMessage > 2)
+ {
+ Trace(KDebugPrintD, "Display mode invalid: ", tempRetMessage);
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+ else
+ {
+ iDisplayRetMessage = tempRetMessage;
+ }
+ }
+
+ // now parse the USSD command
+ TPtrC8 command = iATCmdParser.NextTextParam(ret);
+
+ if (ret == KErrNone)
+ {
+ if(iUSSDCommand.Create(command.Length()) != KErrNone)
+ {
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+
+ if(Pack(command, iUSSDCommand) < 0)
+ {
+ Trace(KDebugPrintS, "Pack() returned error, command: ", &command);
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+ }
+
+ TInt tempDcs = -1;
+ ret = iATCmdParser.NextIntParam(tempDcs);
+
+ if(ret == KErrNone)
+ {
+ if(!IsDcsValid(tempDcs))
+ {
+ Trace(KDebugPrintD, "Invalid coding standard: ", tempDcs);
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+ else
+ {
+ iSendAttributes.iDcs = tempDcs;
+ }
+ }
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+void CCUSDCommandHandler::HandleSendMessageComplete(TInt aResult)
+ {
+ TRACE_FUNC_ENTRY
+ if(aResult == KErrNone)
+ {
+ iReply.Create(KDefaultCmdBufLength);
+ iReply.Append(KCRLF);
+ iReply.Append(KAtCUSD);
+ iReply.Append(KCRLF);
+ iCallback->CreateReplyAndComplete( EReplyTypeOther, iReply );
+ }
+ else
+ {
+ iCallback->CreateReplyAndComplete(EReplyTypeError);
+ }
+
+ iSendCommandSent = EFalse;
+ iUSSDCommand.Close();
+ TRACE_FUNC_EXIT
+ }
+
+void CCUSDCommandHandler::HandleReadMessageComplete(TInt aResult)
+ {
+ TRACE_FUNC_ENTRY
+ if(iDisplayRetMessage)
+ {
+ FormatUSSDReceivedData();
+
+ if(iSendCommandSent)
+ {
+ iCallback->CreateReplyAndComplete( EReplyTypeOther, iReply );
+ }
+ else
+ {
+ iCallback->HandleUnsolicitedRequest(iReply);
+ }
+ }
+ // re-issue the read request
+ iUSSDReader->ReadUSSDMessage(iReceivedData, iReceiveAttributes);
+ TRACE_FUNC_EXIT
+ }
+
+TInt CCUSDCommandHandler::Pack(const TDesC8& aIn, TDes8& aOut)
+ {
+ TRACE_FUNC_ENTRY
+ TInt startBit = 0;
+
+ // Ensure we've got the right length
+ TInt packedOctetsRequired = PackedOctetsRequired( aIn.Length() );
+ if ( packedOctetsRequired > ( aOut.MaxLength() - aOut.Length() ) )
+ {
+ Trace(KDebugPrintD, "packedOctetsRequired: ", packedOctetsRequired);
+ TRACE_FUNC_EXIT
+ return KErrOverflow;
+ }
+
+ // Do the conversion
+ TInt elementSizeInBits = ElementSizeInBits(TSmsDataCodingScheme::ESmsAlphabet7Bit);
+ if ( elementSizeInBits == 8 ) // 8 bit data
+ {
+ // Straight copy here
+ aOut.Append( aIn );
+ }
+ else if ( elementSizeInBits == 7 ) // Need packing to 7-bit
+ {
+ // Get raw pointers and do packing
+ TUint8* outPtr = ( TUint8* )aOut.Ptr() + aOut.Length();
+ const TUint8* inPtr = aIn.Ptr();
+
+ outPtr[0] = 0;
+ for ( TInt i = 0; i < aIn.Length() ; ++i )
+ {
+ TUint8 to = inPtr[i];
+ *outPtr |= ( to << startBit );
+ if ( startBit )
+ {
+ ++outPtr;
+ *outPtr = ( TUint8 ) ( to >> ( 8 - startBit ) );
+ }
+ startBit = ( startBit + 7 )%8; // roll 0,1,2,3,4,5,6,7,0,1,2,...
+
+ if ( i == aIn.Length() - 1 ) // if this is the last time
+ {
+ if ( ( to == KPhCltUssdCarriageReturn && startBit == 0 ) ||
+ startBit == 1 )
+ {
+ //We have to add one CR more
+ *outPtr |= ( KPhCltUssdCarriageReturn << startBit );
+ if ( startBit )
+ {
+ ++outPtr;
+ *outPtr = ( TUint8 ) ( KPhCltUssdCarriageReturn >> ( 8 - startBit ) );
+ }
+ else
+ {
+ ++packedOctetsRequired;
+ }
+ startBit = ( startBit + 7 )%8;
+ }
+ }
+ }
+ // Increment the length for the packed data
+ aOut.SetLength( aOut.Length() + packedOctetsRequired );
+ }
+
+ // Return number of bytes used
+ TRACE_FUNC_EXIT
+ return packedOctetsRequired;
+ }
+
+ TInt CCUSDCommandHandler::PackedOctetsRequired( TInt aNumUDUnits ) const
+ {
+ TRACE_FUNC_ENTRY
+ TInt startBit = 0;
+
+ TInt octetsRequired = 0;
+ TInt elementSizeInBits = ElementSizeInBits(TSmsDataCodingScheme::ESmsAlphabet7Bit);
+ if ( elementSizeInBits == 8 )
+ {
+ octetsRequired=aNumUDUnits;
+ }
+ else
+ {
+ octetsRequired = ( startBit + aNumUDUnits*elementSizeInBits + 7 )/8; // Rounds up
+ }
+ TRACE_FUNC_EXIT
+ return octetsRequired;
+ }
+
+ TBool CCUSDCommandHandler::IsDcsValid( const TUint8 aDcs ) const
+ {
+ TRACE_FUNC_ENTRY
+ TBool isDcsValid( EFalse );
+ // 76543210
+ TUint8 codingGroup = ( aDcs & 0xF0 ) >> KHighNibbleShift; // bits XXXX____
+ TUint8 characterSet = ( aDcs & 0x0C ) >> KQuarterShift; // bits ____XX__
+ TUint8 lowQuartet = ( aDcs & 0x0F ); // bits ____XXXX
+
+ switch ( codingGroup )
+ {
+ case 0x00:
+ case 0x02:
+ case 0x03:
+ case 0x0F:
+ {
+ isDcsValid = ETrue;
+ break;
+ }
+
+ case 0x01:
+ {
+ if ( ( KDcsCharacterSet7Bit2 == lowQuartet ) ||
+ ( KDcsCharacterSet16Bit2 == lowQuartet ) )
+ {
+ isDcsValid = ETrue;
+ }
+ break;
+ }
+
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0x09:
+ {
+ if ( ( KDcsCharacterSet7Bit == characterSet ) ||
+ ( KDcsCharacterSet8Bit == characterSet ) ||
+ ( KDcsCharacterSet16Bit == characterSet ) )
+ {
+ isDcsValid = ETrue;
+ }
+ break;
+ }
+ }
+ TRACE_FUNC_EXIT
+ return isDcsValid;
+ }
+
+TInt CCUSDCommandHandler::ElementSizeInBits(TSmsDataCodingScheme::TSmsAlphabet aAlphabet) const
+ {
+ TRACE_FUNC_ENTRY
+ TInt ret;
+ switch ( aAlphabet )
+ {
+ case TSmsDataCodingScheme::ESmsAlphabet7Bit:
+ {
+ ret = 7;
+ break;
+ }
+ case TSmsDataCodingScheme::ESmsAlphabet8Bit:
+ case TSmsDataCodingScheme::ESmsAlphabetUCS2:
+ {
+ ret = 8;
+ break;
+ }
+ default:
+ {
+ ret = KErrGsmSMSDataCodingSchemeNotSupported;
+ }
+ }
+ TRACE_FUNC_EXIT
+ return ret;
+ }
+
+void CCUSDCommandHandler::FormatUSSDReceivedData()
+ {
+ TRACE_FUNC_ENTRY
+ iReply.Create(KDefaultCmdBufLength);
+
+ iReply.Append(KCRLF);
+ iReply.Append(KAtCUSD);
+ iReply.AppendNum(iDisplayRetMessage);
+ iReply.Append(',');
+ iReply.Append('"');
+
+ TInt length = iReceivedData.Length();
+ for(TInt i = 0; i < length; ++i)
+ {
+ iReply.AppendNum(iReceivedData[i], EHex);
+ }
+ iReply.Append('"');
+ iReply.Append(',');
+
+ iReply.AppendNum(iReceiveAttributes.iDcs);
+ iReply.Append(KCRLF);
+ TRACE_FUNC_EXIT
+ }