1 // Copyright (c) 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 // @file smsatutil.cpp |
|
15 // This contains SmsAtUtil which is util for Sms At command |
|
16 // |
|
17 |
|
18 // user include |
|
19 #include "smsatutil.h" |
|
20 #include "ltsycommondefine.h" |
|
21 #include "panic.h" |
|
22 |
|
23 /** |
|
24 * Receive PDU example |
|
25 * 0891683108200805F0040D91683188902848F4000850208151754500108FD9662F4E0067616D4B8BD577ED4FE1 |
|
26 * 08 ocet length including 91 |
|
27 * 91 Identify Address Type |
|
28 * 683108200805F0 SCA address |
|
29 * 04 |
|
30 * 0D91683188902848F4 |
|
31 * 00 |
|
32 * 08 |
|
33 * 50208151754500 |
|
34 * 10 |
|
35 * 8FD9662F4E0067616D4B8BD577ED4FE1 |
|
36 */ |
|
37 // --------------------------------------------------------------------------- |
|
38 // SmsAtUtil::ConvertAsciiToBinary |
|
39 // other items were commented in a header |
|
40 // --------------------------------------------------------------------------- |
|
41 TInt SmsAtUtil::ConvertAsciiToBinary(const TDesC8& aAscii,TDes8& aData) |
|
42 { |
|
43 aData.Zero(); |
|
44 TLex8 lex; |
|
45 TUint8 val; |
|
46 TInt ret; |
|
47 const TInt count(aAscii.Length()); |
|
48 for(TInt i = 0;i < count;i = i + 2) |
|
49 { |
|
50 lex = aAscii.Mid(i,2); |
|
51 ret = lex.Val(val,EHex); |
|
52 if(ret != KErrNone) |
|
53 { |
|
54 return ret; |
|
55 } |
|
56 aData.Append(val); |
|
57 } |
|
58 return KErrNone; |
|
59 } |
|
60 |
|
61 // ------------------------------------------------------------------------------- |
|
62 // SmsAtUtil::AppendAddressToAscii |
|
63 // other items were commented in a header |
|
64 // ------------------------------------------------------------------------------- |
|
65 TInt SmsAtUtil::AppendAddressToAscii(TDes8& aAscii, |
|
66 const RMobilePhone::TMobileAddress& aAddress) |
|
67 { |
|
68 // Duplicate tel number, removing all the weird chars |
|
69 TBuf<RMobilePhone::KMaxMobileTelNumberSize> telNumber; |
|
70 const TInt count(aAddress.iTelNumber.Length()); |
|
71 // Validate the size of the supplied SCA |
|
72 if(count >= RMobilePhone::KMaxMobileTelNumberSize) |
|
73 { |
|
74 return KErrOverflow; |
|
75 } |
|
76 TInt i; |
|
77 for(i = 0;i < count;++i) |
|
78 { |
|
79 if(IsAddressChar(TChar(aAddress.iTelNumber[i]))) |
|
80 telNumber.Append(aAddress.iTelNumber[i]); |
|
81 } |
|
82 |
|
83 const TInt telNumberLength(telNumber.Length()); |
|
84 |
|
85 // Code Address-Length |
|
86 AppendOctet(1 + (telNumberLength/2) + (telNumberLength%2),aAscii); |
|
87 |
|
88 // Code Type-Of-Address |
|
89 TInt typeOfNumber = ConvertTypeOfNumber(aAddress.iTypeOfNumber); |
|
90 TInt numberingPlan = ConvertNumberingPlan(aAddress.iNumberPlan); |
|
91 AppendOctet(0x80+(typeOfNumber<<4) + (numberingPlan),aAscii); |
|
92 |
|
93 // Code Address-Value |
|
94 TInt highSemiOctet; |
|
95 TInt lowSemiOctet; |
|
96 const TInt octets(telNumberLength/2); // This division will be rounded down |
|
97 for(i = 0; i < octets; ++i) |
|
98 { |
|
99 // See ETSI 03.40 section 9.1.2.3 |
|
100 // Address digits are coded into octets as pairs. |
|
101 lowSemiOctet = ConvertAddressChar(TChar(telNumber[i*2])); |
|
102 highSemiOctet = ConvertAddressChar(TChar(telNumber[(i*2)+1])); |
|
103 AppendOctet((highSemiOctet<<4)+lowSemiOctet,aAscii); |
|
104 } |
|
105 |
|
106 // If number of semi octects is odd then process the final octet |
|
107 if(telNumberLength%2 == 1) |
|
108 { |
|
109 lowSemiOctet = ConvertAddressChar(TChar(telNumber[telNumberLength-1])); |
|
110 AppendOctet(0xf0+lowSemiOctet,aAscii); |
|
111 } |
|
112 |
|
113 __ASSERT_DEBUG(aAscii.Length()%2 == 0,Panic(EATSmsUtilsOddNumberOfSemiOctets)); |
|
114 return KErrNone; |
|
115 } |
|
116 |
|
117 |
|
118 // --------------------------------------------------------------------------- |
|
119 // SmsAtUtil::AppendDataToAscii |
|
120 // other items were commented in a header |
|
121 // --------------------------------------------------------------------------- |
|
122 void SmsAtUtil::AppendDataToAscii(TDes8& aAscii,const TDesC8& aData) |
|
123 { |
|
124 const TInt count(aData.Length()); |
|
125 __ASSERT_DEBUG((aAscii.MaxLength()-aAscii.MaxLength())<=(count*2),Panic(EATSmsUtilsDescriptorOverflow)); |
|
126 |
|
127 for(TInt i = 0; i < count; ++i) |
|
128 { |
|
129 AppendOctet(aData[i],aAscii); |
|
130 } |
|
131 |
|
132 __ASSERT_DEBUG(aAscii.Length()%2==0,Panic(EATSmsUtilsOddNumberOfSemiOctets)); |
|
133 } |
|
134 |
|
135 // ---------------------------------------------------------------------------------- |
|
136 // SmsAtUtil::ReadAndRemoveAddressFromAscii |
|
137 // other items were commented in a header |
|
138 // ---------------------------------------------------------------------------------- |
|
139 TInt SmsAtUtil::ReadAndRemoveAddressFromAscii(TDes8& aAscii, |
|
140 RMobilePhone::TMobileAddress& aAddress) |
|
141 { |
|
142 __ASSERT_DEBUG(aAscii.Length()%2==0,Panic(EATSmsUtilsOddNumberOfSemiOctets)); |
|
143 TInt ret(KErrNone); |
|
144 |
|
145 ret = ReadAddressFromAscii(aAscii,aAddress); |
|
146 |
|
147 if(ret==KErrNone) |
|
148 { |
|
149 // Delete address from aAscii (using Address-length at start of string) |
|
150 TLex8 lex(aAscii.Mid(0,2)); |
|
151 TUint val; |
|
152 ret=lex.Val(val,EHex); |
|
153 if(ret == KErrNone) |
|
154 { |
|
155 // +1 to include 1 octect of Address-Length |
|
156 val = val+1; |
|
157 |
|
158 // double value to change from 'octets used' to 'ASCII chars used' |
|
159 val = val*2; |
|
160 |
|
161 aAscii.Delete(0,val); |
|
162 __ASSERT_DEBUG(aAscii.Length()%2==0,Panic(EATSmsUtilsOddNumberOfSemiOctets)); |
|
163 } |
|
164 } |
|
165 return ret; |
|
166 } |
|
167 |
|
168 // --------------------------------------------------------------------------- |
|
169 // SmsAtUtil::ReadAddressFromAscii |
|
170 // other items were commented in a header |
|
171 // --------------------------------------------------------------------------- |
|
172 TInt SmsAtUtil::ReadAddressFromAscii(const TDesC8& aAscii, |
|
173 RMobilePhone::TMobileAddress& aAddress) |
|
174 { |
|
175 TLex8 lex; |
|
176 TInt ret; |
|
177 TUint8 val; |
|
178 |
|
179 // get address length + 1 octet Address Type(91) |
|
180 lex = aAscii.Mid(0,2); |
|
181 ret = lex.Val(val,EHex); |
|
182 if(ret != KErrNone) |
|
183 { |
|
184 return ret; |
|
185 } |
|
186 |
|
187 // we exclude the Address Type as address should not include this |
|
188 TInt addrLen = val-1; |
|
189 |
|
190 // Type-Of-Number (see example above as 9) |
|
191 lex = aAscii.Mid(2,1); |
|
192 ret = lex.Val(val,EHex); |
|
193 if(ret != KErrNone) |
|
194 { |
|
195 return ret; |
|
196 } |
|
197 |
|
198 // Highest bit is not part of Type-Of-Number |
|
199 aAddress.iTypeOfNumber = ConvertTypeOfNumber(val&0x07); |
|
200 |
|
201 // Number-Plan |
|
202 lex = aAscii.Mid(3,1); |
|
203 ret = lex.Val(val,EHex); |
|
204 if(ret != KErrNone) |
|
205 { |
|
206 return ret; |
|
207 } |
|
208 |
|
209 // we got Number-Plan which should be compatiable with Symbian defination |
|
210 aAddress.iNumberPlan = ConvertNumberingPlan(val); |
|
211 |
|
212 // Address (loop for each octet ie. two hex chars from aAscii) |
|
213 aAddress.iTelNumber.Zero(); |
|
214 for(TInt i = 0; i < addrLen; ++i) |
|
215 { |
|
216 // Process semi-octet |
|
217 lex = aAscii.Mid((i*2)+5,1); |
|
218 ret = lex.Val(val,EHex); |
|
219 if(ret != KErrNone) |
|
220 { |
|
221 return ret; |
|
222 } |
|
223 // 0xF is consider a pedding when the address length is odd number, so we do not need to append it to address field |
|
224 if(val < 0xF) |
|
225 aAddress.iTelNumber.Append(ConvertAddressChar(val)); |
|
226 |
|
227 // Process semi-octet |
|
228 lex = aAscii.Mid((i*2)+4,1); |
|
229 ret = lex.Val(val,EHex); |
|
230 if(ret != KErrNone) |
|
231 { |
|
232 return ret; |
|
233 } |
|
234 |
|
235 // 0xF is consider a pedding when the address length is odd number, so we do not need to append it to address field |
|
236 if(val < 0xF) |
|
237 aAddress.iTelNumber.Append(ConvertAddressChar(val)); |
|
238 } |
|
239 return KErrNone; |
|
240 } |
|
241 |
|
242 // ---------------------------------------------------------------------------------------- |
|
243 // SmsAtUtil::ReadAndRemoveAddressFromPdu |
|
244 // other items were commented in a header |
|
245 // ---------------------------------------------------------------------------------------- |
|
246 void SmsAtUtil::ReadAndRemoveAddressFromPdu(TPtrC8& aPdu, |
|
247 RMobilePhone::TMobileAddress& aGsmServiceCentre) |
|
248 { |
|
249 const TUint8 KTONBitMask = 0x70; |
|
250 const TUint8 KNPIBitMask = 0x0f; |
|
251 const TUint8 KTONBitShift = 4; |
|
252 const TUint8 KNPIBitShift = 0; |
|
253 _LIT(KInternationalPrefix,"+"); |
|
254 |
|
255 aGsmServiceCentre.iTypeOfNumber = (RMobilePhone::TMobileTON)0; |
|
256 aGsmServiceCentre.iNumberPlan = (RMobilePhone::TMobileNPI)0; |
|
257 aGsmServiceCentre.iTelNumber.Zero(); |
|
258 |
|
259 TUint8 len = aPdu[0]; |
|
260 |
|
261 if(len == 0) |
|
262 { |
|
263 // A zero length SCA has been prepended - just strip this first byte off |
|
264 aPdu.Set(aPdu.Mid(len+1)); |
|
265 return; |
|
266 } |
|
267 |
|
268 TUint8 numDes = aPdu[1]; |
|
269 aGsmServiceCentre.iTypeOfNumber = (RMobilePhone::TMobileTON)((numDes&KTONBitMask)>>KTONBitShift); |
|
270 aGsmServiceCentre.iNumberPlan = (RMobilePhone::TMobileNPI)((numDes&KNPIBitMask)>>KNPIBitShift); |
|
271 |
|
272 if(aGsmServiceCentre.iTypeOfNumber == RMobilePhone::EInternationalNumber) |
|
273 aGsmServiceCentre.iTelNumber.Append(KInternationalPrefix); |
|
274 |
|
275 TInt i; |
|
276 TUint16 digit; |
|
277 for(i = 2;i<(len+1);i++) |
|
278 { |
|
279 digit = (TUint16)((aPdu[i]&0x0f) + 0x30); |
|
280 aGsmServiceCentre.iTelNumber.Append(digit); |
|
281 digit = (TUint16)(((aPdu[i]&0xf0)>>4) + 0x30); |
|
282 if(digit == 0x003f) // 'F' is the padding digit at the end of a number |
|
283 break; |
|
284 aGsmServiceCentre.iTelNumber.Append(digit); |
|
285 } |
|
286 aPdu.Set(aPdu.Mid(len + 1)); |
|
287 } |
|
288 |
|
289 // --------------------------------------------------------------------------- |
|
290 // SmsAtUtil::IsAddressChar |
|
291 // other items were commented in a header |
|
292 // --------------------------------------------------------------------------- |
|
293 TBool SmsAtUtil::IsAddressChar(TChar aChar) |
|
294 { |
|
295 if(aChar.IsDigit()) |
|
296 { |
|
297 return ETrue; |
|
298 } |
|
299 if(aChar == TChar('*') || |
|
300 aChar == TChar('#') || |
|
301 aChar == TChar('a') || |
|
302 aChar == TChar('b') || |
|
303 aChar == TChar('c')) |
|
304 { |
|
305 return ETrue; |
|
306 } |
|
307 return EFalse; |
|
308 } |
|
309 |
|
310 // --------------------------------------------------------------------------- |
|
311 // SmsAtUtil::ConvertNumberingPlan |
|
312 // other items were commented in a header |
|
313 // --------------------------------------------------------------------------- |
|
314 RMobilePhone::TMobileNPI SmsAtUtil::ConvertNumberingPlan(TInt aValue) |
|
315 { |
|
316 switch(aValue) |
|
317 { |
|
318 // The below 'magic numbers' come from the ETSI 03.40 |
|
319 // specification for Address Fields (section 9.1.2.5) |
|
320 case 1: |
|
321 return RMobilePhone::EIsdnNumberPlan; |
|
322 case 3: |
|
323 return RMobilePhone::EDataNumberPlan; |
|
324 case 4: |
|
325 return RMobilePhone::ETelexNumberPlan; |
|
326 case 8: |
|
327 return RMobilePhone::ENationalNumberPlan; |
|
328 case 9: |
|
329 return RMobilePhone::EPrivateNumberPlan; |
|
330 default: |
|
331 return RMobilePhone::EUnknownNumberingPlan; |
|
332 } |
|
333 } |
|
334 |
|
335 // --------------------------------------------------------------------------- |
|
336 // SmsAtUtil::ConvertTypeOfNumber |
|
337 // other items were commented in a header |
|
338 // --------------------------------------------------------------------------- |
|
339 RMobilePhone::TMobileTON SmsAtUtil::ConvertTypeOfNumber(TInt aValue) |
|
340 { |
|
341 switch(aValue) |
|
342 { |
|
343 // The below 'magic numbers' come from the ETSI 03.40 |
|
344 // specification for Address Fields (section 9.1.2.5) |
|
345 case 0: |
|
346 return RMobilePhone::EUnknownNumber; |
|
347 case 1: |
|
348 return RMobilePhone::EInternationalNumber; |
|
349 case 2: |
|
350 return RMobilePhone::ENationalNumber; |
|
351 case 3: |
|
352 return RMobilePhone::ENetworkSpecificNumber; |
|
353 case 4: |
|
354 return RMobilePhone::ESubscriberNumber; |
|
355 default: |
|
356 return RMobilePhone::EUnknownNumber; |
|
357 } |
|
358 } |
|
359 |
|
360 // --------------------------------------------------------------------------- |
|
361 // SmsAtUtil::AppendOctet |
|
362 // other items were commented in a header |
|
363 // --------------------------------------------------------------------------- |
|
364 void SmsAtUtil::AppendOctet(TInt aOctet,TDes8& aAscii) |
|
365 { |
|
366 // Ensure client has only passed us a octet (ie. low 8 bits only) |
|
367 aOctet = aOctet&0xff; |
|
368 // Append octet |
|
369 // (prefix '0' if the octets value only uses one digit as final |
|
370 // octet coding must use two digits) |
|
371 if(aOctet <= 0x0f) |
|
372 { |
|
373 aAscii.Append(TChar('0')); |
|
374 } |
|
375 |
|
376 aAscii.AppendNum(aOctet,EHex); |
|
377 } |
|
378 |
|
379 // --------------------------------------------------------------------------- |
|
380 // SmsAtUtil::ConvertAddressChar |
|
381 // other items were commented in a header |
|
382 // --------------------------------------------------------------------------- |
|
383 TInt SmsAtUtil::ConvertAddressChar(TChar aChar) |
|
384 { |
|
385 aChar.LowerCase(); |
|
386 if(aChar-TChar('0') <= 9) |
|
387 { |
|
388 // it should be digital number from 0~9 |
|
389 return aChar-TChar('0'); |
|
390 } |
|
391 else if(aChar == TChar('*')) |
|
392 { |
|
393 return 10; |
|
394 } |
|
395 else if(aChar == TChar('#')) |
|
396 { |
|
397 return 11; |
|
398 } |
|
399 else if(aChar == TChar('a')) |
|
400 { |
|
401 return 12; |
|
402 } |
|
403 else if(aChar == TChar('b')) |
|
404 { |
|
405 return 13; |
|
406 } |
|
407 else if(aChar == TChar('c')) |
|
408 { |
|
409 return 14; |
|
410 } |
|
411 return 15; |
|
412 } |
|
413 |
|
414 // --------------------------------------------------------------------------- |
|
415 // SmsAtUtil::ConvertAddressChar |
|
416 // other items were commented in a header |
|
417 // --------------------------------------------------------------------------- |
|
418 TChar SmsAtUtil::ConvertAddressChar(TInt aBinary) |
|
419 { |
|
420 if(aBinary >= 0 && aBinary <= 9) |
|
421 { |
|
422 return aBinary + TChar('0'); // Assumes digit characters are one after each other |
|
423 } |
|
424 else if(aBinary == 10) |
|
425 { |
|
426 return TChar('*'); |
|
427 } |
|
428 else if(aBinary == 11) |
|
429 { |
|
430 return TChar('#'); |
|
431 } |
|
432 else if(aBinary == 12) |
|
433 { |
|
434 return TChar('a'); |
|
435 } |
|
436 else if(aBinary == 13) |
|
437 { |
|
438 return TChar('b'); |
|
439 } |
|
440 else if(aBinary == 14) |
|
441 { |
|
442 return TChar('c'); |
|
443 } |
|
444 return TChar(0); // This is the cloest I can find to a NULL char |
|
445 } |
|
446 |
|
447 // End of file |
|