telephonyserverplugins/multimodetsy/Multimode/sms/cmt_unstored.cpp
changeset 0 3553901f7fa8
equal deleted inserted replaced
-1:000000000000 0:3553901f7fa8
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <etelmm.h>				// for RMobileSmsMessaging::TMobileSmsReceiveAttributesV1
       
    17 #include "mSLOGGER.H"			// for LOGTEXT2 and other logging utilities
       
    18 #include "ATIO.H"			
       
    19 #include "Matstd.h"
       
    20 #include "cmt_unstored.h"		// header file for this cpp file
       
    21 #include "sms_rx_queue.h"		// for CReceiveSmsQueue
       
    22 
       
    23 #ifdef __LOGDEB__
       
    24 _LIT8(KLogEntry,"CATSmsWaitForAndHandleCMTUnstored::%S\t%S");
       
    25 #define LOCAL_LOGTEXT(function,text) {_LIT8(F,function);_LIT8(T,text);LOGTEXT3(KLogEntry,&F,&T);}
       
    26 #else
       
    27 #define LOCAL_LOGTEXT(function,text)
       
    28 #endif
       
    29 
       
    30 
       
    31 CATSmsWaitForAndHandleCMTUnstored* CATSmsWaitForAndHandleCMTUnstored::NewL(CATIO* aIo,CTelObject* aTelObject, CPhoneGlobals* aGlobals,
       
    32 									                                     CReceiveSmsQueue& aReceiveQueue)
       
    33 	{
       
    34 	CATSmsWaitForAndHandleCMTUnstored* wait=new(ELeave) CATSmsWaitForAndHandleCMTUnstored(aIo,aTelObject,aGlobals,aReceiveQueue);
       
    35 	// Currently no need for a ConstructL call
       
    36 	return wait;
       
    37 	}
       
    38 
       
    39 CATSmsWaitForAndHandleCMTUnstored::CATSmsWaitForAndHandleCMTUnstored(CATIO* aIo, CTelObject* aTelObject,
       
    40 												   CPhoneGlobals* aGlobals, CReceiveSmsQueue& aReceiveQueue) 
       
    41 	:CATBase(aIo,aTelObject,aGlobals)
       
    42 	,iReceiveQueue(aReceiveQueue)
       
    43 	{}
       
    44 
       
    45 
       
    46 CATSmsWaitForAndHandleCMTUnstored::~CATSmsWaitForAndHandleCMTUnstored()
       
    47 	{
       
    48 	iIo->RemoveExpectStrings(this);	
       
    49 	// We do not need to NULL iCMTExpectString and iCDSExpectString
       
    50 	// as this object is about to de destroyed
       
    51 	}
       
    52 
       
    53 void CATSmsWaitForAndHandleCMTUnstored::Enable()
       
    54 	{
       
    55 	LOCAL_LOGTEXT("Enable","Enabled listening for CMT & CDS");
       
    56 
       
    57 	if (iState==ENoState)
       
    58 		{
       
    59 		iState=EWaitForCMT;
       
    60 		
       
    61 		// Add +CMT:* expect string
       
    62 		if (!iCMTExpectString)
       
    63 			iCMTExpectString=iIo->AddExpectString(this,KCMTMatchString);
       
    64 
       
    65 		// Add +CDS:* expect string
       
    66 		if (!iCDSExpectString)
       
    67 			iCDSExpectString=iIo->AddExpectString(this,KCDSMatchString);
       
    68 		}
       
    69 	}
       
    70 
       
    71 void CATSmsWaitForAndHandleCMTUnstored::Disable()
       
    72 	{
       
    73 	LOCAL_LOGTEXT("Disable","Disabled listening for CMT & CDS");
       
    74 	
       
    75 	if (iState!=EWaitForCmtSecondLine)
       
    76 		{
       
    77 		iIo->RemoveExpectStrings(this);		
       
    78 		iCMTExpectString=NULL;
       
    79 		iCDSExpectString=NULL;
       
    80 		iState=ENoState;
       
    81 		}
       
    82 	else
       
    83 		{
       
    84 		// wait to receive message we're half-way through before disabling
       
    85 		iState=EWaitForCmtSecondLineThenDisable;
       
    86 		}
       
    87 	}
       
    88 
       
    89 
       
    90 void CATSmsWaitForAndHandleCMTUnstored::EventSignal(TEventSource aSource)
       
    91 /**
       
    92  * Called when a '+CMT:' or '+CDS:' is received.
       
    93  * +CMT: [<alpha>],<length><CR><LF><pdu>
       
    94  * +CDS: <length><CR><LF><pdu>
       
    95  *
       
    96  * This is a two state machine that first waits for the +CMT: [<alpha>],<length><CR><LF>
       
    97  * and then waits for the final <pdu>
       
    98  *
       
    99  * When a PDU has been read from the phone, it is pushed into the CReceiveSmsQueue.
       
   100  */
       
   101 	{
       
   102 	TInt ret(KErrNone);
       
   103 	iIo->WriteAndTimerCancel(this);
       
   104 	LOCAL_LOGTEXT("EventSignal","Enter function");
       
   105 		
       
   106 	switch(iState)
       
   107 		{
       
   108 	case EWaitForCMT:
       
   109 		LOCAL_LOGTEXT("EventSignal","EWaitForCMT");
       
   110 		__ASSERT_ALWAYS(aSource == EReadCompletion, Panic(EATCommand_IllegalCompletionReadExpected));
       
   111 		
       
   112 		TRAP(ret,ParseFirstCMTLineL(iPduLen));
       
   113 		if(ret!=KErrNone)
       
   114 			{
       
   115 			LOCAL_LOGTEXT("EventSignal","Failed to parse 1st line");
       
   116 			// No need for more error handling - just wait for next CMT
       
   117 			}
       
   118 		else
       
   119 			{
       
   120 			//
       
   121 			// Add the expect string * so that we receive whatever is on the next line
       
   122 			// (the conditional expression below ensures no memory leak if "+CMT:"
       
   123 			// is found on consecutive lines)
       
   124 			if(!iWaitForAnything)
       
   125 				iWaitForAnything=iIo->AddExpectString(this,KAsterisk);
       
   126 		
       
   127 			//
       
   128 			// We need to keep the buffered data so we...
       
   129 			iIo->SetPreserveBufferFlag(ETrue);			
       
   130 
       
   131 			//
       
   132 			// Wait for the reception of the second line
       
   133 			iState=EWaitForCmtSecondLine;
       
   134 			}
       
   135 		break;
       
   136 
       
   137 	case EWaitForCmtSecondLine:
       
   138 	case EWaitForCmtSecondLineThenDisable:
       
   139 
       
   140 		LOCAL_LOGTEXT("EventSignal","EWaitForCmtSecondLine");
       
   141 		__ASSERT_ALWAYS(aSource == EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected));
       
   142 		iIo->RemoveExpectString(iWaitForAnything);
       
   143 		iWaitForAnything=NULL;
       
   144 		iIo->SetPreserveBufferFlag(EFalse);			// We've got the PDU, and will delete the buffer when the line is parsed
       
   145 
       
   146 		{		// Curly brackets used to scope pdu and attr local data
       
   147 		//
       
   148 		// Parse and Push received message into CReceiveSmsQueue
       
   149 		RMobileSmsMessaging::TMobileSmsGsmTpdu pdu;
       
   150 		RMobileSmsMessaging::TMobileSmsReceiveAttributesV1 attr;
       
   151 		TRAPD(ret,ParseSecondCMTLineL(pdu,attr));
       
   152 		if(ret!=KErrNone)
       
   153 			{
       
   154 			LOCAL_LOGTEXT("EventSignal","Failed to parse 2nd line");
       
   155 			}
       
   156 		else
       
   157 			{
       
   158 			LOCAL_LOGTEXT("EventSignal","Adding SMS to iReceiveQueue");
       
   159 			iReceiveQueue.Push(pdu,attr);
       
   160 			}
       
   161 		}
       
   162 
       
   163 		//
       
   164 		// We are done, but there is no client request to complete
       
   165 		// we just return and wait until we get our next CMT command
       
   166 		// unless we should disable now
       
   167 		if (iState==EWaitForCmtSecondLineThenDisable)
       
   168 			Disable();
       
   169 		else
       
   170 			iState=EWaitForCMT;
       
   171 		break;
       
   172 
       
   173 	case ENoState:
       
   174 	default:
       
   175 		// We should never get here, but we don't need to panic in release code.
       
   176 		__ASSERT_DEBUG(EFalse,Panic(EATWaitForCMTNoState));
       
   177 		break;
       
   178 		} 
       
   179 	}
       
   180 
       
   181 
       
   182 
       
   183 void CATSmsWaitForAndHandleCMTUnstored::ParseFirstCMTLineL(TInt& aPduLen)
       
   184 /**
       
   185  * Parse 1st line of CMT response, of the format: "+CMT: [<alpha>], <pdu_len>"
       
   186  * Stores the <pdu_len> in aPduLen
       
   187  */
       
   188 	{
       
   189 	ParseLineLC();
       
   190 
       
   191 	CATParamListEntry* entry;
       
   192 	CATParamListEntry* alpha;
       
   193 	TDblQueIter<CATParamListEntry> iter(iRxResults);
       
   194 
       
   195 	entry=iter++;
       
   196 	if (entry==NULL || (entry->iResultPtr!=KCMTResponseString && entry->iResultPtr!=KCDSResponseString))
       
   197 		{
       
   198 		LOCAL_LOGTEXT("ParseFirstCMTLineL","Failed to find response +CMT: or +CDS:");
       
   199 		User::Leave(KErrGeneral);
       
   200 		}
       
   201 
       
   202 	//
       
   203 	// Get the <alpha> token, optional this token may return the message length token
       
   204 	alpha=iter++;
       
   205 	if(alpha==NULL)
       
   206 		{
       
   207 		LOCAL_LOGTEXT("ParseFirstCMTLineL","Failed with 1st argument");
       
   208 		User::Leave(KErrGeneral);
       
   209 		}
       
   210 
       
   211 	//
       
   212 	// Get the message length token
       
   213 	entry=iter++;
       
   214 	if(entry==NULL)
       
   215 		entry=alpha;	// The alpha token must have been missing and thus alpha holds the message length
       
   216 
       
   217 	if(entry==NULL)		
       
   218 		{
       
   219 		LOCAL_LOGTEXT("ParseFirstCMTLineL","Failed with 2nd argument");
       
   220 		User::Leave(KErrGeneral);
       
   221 		}
       
   222 
       
   223 	//
       
   224 	// Process the message length
       
   225 	aPduLen=CATParamListEntry::EntryValL(entry);
       
   226 	LOGTEXT2(_L8("New SMS detected of length %d"),iPduLen);
       
   227 
       
   228 	CleanupStack::PopAndDestroy();		// ParseLineLC pushed object
       
   229 	}
       
   230 
       
   231 
       
   232 void CATSmsWaitForAndHandleCMTUnstored::ParseSecondCMTLineL(RMobileSmsMessaging::TMobileSmsGsmTpdu& aPdu,RMobileSmsMessaging::TMobileSmsReceiveAttributesV1& aAttr)
       
   233 /**
       
   234  * Parse second line of CMT or DS response, of the format: "<pdu>"
       
   235  * The <pdu> is saved to aPdu. If the <pdu> is found to have a prefixed SCA
       
   236  * then that is removed before the save to aPdu.
       
   237  */
       
   238 	{
       
   239 	LOCAL_LOGTEXT("ParseSecondCMTLineL","Enter funciton");
       
   240 
       
   241 	// Intiailise the attributes
       
   242 	aAttr.iFlags=0;
       
   243 	//
       
   244 	// Copy the received pdu to local storage so that we can process
       
   245 	// and modify it.
       
   246 	// Buffer size calculated as follows;
       
   247 	//   (max pdu size + max prefixed SCA size) * number of ASCII chars used to code an octet
       
   248 	TBuf8<(RMobileSmsMessaging::KGsmTpduSize+12)*2> localPdu;	
       
   249 	{
       
   250 	ParseLineLC();
       
   251 	TDblQueIter<CATParamListEntry> iter(iRxResults);
       
   252 	CATParamListEntry* entry=iter++;			// Have to increment iter so it returns a pointer
       
   253 	if(entry==NULL)
       
   254 		User::Leave(KErrGeneral);		// Would prefer not to leave and return an error
       
   255 		                                // but this function has to be trapped as we 
       
   256 										// have the ParseLineLC() call.
       
   257 	localPdu.Copy(entry->iResultPtr);
       
   258 	CleanupStack::PopAndDestroy();		// ParseLineLC pushed object
       
   259 	}
       
   260 
       
   261 	// Nokia 9210 sometimes aborts the CMT frame in the middle of pdu.
       
   262 	// Worst, it is sometimes contains odd number of nibbles which
       
   263 	// causes panic in ConvertAsciiToBinary() method. This type of
       
   264 	// frames will simply be discarded.
       
   265 	if(localPdu.Length()<(iPduLen*2))
       
   266 		User::Leave(KErrUnderflow);
       
   267 	
       
   268 	//
       
   269 	// Check if we have a prefixed SCA on our pdu.
       
   270 	// If we do then remove it.
       
   271 	if(localPdu.Length()>(iPduLen*2))
       
   272 		{
       
   273 		if(CATSmsUtils::ReadAndRemoveAddressFromAscii(localPdu,aAttr.iGsmServiceCentre,ETrue)!=KErrNone)
       
   274 			{
       
   275 			LOCAL_LOGTEXT("ParseAndStoreCMGRResponseL","Failed to read and remove SCA from PDU");
       
   276 			}
       
   277 		else
       
   278 			{
       
   279 			aAttr.iFlags|=RMobileSmsMessaging::KGsmServiceCentre;
       
   280 			}
       
   281 		}
       
   282 
       
   283 	//
       
   284 	// Convert received pdu from ASCII into binary
       
   285 	if (CATSmsUtils::ConvertAsciiToBinary(localPdu,aPdu)!=KErrNone)
       
   286 		{
       
   287 		LOCAL_LOGTEXT("ParseAndStoreCMGRResponseL","Failed to code PDU into binary");
       
   288 		}
       
   289 	else
       
   290 		{
       
   291 		aAttr.iDataFormat=RMobileSmsMessaging::EFormatGsmTpdu;
       
   292 		aAttr.iFlags|=RMobileSmsMessaging::KSmsDataFormat;
       
   293 		aAttr.iStatus=RMobileSmsMessaging::EMtMessageUnstoredPhoneAck;
       
   294 		aAttr.iFlags|=RMobileSmsMessaging::KIncomingStatus;
       
   295 		}
       
   296 	}	
       
   297 	
       
   298 
       
   299 
       
   300 void CATSmsWaitForAndHandleCMTUnstored::CompleteWithIOError(TEventSource /*aSource*/,TInt aStatus)
       
   301 	{
       
   302 	LOCAL_LOGTEXT("CompleteWithIOError","Enter function");
       
   303 	// CATIO removes expect strings in event of IO error so don't do it here
       
   304 	iCMTExpectString=NULL;			
       
   305 	iCDSExpectString=NULL;			
       
   306 	// inform client of error so that it does not continue to wait for incoming SMS
       
   307 	// now that this wait object has been disabled
       
   308 	iReceiveQueue.CompleteClientReqWithError(aStatus);
       
   309 	}
       
   310