|
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 // Implementation of CATSmsMessagingSend. |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 */ |
|
21 |
|
22 |
|
23 #include <etelmm.h> |
|
24 |
|
25 #include "NOTIFY.H" |
|
26 #include "mSMSMESS.H" |
|
27 #include "mSMSSEND.H" |
|
28 #include "mSLOGGER.H" |
|
29 #include "ATIO.H" |
|
30 #include "smsutil.h" // for CATSmsUtils |
|
31 |
|
32 // |
|
33 // Constants |
|
34 // |
|
35 const TInt KPduMode=0; |
|
36 |
|
37 // |
|
38 // Macros |
|
39 // |
|
40 |
|
41 #ifdef __LOGDEB__ |
|
42 _LIT8(KLogEntry,"CATSmsMessagingSend::%S\t%S"); |
|
43 #define LOCAL_LOGTEXT(function,text) {_LIT8(F,function);_LIT8(T,text);LOGTEXT3(KLogEntry,&F,&T);} |
|
44 #else |
|
45 #define LOCAL_LOGTEXT(function,text) |
|
46 #endif |
|
47 |
|
48 /** |
|
49 * CANCEL_AND_RETURN_IF_NEEDED |
|
50 * Used to implement cancellation at safe points inside CATSmsMessagingSend::EventSignal |
|
51 */ |
|
52 #define CANCEL_AND_RETURN_IF_NEEDED()\ |
|
53 {\ |
|
54 if(iStop)\ |
|
55 {\ |
|
56 Complete(KErrCancel);\ |
|
57 LOCAL_LOGTEXT("CANCEL_AND_RETURN_IF_NEEDED","Cancelled");\ |
|
58 return;\ |
|
59 }\ |
|
60 } |
|
61 |
|
62 |
|
63 // |
|
64 // Class Implementation |
|
65 // |
|
66 CATSmsMessagingSend* CATSmsMessagingSend::NewL( CATIO* aIo, |
|
67 CTelObject* aTelObject, |
|
68 CATInit* aInit, |
|
69 CPhoneGlobals* aGsmStatus) |
|
70 /** |
|
71 * Creates a new instance of CATSmsMessagingSend |
|
72 */ |
|
73 { |
|
74 CATSmsMessagingSend* self=new(ELeave) CATSmsMessagingSend(aIo,aTelObject,aInit,aGsmStatus); |
|
75 CleanupStack::PushL(self); |
|
76 self->ConstructL(); |
|
77 CleanupStack::Pop(); |
|
78 return self; |
|
79 } |
|
80 |
|
81 CATSmsMessagingSend::CATSmsMessagingSend( CATIO* aIo, |
|
82 CTelObject* aTelObject, |
|
83 CATInit* aInit, |
|
84 CPhoneGlobals* aGsmStatus) |
|
85 :CATSmsCommands(aIo,aTelObject,aInit,aGsmStatus) |
|
86 /** |
|
87 * C++ constructor |
|
88 */ |
|
89 {} |
|
90 |
|
91 void CATSmsMessagingSend::ConstructL() |
|
92 /** |
|
93 * 2nd phase contructor |
|
94 */ |
|
95 { |
|
96 CATCommands::ConstructL(); |
|
97 iMsgDataAscii.Zero(); // Just in case |
|
98 } |
|
99 |
|
100 CATSmsMessagingSend::~CATSmsMessagingSend() |
|
101 /** |
|
102 * C++ destructor |
|
103 */ |
|
104 { |
|
105 delete iMsgData; |
|
106 } |
|
107 |
|
108 void CATSmsMessagingSend::Start(TTsyReqHandle aTsyReqHandle,TAny* aParams) |
|
109 /** |
|
110 * Starts the procedure of sending an SMS |
|
111 * @param aTsyReqHandle Handle to client, to be completed when operation done |
|
112 * @param aParams Pointer to the SMS PDU (with or without SC prefixed) to be sent |
|
113 */ |
|
114 { |
|
115 LOCAL_LOGTEXT("Start","Have been requested to send a message"); |
|
116 |
|
117 // Intialize data |
|
118 iHaveRetriedWithOtherPduStd=EFalse; |
|
119 iStop=EFalse; |
|
120 |
|
121 // ::SetMsgAttributes must be called before ::Start is called |
|
122 __ASSERT_DEBUG(iMsgAttributes,Panic(EATSmsMessagingSendNullMsgAttributes)); |
|
123 |
|
124 // Save access to the data we be given thru our parameters |
|
125 iReqHandle=aTsyReqHandle; |
|
126 delete iMsgData; // Ensure we don't orphan some memory |
|
127 iMsgData=((TDesC8*)aParams)->Alloc(); |
|
128 if(!iMsgData) |
|
129 Complete(KErrNoMemory); |
|
130 |
|
131 // Kick off first AT stuff |
|
132 LOCAL_LOGTEXT("Start","Setting phone to PDU mode (as opposed to text mode)"); |
|
133 iTxBuffer.Format(KSmsFormatCommand,KPduMode); |
|
134 WriteTxBufferToPhone(ESetPhoneToPDUMode); |
|
135 } |
|
136 |
|
137 |
|
138 void CATSmsMessagingSend::StartFindSCA() |
|
139 /** |
|
140 * Attempt to find an SCA to use when sending message. |
|
141 * The following SCA sources are checked in this order... |
|
142 * Supplied by client in iMsgAttributes.iSc |
|
143 * Use default SCA in the phone's memory |
|
144 * Use default SCA in the phone's memory after doing 'AT+CRES=1' |
|
145 */ |
|
146 { |
|
147 LOCAL_LOGTEXT("StartFindSCA",""); |
|
148 |
|
149 // Did client supply SCA in iMsgAttributes.iSc |
|
150 if(iMsgAttributes->iFlags&RMobileSmsMessaging::KGsmServiceCentre && iMsgAttributes->iGsmServiceCentre.iTelNumber.Length()!=0) |
|
151 { |
|
152 iMsgSCA=iMsgAttributes->iGsmServiceCentre; |
|
153 DoneFindSCA(); |
|
154 } |
|
155 |
|
156 // Does the phone have a default SCA in memory |
|
157 else |
|
158 { |
|
159 TInt ret=CATSmsCommands::RequestATCommand(CATSmsCommands::EGetSCAFromPhone); |
|
160 if(ret!=KErrNone) |
|
161 Complete(ret); |
|
162 } |
|
163 |
|
164 } |
|
165 |
|
166 |
|
167 void CATSmsMessagingSend::DoneFindSCA() |
|
168 { |
|
169 LOCAL_LOGTEXT("DoneFindSCA",""); |
|
170 // At this point in the execution we can guarantee that... |
|
171 // iMsgData holds the PDU to be sent in binary format without a prepended SCA |
|
172 // iMsgSCA holds the SCA to be used to send the PDU |
|
173 |
|
174 // Check we can handle the Type-Of-Address of the SCA |
|
175 if(!(iMsgSCA.iNumberPlan==RMobilePhone::EIsdnNumberPlan && |
|
176 (iMsgSCA.iTypeOfNumber==RMobilePhone::EInternationalNumber || |
|
177 iMsgSCA.iTypeOfNumber==RMobilePhone::EUnknownNumber))) |
|
178 { |
|
179 LOCAL_LOGTEXT("DoneFindSCA","SCA type unsupported"); |
|
180 Complete(KErrCorrupt); |
|
181 return; |
|
182 } |
|
183 |
|
184 // Check which ETSI standard we think phone conforms to |
|
185 if(PhoneUsesNewPDUStandard()) |
|
186 SendMessageToNewPhone(); |
|
187 else |
|
188 SendMessageToOldPhone(); |
|
189 } |
|
190 |
|
191 |
|
192 void CATSmsMessagingSend::SendMessageToOldPhone() |
|
193 /** |
|
194 * Send message to phone which uses new ETSI standard (no SCA prefixed to PDU expected, |
|
195 * use phone's default SCA setting instead). |
|
196 */ |
|
197 { |
|
198 LOCAL_LOGTEXT("SendMessageToOldPhone",""); |
|
199 // Set the SCA to use as the default in the phone's memory |
|
200 iRequestSCA=iMsgSCA; |
|
201 TInt ret=CATSmsCommands::RequestATCommand(CATSmsCommands::ESetSCAInPhone); |
|
202 if(ret!=KErrNone) |
|
203 Complete(ret); |
|
204 } |
|
205 |
|
206 |
|
207 void CATSmsMessagingSend::SendMessageToOldPhone_Stage2() |
|
208 { |
|
209 // Convert PDU from binary to ASCII |
|
210 iMsgDataAscii.Zero(); |
|
211 CATSmsUtils::AppendDataToAscii(iMsgDataAscii,*iMsgData); |
|
212 if(iMsgDataAscii.Length()==0) |
|
213 { |
|
214 LOCAL_LOGTEXT("SendMessageToOldPhone_Stage2","Failed to convert binary PDU to ASCII"); |
|
215 Complete(KErrCorrupt); |
|
216 return; |
|
217 } |
|
218 |
|
219 // Send PDU length to the phone |
|
220 const TInt pduLengthSemiOctets(iMsgDataAscii.Length()); |
|
221 const TInt pduLengthOctets(pduLengthSemiOctets/2+pduLengthSemiOctets%2); |
|
222 iTxBuffer.Format(KSmsSendPduLengthCommand,pduLengthOctets); |
|
223 WriteTxBufferToPhone(ESendPDULengthToPhone); |
|
224 } |
|
225 |
|
226 void CATSmsMessagingSend::SendPDUToPhone() |
|
227 { |
|
228 LOCAL_LOGTEXT("SendPDUToPhone",""); |
|
229 // Send PDU to phone |
|
230 iTxBuffer.Format(iMsgDataAscii); |
|
231 iTxBuffer.Append(KCtrlZChar); |
|
232 WriteTxBufferToPhone(ESendPDUToPhone); |
|
233 } |
|
234 |
|
235 void CATSmsMessagingSend::SendPDUToPhone_Stage2() |
|
236 { |
|
237 // Get the message reference number & submit report and then we've finished |
|
238 Complete(ParseCMGSResponse()); |
|
239 } |
|
240 |
|
241 void CATSmsMessagingSend::SendMessageToNewPhone() |
|
242 /** |
|
243 * Send message to phone which uses new ETSI standard (SCA prefixed to PDU expected). |
|
244 */ |
|
245 { |
|
246 LOCAL_LOGTEXT("SendMessageToNewPhone",""); |
|
247 |
|
248 // Convert SCA to ASCII (ensure that 03.40 format is used to create SCA) |
|
249 iMsgDataAscii.Zero(); |
|
250 if(CATSmsUtils::AppendAddressToAscii(iMsgDataAscii,iMsgSCA,ETrue)!=KErrNone || iMsgDataAscii.Length()==0) |
|
251 { |
|
252 LOCAL_LOGTEXT("SendMessageToNewPhone","Failed to prepend SCA to PDU"); |
|
253 Complete(KErrCorrupt); |
|
254 return; |
|
255 } |
|
256 |
|
257 // Convert PDU to ASCII |
|
258 const TInt msgDataAsciiLen(iMsgDataAscii.Length()); |
|
259 CATSmsUtils::AppendDataToAscii(iMsgDataAscii,*iMsgData); |
|
260 if(iMsgDataAscii.Length()==msgDataAsciiLen) |
|
261 { |
|
262 LOCAL_LOGTEXT("SendMessageToNewPhone","Failed to convert binary PDU to ASCII"); |
|
263 Complete(KErrCorrupt); |
|
264 return; |
|
265 } |
|
266 |
|
267 // Send PDU length to the phone |
|
268 const TInt pduLengthSemiOctets(iMsgDataAscii.Length()-msgDataAsciiLen); // Must not include the prefixed SCA in calculation |
|
269 const TInt pduLengthOctets(pduLengthSemiOctets/2+pduLengthSemiOctets%2); |
|
270 iTxBuffer.Format(KSmsSendPduLengthCommand,pduLengthOctets); |
|
271 WriteTxBufferToPhone(ESendPDULengthToPhone); |
|
272 } |
|
273 |
|
274 |
|
275 void CATSmsMessagingSend::EventSignal(TEventSource aSource) |
|
276 /** |
|
277 * Handle the events from the comm port |
|
278 * |
|
279 * This code is first called after the phone has been set to PDU mode. |
|
280 * First we find the SCA that we are going to use. |
|
281 * Secondly we send the message to the phone depending on whether the phone seems to be using |
|
282 * the new ETSI format (SCA prefixed to PDU expected) or the old ETSI format (no SCA prefixed |
|
283 * to PDU expected). |
|
284 * |
|
285 * @param aSource denotes if event is due to read, write or timeout |
|
286 */ |
|
287 { |
|
288 LOCAL_LOGTEXT("EventSignal",""); |
|
289 LOGTEXT3(_L8("iState=%D iSource=%D"),iState,aSource); |
|
290 LOGTEXT2(_L8("iStop=%D"),iStop); |
|
291 |
|
292 // Check to see if this class or our base class need to process the event |
|
293 if(CATSmsCommands::RequestATActive()) |
|
294 { |
|
295 // |
|
296 // Allow base class to handle event, and find out if a request completed |
|
297 // |
|
298 CATSmsCommands::EventSignal(aSource); |
|
299 const CATSmsCommands::TRequest reqCompleted(CATSmsCommands::RequestATCompleted()); |
|
300 |
|
301 if(reqCompleted!=ENone) |
|
302 CANCEL_AND_RETURN_IF_NEEDED(); |
|
303 |
|
304 // Otheriwse, Check if a request completed as a result of the event processing |
|
305 switch(reqCompleted) |
|
306 { |
|
307 case CATSmsCommands::EGetSCAFromPhone: |
|
308 LOCAL_LOGTEXT("EventSignal","EGetSCAFromPhone completed"); |
|
309 if(iRequestError==KErrNone) |
|
310 { |
|
311 iMsgSCA=iRequestSCA; |
|
312 DoneFindSCA(); |
|
313 } |
|
314 else |
|
315 { |
|
316 LOCAL_LOGTEXT("EventSignal","Failed to find an SCA to use"); |
|
317 Complete(iRequestError,aSource); |
|
318 } |
|
319 break; |
|
320 |
|
321 case CATSmsCommands::ESetSCAInPhone: |
|
322 LOCAL_LOGTEXT("EventSignal","ESetSCAInPhone completed"); |
|
323 if(iRequestError==KErrNone) |
|
324 SendMessageToOldPhone_Stage2(); |
|
325 else |
|
326 { |
|
327 LOCAL_LOGTEXT("EventSignal","Failed to set SCA in phone"); |
|
328 Complete(iRequestError,aSource); |
|
329 } |
|
330 break; |
|
331 |
|
332 case CATSmsCommands::ENone: // Must not be caught by default case |
|
333 break; |
|
334 default: |
|
335 LOCAL_LOGTEXT("EventSignal","CATSmsCommands unknown request completed"); |
|
336 __ASSERT_DEBUG(EFalse,Panic(EATSmsMessagingUnknownRequestCompleted)); |
|
337 } |
|
338 } |
|
339 else |
|
340 { |
|
341 // |
|
342 // This class will handle event |
|
343 // |
|
344 if (aSource==ETimeOutCompletion) |
|
345 { |
|
346 LOCAL_LOGTEXT("EventSignal","Timeout error"); |
|
347 iIo->WriteAndTimerCancel(this); |
|
348 Complete(KErrTimedOut, aSource); |
|
349 } |
|
350 |
|
351 TInt ret(KErrNone); |
|
352 switch(iState) |
|
353 { |
|
354 case ESetPhoneToPDUMode: |
|
355 if(aSource==EWriteCompletion) |
|
356 HandleWriteCompletion(aSource); |
|
357 else |
|
358 { |
|
359 ret=HandleResponseCompletion(aSource,EFalse); |
|
360 if (ret!=KErrNone) |
|
361 { |
|
362 Complete(ret,aSource); |
|
363 return; |
|
364 } |
|
365 StartFindSCA(); |
|
366 } |
|
367 break; |
|
368 |
|
369 case ESendPDULengthToPhone: |
|
370 if(aSource==EWriteCompletion) |
|
371 { |
|
372 HandleWriteCompletion(aSource); |
|
373 iExpectString=iIo->AddExpectString(this,KSmsEnterPduModeResponse,ETrue); |
|
374 } |
|
375 else |
|
376 { |
|
377 ret=HandleResponseCompletion(aSource,EFalse); |
|
378 if (ret!=KErrNone) |
|
379 { |
|
380 Complete(ret,aSource); |
|
381 return; |
|
382 } |
|
383 ret=ConvertCMSErrorToKErr(CMSErrorValue()); |
|
384 iIo->RemoveExpectString(iExpectString); |
|
385 iExpectString=NULL; |
|
386 if (ret!=KErrNone) |
|
387 { |
|
388 Complete(ret,aSource); |
|
389 return; |
|
390 } |
|
391 |
|
392 // If we get a Cancel request just before we send the PDU, we instead send an escape |
|
393 // character to trigger a PDU send failure and then continue as normal. |
|
394 if (iStop) |
|
395 { |
|
396 LOCAL_LOGTEXT("EventSignal","Cancel requested. Sending Escape Character instead of PDU"); |
|
397 |
|
398 // In case of Ericsson phone, after sending the escape char we are not receiving expected |
|
399 // response (OK/ERROR), it is just echoing those char. But if the escape char is prefixed |
|
400 // by "at", then it responds with expected response. |
|
401 |
|
402 // But in case of other phones, we believe the escape char alone works. We have confirmed |
|
403 // this with Nokia phones. |
|
404 |
|
405 _LIT16(KEricsson,"*ERICSSON*"); |
|
406 if(iPhoneGlobals->iPhoneId.iManufacturer.MatchF(KEricsson)==0) |
|
407 { |
|
408 _LIT8(KEscapeSequenceString,"at%S\r"); |
|
409 iTxBuffer.Format(KEscapeSequenceString,&KEscapeChar); |
|
410 } |
|
411 else |
|
412 { |
|
413 iTxBuffer.Format(KEscapeChar); |
|
414 } |
|
415 WriteTxBufferToPhone(ESendEscapeCharToPhone); |
|
416 } |
|
417 else |
|
418 SendPDUToPhone(); |
|
419 } |
|
420 break; |
|
421 |
|
422 case ESendPDUToPhone: |
|
423 if(aSource==EWriteCompletion) |
|
424 { |
|
425 HandleWriteCompletion(aSource); |
|
426 } |
|
427 else |
|
428 { |
|
429 const TInt err=ConvertCMSErrorToKErr(CMSErrorValue()); |
|
430 ret=HandleResponseCompletion(aSource,EFalse); |
|
431 if (ret!=KErrNone) |
|
432 { |
|
433 Complete(ret,aSource); |
|
434 return; |
|
435 } |
|
436 |
|
437 // Check if an error occurred |
|
438 if(err!=KErrNone) |
|
439 { |
|
440 // If we have not already, then retry using the other Pdu standard |
|
441 if(!iHaveRetriedWithOtherPduStd) |
|
442 { |
|
443 CANCEL_AND_RETURN_IF_NEEDED(); |
|
444 // Retry with new standard |
|
445 LOCAL_LOGTEXT("EventSignal","Failed to send message, will retry using other phone standard"); |
|
446 iHaveRetriedWithOtherPduStd=ETrue; |
|
447 TogglePhonePDUStandard(); |
|
448 DoneFindSCA(); |
|
449 } |
|
450 else |
|
451 { |
|
452 // We have tried both PDU standards and have failed :-( |
|
453 LOCAL_LOGTEXT("EventSignal","Failed to send message :-("); |
|
454 Complete(err,aSource); |
|
455 } |
|
456 } |
|
457 else |
|
458 { |
|
459 // Success, we have sent the message ;-) |
|
460 if (iStop) {LOCAL_LOGTEXT("EventSignal","Message send successful, Cancel request to late, PDU already sent");} |
|
461 else {LOCAL_LOGTEXT("EventSignal","Message send successful ;-)");} |
|
462 SendPDUToPhone_Stage2(); |
|
463 } |
|
464 } |
|
465 break; |
|
466 |
|
467 case ESendEscapeCharToPhone: |
|
468 if(aSource==EWriteCompletion) |
|
469 { |
|
470 HandleWriteCompletion(aSource); |
|
471 } |
|
472 else |
|
473 { |
|
474 ret=HandleResponseCompletion(aSource,EFalse); |
|
475 if (ret!=KErrNone) |
|
476 { |
|
477 Complete(ret,aSource); |
|
478 return; |
|
479 } |
|
480 Complete(KErrCancel,aSource); |
|
481 } |
|
482 break; |
|
483 |
|
484 case ENotInProgress: // Required to stop 'unhandled enum' warning with ARM4 |
|
485 break; |
|
486 } |
|
487 } |
|
488 } |
|
489 |
|
490 |
|
491 void CATSmsMessagingSend::Complete(TInt aError,TEventSource aSource) |
|
492 { |
|
493 LOCAL_LOGTEXT("Complete",""); |
|
494 LOGTEXT3(_L8("aError=%D aSource=%D"),aError,aSource); |
|
495 |
|
496 iIo->WriteAndTimerCancel(this); |
|
497 iIo->RemoveExpectStrings(this); |
|
498 iOKExpectString = NULL; |
|
499 iErrorExpectString = NULL; |
|
500 CATCommands::Complete(aError,aSource); |
|
501 iTelObject->ReqCompleted(iReqHandle, aError); |
|
502 if (aSource==EWriteCompletion) |
|
503 iIo->Read(); |
|
504 iState = ENotInProgress; |
|
505 } |
|
506 |
|
507 void CATSmsMessagingSend::SetMsgAttributes(RMobileSmsMessaging::TMobileSmsSendAttributesV1* aMsgAttributes) |
|
508 { |
|
509 iMsgAttributes=aMsgAttributes; |
|
510 } |
|
511 |
|
512 void CATSmsMessagingSend::Stop(TTsyReqHandle aTsyReqHandle) |
|
513 // |
|
514 // Attempts to halt the process |
|
515 // |
|
516 { |
|
517 LOCAL_LOGTEXT("Stop","Client has requested cancel"); |
|
518 __ASSERT_ALWAYS(aTsyReqHandle == iReqHandle, Panic(EIllegalTsyReqHandle)); |
|
519 |
|
520 // Ensure our base class notes that a cancel has been requested |
|
521 CATSmsCommands::RequestATCommandCancel(); |
|
522 |
|
523 // Set our flag to denote we should cancel as soon as possible |
|
524 iStop=ETrue; |
|
525 } |
|
526 |
|
527 void CATSmsMessagingSend::CompleteWithIOError(TEventSource /*aSource*/,TInt aStatus) |
|
528 { |
|
529 if (iState!=ENotInProgress) |
|
530 { |
|
531 iIo->WriteAndTimerCancel(this); |
|
532 iTelObject->ReqCompleted(iReqHandle, aStatus); |
|
533 iState = ENotInProgress; |
|
534 } |
|
535 } |
|
536 |
|
537 // |
|
538 // Utility functions |
|
539 // |
|
540 TBool CATSmsMessagingSend::PhoneUsesNewPDUStandard() |
|
541 /** |
|
542 * This code assumes that EPhoneTestOldStandard and EPhoneTestUndefined are |
|
543 * the same. |
|
544 */ |
|
545 { |
|
546 return (iPhoneGlobals->iPhoneTestState==CPhoneGlobals::EPhoneTestNewStandard); |
|
547 } |
|
548 |
|
549 void CATSmsMessagingSend::TogglePhonePDUStandard() |
|
550 /** |
|
551 * This code assumes that EPhoneTestOldStandard and EPhoneTestUndefined are |
|
552 * the same. |
|
553 */ |
|
554 { |
|
555 if(iPhoneGlobals->iPhoneTestState==CPhoneGlobals::EPhoneTestNewStandard) |
|
556 iPhoneGlobals->iPhoneTestState=CPhoneGlobals::EPhoneTestOldStandard; |
|
557 else |
|
558 iPhoneGlobals->iPhoneTestState=CPhoneGlobals::EPhoneTestNewStandard; |
|
559 } |
|
560 |
|
561 void CATSmsMessagingSend::WriteTxBufferToPhone(TState aNewState) |
|
562 /** |
|
563 * Sends the contents of iTxBuffer to the phone |
|
564 */ |
|
565 { |
|
566 iIo->Write(this,iTxBuffer); |
|
567 iIo->SetTimeOut(this,KATWriteTimeout); |
|
568 iState=aNewState; |
|
569 } |
|
570 |
|
571 |
|
572 TInt CATSmsMessagingSend::ParseCMGSResponse() |
|
573 /** |
|
574 * Parse CMGS response string for Message Reference Number & |
|
575 * SUBMIT-REPORT PDU (optional) and store their values in the clients data space. |
|
576 * |
|
577 * @return Standard KErr... values |
|
578 */ |
|
579 { |
|
580 __ASSERT_DEBUG(iMsgAttributes,Panic(EATSmsMessagingSendNullMsgAttributes)); |
|
581 |
|
582 iBuffer.Set(iIo->Buffer()); |
|
583 TInt pos=iBuffer.FindF(KCMGSResponseString); |
|
584 if (pos==KErrNotFound) |
|
585 { |
|
586 LOCAL_LOGTEXT("ParseCMGSResponse","Cannot find '+CMGS:' string"); |
|
587 return KErrNotFound; |
|
588 } |
|
589 |
|
590 // Locate the message reference number |
|
591 // (ie. read in all digits form the first found to the end of the string) |
|
592 const TInt bufLength=iBuffer.Length(); |
|
593 pos+=KCMGSResponseStringLength; |
|
594 while(pos<bufLength && !(TChar(iBuffer[pos]).IsDigit())) |
|
595 ++pos; |
|
596 if(pos>=bufLength) |
|
597 { |
|
598 LOCAL_LOGTEXT("ParseCMGSResponse","Cannot find any digits after '+CMGS:'"); |
|
599 return KErrNotFound; |
|
600 } |
|
601 |
|
602 // Read message number and store in clients data structure |
|
603 TPtrC8 ptr=iBuffer.Mid(pos); |
|
604 TLex8 lex(ptr); |
|
605 TUint16 val; |
|
606 TInt ret=lex.Val(val,EDecimal); |
|
607 if(ret!=KErrNone) |
|
608 { |
|
609 LOCAL_LOGTEXT("ParseCMGSResponse","Unable to read Message Reference Number"); |
|
610 return ret; |
|
611 } |
|
612 LOGTEXT2(_L8("CATSmsMessagingSend Message reference number %d"),val); |
|
613 iMsgAttributes->iMsgRef=val; |
|
614 iMsgAttributes->iFlags|=RMobileSmsMessaging::KMessageReference; |
|
615 |
|
616 // Locate SUBMIT-REPORT (it does not have to exist) |
|
617 pos=iBuffer.FindF(KCommaChar); |
|
618 if(pos!=KErrNotFound) |
|
619 { |
|
620 while(pos<bufLength && !(TChar(iBuffer[pos]).IsHexDigit())) |
|
621 ++pos; |
|
622 |
|
623 if(pos<bufLength) |
|
624 { |
|
625 // We have found a SUBMIT-REPORT PDU, so save it to clients data space |
|
626 LOCAL_LOGTEXT("ParseCMGSResponse","Found SUBMIT-REPORT PDU"); |
|
627 |
|
628 iMsgAttributes->iSubmitReport.Zero(); |
|
629 while(pos<bufLength && TChar(iBuffer[pos]).IsHexDigit()) |
|
630 { |
|
631 iMsgAttributes->iSubmitReport.Append(TChar(iBuffer[pos])); |
|
632 ++pos; |
|
633 } |
|
634 iMsgAttributes->iFlags|=RMobileSmsMessaging::KGsmSubmitReport; |
|
635 } |
|
636 } |
|
637 |
|
638 return KErrNone; |
|
639 } |
|
640 |
|
641 |