diff -r f7fbeaeb166a -r b23265fb36da cbsatplugin/atmisccmdplugin/src/atmisccmdplugin.cpp --- /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 // 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 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 + }