--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cbsatplugin/atmisccmdplugin/src/atmisccmdplugin.cpp Tue Apr 27 16:49:44 2010 +0300
@@ -0,0 +1,529 @@
+/*
+* 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: Main handler for incoming requests
+*
+*/
+
+#include "atmisccmdplugin.h"
+
+#include "clckcommandhandler.h"
+#include "cpwdcommandhandler.h"
+#include "cpincommandhandler.h"
+#include "cusdcommandhandler.h"
+#include "cnumcommandhandler.h"
+#include "cfuncommandhandler.h"
+#include "cbccommandhandler.h"
+
+#include "atmisccmdpluginconsts.h"
+#include "debug.h"
+
+#include <EXTERROR.H> // Additional RMobilePhone error code
+
+
+// +CME error code
+_LIT8(KCMEIncorrectPassword, "+CME: 16\r\n"); // Incorrect password.\r\n
+_LIT8(KCMEPUKRequired, "+CME: 12\r\n"); // PUK required.\r\n
+_LIT8(KCMENotAllowed, "+CME: 3\r\n"); // Operation not allowed.\r\n
+_LIT8(KCMEPhoneError, "+CME: 0\r\n"); // Phone failure.\r\n
+_LIT8(KCMEPhoneUnknown, "+CME: 100\r\n"); // unknown error
+
+const TInt KErrorReplyLength = 9; // CR+LF+"ERROR"+CR+LF
+
+CATMiscCmdPlugin* CATMiscCmdPlugin::NewL()
+ {
+ CATMiscCmdPlugin* self = new (ELeave) CATMiscCmdPlugin();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CATMiscCmdPlugin::~CATMiscCmdPlugin()
+ {
+ iReplyBuffer.Close();
+
+ delete iCLCKHandler;
+ delete iCPWDHandler;
+ delete iCPINHandler;
+ delete iCUSDHandler;
+ delete iCNUMHandler;
+ delete iCFUNHandler;
+ delete iCBCHandler;
+
+ iPhone.Close();
+ iTelServer.Close();
+ }
+
+CATMiscCmdPlugin::CATMiscCmdPlugin() :
+ CATExtPluginBase()
+ {
+ }
+
+void CATMiscCmdPlugin::ConstructL()
+ {
+ TRACE_FUNC_ENTRY
+ ConnectToEtelL(iTelServer, iPhone);
+
+ iCLCKHandler = CCLCKCommandHandler::NewL(this, iCommandParser, iPhone);
+ iCPWDHandler = CCPWDCommandHandler::NewL(this, iCommandParser, iPhone);
+ iCUSDHandler = CCUSDCommandHandler::NewL(this, iCommandParser, iPhone);
+ iCPINHandler = CCPINCommandHandler::NewL(this, iCommandParser, iPhone);
+ iCNUMHandler = CCNUMCommandHandler::NewL(this, iCommandParser, iPhone, iTelServer);
+ iCFUNHandler = CCFUNCommandHandler::NewL(this, iCommandParser, iPhone);
+ iCBCHandler = CCBCCommandHandler::NewL(this, iCommandParser, iPhone);
+ TRACE_FUNC_EXIT
+ }
+
+/**
+ * @see CATExtPluginBase::ReportConnectionName
+ */
+void CATMiscCmdPlugin::ReportConnectionName( const TDesC8& /*aName*/ )
+ {
+ TRACE_FUNC_ENTRY
+ TRACE_FUNC_EXIT
+ }
+
+/**
+ * @see CATExtPluginBase::IsCommandSupported
+ */
+TBool CATMiscCmdPlugin::IsCommandSupported( const TDesC8& aCmd )
+ {
+ TRACE_FUNC_ENTRY
+ iHcCmd = NULL;
+ iHcReply = NULL;
+ iCurrentHandler = NULL;
+ TBool supported = ETrue;
+
+ Trace(KDebugPrintS, "aCmd: ", &aCmd);
+
+ iCommandParser.ParseAtCommand(aCmd);
+
+ Trace(KDebugPrintD, "Command: ", iCommandParser.Command());
+ // TODO: check if the type is supported?
+ // iCommandParser.CommandHandlerType() != TAtCommandParser::ECmdHandlerTypeUndefined
+ switch (iCommandParser.Command())
+ {
+ case (TAtCommandParser::ECmdAtClck):
+ {
+ iCurrentHandler = iCLCKHandler;
+ break;
+ }
+ case (TAtCommandParser::ECmdAtCpwd):
+ {
+ iCurrentHandler = iCPWDHandler;
+ break;
+ }
+ case (TAtCommandParser::ECmdAtCpin):
+ {
+ iCurrentHandler = iCPINHandler;
+ break;
+ }
+ case (TAtCommandParser::ECmdAtCusd):
+ {
+ iCurrentHandler = iCUSDHandler;
+ break;
+ }
+ case (TAtCommandParser::ECmdAtCnum):
+ {
+ iCurrentHandler = iCNUMHandler;
+ break;
+ }
+ case (TAtCommandParser::ECmdAtCfun):
+ {
+ iCurrentHandler = iCFUNHandler;
+ break;
+ }
+ case (TAtCommandParser::ECmdAtCbc):
+ {
+ iCurrentHandler = iCBCHandler;
+ break;
+ }
+ case (TAtCommandParser::EUnknown):
+ default:
+ {
+ supported = EFalse;
+ break;
+ }
+ }
+ Trace(KDebugPrintD, "supported: ", supported);
+ TRACE_FUNC_EXIT
+ return supported;
+ }
+
+/**
+ * @see CATExtPluginBase::HandleCommand
+ */
+void CATMiscCmdPlugin::HandleCommand( const TDesC8& aCmd,
+ RBuf8& aReply,
+ TBool aReplyNeeded )
+ {
+ TRACE_FUNC_ENTRY
+
+ if (iCurrentHandler != NULL)
+ {
+ iHcCmd = &aCmd;
+ iHcReply = &aReply;
+ iCurrentHandler->HandleCommand( aCmd, aReply, aReplyNeeded );
+ }
+ TRACE_FUNC_EXIT
+ }
+
+/**
+ * @see CATExtPluginBase::HandleCommandCancel
+ */
+void CATMiscCmdPlugin::HandleCommandCancel()
+ {
+ TRACE_FUNC_ENTRY
+ if (iCurrentHandler != NULL)
+ {
+ iCurrentHandler->HandleCommandCancel();
+ }
+ TRACE_FUNC_EXIT
+ }
+
+/**
+ * @see CATExtPluginBase::NextReplyPartLength
+ */
+TInt CATMiscCmdPlugin::NextReplyPartLength()
+ {
+ TRACE_FUNC_ENTRY
+ TInt length = iReplyBuffer.Length();
+ if ( length >= KDefaultCmdBufLength )
+ {
+ length = KDefaultCmdBufLength;
+ }
+ TRACE_FUNC_EXIT
+ return length;
+ }
+
+/**
+ * @see CATExtPluginBase::GetNextPartOfReply
+ */
+TInt CATMiscCmdPlugin::GetNextPartOfReply( RBuf8& aNextReply )
+ {
+ TRACE_FUNC_ENTRY
+ TInt retVal = CreatePartOfReply( aNextReply );
+ TRACE_FUNC_EXIT
+ return retVal;
+ }
+
+/**
+ * @see CATExtPluginBase::ReceiveUnsolicitedResult
+ */
+void CATMiscCmdPlugin::ReceiveUnsolicitedResult()
+ {
+ TRACE_FUNC_ENTRY
+ TRACE_FUNC_EXIT
+ }
+
+/**
+ * @see CATExtPluginBase::ReceiveUnsolicitedResultCancel
+ */
+void CATMiscCmdPlugin::ReceiveUnsolicitedResultCancel()
+ {
+ TRACE_FUNC_ENTRY
+ TRACE_FUNC_EXIT
+ }
+
+/**
+ * @see CATExtPluginBase::ReportNvramStatusChange
+ */
+void CATMiscCmdPlugin::ReportNvramStatusChange( const TDesC8& /*aNvram*/ )
+ {
+ TRACE_FUNC_ENTRY
+ TRACE_FUNC_EXIT
+ }
+
+/**
+ * @see CATExtPluginBase::ReportExternalHandleCommandError
+ */
+void CATMiscCmdPlugin::ReportExternalHandleCommandError()
+ {
+ TRACE_FUNC_ENTRY
+ TRACE_FUNC_EXIT
+ }
+
+/**
+ * Creates part of reply from the global reply buffer to the destination
+ * buffer. Used with APIs which need the next part of reply in multipart
+ * reply requests.
+ *
+ * @param aBuffer Destination buffer; the next part of reply is stored to
+ * this buffer.
+ * @return None
+ */
+TInt CATMiscCmdPlugin::CreatePartOfReply( RBuf8& aBuffer )
+ {
+ TRACE_FUNC_ENTRY
+ TInt ret = KErrNone;
+ TInt partLength;
+ if ( iReplyBuffer.Length() <= 0 )
+ {
+ ret = KErrGeneral;
+ }
+ else
+ {
+ partLength = NextReplyPartLength();
+ if ( iReplyBuffer.Length() < partLength )
+ {
+ ret = KErrNotFound;
+ }
+ }
+ Trace(KDebugPrintD, "ret: ", ret);
+ if (ret == KErrNone)
+ {
+ aBuffer.Create( iReplyBuffer, partLength );
+ iReplyBuffer.Delete( 0, partLength );
+ if ( iReplyBuffer.Length() == 0 )
+ {
+ iReplyBuffer.Close();
+ }
+ }
+
+ TRACE_FUNC_EXIT
+ return ret;
+ }
+
+/**
+ * @see MATMiscCmdPlugin::CreateReplyAndComplete
+ */
+TInt CATMiscCmdPlugin::CreateReplyAndComplete( TATExtensionReplyType aReplyType,
+ const TDesC8& aSrcBuffer,
+ TInt aError )
+ {
+ TRACE_FUNC_ENTRY
+ iReplyBuffer.Close();
+ Trace(KDebugPrintD, "aError: ", aError);
+ if ( aError != KErrNone )
+ {
+ HandleCommandCompleted( aError, EReplyTypeUndefined );
+ iHcCmd = NULL;
+ iHcReply = NULL;
+ iCurrentHandler = NULL;
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+ Trace(KDebugPrintS, "iHcReply: ", &iHcReply);
+ if (iHcReply == NULL)
+ {
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+
+ Trace(KDebugPrintD, "iQuietMode: ", iQuietMode);
+ if ( iQuietMode )
+ {
+ iReplyBuffer.Create( KNullDesC8 );
+ }
+ else
+ {
+ iReplyBuffer.Create( aSrcBuffer );
+ }
+
+ Trace(KDebugPrintD, "aReplyType: ", aReplyType);
+ switch ( aReplyType )
+ {
+ case EReplyTypeOther:
+ break;
+ case EReplyTypeOk:
+ CreateOkOrErrorReply( iReplyBuffer, ETrue );
+ break;
+ case EReplyTypeError:
+ CreateOkOrErrorReply( iReplyBuffer, EFalse );
+ break;
+ default:
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+ CreatePartOfReply( *iHcReply );
+ HandleCommandCompleted( KErrNone, aReplyType );
+ iHcCmd = NULL;
+ iHcReply = NULL;
+ iCurrentHandler = NULL;
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+/**
+ * @see MATMiscCmdPlugin::CreateOkOrErrorReply
+ */
+TInt CATMiscCmdPlugin::CreateOkOrErrorReply( RBuf8& aReplyBuffer,
+ TBool aOkReply )
+ {
+ TRACE_FUNC_ENTRY
+ _LIT8( KErrorReplyVerbose, "ERROR" );
+ _LIT8( KOkReplyVerbose, "OK" );
+ _LIT8( KErrorReplyNumeric, "4" );
+ _LIT8( KOkReplyNumeric, "0" );
+ TBuf8<KErrorReplyLength> replyBuffer;
+ if ( iVerboseMode )
+ {
+ replyBuffer.Append( iCarriageReturn );
+ replyBuffer.Append( iLineFeed );
+ if ( aOkReply )
+ {
+ replyBuffer.Append( KOkReplyVerbose );
+ }
+ else
+ {
+ replyBuffer.Append( KErrorReplyVerbose );
+ }
+ replyBuffer.Append( iCarriageReturn );
+ replyBuffer.Append( iLineFeed );
+ }
+ else
+ {
+ if ( aOkReply )
+ {
+ replyBuffer.Append( KOkReplyNumeric );
+ }
+ else
+ {
+ replyBuffer.Append( KErrorReplyNumeric );
+ }
+ replyBuffer.Append( iCarriageReturn );
+ }
+
+ aReplyBuffer.ReAlloc(aReplyBuffer.Length() + replyBuffer.Length());
+ aReplyBuffer.Append( replyBuffer );
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+/**
+ * @see MATMiscCmdPlugin::GetCharacterValue
+ */
+TInt CATMiscCmdPlugin::GetCharacterValue( TCharacterTypes aCharType,
+ TChar& aChar )
+ {
+ TRACE_FUNC_ENTRY
+ TInt retVal = KErrNone;
+ switch ( aCharType )
+ {
+ case ECharTypeCR:
+ aChar = iCarriageReturn;
+ break;
+ case ECharTypeLF:
+ aChar = iLineFeed;
+ break;
+ case ECharTypeBS:
+ aChar = iBackspace;
+ break;
+ default:
+ retVal = KErrNotFound;
+ break;
+ }
+ TRACE_FUNC_EXIT
+ return retVal;
+ }
+
+/**
+ * @see MATMiscCmdPlugin::GetModeValue
+ */
+TInt CATMiscCmdPlugin::GetModeValue( TModeTypes aModeType, TBool& aMode )
+ {
+ TRACE_FUNC_ENTRY
+ TInt retVal = KErrNone;
+ switch ( aModeType )
+ {
+ case EModeTypeQuiet:
+ aMode = iQuietMode;
+ break;
+ case EModeTypeVerbose:
+ aMode = iVerboseMode;
+ break;
+ default:
+ retVal = KErrNotFound;
+ break;
+ }
+ TRACE_FUNC_EXIT
+ return retVal;
+ }
+
+void CATMiscCmdPlugin::CreateCMEReplyAndComplete(TInt aError)
+ {
+ TRACE_FUNC_ENTRY
+
+ // TODO should return CME error according to CME state (and quiet mode?)
+ RBuf8 response;
+ response.Create(KDefaultCmdBufLength);
+
+ // log error code
+ response.AppendNum(aError);
+ Trace(KDebugPrintD, "complete with error ", &response);
+
+ // return error code to AT client
+ response.Zero(); // reuse RBuf
+ response.Append(KCRLF);
+ switch(aError)
+ {
+ case KErrGsm0707IncorrectPassword:
+ case KErrAccessDenied:
+ {
+ // code was entered erroneously
+ response.Append(KCMEIncorrectPassword);
+ break;
+ }
+ case KErrGsmSSPasswordAttemptsViolation:
+ case KErrLocked:
+ {
+ // Pin blocked
+ response.Append(KCMEPUKRequired);
+ break;
+ }
+ case KErrGsm0707OperationNotAllowed:
+ {
+ // not allowed with this sim
+ response.Append(KCMENotAllowed);
+ break;
+ }
+ case KErrUnknown:
+ {
+ // unknown error
+ response.Append(KCMEPhoneUnknown);
+ break;
+ }
+ default:
+ response.Append(KCMEPhoneError);
+ }
+ CreateReplyAndComplete( EReplyTypeError, response );
+ response.Close();
+ TRACE_FUNC_EXIT
+ }
+
+
+TInt CATMiscCmdPlugin::HandleUnsolicitedRequest(const TDesC8& aAT )
+ {
+ return SendUnsolicitedResult(aAT);
+ }
+
+void CATMiscCmdPlugin::ConnectToEtelL(RTelServer& aTelServer, RMobilePhone& aPhone)
+ {
+ TRACE_FUNC_ENTRY
+ User::LeaveIfError(aTelServer.Connect());
+
+ // get the name of the first available phone
+ TInt phoneCount;
+ RTelServer::TPhoneInfo info;
+
+ User::LeaveIfError(aTelServer.EnumeratePhones(phoneCount));
+ if (phoneCount < 1)
+ {
+ User::Leave(KErrNotFound); // TODO: appropriate error code
+ }
+ User::LeaveIfError(aTelServer.GetPhoneInfo(0, info));
+ User::LeaveIfError(aPhone.Open(aTelServer, info.iName));
+ TRACE_FUNC_EXIT
+ }