--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/telephonyserverplugins/multimodetsy/Multimode/sms/mSMSWRIT.CPP Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,426 @@
+// Copyright (c) 1997-2009 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:
+// This writes an SMS message and stores the message location number. AT+CMGW=xx
+//
+//
+
+#include "NOTIFY.H"
+#include "mSMSMESS.H"
+#include "mSMSWRIT.H"
+#include "mSLOGGER.H"
+#include "ATIO.H"
+#include "mSMSSTOR.H"
+#include "smsutil.h"
+#include "et_phone_util.h"
+
+_LIT8(KSmsWriteLengthCommand,"AT+CMGW = %d\r");
+_LIT8(KSmsWriteCommand,"AT+CMGW = %d,%d\r");
+
+CATSmsMessagingWrite* CATSmsMessagingWrite::NewL(CATIO* aIo, CTelObject* aTelObject, CATInit* aInit, CPhoneGlobals* aMmStatus)
+ {
+ CATSmsMessagingWrite* self = new(ELeave) CATSmsMessagingWrite(aIo, aTelObject, aInit, aMmStatus);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+CATSmsMessagingWrite::CATSmsMessagingWrite(CATIO* aIo, CTelObject* aTelObject, CATInit* aInit, CPhoneGlobals* aMmStatus)
+ :CATSmsCommands(aIo, aTelObject, aInit, aMmStatus)
+ ,iExpectString(NULL)
+ ,iSmsEntry(NULL)
+ ,iCancelled(EFalse)
+ ,iSmsStore(reinterpret_cast<CMobileSmsStore*>(aTelObject))
+ {
+ }
+
+CATSmsMessagingWrite::~CATSmsMessagingWrite()
+ {}
+
+void CATSmsMessagingWrite::Start(TTsyReqHandle aTsyReqHandle, TAny* aParams)
+ {
+ __ASSERT_DEBUG(aParams,Panic(EMobileSmsMessagingNullParameter));
+ __ASSERT_DEBUG(aTsyReqHandle!=TSY_HANDLE_INIT_VALUE,Panic(EMobileSmsMessagingNullParameter));
+
+ // Save the parameters into our class data
+ iReqHandle = aTsyReqHandle;
+ iCancelled=EFalse;
+ iSmsEntry = reinterpret_cast<RMobileSmsStore::TMobileGsmSmsEntryV1*>(aParams);
+
+ iNextAttempt=iPhoneGlobals->iPhoneTestState;
+ // If undefined, try old standard first
+ if(iNextAttempt==CPhoneGlobals::EPhoneTestUndefined)
+ iNextAttempt=CPhoneGlobals::EPhoneTestOldStandard;
+
+ iPhoneGlobals->iEventSignalActive = ETrue;
+ if (ComparePrefMem(iSmsStore->iStoreName))
+ StartPduWrite();
+ else // Compared memories are different
+ {
+ SetCurrentPrefMem(iSmsStore->iStoreName);
+ iState = EATWaitForSendingPrefMemComplete;
+ }
+ }
+
+void CATSmsMessagingWrite::EventSignal(TEventSource aSource)
+ {
+ LOGTEXT2(_L8("CATSmsMessagingWrite:\tiState = %D"), iState);
+
+ if (aSource == ETimeOutCompletion)
+ {
+ LOGTEXT(_L8("CATSmsMessagingWrite:\tTimeout Error during Sms Messaging Write"));
+ iPhoneGlobals->iPhoneStatus.iModemDetected = RPhone::EDetectedNotPresent;
+ RemoveStdExpectStrings();
+ if ((iState != EATWaitForPrefMemResponse)&&!ComparePrefMem(iSmsStore->iStoreName))
+ iPhoneGlobals->iPhonePrefMem = iSmsStore->iStoreName;
+ Complete(KErrTimedOut, aSource);
+ return;
+ } //if
+
+ switch(iState)
+ {
+ // the following 3 cases are special cases, occuring only when the PhonePrefMem != ClientPrefMem
+ case EATWaitForSendingPrefMemComplete:
+ //
+ // Finished writing preferred memory, now wait for response
+ //
+ {
+ HandleWriteCompletion(aSource);
+ iState = EATWaitForPrefMemResponse;
+ }
+ break;
+
+ case EATWaitForPrefMemResponse:
+ //
+ // Got response from writing preferred memory. Validate response, and if
+ // successful, then start the write sequence
+ //
+ {
+ TInt ret=HandleResponseCompletion(aSource,EFalse);
+ if (ret!=KErrNone)
+ {
+ Complete(ret,aSource);
+ return;
+ }
+ TInt pos=iIo->BufferFindF(KCPMSResponseString);
+ if (pos == KErrNotFound)
+ {
+ Complete(pos, aSource);
+ return;
+ }
+ LOGTEXT(_L8("CATSmsMessagingWrite:\tPhone's preferred memory successfully set to client's preferred memory."));
+ iPhoneGlobals->iPhonePrefMem=iSmsStore->iStoreName;
+ if (iCancelled)
+ Complete(KErrCancel,aSource);
+ else
+ StartPduWrite();
+ }
+ break;
+
+ case EATWaitForSendingPduLengthComplete:
+ //
+ // Finished sending pdu length command, now wait for response
+ //
+ {
+ HandleWriteCompletion(aSource);
+ iExpectString=iIo->AddExpectString(this,KSmsEnterPduModeResponse,ETrue); // Expecting "> "
+ iIo->SetTimeOut(this, 5000);
+ iState=EATReadPduEnterPduModeResponseCompleted;
+ }
+ break;
+
+ case EATReadPduEnterPduModeResponseCompleted:
+ //
+ // Received a response to the pdu length command. Validate, and if successful
+ // send the actual pdu in ascii form
+ //
+ {
+ TInt ret=HandleResponseCompletion(aSource,EFalse);
+ if (ret!=KErrNone)
+ {
+ Complete(ret,aSource);
+ return;
+ }
+ ret=ConvertCMSErrorToKErr(CMSErrorValue());
+ iIo->RemoveExpectString(iExpectString);
+ iExpectString=NULL;
+ if(ret)
+ {
+ Complete(ret,aSource);
+ return;
+ }
+ iMsgDataAscii.Append(KCtrlZChar); // Adding the CTRL-Z that indicates the end of the PDU
+ iIo->Write(this,iMsgDataAscii);
+ iIo->SetTimeOut(this, 5000);
+ iState=EATWaitForSendingPduComplete;
+ }
+ break;
+
+ case EATWaitForSendingPduComplete:
+ //
+ // Finished writing pdu, wait for a response
+ //
+ {
+ HandleWriteCompletion(aSource);
+ iState=EATReadSmsRefNumCompleted;
+ }
+ break;
+
+ case EATReadSmsRefNumCompleted:
+ //
+ // Received response to pdu write, validate and if successful set preferred
+ // memory back to original value if it was changed for this command,
+ // otherwise on failure try the new format if the current attempt used the
+ // old ETSI format
+ //
+ {
+ TInt ret=HandleResponseCompletion(aSource,EFalse);
+ if (ret!=KErrNone)
+ {
+ Complete(ret,aSource);
+ return;
+ }
+ TInt err=ConvertCMSErrorToKErr(CMSErrorValue());
+
+ if (err==KErrNone)
+ TRAP(err,ParseResponseL());
+
+ if(err!=KErrNone)
+ {
+ if (iCancelled)
+ Complete(KErrCancel,aSource);
+ else
+ {
+ // Try new standard if old standard failed
+ LOGTEXT2(_L8("CATSmsMessagingWrite:\tFailed with code %d"),err);
+ if (iNextAttempt==CPhoneGlobals::EPhoneTestOldStandard)
+ {
+ iNextAttempt=CPhoneGlobals::EPhoneTestNewStandard;
+ StartPduWrite();
+ }
+ else
+ // Must have tried new standard and this failed too
+ Complete(err);
+ }
+ }
+ else
+ {
+ // If new standard worked then store this is as default for this phone
+ if (iNextAttempt==CPhoneGlobals::EPhoneTestNewStandard)
+ iPhoneGlobals->iPhoneTestState=CPhoneGlobals::EPhoneTestNewStandard;
+ Complete(KErrNone,aSource);
+ }
+ }
+ break;
+
+
+ case EATCancellingWaitForWriteComplete:
+ //
+ // Finished writing cancel request, now wait for response
+ //
+ {
+ __ASSERT_ALWAYS(aSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected));
+ AddStdExpectStrings();
+ iIo->SetTimeOut(this);
+ iState=EATCancellingReadCompleted;
+ }
+ break;
+
+ case EATCancellingReadCompleted:
+ //
+ // Cancel command response received
+ //
+ {
+ __ASSERT_ALWAYS(aSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected));
+ iIo->WriteAndTimerCancel(this);
+ Complete(KErrCancel, aSource);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+void CATSmsMessagingWrite::StartPduWrite()
+/**
+ * Kicks off the writing of the actual pdu. Begins by converting the pdu
+ * into ascii form, and writing the pdu length and message status to the phone.
+ */
+ {
+ iMsgDataAscii.Zero();
+
+ // Convert PDU from binary to ASCII
+ CATSmsUtils::AppendDataToAscii(iMsgDataAscii,iSmsEntry->iMsgData);
+ if(iMsgDataAscii.Length()==0)
+ {
+ LOGTEXT(_L8("CATSmsMessagingWrite:\tStartPduWrite - Failed to convert binary PDU to ASCII"));
+ Complete(KErrCorrupt);
+ return;
+ }
+
+ // Send PDU length to the phone
+ const TInt pduLengthSemiOctets(iMsgDataAscii.Length());
+ const TInt pduLengthOctets(pduLengthSemiOctets/2+pduLengthSemiOctets%2);
+
+ if (iNextAttempt==CPhoneGlobals::EPhoneTestNewStandard)
+ {
+ // Prepend a zero length SCA to PDU - this forces phone to use default SCA
+ // See GSM 07.05 for details
+ _LIT8(zeroLengthSca, "00");
+ iMsgDataAscii.Insert(0,zeroLengthSca);
+ }
+
+ iTxBuffer.Zero();
+ TInt stat=SetMsgStatus();
+ if (stat==KErrNotSupported)
+ iTxBuffer.Format(KSmsWriteLengthCommand,pduLengthOctets);
+ else
+ iTxBuffer.Format(KSmsWriteCommand,pduLengthOctets,stat);
+ iIo->Write(this,iTxBuffer);
+ iIo->SetTimeOut(this,5000);
+ iState=EATWaitForSendingPduLengthComplete;
+ }
+
+void CATSmsMessagingWrite::Complete(TInt aError)
+ {
+ Complete(aError, EReadCompletion);
+ }
+
+void CATSmsMessagingWrite::Complete(TInt aError, TEventSource aSource)
+ {
+ iIo->WriteAndTimerCancel(this);
+ iIo->RemoveExpectStrings(this);
+ iOKExpectString = NULL;
+ iErrorExpectString = NULL;
+ iExpectString = NULL;
+ iPhoneGlobals->iEventSignalActive = EFalse;
+ if (iReqHandle != 0)
+ iTelObject->ReqCompleted(iReqHandle, aError);
+ if (aSource == EWriteCompletion)
+ iIo->Read();
+
+ //
+ // Call our base classes Complete so that
+ // we allow it do what ever it needs to do.
+ CATCommands::Complete(aError,aSource);
+
+ iState = EATNotInProgress;
+ }
+
+void CATSmsMessagingWrite::ParseResponseL()
+//
+// Parse the message reference number and return in smsEntry.iIndex
+//
+ {
+ LOGTEXT(_L8("CATSmsMessagingWrite:\tRetrieving message reference number"));
+ iBuffer.Set(iIo->Buffer());
+ TInt pos = iBuffer.FindF(KCMGWResponseString);
+ if (pos == KErrNotFound)
+ {
+ LOGTEXT(_L8("CATSmsMessagingWrite:\tError - Cannot find '+CMGW:' string"));
+ pos = iBuffer.FindF(KErrorString);
+ if (pos != KErrNotFound)
+ User::Leave(KErrGeneral);
+ User::Leave(pos);
+ }
+ pos += 6;
+
+ // Place the message reference number into buffer (ie: everything after +CMGW: string)
+ TInt woop = iBuffer.Length()-pos;
+ iBuffer.Set(iBuffer.Right(woop));
+
+ TLex8 yyLex(iBuffer);
+ yyLex.Inc(); // steps over the ':' Should always do this....NEVER falls over!
+ yyLex.SkipSpace();
+ TUint val;
+ if(yyLex.Val(val)==KErrNone) // Grab the message reference number.
+ {
+ iSmsEntry->iIndex = val;
+ }
+ else
+ {
+ LOGTEXT(_L8("CATSmsMessagingWrite:\tError. Invalid Message Reference Number."));
+ User::Leave(KErrGeneral);
+ }
+ }
+
+void CATSmsMessagingWrite::Stop(TTsyReqHandle aTsyReqHandle)
+//
+// Attempts to halt the process
+//
+ {
+ __ASSERT_ALWAYS(aTsyReqHandle == iReqHandle,Panic(EIllegalTsyReqHandle));
+ LOGTEXT(_L8("CATSmsMessagingWrite:\tCancelling Sms Write"));
+
+ if ((iState==EATWaitForSendingPduLengthComplete) ||
+ (iState==EATReadPduEnterPduModeResponseCompleted) ||
+ (iState==EATWaitForSendingPduComplete) ||
+ (iState==EATReadSmsRefNumCompleted))
+ {
+ // Attempt to cancel write command if we can
+ RemoveStdExpectStrings();
+ iIo->WriteAndTimerCancel(this);
+ iTxBuffer.Format(KEscapeChar);
+ iIo->Write(this,iTxBuffer);
+ iIo->SetTimeOut(this);
+ iState = EATCancellingWaitForWriteComplete;
+ }
+ else
+ // Wait until safe point to cancel the write
+ iCancelled=ETrue;
+ }
+
+void CATSmsMessagingWrite::CompleteWithIOError(TEventSource /*aSource*/,TInt aStatus)
+ {
+ if (iState!=EATNotInProgress)
+ {
+ iIo->WriteAndTimerCancel(this);
+ iTelObject->ReqCompleted(iReqHandle, aStatus);
+ iState = EATNotInProgress;
+ }
+ }
+
+TInt CATSmsMessagingWrite::SetMsgStatus()
+//
+// Sets the message status
+//
+ {
+ TInt status;
+ switch(iSmsEntry->iMsgStatus)
+ {
+ case (RMobileSmsStore::EStoredMessageUnread):
+ status = 0;
+ break;
+
+ case (RMobileSmsStore::EStoredMessageRead):
+ status = 1;
+ break;
+
+ case (RMobileSmsStore::EStoredMessageUnsent):
+ status = 2;
+ break;
+
+ case (RMobileSmsStore::EStoredMessageSent):
+ case (RMobileSmsStore::EStoredMessageDelivered):
+ status = 3;
+ break;
+
+ default:
+ status = KErrNotSupported;
+ break;
+ }
+ return status;
+ }
+