6 #include "../../gsmcomon.h"
7 #include "../../misc/coding/coding.h"
10 #include "../gsmlogo.h"
11 #include "../gsmring.h"
12 #include "../gsmwap.h"
13 #include "../gsmnet.h"
16 /* User data headers */
17 static GSM_UDHHeader UDHHeaders
[] = {
18 /* See GSM 03.40 section 9.2.3.24.1
21 * 1 byte 0x01: unique ID for message series
22 * 1 byte 0x00: how many SMS in sequence
23 * 1 byte 0x00: number of current SMS in sequence */
24 { UDH_ConcatenatedMessages
, 0x05, "\x00\x03\x01\x00\x00",2,-1,4,3},
26 /* See GSM 03.40 section 9.2.3.24.2 for voice, fax and email messages */
27 { UDH_DisableVoice
, 0x04, "\x01\x02\x00\x00",-1,-1,-1,-1},
28 { UDH_DisableFax
, 0x04, "\x01\x02\x01\x00",-1,-1,-1,-1},
29 { UDH_DisableEmail
, 0x04, "\x01\x02\x02\x00",-1,-1,-1,-1},
30 { UDH_EnableVoice
, 0x04, "\x01\x02\x00\x01",-1,-1,-1,-1},
31 { UDH_EnableFax
, 0x04, "\x01\x02\x01\x01",-1,-1,-1,-1},
32 { UDH_EnableEmail
, 0x04, "\x01\x02\x02\x01",-1,-1,-1,-1},
34 /* When send such SMS to some phones, they don't display anything,
35 * only beep and enable vibra/light
37 { UDH_VoidSMS
, 0x08, "\x01\x02\x02\x01\x01\x02\x02\x00",-1,-1,-1,-1},
39 /* Nokia Smart Messaging (short version) UDH
41 * 1 byte 0x05 : IEI application port addressing scheme, 16 bit address
42 * 1 byte 0x04 : IEI length
43 * 2 bytes : destination address : high & low byte
44 * 2 bytes 0x00 0x00 : originator address : high & low byte */
45 { UDH_NokiaRingtone
, 0x06, "\x05\x04\x15\x81\x00\x00",-1,-1,-1,-1},
46 { UDH_NokiaOperatorLogo
, 0x06, "\x05\x04\x15\x82\x00\x00",-1,-1,-1,-1},
47 { UDH_NokiaCallerLogo
, 0x06, "\x05\x04\x15\x83\x00\x00",-1,-1,-1,-1},
48 { UDH_NokiaWAP
, 0x06, "\x05\x04\xc3\x4f\x00\x00",-1,-1,-1,-1},
50 /* Nokia Smart Messaging (long version) UDH and other
52 * 1 byte 0x05 : IEI application port addressing scheme, 16 bit address
53 * 1 byte 0x04 : IEI length
54 * 2 bytes 0x00 0x00 : destination address : high & low byte
55 * 2 bytes 0x00 0x00 : originator address : high & low byte
57 * 1 byte 0x03 : SAR length
58 * 1 byte : diagram reference number (unique ID for message series)
59 * 1 byte : number of all SMS
60 * 1 byte : number of current SMS */
61 { UDH_NokiaCalendarLong
, 0x0b, "\x05\x04\x00\xe4\x00\x00\x00\x03\xc7\x00\x00",8,-1,10,9},
62 { UDH_MMSIndicatorLong
, 0x0b, "\x05\x04\x0b\x84\x23\xf0\x00\x03\xe5\x00\x00",8,-1,10,9},
63 { UDH_NokiaRingtoneLong
, 0x0b, "\x05\x04\x15\x81\x00\x00\x00\x03\x01\x00\x00",8,-1,10,9},
64 { UDH_NokiaOperatorLogoLong
, 0x0b, "\x05\x04\x15\x82\x00\x00\x00\x03\x02\x00\x00",8,-1,10,9},
65 { UDH_NokiaProfileLong
, 0x0b, "\x05\x04\x15\x8a\x00\x00\x00\x03\xce\x00\x00",8,-1,10,9},
66 { UDH_NokiaPhonebookLong
, 0x0b, "\x05\x04\x23\xf4\x00\x00\x00\x03\x01\x00\x00",8,-1,10,9},
67 { UDH_NokiaWAPLong
, 0x0b, "\x05\x04\xc3\x4f\x00\x00\x00\x03\x7f\x00\x00",8,-1,10,9},
69 { UDH_ConcatenatedMessages16bit
,0x06, "\x08\x04\x00\x00\x00\x00",-1,2,5,4},
71 { UDH_NoUDH
, 0x00, "",-1,-1,-1,-1}
74 /* --------------------------- Unpacking SMS ------------------------------- */
76 /* See GSM 03.40 section 9.2.3.11 */
77 static GSM_Error
GSM_DecodeSMSDateTime(GSM_DateTime
*DT
, unsigned char *req
)
79 DT
->Year
= DecodeWithBCDAlphabet(req
[0]);
80 if (DT
->Year
<90) DT
->Year
=DT
->Year
+2000; else DT
->Year
=DT
->Year
+1990;
81 DT
->Month
= DecodeWithBCDAlphabet(req
[1]);
82 DT
->Day
= DecodeWithBCDAlphabet(req
[2]);
83 DT
->Hour
= DecodeWithBCDAlphabet(req
[3]);
84 DT
->Minute
= DecodeWithBCDAlphabet(req
[4]);
85 DT
->Second
= DecodeWithBCDAlphabet(req
[5]);
87 /* Base for timezone is GMT. It's in quarters */
88 DT
->Timezone
=(10*(req
[6]&0x07)+(req
[6]>>4))/4;
90 if (req
[6]&0x08) DT
->Timezone
= -DT
->Timezone
;
92 dbgprintf("Decoding date & time: ");
93 dbgprintf("%s %4d/%02d/%02d ", DayOfWeek(DT
->Year
, DT
->Month
, DT
->Day
),
94 DT
->Year
, DT
->Month
, DT
->Day
);
95 dbgprintf("%02d:%02d:%02d %02d00\n", DT
->Hour
, DT
->Minute
, DT
->Second
, DT
->Timezone
);
100 void GSM_DecodeUDHHeader(GSM_UDHHeader
*UDH
)
105 UDH
->Type
= UDH_UserUDH
;
108 UDH
->PartNumber
= -1;
114 if (UDHHeaders
[i
].Type
==UDH_NoUDH
) break;
116 tmp
=UDHHeaders
[i
].Length
;
117 /* if length is the same */
118 if (tmp
==UDH
->Text
[0]) {
120 if (tmp
==0x05) tmp
=tmp
-3;/*three last bytes can be different for such UDH*/
121 if (tmp
==0x0b) tmp
=tmp
-3;/*three last bytes can be different for such UDH*/
122 if (tmp
==0x06 && UDH
->Text
[1] == 0x08) tmp
=tmp
-4;
125 for (w
=0;w
<tmp
;w
++) {
126 if (UDHHeaders
[i
].Text
[w
]!=UDH
->Text
[w
+1]) {
132 UDH
->Type
=UDHHeaders
[i
].Type
;
134 if (UDHHeaders
[i
].ID8bit
!=-1) UDH
->ID8bit
= UDH
->Text
[UDHHeaders
[i
].ID8bit
+1];
135 if (UDHHeaders
[i
].ID16bit
!=-1) UDH
->ID16bit
= UDH
->Text
[UDHHeaders
[i
].ID16bit
+1]*256+UDH
->Text
[UDHHeaders
[i
].ID16bit
+2];
136 if (UDHHeaders
[i
].PartNumber
!=-1) UDH
->PartNumber
= UDH
->Text
[UDHHeaders
[i
].PartNumber
+1];
137 if (UDHHeaders
[i
].AllParts
!=-1) UDH
->AllParts
= UDH
->Text
[UDHHeaders
[i
].AllParts
+1];
144 dbgprintf("Type of UDH: ");
146 case UDH_ConcatenatedMessages
: dbgprintf("Concatenated (linked) message"); break;
147 case UDH_ConcatenatedMessages16bit
: dbgprintf("Concatenated (linked) message"); break;
148 case UDH_DisableVoice
: dbgprintf("Disables voice indicator"); break;
149 case UDH_EnableVoice
: dbgprintf("Enables voice indicator"); break;
150 case UDH_DisableFax
: dbgprintf("Disables fax indicator"); break;
151 case UDH_EnableFax
: dbgprintf("Enables fax indicator"); break;
152 case UDH_DisableEmail
: dbgprintf("Disables email indicator"); break;
153 case UDH_EnableEmail
: dbgprintf("Enables email indicator"); break;
154 case UDH_VoidSMS
: dbgprintf("Void SMS"); break;
155 case UDH_NokiaWAP
: dbgprintf("Nokia WAP Bookmark"); break;
156 case UDH_NokiaOperatorLogoLong
: dbgprintf("Nokia operator logo"); break;
157 case UDH_NokiaWAPLong
: dbgprintf("Nokia WAP Bookmark or WAP/MMS Settings"); break;
158 case UDH_NokiaRingtone
: dbgprintf("Nokia ringtone"); break;
159 case UDH_NokiaRingtoneLong
: dbgprintf("Nokia ringtone"); break;
160 case UDH_NokiaOperatorLogo
: dbgprintf("Nokia GSM operator logo"); break;
161 case UDH_NokiaCallerLogo
: dbgprintf("Nokia caller logo"); break;
162 case UDH_NokiaProfileLong
: dbgprintf("Nokia profile"); break;
163 case UDH_NokiaCalendarLong
: dbgprintf("Nokia calendar note"); break;
164 case UDH_NokiaPhonebookLong
: dbgprintf("Nokia phonebook entry"); break;
165 case UDH_UserUDH
: dbgprintf("User UDH"); break;
166 case UDH_MMSIndicatorLong
: dbgprintf("MMS indicator"); break;
167 case UDH_NoUDH
: break;
169 if (UDH
->ID8bit
!= -1) dbgprintf(", ID 8 bit %i",UDH
->ID8bit
);
170 if (UDH
->ID16bit
!= -1) dbgprintf(", ID 16 bit %i",UDH
->ID16bit
);
171 if (UDH
->PartNumber
!= -1 && UDH
->AllParts
!= -1) {
172 dbgprintf(", part %i of %i",UDH
->PartNumber
,UDH
->AllParts
);
175 if (di
.dl
== DL_TEXTALL
|| di
.dl
== DL_TEXTALLDATE
) DumpMessage(di
.df
, UDH
->Text
, UDH
->Length
);
179 GSM_Error
GSM_DecodeSMSFrameText(GSM_SMSMessage
*SMS
, unsigned char *buffer
, GSM_SMSMessageLayout Layout
)
181 int off
=0; /* off - length of the user data header */
183 unsigned char output
[161];
186 /* UDH header available */
187 if (buffer
[Layout
.firstbyte
] & 64) {
188 /* Length of UDH header */
189 off
= (buffer
[Layout
.Text
] + 1);
190 SMS
->UDH
.Length
= off
;
191 dbgprintf("UDH header available (length %i)\n",off
);
193 /* Copy UDH header into SMS->UDH */
194 for (i
= 0; i
< off
; i
++) SMS
->UDH
.Text
[i
] = buffer
[Layout
.Text
+ i
];
196 GSM_DecodeUDHHeader(&SMS
->UDH
);
199 /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme) and GSM 03.38 section 4 */
200 if ((buffer
[Layout
.TPDCS
] & 0xf4) == 0xf4) SMS
->Coding
=GSM_Coding_8bit
;
201 if ((buffer
[Layout
.TPDCS
] & 0x08) == 0x08) SMS
->Coding
=GSM_Coding_Unicode
;
203 switch (SMS
->Coding
) {
204 case GSM_Coding_Default
:
210 SMS
->Length
=buffer
[Layout
.TPUDL
] - (off
*8 + w
) / 7;
211 tmp
=GSM_UnpackEightBitsToSeven(w
, buffer
[Layout
.TPUDL
]-off
, SMS
->Length
, buffer
+(Layout
.Text
+off
), output
);
212 dbgprintf("7 bit SMS, length %i\n",SMS
->Length
);
213 DecodeDefault (SMS
->Text
, output
, SMS
->Length
, true, NULL
);
214 dbgprintf("%s\n",DecodeUnicodeString(SMS
->Text
));
216 case GSM_Coding_8bit
:
217 SMS
->Length
=buffer
[Layout
.TPUDL
] - off
;
218 memcpy(SMS
->Text
,buffer
+(Layout
.Text
+off
),SMS
->Length
);
220 dbgprintf("8 bit SMS, length %i\n",SMS
->Length
);
221 if (di
.dl
== DL_TEXTALL
|| di
.dl
== DL_TEXTALLDATE
) DumpMessage(di
.df
, SMS
->Text
, SMS
->Length
);
224 case GSM_Coding_Unicode
:
225 SMS
->Length
=(buffer
[Layout
.TPUDL
] - off
) / 2;
226 DecodeUnicodeSpecialNOKIAChars(SMS
->Text
,buffer
+(Layout
.Text
+off
), SMS
->Length
);
228 dbgprintf("Unicode SMS, length %i\n",SMS
->Length
);
229 if (di
.dl
== DL_TEXTALL
|| di
.dl
== DL_TEXTALLDATE
) DumpMessage(di
.df
,buffer
+(Layout
.Text
+off
), SMS
->Length
*2);
230 dbgprintf("%s\n",DecodeUnicodeString(SMS
->Text
));
238 GSM_Error
GSM_DecodeSMSFrameStatusReportData(GSM_SMSMessage
*SMS
, unsigned char *buffer
, GSM_SMSMessageLayout Layout
)
240 SMS
->DeliveryStatus
= buffer
[Layout
.TPStatus
];
242 if (buffer
[Layout
.TPStatus
] < 0x03) {
243 EncodeUnicode(SMS
->Text
,"Delivered",9);
245 } else if (buffer
[Layout
.TPStatus
] & 0x40) {
246 EncodeUnicode(SMS
->Text
,"Failed",6);
248 } else if (buffer
[Layout
.TPStatus
] & 0x20) {
249 EncodeUnicode(SMS
->Text
,"Pending",7);
252 EncodeUnicode(SMS
->Text
,"Unknown",7);
257 /* See GSM 03.40 section 9.2.3.15 (TP-Status) */
258 if (buffer
[Layout
.TPStatus
] & 0x40) {
259 if (buffer
[Layout
.TPStatus
] & 0x20) {
260 /* 0x60, 0x61, ... */
261 dbgprintf("Temporary error, SC is not making any more transfer attempts\n");
263 /* 0x40, 0x41, ... */
264 dbgprintf("Permanent error, SC is not making any more transfer attempts\n");
266 } else if (buffer
[Layout
.TPStatus
] & 0x20) {
267 /* 0x20, 0x21, ... */
268 dbgprintf("Temporary error, SC still trying to transfer SM\n");
270 switch (buffer
[Layout
.TPStatus
]) {
271 case 0x00: dbgprintf("SM received by the SME"); break;
272 case 0x01: dbgprintf("SM forwarded by the SC to the SME but the SC is unable to confirm delivery");break;
273 case 0x02: dbgprintf("SM replaced by the SC"); break;
274 case 0x20: dbgprintf("Congestion"); break;
275 case 0x21: dbgprintf("SME busy"); break;
276 case 0x22: dbgprintf("No response from SME"); break;
277 case 0x23: dbgprintf("Service rejected"); break;
278 case 0x24: dbgprintf("Quality of service not available"); break;
279 case 0x25: dbgprintf("Error in SME"); break;
280 case 0x40: dbgprintf("Remote procedure error"); break;
281 case 0x41: dbgprintf("Incompatibile destination"); break;
282 case 0x42: dbgprintf("Connection rejected by SME"); break;
283 case 0x43: dbgprintf("Not obtainable"); break;
284 case 0x44: dbgprintf("Quality of service not available"); break;
285 case 0x45: dbgprintf("No internetworking available"); break;
286 case 0x46: dbgprintf("SM Validity Period Expired"); break;
287 case 0x47: dbgprintf("SM deleted by originating SME"); break;
288 case 0x48: dbgprintf("SM Deleted by SC Administration"); break;
289 case 0x49: dbgprintf("SM does not exist"); break;
290 case 0x60: dbgprintf("Congestion"); break;
291 case 0x61: dbgprintf("SME busy"); break;
292 case 0x62: dbgprintf("No response from SME"); break;
293 case 0x63: dbgprintf("Service rejected"); break;
294 case 0x64: dbgprintf("Quality of service not available"); break;
295 case 0x65: dbgprintf("Error in SME"); break;
296 default : dbgprintf("Reserved/Specific to SC: %x",buffer
[Layout
.TPStatus
]); break;
304 GSM_Error
GSM_DecodeSMSFrame(GSM_SMSMessage
*SMS
, unsigned char *buffer
, GSM_SMSMessageLayout Layout
)
307 if (Layout
.firstbyte
== 255) {
308 dbgprintf("ERROR: firstbyte in SMS layout not set\n");
311 if (Layout
.TPDCS
!= 255) dbgprintf("TPDCS : %02x %i\n",buffer
[Layout
.TPDCS
] ,buffer
[Layout
.TPDCS
]);
312 if (Layout
.TPMR
!= 255) dbgprintf("TPMR : %02x %i\n",buffer
[Layout
.TPMR
] ,buffer
[Layout
.TPMR
]);
313 if (Layout
.TPPID
!= 255) dbgprintf("TPPID : %02x %i\n",buffer
[Layout
.TPPID
] ,buffer
[Layout
.TPPID
]);
314 if (Layout
.TPUDL
!= 255) dbgprintf("TPUDL : %02x %i\n",buffer
[Layout
.TPUDL
] ,buffer
[Layout
.TPUDL
]);
315 if (Layout
.firstbyte
!= 255) dbgprintf("FirstByte : %02x %i\n",buffer
[Layout
.firstbyte
],buffer
[Layout
.firstbyte
]);
316 if (Layout
.Text
!= 255) dbgprintf("Text : %02x %i\n",buffer
[Layout
.Text
] ,buffer
[Layout
.Text
]);
319 SMS
->UDH
.Type
= UDH_NoUDH
;
320 SMS
->Coding
= GSM_Coding_Default
;
322 SMS
->SMSC
.Number
[0] = 0;
323 SMS
->SMSC
.Number
[1] = 0;
328 SMS
->ReplyViaSameSMSC
= false;
329 if (Layout
.SMSCNumber
!=255) {
330 GSM_UnpackSemiOctetNumber(SMS
->SMSC
.Number
,buffer
+Layout
.SMSCNumber
,false);
331 dbgprintf("SMS center number : \"%s\"\n",DecodeUnicodeString(SMS
->SMSC
.Number
));
333 if ((buffer
[Layout
.firstbyte
] & 0x80)!=0) SMS
->ReplyViaSameSMSC
=true;
335 if (SMS
->ReplyViaSameSMSC
) dbgprintf("SMS centre set for reply\n");
337 if (Layout
.Number
!=255) {
338 GSM_UnpackSemiOctetNumber(SMS
->Number
,buffer
+Layout
.Number
,true);
339 dbgprintf("Remote number : \"%s\"\n",DecodeUnicodeString(SMS
->Number
));
341 if (Layout
.Text
!= 255 && Layout
.TPDCS
!=255 && Layout
.TPUDL
!=255) {
342 GSM_DecodeSMSFrameText(SMS
, buffer
, Layout
);
344 if (Layout
.DateTime
!= 255) {
345 GSM_DecodeSMSDateTime(&SMS
->DateTime
,buffer
+(Layout
.DateTime
));
347 if (Layout
.SMSCTime
!= 255 && Layout
.TPStatus
!= 255) {
348 /* See GSM 03.40 section 9.2.3.11 (TP-Service-Centre-Time-Stamp) */
349 dbgprintf("SMSC response date: ");
350 GSM_DecodeSMSDateTime(&SMS
->SMSCTime
, buffer
+(Layout
.SMSCTime
));
351 GSM_DecodeSMSFrameStatusReportData(SMS
,buffer
,Layout
);
354 if (Layout
.TPDCS
!= 255) {
355 if ((buffer
[Layout
.TPDCS
] & 0xF3)==0xF0) SMS
->Class
= 0;
356 if ((buffer
[Layout
.TPDCS
] & 0xF3)==0xF1) SMS
->Class
= 1;
357 if ((buffer
[Layout
.TPDCS
] & 0xF3)==0xF2) SMS
->Class
= 2;
358 if ((buffer
[Layout
.TPDCS
] & 0xF3)==0xF3) SMS
->Class
= 3;
360 dbgprintf("SMS class: %i\n",SMS
->Class
);
361 SMS
->MessageReference
= 0;
362 if (Layout
.TPMR
!= 255) {
363 SMS
->MessageReference
= buffer
[Layout
.TPMR
];
365 SMS
->ReplaceMessage
= 0;
366 if (Layout
.TPPID
!= 255) {
367 if (buffer
[Layout
.TPPID
] > 0x40 && buffer
[Layout
.TPPID
] < 0x48) {
368 SMS
->ReplaceMessage
= buffer
[Layout
.TPPID
] - 0x40;
371 SMS
->RejectDuplicates
= false;
372 if ((buffer
[Layout
.firstbyte
] & 0x04)==0x04) SMS
->RejectDuplicates
= true;
377 /* ----------------------------- Packing SMS ------------------------------- */
379 /* See GSM 03.40 section 9.2.3.11 */
380 static GSM_Error
GSM_EncodeSMSDateTime(GSM_DateTime
*DT
, unsigned char *req
)
384 dbgprintf("Encoding SMS datetime: %02i/%02i/%04i %02i:%02i:%02i\n",
385 DT
->Day
,DT
->Month
,DT
->Year
,DT
->Hour
,DT
->Minute
,DT
->Second
);
387 /* We need to have only two last digits of year */
390 if (DT
->Year
<2000) Year
= DT
->Year
-1900;
391 else Year
= DT
->Year
-2000;
392 } else Year
= DT
->Year
;
394 req
[0]=EncodeWithBCDAlphabet(Year
);
395 req
[1]=EncodeWithBCDAlphabet(DT
->Month
);
396 req
[2]=EncodeWithBCDAlphabet(DT
->Day
);
397 req
[3]=EncodeWithBCDAlphabet(DT
->Hour
);
398 req
[4]=EncodeWithBCDAlphabet(DT
->Minute
);
399 req
[5]=EncodeWithBCDAlphabet(DT
->Second
);
402 req
[6]=0; /* TimeZone = +-0 */
407 static int GSM_EncodeSMSFrameText(GSM_SMSMessage
*SMS
, unsigned char *buffer
, GSM_SMSMessageLayout Layout
)
409 int off
= 0; /* off - length of the user data header */
410 int size
= 0, size2
= 0, w
,p
;
413 if (SMS
->UDH
.Type
!=UDH_NoUDH
) {
414 buffer
[Layout
.firstbyte
] |= 0x40; /* GSM 03.40 section 9.2.3.23 (TP-User-Data-Header-Indicator) */
415 off
= 1 + SMS
->UDH
.Text
[0]; /* off - length of the user data header */
416 memcpy(buffer
+Layout
.Text
, SMS
->UDH
.Text
, off
); /* we copy the udh */
418 dbgprintf("UDH, length %i\n",off
);
419 if (di
.dl
== DL_TEXTALL
|| di
.dl
== DL_TEXTALLDATE
) DumpMessage(di
.df
, SMS
->UDH
.Text
, off
);
422 switch (SMS
->Coding
) {
423 case GSM_Coding_8bit
:
424 /* the mask for the 8-bit data */
425 /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme)
426 * and GSM 03.38 section 4 */
427 buffer
[Layout
.TPDCS
] |= 0xf4;
428 memcpy(buffer
+(Layout
.Text
+off
), SMS
->Text
, SMS
->Length
);
429 size2
= size
= SMS
->Length
+off
;
431 dbgprintf("8 bit SMS, length %i\n",SMS
->Length
);
432 if (di
.dl
== DL_TEXTALL
|| di
.dl
== DL_TEXTALLDATE
) DumpMessage(di
.df
,SMS
->Text
,SMS
->Length
);
435 case GSM_Coding_Default
:
441 p
= UnicodeLength(SMS
->Text
);
442 EncodeDefault(buff
, SMS
->Text
, &p
, true, NULL
);
443 size
= GSM_PackSevenBitsToEight(w
, buff
, buffer
+(Layout
.Text
+off
), p
);
445 size2
= (off
*8 + w
) / 7 + p
;
446 dbgprintf("7 bit SMS, length %i, %i\n",size
,size2
);
447 dbgprintf("%s\n",DecodeUnicodeString(SMS
->Text
));
448 if (size
> GSM_MAX_8BIT_SMS_LENGTH
) {
452 case GSM_Coding_Unicode
:
453 /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme)
454 * and GSM 03.38 section 4 */
455 buffer
[Layout
.TPDCS
] |= 0x08;
456 EncodeUnicodeSpecialNOKIAChars(buffer
+(Layout
.Text
+off
), SMS
->Text
, UnicodeLength(SMS
->Text
));
457 size
=size2
=UnicodeLength(buffer
+(Layout
.Text
+off
))*2+off
;
459 dbgprintf("Unicode SMS, length %i\n",(size2
-off
)/2);
460 if (di
.dl
== DL_TEXTALL
|| di
.dl
== DL_TEXTALLDATE
) DumpMessage(di
.df
,buffer
+(Layout
.Text
+off
), size2
-off
);
461 dbgprintf("%s\n",DecodeUnicodeString(buffer
+(Layout
.Text
+off
)));
467 - integer representation of the number od octets within the user data
468 when UD is coded using 8bit data
469 - the sum of the number of septets in UDH including any padding
470 and number of septets in UD in other case */
471 /* GSM 03.40 section 9.2.3.16 (TP-User-Data-Length) */
472 buffer
[Layout
.TPUDL
] = size2
;
476 GSM_Error
GSM_EncodeSMSFrame(GSM_SMSMessage
*SMS
, unsigned char *buffer
, GSM_SMSMessageLayout Layout
, int *length
, bool clear
)
481 /* Cleaning up to the SMS text */
482 for (i
=0;i
<Layout
.Text
;i
++) buffer
[i
] = 0;
485 /* GSM 03.40 section 9.2.3.1 (TP-Message-Type-Indicator) */
488 buffer
[Layout
.firstbyte
] |= 0x01;
490 /* SMS_Status_Report when Submit sms should have delivery report */
491 /* We DON'T CREATE FRAME FOR REAL SMS_STATUS_REPORT */
492 case SMS_Status_Report
:
493 buffer
[Layout
.firstbyte
] |= 0x01;
494 /* GSM 03.40 section 9.2.3.5 (TP-Status-Raport-Request) */
495 /* Mask when want delivery report from SMSC */
496 buffer
[Layout
.firstbyte
] |= 0x20;
499 buffer
[Layout
.firstbyte
] |= 0x00;
502 /* GSM 03.40 section 9.2.3.17 (TP-Reply-Path) */
503 if (SMS
->ReplyViaSameSMSC
) buffer
[Layout
.firstbyte
] |= 0x80;
505 if (Layout
.Number
!=255) {
506 buffer
[Layout
.Number
] = GSM_PackSemiOctetNumber(SMS
->Number
,buffer
+(Layout
.Number
+1),true);
507 dbgprintf("Recipient number \"%s\"\n",DecodeUnicodeString(SMS
->Number
));
509 if (Layout
.SMSCNumber
!=255) {
510 buffer
[Layout
.SMSCNumber
]=GSM_PackSemiOctetNumber(SMS
->SMSC
.Number
,buffer
+(Layout
.SMSCNumber
+1), false);
511 dbgprintf("SMSC number \"%s\"\n",DecodeUnicodeString(SMS
->SMSC
.Number
));
515 /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme) and GSM 03.38 section 4 */
516 if (Layout
.TPDCS
!= 255) {
517 if (SMS
->Class
>=0 && SMS
->Class
<5) buffer
[Layout
.TPDCS
] |= (240+SMS
->Class
);
520 if (Layout
.TPVP
!= 255) {
521 /* GSM 03.40 section 9.2.3.3 (TP-Validity-Period-Format) */
522 /* Bits 4 and 3: 10. TP-VP field present and integer represent (relative) */
523 buffer
[Layout
.firstbyte
] |= 0x10;
524 buffer
[Layout
.TPVP
]=((unsigned char)SMS
->SMSC
.Validity
.Relative
);
525 dbgprintf("SMS validity %02x\n",SMS
->SMSC
.Validity
.Relative
);
528 if (Layout
.DateTime
!= 255) {
529 GSM_EncodeSMSDateTime(&SMS
->DateTime
, buffer
+Layout
.DateTime
);
532 if (Layout
.TPMR
!= 255) {
533 buffer
[Layout
.TPMR
] = SMS
->MessageReference
;
536 if (SMS
->RejectDuplicates
) {
537 /* GSM 03.40 section 9.2.3.25 (TP Reject Duplicates) */
538 buffer
[Layout
.firstbyte
] |= 0x04;
541 if (Layout
.TPPID
!= 255) {
542 buffer
[Layout
.TPPID
] = 0;
543 if (SMS
->ReplaceMessage
> 0 && SMS
->ReplaceMessage
< 8) {
544 buffer
[Layout
.TPPID
] = 0x40 + SMS
->ReplaceMessage
;
548 /* size is the length of the data in octets including udh */
549 *length
=GSM_EncodeSMSFrameText(SMS
,buffer
,Layout
);
550 // if (*length == 0) return GE_UNKNOWN;
551 *length
+= Layout
.Text
;
556 /* ----------------- Some help functions ----------------------------------- */
558 void GSM_SetDefaultSMSData(GSM_SMSMessage
*SMS
)
561 SMS
->SMSC
.Location
= 1;
562 SMS
->SMSC
.Validity
.VPF
= GSM_RelativeFormat
;
563 SMS
->SMSC
.Validity
.Relative
= GSMV_Max_Time
;
564 SMS
->ReplyViaSameSMSC
= false;
565 SMS
->UDH
.Type
= UDH_NoUDH
;
567 SMS
->UDH
.Text
[0] = 0;
569 SMS
->UDH
.ID16bit
= 0;
570 SMS
->UDH
.PartNumber
= 0;
571 SMS
->UDH
.AllParts
= 0;
572 SMS
->Coding
= GSM_Coding_Default
;
575 SMS
->PDU
= SMS_Submit
;
576 SMS
->RejectDuplicates
= false;
577 SMS
->MessageReference
= 0;
578 SMS
->ReplaceMessage
= 0;
581 /* This part is required to save SMS */
582 SMS
->State
= GSM_UnSent
;
584 SMS
->Folder
= 0x02; /*Outbox*/
585 GSM_GetCurrentDateTime (&SMS
->DateTime
);
591 * GSM 03.40 section 9.2.3.24
593 void GSM_EncodeUDHHeader(GSM_UDHHeader
*UDH
)
602 UDH
->Length
= UDH
->Text
[0] + 1;
606 if (UDHHeaders
[i
].Type
==UDH_NoUDH
) {
607 dbgprintf("Not supported UDH type\n");
610 if (UDHHeaders
[i
].Type
==UDH
->Type
) {
612 UDH
->Text
[0] = UDHHeaders
[i
].Length
;
613 memcpy(UDH
->Text
+1, UDHHeaders
[i
].Text
, UDHHeaders
[i
].Length
);
614 UDH
->Length
= UDH
->Text
[0] + 1;
616 if (UDHHeaders
[i
].ID8bit
!= -1) {
617 UDH
->Text
[UDHHeaders
[i
].ID8bit
+1] = UDH
->ID8bit
% 256;
621 if (UDHHeaders
[i
].ID16bit
!= -1) {
622 UDH
->Text
[UDHHeaders
[i
].ID16bit
+1] = UDH
->ID16bit
/ 256;
623 UDH
->Text
[UDHHeaders
[i
].ID16bit
+2] = UDH
->ID16bit
% 256;
627 if (UDHHeaders
[i
].PartNumber
!= -1) {
628 UDH
->Text
[UDHHeaders
[i
].PartNumber
+1] = UDH
->PartNumber
;
630 UDH
->PartNumber
= -1;
632 if (UDHHeaders
[i
].AllParts
!= -1) {
633 UDH
->Text
[UDHHeaders
[i
].AllParts
+1] = UDH
->AllParts
;
644 /* How should editor hadle tabs in this file? Add editor commands here.
645 * vim: noexpandtab sw=8 ts=8 sts=8: