6 #include "../gsmcomon.h"
7 #include "../misc/coding/coding.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 /* The timezone is given in quarters. The base is GMT. */
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 aviable"); 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 for request for 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
);
590 /* This function encodes the UserDataHeader as described in:
591 * - GSM 03.40 version 6.1.0 Release 1997, section 9.2.3.24
592 * - Smart Messaging Specification, Revision 1.0.0, September 15, 1997
594 void GSM_EncodeUDHHeader(GSM_UDHHeader
*UDH
)
603 UDH
->Length
= UDH
->Text
[0] + 1;
607 if (UDHHeaders
[i
].Type
==UDH_NoUDH
)
609 dbgprintf("Not supported UDH type\n");
612 if (UDHHeaders
[i
].Type
==UDH
->Type
)
615 UDH
->Text
[0] = UDHHeaders
[i
].Length
;
616 memcpy(UDH
->Text
+1, UDHHeaders
[i
].Text
, UDHHeaders
[i
].Length
);
617 UDH
->Length
= UDH
->Text
[0] + 1;
619 if (UDHHeaders
[i
].ID8bit
!= -1) {
620 UDH
->Text
[UDHHeaders
[i
].ID8bit
+1] = UDH
->ID8bit
% 256;
624 if (UDHHeaders
[i
].ID16bit
!= -1) {
625 UDH
->Text
[UDHHeaders
[i
].ID16bit
+1] = UDH
->ID16bit
/ 256;
626 UDH
->Text
[UDHHeaders
[i
].ID16bit
+2] = UDH
->ID16bit
% 256;
630 if (UDHHeaders
[i
].PartNumber
!= -1) {
631 UDH
->Text
[UDHHeaders
[i
].PartNumber
+1] = UDH
->PartNumber
;
633 UDH
->PartNumber
= -1;
635 if (UDHHeaders
[i
].AllParts
!= -1) {
636 UDH
->Text
[UDHHeaders
[i
].AllParts
+1] = UDH
->AllParts
;
647 /* ----------------- Splitting SMS into parts ------------------------------ */
649 static unsigned char GSM_MakeSMSIDFromTime()
652 unsigned char retval
;
654 GSM_GetCurrentDateTime (&Date
);
655 retval
= Date
.Second
;
656 switch (Date
.Minute
/10) {
657 case 2: case 7: retval
= retval
+ 60; break;
658 case 4: case 8: retval
= retval
+ 120; break;
659 case 9: case 5: case 0: retval
= retval
+ 180; break;
661 retval
+= Date
.Minute
/10;
665 static void GSM_Find_Free_Used_SMS2(GSM_Coding_Type Coding
,GSM_SMSMessage SMS
, int *UsedText
, int *FreeText
, int *FreeBytes
)
670 case GSM_Coding_Default
:
671 FindDefaultAlphabetLen(SMS
.Text
,&UsedBytes
,UsedText
,500);
672 UsedBytes
= *UsedText
* 7 / 8;
673 if (UsedBytes
* 8 / 7 != *UsedText
) UsedBytes
++;
674 *FreeBytes
= GSM_MAX_8BIT_SMS_LENGTH
- SMS
.UDH
.Length
- UsedBytes
;
675 *FreeText
= (GSM_MAX_8BIT_SMS_LENGTH
- SMS
.UDH
.Length
) * 8 / 7 - *UsedText
;
677 case GSM_Coding_Unicode
:
678 *UsedText
= UnicodeLength(SMS
.Text
);
679 UsedBytes
= *UsedText
* 2;
680 *FreeBytes
= GSM_MAX_8BIT_SMS_LENGTH
- SMS
.UDH
.Length
- UsedBytes
;
681 *FreeText
= *FreeBytes
/ 2;
683 case GSM_Coding_8bit
:
684 *UsedText
= UsedBytes
= SMS
.Length
;
685 *FreeBytes
= GSM_MAX_8BIT_SMS_LENGTH
- SMS
.UDH
.Length
- UsedBytes
;
686 *FreeText
= *FreeBytes
;
689 dbgprintf("UDH len %i, UsedBytes %i, FreeText %i, UsedText %i, FreeBytes %i\n",SMS
.UDH
.Length
,UsedBytes
,*FreeText
,*UsedText
,*FreeBytes
);
692 GSM_Error
GSM_AddSMS_Text_UDH(GSM_MultiSMSMessage
*SMS
,
693 GSM_Coding_Type Coding
,
701 int FreeText
,FreeBytes
,Copy
,i
,j
;
703 dbgprintf("Checking used\n");
704 GSM_Find_Free_Used_SMS2(Coding
,SMS
->SMS
[SMS
->Number
], UsedText
, &FreeText
, &FreeBytes
);
707 dbgprintf("Adding UDH\n");
708 if (FreeBytes
- BufferLen
<= 0) {
709 dbgprintf("Going to the new SMS\n");
711 GSM_Find_Free_Used_SMS2(Coding
,SMS
->SMS
[SMS
->Number
], UsedText
, &FreeText
, &FreeBytes
);
713 if (SMS
->SMS
[SMS
->Number
].UDH
.Length
== 0) {
714 SMS
->SMS
[SMS
->Number
].UDH
.Length
= 1;
715 SMS
->SMS
[SMS
->Number
].UDH
.Text
[0] = 0x00;
717 memcpy(SMS
->SMS
[SMS
->Number
].UDH
.Text
+SMS
->SMS
[SMS
->Number
].UDH
.Length
,Buffer
,BufferLen
);
718 SMS
->SMS
[SMS
->Number
].UDH
.Length
+= BufferLen
;
719 SMS
->SMS
[SMS
->Number
].UDH
.Text
[0] += BufferLen
;
720 SMS
->SMS
[SMS
->Number
].UDH
.Type
= UDH_UserUDH
;
721 dbgprintf("UDH added %i\n",BufferLen
);
723 dbgprintf("Adding text\n");
725 dbgprintf("Going to the new SMS\n");
727 GSM_Find_Free_Used_SMS2(Coding
,SMS
->SMS
[SMS
->Number
], UsedText
, &FreeText
, &FreeBytes
);
731 dbgprintf("copy %i\n",Copy
);
732 if (BufferLen
< Copy
) Copy
= BufferLen
;
733 dbgprintf("copy %i\n",Copy
);
736 case GSM_Coding_Default
:
737 FindDefaultAlphabetLen(Buffer
,&i
,&j
,FreeText
);
738 dbgprintf("def length %i %i\n",i
,j
);
739 SMS
->SMS
[SMS
->Number
].Text
[UnicodeLength(SMS
->SMS
[SMS
->Number
].Text
)*2+i
*2] = 0;
740 SMS
->SMS
[SMS
->Number
].Text
[UnicodeLength(SMS
->SMS
[SMS
->Number
].Text
)*2+i
*2+1] = 0;
741 memcpy(SMS
->SMS
[SMS
->Number
].Text
+UnicodeLength(SMS
->SMS
[SMS
->Number
].Text
)*2,Buffer
,i
*2);
744 SMS
->SMS
[SMS
->Number
].Length
+= i
;
746 case GSM_Coding_Unicode
:
747 SMS
->SMS
[SMS
->Number
].Text
[UnicodeLength(SMS
->SMS
[SMS
->Number
].Text
)*2+Copy
*2] = 0;
748 SMS
->SMS
[SMS
->Number
].Text
[UnicodeLength(SMS
->SMS
[SMS
->Number
].Text
)*2+Copy
*2+1] = 0;
749 memcpy(SMS
->SMS
[SMS
->Number
].Text
+UnicodeLength(SMS
->SMS
[SMS
->Number
].Text
)*2,Buffer
,Copy
*2);
750 *CopiedText
= *CopiedSMSText
= Copy
;
751 SMS
->SMS
[SMS
->Number
].Length
+= Copy
;
753 case GSM_Coding_8bit
:
754 memcpy(SMS
->SMS
[SMS
->Number
].Text
+SMS
->SMS
[SMS
->Number
].Length
,Buffer
,Copy
);
755 SMS
->SMS
[SMS
->Number
].Length
+= Copy
;
756 *CopiedText
= *CopiedSMSText
= Copy
;
759 dbgprintf("Text added\n");
762 dbgprintf("Checking on the end\n");
763 GSM_Find_Free_Used_SMS2(Coding
,SMS
->SMS
[SMS
->Number
], UsedText
, &FreeText
, &FreeBytes
);
768 void GSM_MakeMultiPartSMS(GSM_MultiSMSMessage
*SMS
,
769 unsigned char *MessageBuffer
,
772 GSM_Coding_Type Coding
,
774 unsigned char ReplaceMessage
)
776 int j
,Len
,UsedText
,CopiedText
,CopiedSMSText
;
782 GSM_SetDefaultSMSData(&SMS
->SMS
[SMS
->Number
]);
783 SMS
->SMS
[SMS
->Number
].Class
= Class
;
784 SMS
->SMS
[SMS
->Number
].Coding
= Coding
;
786 SMS
->SMS
[SMS
->Number
].UDH
.Type
= UDHType
;
787 GSM_EncodeUDHHeader(&SMS
->SMS
[SMS
->Number
].UDH
);
789 if (Coding
== GSM_Coding_8bit
) {
790 GSM_AddSMS_Text_UDH(SMS
,Coding
,MessageBuffer
+Len
,MessageLength
- Len
,false,&UsedText
,&CopiedText
,&CopiedSMSText
);
792 GSM_AddSMS_Text_UDH(SMS
,Coding
,MessageBuffer
+Len
*2,MessageLength
- Len
,false,&UsedText
,&CopiedText
,&CopiedSMSText
);
795 dbgprintf("%i %i\n",Len
,MessageLength
);
796 if (Len
== MessageLength
) break;
797 if (SMS
->Number
== MAX_MULTI_SMS
) break;
803 UDHID
= GSM_MakeSMSIDFromTime();
804 GSM_GetCurrentDateTime (&Date
);
805 for (j
=0;j
<SMS
->Number
;j
++)
807 SMS
->SMS
[j
].UDH
.Type
= UDHType
;
808 SMS
->SMS
[j
].UDH
.ID8bit
= UDHID
;
809 SMS
->SMS
[j
].UDH
.ID16bit
= UDHID
+ 256 * Date
.Hour
;
810 SMS
->SMS
[j
].UDH
.PartNumber
= j
+1;
811 SMS
->SMS
[j
].UDH
.AllParts
= SMS
->Number
;
812 GSM_EncodeUDHHeader(&SMS
->SMS
[j
].UDH
);
814 if (SMS
->Number
== 1) SMS
->SMS
[0].ReplaceMessage
= ReplaceMessage
;
817 /* Calculates number of SMS and number of left chars in SMS */
818 void GSM_SMSCounter(int MessageLength
,
819 unsigned char *MessageBuffer
,
821 GSM_Coding_Type Coding
,
825 int UsedText
,FreeBytes
;
826 GSM_MultiSMSMessage MultiSMS
;
829 GSM_MakeMultiPartSMS(&MultiSMS
,MessageBuffer
,MessageLength
,UDHType
,Coding
,-1,false);
830 GSM_Find_Free_Used_SMS2(Coding
,MultiSMS
.SMS
[MultiSMS
.Number
-1], &UsedText
, CharsLeft
, &FreeBytes
);
831 *SMSNum
= MultiSMS
.Number
;
834 /* Nokia Smart Messaging 3.0 */
835 static void GSM_EncodeSMS30MultiPartSMS(GSM_EncodeMultiPartSMSInfo
*Info
,
836 char *Buffer
, int *Length
)
840 /*SM version. Here 3.0*/
841 Buffer
[(*Length
)++] = 0x30;
843 if (Info
->Entries
[0].ID
== SMS_NokiaProfileLong
) {
844 if (Info
->Entries
[0].Buffer
!= NULL
) {
845 if (Info
->Entries
[0].Buffer
[0]!=0x00 || Info
->Entries
[0].Buffer
[1]!=0x00) {
846 Buffer
[(*Length
)++] = SM30_PROFILENAME
;
847 Buffer
[(*Length
)++] = 0x00;
848 Buffer
[(*Length
)++] = 2*UnicodeLength(Info
->Entries
[0].Buffer
);
849 CopyUnicodeString(Buffer
+(*Length
),Info
->Entries
[0].Buffer
);
850 *Length
= *Length
+ 2*UnicodeLength(Info
->Entries
[0].Buffer
);
853 if (Info
->Entries
[0].Ringtone
!= NULL
) {
854 Buffer
[(*Length
)++] = SM30_RINGTONE
;
855 /* Length for this part later will be changed */
856 Buffer
[(*Length
)++] = 0x01;
857 Buffer
[(*Length
)++] = 0x00;
858 /* Smart Messaging 3.0 says: 16*9=144 bytes,
859 * but on 3310 4.02 it was possible to save about 196 chars
860 * (without cutting) */
862 Info
->Entries
[0].RingtoneNotes
=GSM_EncodeNokiaRTTLRingtone(*Info
->Entries
[0].Ringtone
,Buffer
+(*Length
),&len
);
863 Buffer
[(*Length
)-2] = len
/ 256;
864 Buffer
[(*Length
)-1] = len
% 256;
865 *Length
= *Length
+ len
;
868 if (Info
->Entries
[0].Bitmap
!= NULL
) {
869 if (Info
->Entries
[0].ID
== SMS_NokiaPictureImageLong
) {
870 Buffer
[(*Length
)++] = SM30_OTA
;
872 Buffer
[(*Length
)++] = SM30_SCREENSAVER
;
874 Buffer
[(*Length
)++] = 0x01;
875 Buffer
[(*Length
)++] = 0x00;
876 NOKIA_CopyBitmap(GSM_NokiaPictureImage
, &Info
->Entries
[0].Bitmap
->Bitmap
[0], Buffer
, Length
);
877 if (Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
[0]!=0 || Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
[1]!=0) {
878 if (Info
->UnicodeCoding
) {
879 Buffer
[(*Length
)++] = SM30_UNICODETEXT
;
880 /* Length for text part */
881 Buffer
[(*Length
)++] = 0x00;
882 Buffer
[(*Length
)++] = UnicodeLength(Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
)*2;
883 memcpy(Buffer
+(*Length
),Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
,UnicodeLength(Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
)*2);
884 *Length
= *Length
+ UnicodeLength(Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
)*2;
886 /*ID for ISO-8859-1 text*/
887 Buffer
[(*Length
)++] = SM30_ISOTEXT
;
888 Buffer
[(*Length
)++] = 0x00;
889 Buffer
[(*Length
)++] = UnicodeLength(Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
);
890 memcpy(Buffer
+(*Length
),DecodeUnicodeString(Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
),UnicodeLength(Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
));
891 *Length
= *Length
+UnicodeLength(Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
);
897 /* EMS Developers' Guidelines from www.sonyericsson.com
900 static GSM_Error
GSM_EncodeEMSMultiPartSMS(GSM_EncodeMultiPartSMSInfo
*Info
,
901 GSM_MultiSMSMessage
*SMS
,
904 unsigned char Buffer
[GSM_MAX_SMS_LENGTH
*2*MAX_MULTI_SMS
];
905 int i
,UsedText
,j
,Length
,Width
,Height
,z
,x
,y
;
907 int Used
,FreeText
,FreeBytes
,Width2
,CopiedText
,CopiedSMSText
;
909 GSM_Bitmap Bitmap
,Bitmap2
;
911 GSM_Coding_Type Coding
= GSM_Coding_Default
;
912 GSM_Phone_Bitmap_Types BitmapType
;
913 EncodeMultiPartSMSEntry
*Entry
;
918 if (UDHType
!= UDH_NoUDH
) dbgprintf("linked EMS\n");
921 if (Info
->UnicodeCoding
) Coding
= GSM_Coding_Unicode
;
923 /* Cleaning on the start */
924 for (i
=0;i
<MAX_MULTI_SMS
;i
++) {
925 GSM_SetDefaultSMSData(&SMS
->SMS
[i
]);
926 SMS
->SMS
[i
].UDH
.Type
= UDHType
;
927 GSM_EncodeUDHHeader(&SMS
->SMS
[i
].UDH
);
928 SMS
->SMS
[i
].Coding
= Coding
;
932 for (i
=0;i
<Info
->EntriesNum
;i
++) {
933 Entry
= &Info
->Entries
[i
];
936 case SMS_ConcatenatedTextLong
:
937 case SMS_ConcatenatedTextLong16bit
:
940 if (Entry
->Left
|| Entry
->Right
||
941 Entry
->Center
|| Entry
->Large
||
942 Entry
->Small
|| Entry
->Bold
||
943 Entry
->Italic
|| Entry
->Underlined
||
944 Entry
->Strikethrough
) {
945 Buffer
[0] = 0x0A; /* ID for text format */
946 Buffer
[1] = 0x03; /* length of rest */
947 Buffer
[2] = 0x00; /* Position in EMS msg */
948 Buffer
[3] = 0x00; /* how many chars */
949 Buffer
[4] = 0x00; /* formatting bits */
951 } else if (Entry
->Right
) { Buffer
[4] |= 1;
952 } else if (Entry
->Center
) { Buffer
[4] |= 2;
953 } else Buffer
[4] |= 3;
954 if (Entry
->Large
) { Buffer
[4] |= 4;
955 } else if (Entry
->Small
) { Buffer
[4] |= 8;}
956 if (Entry
->Bold
) Buffer
[4] |= 16;
957 if (Entry
->Italic
) Buffer
[4] |= 32;
958 if (Entry
->Underlined
) Buffer
[4] |= 64;
959 if (Entry
->Strikethrough
) Buffer
[4] |= 128;
960 GSM_AddSMS_Text_UDH(SMS
,Coding
,Buffer
,5,true,&UsedText
,&CopiedText
,&CopiedSMSText
);
961 GSM_Find_Free_Used_SMS2(Coding
,SMS
->SMS
[SMS
->Number
], &UsedText
, &FreeText
, &FreeBytes
);
962 if (FreeText
== 0) continue;
964 GSM_AddSMS_Text_UDH(SMS
,Coding
,Entry
->Buffer
+Len
*2,UnicodeLength(Entry
->Buffer
) - Len
,false,&UsedText
,&CopiedText
,&CopiedSMSText
);
965 if (Entry
->Left
|| Entry
->Right
||
966 Entry
->Center
|| Entry
->Large
||
967 Entry
->Small
|| Entry
->Bold
||
968 Entry
->Italic
|| Entry
->Underlined
||
969 Entry
->Strikethrough
) {
970 SMS
->SMS
[SMS
->Number
].UDH
.Text
[SMS
->SMS
[SMS
->Number
].UDH
.Length
-3] = UsedText
;
971 SMS
->SMS
[SMS
->Number
].UDH
.Text
[SMS
->SMS
[SMS
->Number
].UDH
.Length
-2] = CopiedSMSText
;
974 if (Len
== UnicodeLength(Entry
->Buffer
)) break;
975 dbgprintf("%i %i\n",Len
,UnicodeLength(Entry
->Buffer
));
978 case SMS_EMSPredefinedSound
:
979 case SMS_EMSPredefinedAnimation
:
980 if (Entry
->ID
== SMS_EMSPredefinedSound
) {
981 Buffer
[0] = 0x0B; /* ID for def.sound */
983 Buffer
[0] = 0x0D; /* ID for def.animation */
985 Buffer
[1] = 0x02; /* Length of rest */
986 Buffer
[2] = 0x00; /* Position in EMS msg */
987 Buffer
[3] = Entry
->Number
; /* Number of anim. */
988 GSM_AddSMS_Text_UDH(SMS
,Coding
,Buffer
,4,true,&UsedText
,&CopiedText
,&CopiedSMSText
);
989 SMS
->SMS
[SMS
->Number
].UDH
.Text
[SMS
->SMS
[SMS
->Number
].UDH
.Length
-2] = UsedText
;
991 case SMS_EMSSonyEricssonSound
:
994 if (Entry
->Protected
) {
995 Buffer
[0] = 0x17; /* ID for ODI */
996 Buffer
[1] = 2; /* Length of rest */
997 Buffer
[2] = 1; /* Number of protected objects */
998 Buffer
[3] = 1; /* 1=Protected,0=Not protected */
999 GSM_AddSMS_Text_UDH(SMS
,Coding
,Buffer
,4,true,&UsedText
,&CopiedText
,&CopiedSMSText
);
1002 Length
= 128; /* 128 bytes is maximal length from specs */
1003 switch (Entry
->ID
) {
1004 case SMS_EMSSound10
:
1005 Entry
->RingtoneNotes
= GSM_EncodeEMSSound(*Entry
->Ringtone
, Buffer
+3, &Length
, 1.0, true);
1007 case SMS_EMSSound12
:
1008 Entry
->RingtoneNotes
= GSM_EncodeEMSSound(*Entry
->Ringtone
, Buffer
+3, &Length
, 1.2, true);
1010 case SMS_EMSSonyEricssonSound
:
1011 Entry
->RingtoneNotes
= GSM_EncodeEMSSound(*Entry
->Ringtone
, Buffer
+3, &Length
, 0, true);
1017 Buffer
[0] = 0x0C; /* ID for EMS sound */
1018 Buffer
[1] = Length
+1; /* Length of rest */
1019 Buffer
[2] = 0x00; /* Position in EMS msg */
1020 GSM_AddSMS_Text_UDH(SMS
,Coding
,Buffer
,Length
+3,true,&UsedText
,&CopiedText
,&CopiedSMSText
);
1021 SMS
->SMS
[SMS
->Number
].UDH
.Text
[SMS
->SMS
[SMS
->Number
].UDH
.Length
-Length
-1] = UsedText
;
1023 case SMS_EMSSonyEricssonSoundLong
:
1024 case SMS_EMSSound10Long
:
1025 case SMS_EMSSound12Long
:
1026 memcpy(&Ring
,Entry
->Ringtone
,sizeof(GSM_Ringtone
));
1028 /* First check if we can use classic format */
1029 Length
= 128; /* 128 bytes is maximal length from specs */
1030 switch (Entry
->ID
) {
1031 case SMS_EMSSound10Long
:
1032 Entry
->RingtoneNotes
= GSM_EncodeEMSSound(Ring
, Buffer
+3, &Length
, 1.0, true);
1034 case SMS_EMSSound12Long
:
1035 Entry
->RingtoneNotes
= GSM_EncodeEMSSound(Ring
, Buffer
+3, &Length
, 1.2, true);
1037 case SMS_EMSSonyEricssonSoundLong
:
1038 Entry
->RingtoneNotes
= GSM_EncodeEMSSound(Ring
, Buffer
+3, &Length
, 0, true);
1043 if (Entry
->RingtoneNotes
== Ring
.NoteTone
.NrCommands
) {
1044 if (Entry
->Protected
) {
1045 Buffer
[0] = 0x17; /* ID for ODI */
1046 Buffer
[1] = 2; /* Length of rest */
1047 Buffer
[2] = 1; /* Number of protected objects */
1048 Buffer
[3] = 1; /* 1=Protected,0=Not protected */
1049 GSM_AddSMS_Text_UDH(SMS
,Coding
,Buffer
,4,true,&UsedText
,&CopiedText
,&CopiedSMSText
);
1052 Buffer
[0] = 0x0C; /* ID for EMS sound */
1053 Buffer
[1] = Length
+1; /* Length of rest */
1054 Buffer
[2] = 0x00; /* Position in EMS msg */
1055 GSM_AddSMS_Text_UDH(SMS
,Coding
,Buffer
,Length
+3,true,&UsedText
,&CopiedText
,&CopiedSMSText
);
1056 SMS
->SMS
[SMS
->Number
].UDH
.Text
[SMS
->SMS
[SMS
->Number
].UDH
.Length
-Length
-1] = UsedText
;
1060 /* Find free place in first SMS */
1061 GSM_Find_Free_Used_SMS2(Coding
,SMS
->SMS
[SMS
->Number
], &UsedText
, &FreeText
, &FreeBytes
);
1062 Length
= FreeBytes
- 3;
1063 if (Entry
->Protected
) Length
= Length
- 4;
1064 if (Length
< 0) Length
= 128;
1065 if (Length
> 128) Length
= 128;
1067 memcpy(&Ring
,Entry
->Ringtone
,sizeof(GSM_Ringtone
));
1069 /* Checking number of SMS */
1074 if (FreeBytes
!= 0) {
1076 for (j
=FreeBytes
;j
<Ring
.NoteTone
.NrCommands
;j
++) {
1077 memcpy(&Ring
.NoteTone
.Commands
[z
],&Ring
.NoteTone
.Commands
[j
],sizeof(GSM_RingCommand
));
1080 Ring
.NoteTone
.NrCommands
-= FreeBytes
;
1081 if (Ring
.NoteTone
.NrCommands
== 0) break;
1082 Length
= 128; /* 128 bytes is maximal length from specs */
1084 switch (Entry
->ID
) {
1085 case SMS_EMSSound10Long
:
1086 FreeBytes
= GSM_EncodeEMSSound(Ring
, Buffer
+3, &Length
, 1.0, start
);
1088 case SMS_EMSSound12Long
:
1089 FreeBytes
= GSM_EncodeEMSSound(Ring
, Buffer
+3, &Length
, 1.2, start
);
1091 case SMS_EMSSonyEricssonSoundLong
:
1092 FreeBytes
= GSM_EncodeEMSSound(Ring
, Buffer
+3, &Length
, 0, start
);
1100 dbgprintf("Used SMS: %i\n",Used
);
1102 if (Entry
->Protected
) {
1103 Buffer
[0] = 0x17; /* ID for ODI */
1104 Buffer
[1] = 2; /* Length of rest */
1105 Buffer
[2] = Used
+1; /* Number of protected objects */
1106 Buffer
[3] = 1; /* 1=Protected,0=Not protected */
1107 GSM_AddSMS_Text_UDH(SMS
,Coding
,Buffer
,4,true,&UsedText
,&CopiedText
,&CopiedSMSText
);
1111 Buffer
[0] = 0x13; /* ID for UPI */
1112 Buffer
[1] = 1; /* Length of rest */
1113 Buffer
[2] = Used
; /* Number of used parts */
1114 GSM_AddSMS_Text_UDH(SMS
,Coding
,Buffer
,3,true,&UsedText
,&CopiedText
,&CopiedSMSText
);
1116 /* Find free place in first SMS */
1117 GSM_Find_Free_Used_SMS2(Coding
,SMS
->SMS
[SMS
->Number
], &UsedText
, &FreeText
, &FreeBytes
);
1118 Length
= FreeBytes
- 3;
1119 if (Length
< 0) Length
= 128;
1120 if (Length
> 128) Length
= 128;
1122 memcpy(&Ring
,Entry
->Ringtone
,sizeof(GSM_Ringtone
));
1128 if (FreeBytes
!= 0) {
1130 for (j
=FreeBytes
;j
<Ring
.NoteTone
.NrCommands
;j
++) {
1131 memcpy(&Ring
.NoteTone
.Commands
[z
],&Ring
.NoteTone
.Commands
[j
],sizeof(GSM_RingCommand
));
1134 Ring
.NoteTone
.NrCommands
-= FreeBytes
;
1135 if (Ring
.NoteTone
.NrCommands
== 0) break;
1136 Length
= 128; /* 128 bytes is maximal length from specs */
1138 switch (Entry
->ID
) {
1139 case SMS_EMSSound10Long
:
1140 FreeBytes
= GSM_EncodeEMSSound(Ring
, Buffer
+3, &Length
, 1.0, start
);
1142 case SMS_EMSSound12Long
:
1143 FreeBytes
= GSM_EncodeEMSSound(Ring
, Buffer
+3, &Length
, 1.2, start
);
1145 case SMS_EMSSonyEricssonSoundLong
:
1146 FreeBytes
= GSM_EncodeEMSSound(Ring
, Buffer
+3, &Length
, 0, start
);
1151 Buffer
[0] = 0x0C; /* ID for EMS sound */
1152 Buffer
[1] = Length
+1; /* Length of rest */
1153 Buffer
[2] = 0x00; /* Position in EMS msg */
1154 GSM_AddSMS_Text_UDH(SMS
,Coding
,Buffer
,Length
+3,true,&UsedText
,&CopiedText
,&CopiedSMSText
);
1155 SMS
->SMS
[SMS
->Number
].UDH
.Text
[SMS
->SMS
[SMS
->Number
].UDH
.Length
-Length
-1] = UsedText
;
1159 Entry
->RingtoneNotes
= Entry
->Ringtone
->NoteTone
.NrCommands
;
1162 case SMS_EMSAnimation
:
1163 if (Entry
->Protected
) {
1164 Buffer
[0] = 0x17; /* ID for ODI */
1165 Buffer
[1] = 2; /* Length of rest */
1166 Buffer
[2] = 1; /* Number of protected objects */
1167 Buffer
[3] = 1; /* 1=Protected,0=Not protected */
1168 GSM_AddSMS_Text_UDH(SMS
,Coding
,Buffer
,4,true,&UsedText
,&CopiedText
,&CopiedSMSText
);
1171 if (Entry
->Bitmap
->Bitmap
[0].Width
> 8 || Entry
->Bitmap
->Bitmap
[0].Height
> 8) {
1172 BitmapType
= GSM_EMSMediumPicture
; /* Bitmap 16x16 */
1173 Buffer
[0] = 0x0E; /* ID for 16x16 animation */
1175 BitmapType
= GSM_EMSSmallPicture
; /* Bitmap 8x8 */
1176 Buffer
[0] = 0x0F; /* ID for 8x8 animation */
1178 Length
= PHONE_GetBitmapSize(BitmapType
,0,0);
1180 Buffer
[1] = Length
*Entry
->Bitmap
->Number
+ 1; /* Length of rest */
1181 Buffer
[2] = 0x00; /* Position in EMS msg */
1182 for (j
=0;j
<Entry
->Bitmap
->Number
;j
++) {
1183 PHONE_EncodeBitmap(BitmapType
, Buffer
+3+j
*Length
, &Entry
->Bitmap
->Bitmap
[j
]);
1185 GSM_AddSMS_Text_UDH(SMS
,Coding
,Buffer
,3+Length
*Entry
->Bitmap
->Number
,true,&UsedText
,&CopiedText
,&CopiedSMSText
);
1186 SMS
->SMS
[SMS
->Number
].UDH
.Text
[SMS
->SMS
[SMS
->Number
].UDH
.Length
-1-Length
*Entry
->Bitmap
->Number
] = UsedText
;
1188 case SMS_EMSFixedBitmap
:
1189 if (Entry
->Protected
) {
1190 Buffer
[0] = 0x17; /* ID for ODI */
1191 Buffer
[1] = 2; /* Length of rest */
1192 Buffer
[2] = 1; /* Number of protected objects */
1193 Buffer
[3] = 1; /* 1=Protected,0=Not protected */
1194 GSM_AddSMS_Text_UDH(SMS
,Coding
,Buffer
,4,true,&UsedText
,&CopiedText
,&CopiedSMSText
);
1197 if (Entry
->Bitmap
->Bitmap
[0].Width
> 16 || Entry
->Bitmap
->Bitmap
[0].Height
> 16) {
1198 BitmapType
= GSM_EMSBigPicture
; /* Bitmap 32x32 */
1199 Buffer
[0] = 0x10; /* ID for EMS bitmap */
1201 BitmapType
= GSM_EMSMediumPicture
; /* Bitmap 16x16 */
1202 Buffer
[0] = 0x11; /* ID for EMS bitmap */
1204 Length
= PHONE_GetBitmapSize(BitmapType
,0,0);
1205 PHONE_GetBitmapWidthHeight(BitmapType
, &Width
, &Height
);
1207 Buffer
[1] = Length
+ 1; /* Length of rest */
1208 Buffer
[2] = 0x00; /* Position in EMS msg */
1209 PHONE_EncodeBitmap(BitmapType
,Buffer
+3, &Entry
->Bitmap
->Bitmap
[0]);
1210 GSM_AddSMS_Text_UDH(SMS
,Coding
,Buffer
,3+Length
,true,&UsedText
,&CopiedText
,&CopiedSMSText
);
1211 SMS
->SMS
[SMS
->Number
].UDH
.Text
[SMS
->SMS
[SMS
->Number
].UDH
.Length
-1-Length
] = UsedText
;
1213 case SMS_EMSVariableBitmapLong
:
1214 BitmapType
= GSM_EMSVariablePicture
;
1215 Width
= Entry
->Bitmap
->Bitmap
[0].Width
;
1216 Height
= Entry
->Bitmap
->Bitmap
[0].Height
;
1217 memcpy(&Bitmap
,&Entry
->Bitmap
->Bitmap
[0],sizeof(GSM_Bitmap
));
1219 /* First check if we can use classical format */
1221 /* Width should be multiply of 8 */
1222 while (Width
% 8 != 0) Width
--;
1225 if (Width
<= 96 && Height
<= 128) break;
1229 Length
= PHONE_GetBitmapSize(BitmapType
,Width
,Height
);
1230 if (Length
<= 128) {
1231 if (Entry
->Protected
) {
1232 Buffer
[0] = 0x17; /* ID for ODI */
1233 Buffer
[1] = 2; /* Length of rest */
1234 Buffer
[2] = 1; /* Number of protected objects */
1235 Buffer
[3] = 1; /* 1=Protected,0=Not protected */
1236 GSM_AddSMS_Text_UDH(SMS
,Coding
,Buffer
,4,true,&UsedText
,&CopiedText
,&CopiedSMSText
);
1239 Buffer
[0] = 0x12; /* ID for EMS bitmap */
1240 Buffer
[1] = Length
+ 3; /* Length of rest */
1241 Buffer
[2] = 0x00; /* Position in EMS msg */
1242 Buffer
[3] = Width
/8; /* Bitmap width/8 */
1243 Buffer
[4] = Height
; /* Bitmap height */
1245 GSM_ResizeBitmap(&Bitmap
, &Entry
->Bitmap
->Bitmap
[0], Width
, Height
);
1247 if (di
.dl
== DL_TEXTALL
|| di
.dl
== DL_TEXTALLDATE
) GSM_PrintBitmap(di
.df
,&Bitmap
);
1249 PHONE_EncodeBitmap(BitmapType
,Buffer
+5, &Bitmap
);
1250 GSM_AddSMS_Text_UDH(SMS
,Coding
,Buffer
,5+Length
,true,&UsedText
,&CopiedText
,&CopiedSMSText
);
1251 SMS
->SMS
[SMS
->Number
].UDH
.Text
[SMS
->SMS
[SMS
->Number
].UDH
.Length
-3-Length
] = UsedText
;
1255 /* Find free place in first SMS */
1256 GSM_Find_Free_Used_SMS2(Coding
,SMS
->SMS
[SMS
->Number
], &UsedText
, &FreeText
, &FreeBytes
);
1258 Length
= FreeBytes
- 3;
1259 if (Entry
->Protected
) Length
= Length
- 4;
1260 if (Length
< 0) Length
= 128;
1261 if (Length
> 128) Length
= 128;
1263 /* Checking number of SMS */
1265 while (FreeBytes
!= Width
) {
1268 if (FreeBytes
+Width2
== Width
) break;
1270 if (PHONE_GetBitmapSize(BitmapType
,Width2
+8,Height
) > Length
) break;
1272 Width2
= Width2
+ 8;
1274 FreeBytes
= FreeBytes
+ Width2
;
1278 dbgprintf("Used SMS: %i\n",Used
);
1280 if (Entry
->Protected
) {
1281 Buffer
[0] = 0x17; /* ID for ODI */
1282 Buffer
[1] = 2; /* Length of rest */
1283 Buffer
[2] = Used
+1; /* Number of protected objects */
1284 Buffer
[3] = 1; /* 1=Protected,0=Not protected */
1285 GSM_AddSMS_Text_UDH(SMS
,Coding
,Buffer
,4,true,&UsedText
,&CopiedText
,&CopiedSMSText
);
1289 Buffer
[0] = 0x13; /* ID for UPI */
1290 Buffer
[1] = 1; /* Length of rest */
1291 Buffer
[2] = Used
; /* Number of used parts */
1293 /* Find free place in first SMS */
1294 GSM_AddSMS_Text_UDH(SMS
,Coding
,Buffer
,3,true,&UsedText
,&CopiedText
,&CopiedSMSText
);
1295 GSM_Find_Free_Used_SMS2(Coding
,SMS
->SMS
[SMS
->Number
], &UsedText
, &FreeText
, &FreeBytes
);
1296 Length
= FreeBytes
- 3;
1297 if (Length
< 0) Length
= 128;
1298 if (Length
> 128) Length
= 128;
1301 if (di
.dl
== DL_TEXTALL
|| di
.dl
== DL_TEXTALLDATE
) GSM_PrintBitmap(di
.df
,&Bitmap
);
1306 while (FreeBytes
!= Width
) {
1309 if (FreeBytes
+Width2
== Width
) break;
1311 if (PHONE_GetBitmapSize(BitmapType
,Width2
+8,Height
) > Length
) break;
1313 Width2
= Width2
+ 8;
1316 /* Copying part of bitmap to new structure */
1317 Bitmap2
.Width
= Width2
;
1318 Bitmap2
.Height
= Height
;
1319 GSM_ClearBitmap(&Bitmap2
);
1320 for (x
=0;x
<Width2
;x
++) {
1321 for (y
=0;y
<Height
;y
++) {
1322 if (GSM_IsPointBitmap(&Bitmap
,x
+FreeBytes
,y
)) {
1323 GSM_SetPointBitmap(&Bitmap2
, x
, y
);
1328 if (di
.dl
== DL_TEXTALL
|| di
.dl
== DL_TEXTALLDATE
) GSM_PrintBitmap(di
.df
,&Bitmap2
);
1331 /* Adding new bitmap to SMS */
1332 Length
= PHONE_GetBitmapSize(BitmapType
,Width2
,Height
);
1333 Buffer
[0] = 0x12; /* ID for EMS bitmap */
1334 Buffer
[1] = Length
+ 3; /* Length of rest */
1335 Buffer
[2] = 0x00; /* Position in EMS msg */
1336 Buffer
[3] = Width2
/8; /* Bitmap width/8 */
1337 Buffer
[4] = Height
; /* Bitmap height */
1338 PHONE_EncodeBitmap(BitmapType
,Buffer
+5, &Bitmap2
);
1339 GSM_AddSMS_Text_UDH(SMS
,Coding
,Buffer
,5+Length
,true,&UsedText
,&CopiedText
,&CopiedSMSText
);
1340 SMS
->SMS
[SMS
->Number
].UDH
.Text
[SMS
->SMS
[SMS
->Number
].UDH
.Length
-3-Length
] = UsedText
;
1342 FreeBytes
= FreeBytes
+ Width2
;
1346 case SMS_EMSVariableBitmap
:
1347 if (Entry
->Protected
) {
1348 Buffer
[0] = 0x17; /* ID for ODI */
1349 Buffer
[1] = 2; /* Length of rest */
1350 Buffer
[2] = 1; /* Number of protected objects */
1351 Buffer
[3] = 1; /* 1=Protected,0=Not protected */
1352 GSM_AddSMS_Text_UDH(SMS
,Coding
,Buffer
,4,true,&UsedText
,&CopiedText
,&CopiedSMSText
);
1355 BitmapType
= GSM_EMSVariablePicture
;
1356 Width
= Entry
->Bitmap
->Bitmap
[0].Width
;
1357 Height
= Entry
->Bitmap
->Bitmap
[0].Height
;
1360 /* Width should be multiply of 8 */
1361 while (Width
% 8 != 0) Width
--;
1364 if (PHONE_GetBitmapSize(BitmapType
,Width
,Height
) <= 128) break;
1369 Length
= PHONE_GetBitmapSize(BitmapType
,Width
,Height
);
1371 Buffer
[0] = 0x12; /* ID for EMS bitmap */
1372 Buffer
[1] = Length
+ 3; /* Length of rest */
1373 Buffer
[2] = 0x00; /* Position in EMS msg */
1374 Buffer
[3] = Width
/8; /* Bitmap width/8 */
1375 Buffer
[4] = Height
; /* Bitmap height */
1377 GSM_ResizeBitmap(&Bitmap
, &Entry
->Bitmap
->Bitmap
[0], Width
, Height
);
1379 if (di
.dl
== DL_TEXTALL
|| di
.dl
== DL_TEXTALLDATE
) GSM_PrintBitmap(di
.df
,&Bitmap
);
1381 PHONE_EncodeBitmap(BitmapType
,Buffer
+5, &Bitmap
);
1382 GSM_AddSMS_Text_UDH(SMS
,Coding
,Buffer
,5+Length
,true,&UsedText
,&CopiedText
,&CopiedSMSText
);
1383 SMS
->SMS
[SMS
->Number
].UDH
.Text
[SMS
->SMS
[SMS
->Number
].UDH
.Length
-3-Length
] = UsedText
;
1392 if (UDHType
== UDH_ConcatenatedMessages
) {
1393 UDHID
= GSM_MakeSMSIDFromTime();
1394 for (i
=0;i
<SMS
->Number
;i
++) {
1395 SMS
->SMS
[i
].UDH
.Text
[2+1] = UDHID
;
1396 SMS
->SMS
[i
].UDH
.Text
[3+1] = SMS
->Number
;
1397 SMS
->SMS
[i
].UDH
.Text
[4+1] = i
+1;
1400 if (UDHType
== UDH_ConcatenatedMessages16bit
) {
1401 UDHID
= GSM_MakeSMSIDFromTime();
1402 GSM_GetCurrentDateTime (&Date
);
1403 for (i
=0;i
<SMS
->Number
;i
++) {
1404 SMS
->SMS
[i
].UDH
.Text
[2+1] = Date
.Hour
;
1405 SMS
->SMS
[i
].UDH
.Text
[3+1] = UDHID
;
1406 SMS
->SMS
[i
].UDH
.Text
[4+1] = SMS
->Number
;
1407 SMS
->SMS
[i
].UDH
.Text
[5+1] = i
+1;
1412 dbgprintf("SMS number is %i\n",SMS
->Number
);
1413 for (i
=0;i
<SMS
->Number
;i
++) {
1414 dbgprintf("UDH length %i\n",SMS
->SMS
[i
].UDH
.Length
);
1415 DumpMessage(di
.df
, SMS
->SMS
[i
].UDH
.Text
, SMS
->SMS
[i
].UDH
.Length
);
1416 dbgprintf("SMS length %i\n",UnicodeLength(SMS
->SMS
[i
].Text
)*2);
1417 DumpMessage(di
.df
, SMS
->SMS
[i
].Text
, UnicodeLength(SMS
->SMS
[i
].Text
)*2);
1423 GSM_Error
GSM_EncodeMultiPartSMS(GSM_EncodeMultiPartSMSInfo
*Info
,
1424 GSM_MultiSMSMessage
*SMS
)
1426 unsigned char Buffer
[GSM_MAX_SMS_LENGTH
*2*MAX_MULTI_SMS
];
1427 unsigned char Buffer2
[GSM_MAX_SMS_LENGTH
*2*MAX_MULTI_SMS
];
1428 int Length
= 0,smslen
,i
, Class
= -1;
1430 GSM_Coding_Type Coding
= GSM_Coding_8bit
;
1431 GSM_UDH UDH
= UDH_NoUDH
;
1432 GSM_UDHHeader UDHHeader
;
1437 for (i
=0;i
<Info
->EntriesNum
;i
++) {
1438 switch (Info
->Entries
[i
].ID
) {
1439 case SMS_EMSPredefinedAnimation
:
1440 case SMS_EMSPredefinedSound
:
1441 case SMS_EMSSound10
:
1442 case SMS_EMSSound12
:
1443 case SMS_EMSSonyEricssonSound
:
1444 case SMS_EMSSound10Long
:
1445 case SMS_EMSSound12Long
:
1446 case SMS_EMSSonyEricssonSoundLong
:
1447 case SMS_EMSFixedBitmap
:
1448 case SMS_EMSVariableBitmap
:
1449 case SMS_EMSAnimation
:
1450 case SMS_EMSVariableBitmapLong
:
1453 case SMS_ConcatenatedTextLong
:
1454 case SMS_ConcatenatedTextLong16bit
:
1455 if (Info
->Entries
[i
].Left
|| Info
->Entries
[i
].Right
||
1456 Info
->Entries
[i
].Center
|| Info
->Entries
[i
].Large
||
1457 Info
->Entries
[i
].Small
|| Info
->Entries
[i
].Bold
||
1458 Info
->Entries
[i
].Italic
|| Info
->Entries
[i
].Underlined
||
1459 Info
->Entries
[i
].Strikethrough
) {
1468 error
=GSM_EncodeEMSMultiPartSMS(Info
,SMS
,UDH_NoUDH
);
1469 if (error
!= GE_NONE
) return error
;
1470 if (SMS
->Number
!= 1) {
1472 for (i
=0;i
<Info
->EntriesNum
;i
++) {
1473 if (Info
->Entries
[i
].ID
== SMS_ConcatenatedTextLong16bit
) {
1474 return GSM_EncodeEMSMultiPartSMS(Info
,SMS
,UDH_ConcatenatedMessages
);
1477 return GSM_EncodeEMSMultiPartSMS(Info
,SMS
,UDH_ConcatenatedMessages16bit
);
1481 if (Info
->EntriesNum
!= 1) return GE_UNKNOWN
;
1483 switch (Info
->Entries
[0].ID
) {
1484 case SMS_MMSIndicatorLong
:
1486 UDH
= UDH_MMSIndicatorLong
;
1487 GSM_EncodeMMSIndicatorSMSText(Buffer
,&Length
,*Info
->Entries
[0].MMSIndicator
);
1489 case SMS_NokiaRingtoneLong
:
1490 case SMS_NokiaRingtone
:
1491 UDH
= UDH_NokiaRingtone
;
1493 /* 7 = length of UDH_NokiaRingtone UDH header */
1494 Length
= GSM_MAX_8BIT_SMS_LENGTH
-7;
1495 Info
->Entries
[0].RingtoneNotes
= GSM_EncodeNokiaRTTLRingtone(*Info
->Entries
[0].Ringtone
,Buffer
,&Length
);
1496 if (Info
->Entries
[0].ID
== SMS_NokiaRingtone
) break;
1497 if (Info
->Entries
[0].RingtoneNotes
!= Info
->Entries
[0].Ringtone
->NoteTone
.NrCommands
) {
1498 UDH
= UDH_NokiaRingtoneLong
;
1499 Length
= (GSM_MAX_8BIT_SMS_LENGTH
-12)*3;
1500 Info
->Entries
[0].RingtoneNotes
= GSM_EncodeNokiaRTTLRingtone(*Info
->Entries
[0].Ringtone
,Buffer
,&Length
);
1503 case SMS_NokiaOperatorLogoLong
:
1504 if (Info
->Entries
[0].Bitmap
->Bitmap
[0].Width
> 72 || Info
->Entries
[0].Bitmap
->Bitmap
[0].Height
> 14) {
1505 UDH
= UDH_NokiaOperatorLogoLong
;
1507 NOKIA_EncodeNetworkCode(Buffer
, Info
->Entries
[0].Bitmap
->Bitmap
[0].NetworkCode
);
1508 Length
= Length
+ 3;
1509 NOKIA_CopyBitmap(GSM_Nokia7110OperatorLogo
, &Info
->Entries
[0].Bitmap
->Bitmap
[0], Buffer
, &Length
);
1512 case SMS_NokiaOperatorLogo
:
1513 UDH
= UDH_NokiaOperatorLogo
;
1515 NOKIA_EncodeNetworkCode(Buffer
, Info
->Entries
[0].Bitmap
->Bitmap
[0].NetworkCode
);
1516 Length
= Length
+ 3;
1517 NOKIA_CopyBitmap(GSM_NokiaOperatorLogo
, &Info
->Entries
[0].Bitmap
->Bitmap
[0], Buffer
, &Length
);
1519 case SMS_NokiaCallerLogo
:
1520 UDH
= UDH_NokiaCallerLogo
;
1522 NOKIA_CopyBitmap(GSM_NokiaCallerLogo
, &Info
->Entries
[0].Bitmap
->Bitmap
[0], Buffer
, &Length
);
1524 case SMS_NokiaProfileLong
:
1525 case SMS_NokiaPictureImageLong
:
1526 case SMS_NokiaScreenSaverLong
:
1528 UDH
= UDH_NokiaProfileLong
;
1529 GSM_EncodeSMS30MultiPartSMS(Info
,Buffer
,&Length
);
1531 case SMS_NokiaWAPBookmarkLong
:
1533 NOKIA_EncodeWAPBookmarkSMSText(Buffer
,&Length
,Info
->Entries
[0].Bookmark
);
1534 /* 7 = length of UDH_NokiaWAP UDH header */
1535 if (Length
>(GSM_MAX_8BIT_SMS_LENGTH
-7)) {
1536 UDH
=UDH_NokiaWAPLong
;
1541 case SMS_NokiaWAPSettingsLong
:
1543 UDH
= UDH_NokiaWAPLong
;
1544 NOKIA_EncodeWAPMMSSettingsSMSText(Buffer
,&Length
,Info
->Entries
[0].Settings
,false);
1546 case SMS_NokiaMMSSettingsLong
:
1548 UDH
= UDH_NokiaWAPLong
;
1549 NOKIA_EncodeWAPMMSSettingsSMSText(Buffer
,&Length
,Info
->Entries
[0].Settings
,true);
1551 case SMS_NokiaVCARD10Long
:
1552 GSM_EncodeVCARD(Buffer
,&Length
,Info
->Entries
[0].Phonebook
,true,Nokia_VCard10
);
1553 /* is 1 SMS ? 8 = length of ..SCKE2 */
1554 if (Length
<=GSM_MAX_SMS_LENGTH
-8) {
1555 sprintf(Buffer
,"//SCKE2 ");
1557 GSM_EncodeVCARD(Buffer
,&Length
,Info
->Entries
[0].Phonebook
,true,Nokia_VCard10
);
1559 /* FIXME: It wasn't checked */
1560 UDH
= UDH_NokiaPhonebookLong
;
1562 Coding
= GSM_Coding_Default
;
1563 memcpy(Buffer2
,Buffer
,Length
);
1564 EncodeUnicode(Buffer
,Buffer2
,Length
);
1566 case SMS_NokiaVCARD21Long
:
1567 GSM_EncodeVCARD(Buffer
,&Length
,Info
->Entries
[0].Phonebook
,true,Nokia_VCard21
);
1568 /* Is 1 SMS ? 12 = length of ..SCKL23F4 */
1569 if (Length
<=GSM_MAX_SMS_LENGTH
-12) {
1570 sprintf(Buffer
,"//SCKL23F4%c%c",13,10);
1572 GSM_EncodeVCARD(Buffer
,&Length
,Info
->Entries
[0].Phonebook
,true,Nokia_VCard21
);
1574 UDH
= UDH_NokiaPhonebookLong
;
1575 /* Here can be also 8 bit coding */
1577 Coding
= GSM_Coding_Default
;
1578 memcpy(Buffer2
,Buffer
,Length
);
1579 EncodeUnicode(Buffer
,Buffer2
,Length
);
1581 case SMS_VCARD10Long
:
1582 GSM_EncodeVCARD(Buffer
,&Length
,Info
->Entries
[0].Phonebook
,true,Nokia_VCard10
);
1583 if (Length
>GSM_MAX_SMS_LENGTH
) UDH
= UDH_ConcatenatedMessages
;
1584 Coding
= GSM_Coding_Default
;
1585 memcpy(Buffer2
,Buffer
,Length
);
1586 EncodeUnicode(Buffer
,Buffer2
,Length
);
1588 case SMS_VCARD21Long
:
1589 GSM_EncodeVCARD(Buffer
,&Length
,Info
->Entries
[0].Phonebook
,true,Nokia_VCard21
);
1590 if (Length
>GSM_MAX_SMS_LENGTH
) UDH
= UDH_ConcatenatedMessages
;
1591 Coding
= GSM_Coding_Default
;
1592 memcpy(Buffer2
,Buffer
,Length
);
1593 EncodeUnicode(Buffer
,Buffer2
,Length
);
1595 case SMS_NokiaVCALENDAR10Long
:
1596 error
=GSM_EncodeVCALENDAR(Buffer
,&Length
,Info
->Entries
[0].Calendar
,true,Nokia_VCalendar
);
1597 if (error
!= GE_NONE
) return error
;
1598 /* Is 1 SMS ? 8 = length of ..SCKE4 */
1599 if (Length
<=GSM_MAX_SMS_LENGTH
-8) {
1600 sprintf(Buffer
,"//SCKE4 ");
1602 GSM_EncodeVCALENDAR(Buffer
,&Length
,Info
->Entries
[0].Calendar
,true,Nokia_VCalendar
);
1604 UDH
= UDH_NokiaCalendarLong
;
1605 /* can be here 8 bit coding ? */
1607 Coding
= GSM_Coding_Default
;
1608 memcpy(Buffer2
,Buffer
,Length
);
1609 EncodeUnicode(Buffer
,Buffer2
,Length
);
1611 case SMS_NokiaVTODOLong
:
1612 error
=GSM_EncodeVTODO(Buffer
,&Length
,Info
->Entries
[0].ToDo
,true,Nokia_VToDo
);
1613 if (error
!= GE_NONE
) return error
;
1614 UDH
= UDH_NokiaCalendarLong
;
1615 Coding
= GSM_Coding_Default
;
1616 memcpy(Buffer2
,Buffer
,Length
);
1617 EncodeUnicode(Buffer
,Buffer2
,Length
);
1619 case SMS_DisableVoice
:
1620 case SMS_DisableFax
:
1621 case SMS_DisableEmail
:
1622 case SMS_EnableVoice
:
1624 case SMS_EnableEmail
:
1627 Class
= Info
->Class
;
1628 switch (Info
->Entries
[0].ID
) {
1629 case SMS_DisableVoice
: UDH
= UDH_DisableVoice
; break;
1630 case SMS_DisableFax
: UDH
= UDH_DisableFax
; break;
1631 case SMS_DisableEmail
: UDH
= UDH_DisableEmail
; break;
1632 case SMS_EnableVoice
: UDH
= UDH_EnableVoice
; break;
1633 case SMS_EnableFax
: UDH
= UDH_EnableFax
; break;
1634 case SMS_EnableEmail
: UDH
= UDH_EnableEmail
; break;
1635 case SMS_VoidSMS
: UDH
= UDH_VoidSMS
; break;
1636 case SMS_Text
: UDH
= UDH_NoUDH
; break;
1639 UDHHeader
.Type
= UDH
;
1640 GSM_EncodeUDHHeader(&UDHHeader
);
1641 memcpy(Buffer
,Info
->Entries
[0].Buffer
,UnicodeLength(Info
->Entries
[0].Buffer
)*2+2);
1642 if (Info
->UnicodeCoding
) {
1643 Coding
= GSM_Coding_Unicode
;
1644 Length
= UnicodeLength(Info
->Entries
[0].Buffer
);
1645 if (Length
>(140-UDHHeader
.Length
)/2) Length
= (140-UDHHeader
.Length
)/2;
1647 Coding
= GSM_Coding_Default
;
1648 FindDefaultAlphabetLen(Info
->Entries
[0].Buffer
,&Length
,&smslen
,(GSM_MAX_8BIT_SMS_LENGTH
-UDHHeader
.Length
)*8/7);
1651 case SMS_ConcatenatedAutoTextLong
:
1652 case SMS_ConcatenatedAutoTextLong16bit
:
1653 smslen
= UnicodeLength(Info
->Entries
[0].Buffer
);
1654 memcpy(Buffer
,Info
->Entries
[0].Buffer
,smslen
*2);
1655 EncodeDefault(Buffer2
, Buffer
, &smslen
, true, NULL
);
1656 DecodeDefault(Buffer
, Buffer2
, smslen
, true, NULL
);
1658 if (di
.dl
== DL_TEXTALL
|| di
.dl
== DL_TEXTALLDATE
) {
1659 dbgprintf("Info->Entries[0].Buffer:\n");
1660 DumpMessage(di
.df
, Info
->Entries
[0].Buffer
, UnicodeLength(Info
->Entries
[0].Buffer
)*2);
1661 dbgprintf("Buffer:\n");
1662 DumpMessage(di
.df
, Buffer
, UnicodeLength(Buffer
)*2);
1665 Info
->UnicodeCoding
= false;
1666 for (smslen
=0;smslen
<(int)(UnicodeLength(Info
->Entries
[0].Buffer
)*2);smslen
++) {
1667 if (Info
->Entries
[0].Buffer
[smslen
] != Buffer
[smslen
]) {
1668 Info
->UnicodeCoding
= true;
1669 dbgprintf("Setting to Unicode %i\n",smslen
);
1673 /* No break here - we go to the SMS_ConcatenatedTextLong */
1674 case SMS_ConcatenatedTextLong
:
1675 case SMS_ConcatenatedTextLong16bit
:
1676 Class
= Info
->Class
;
1677 memcpy(Buffer
,Info
->Entries
[0].Buffer
,UnicodeLength(Info
->Entries
[0].Buffer
)*2+2);
1679 if (Info
->UnicodeCoding
) {
1680 Coding
= GSM_Coding_Unicode
;
1681 Length
= UnicodeLength(Info
->Entries
[0].Buffer
);
1682 if (Info
->Entries
[0].ID
== SMS_ConcatenatedTextLong16bit
||
1683 Info
->Entries
[0].ID
== SMS_ConcatenatedAutoTextLong16bit
) {
1684 if (Length
>70) UDH
=UDH_ConcatenatedMessages16bit
;
1686 if (Length
>70) UDH
=UDH_ConcatenatedMessages
;
1689 Coding
= GSM_Coding_Default
;
1690 FindDefaultAlphabetLen(Info
->Entries
[0].Buffer
,&Length
,&smslen
,5000);
1691 if (Info
->Entries
[0].ID
== SMS_ConcatenatedTextLong16bit
||
1692 Info
->Entries
[0].ID
== SMS_ConcatenatedAutoTextLong16bit
) {
1693 if (smslen
>GSM_MAX_SMS_LENGTH
) UDH
=UDH_ConcatenatedMessages16bit
;
1695 if (smslen
>GSM_MAX_SMS_LENGTH
) UDH
=UDH_ConcatenatedMessages
;
1701 GSM_MakeMultiPartSMS(SMS
,Buffer
,Length
,UDH
,Coding
,Class
,Info
->ReplaceMessage
);
1705 void GSM_ClearMultiPartSMSInfo(GSM_EncodeMultiPartSMSInfo
*Info
)
1709 for (i
=0;i
<MAX_MULTI_SMS
;i
++) {
1710 Info
->Entries
[i
].Buffer
= NULL
;
1711 Info
->Entries
[i
].Ringtone
= NULL
;
1712 Info
->Entries
[i
].Bitmap
= NULL
;
1713 Info
->Entries
[i
].Phonebook
= NULL
;
1714 Info
->Entries
[i
].Bookmark
= NULL
;
1715 Info
->Entries
[i
].Settings
= NULL
;
1716 Info
->Entries
[i
].Calendar
= NULL
;
1717 Info
->Entries
[i
].ToDo
= NULL
;
1718 Info
->Entries
[i
].MMSIndicator
= NULL
;
1719 Info
->Entries
[i
].Left
= false;
1720 Info
->Entries
[i
].Right
= false;
1721 Info
->Entries
[i
].Center
= false;
1722 Info
->Entries
[i
].Large
= false;
1723 Info
->Entries
[i
].Small
= false;
1724 Info
->Entries
[i
].Bold
= false;
1725 Info
->Entries
[i
].Italic
= false;
1726 Info
->Entries
[i
].Underlined
= false;
1727 Info
->Entries
[i
].Strikethrough
= false;
1729 Info
->Entries
[i
].Protected
= false;
1733 /* ----------------- Joining SMS from parts -------------------------------- */
1735 bool GSM_DecodeMultiPartSMS(GSM_EncodeMultiPartSMSInfo
*Info
,
1736 GSM_MultiSMSMessage
*SMS
)
1739 char Buffer
[GSM_MAX_SMS_LENGTH
*2*MAX_MULTI_SMS
];
1741 bool RetVal
= false, Bitmap
= false, Ringtone
= false, TextBuffer
= false;
1743 if (SMS
->SMS
[0].UDH
.Type
== UDH_NokiaRingtone
&& SMS
->Number
== 1) {
1744 if (GSM_DecodeNokiaRTTLRingtone(Info
->Entries
[0].Ringtone
, SMS
->SMS
[0].Text
, SMS
->SMS
[0].Length
)==GE_NONE
)
1750 if (SMS
->SMS
[0].UDH
.Type
== UDH_NokiaCallerLogo
&& SMS
->Number
== 1) {
1751 PHONE_DecodeBitmap(GSM_NokiaCallerLogo
, SMS
->SMS
[0].Text
+4, &Info
->Entries
[0].Bitmap
->Bitmap
[0]);
1753 if (di
.dl
== DL_TEXTALL
|| di
.dl
== DL_TEXTALLDATE
) GSM_PrintBitmap(di
.df
,&Info
->Entries
[0].Bitmap
->Bitmap
[0]);
1758 if (SMS
->SMS
[0].UDH
.Type
== UDH_NokiaOperatorLogo
&& SMS
->Number
== 1) {
1759 PHONE_DecodeBitmap(GSM_NokiaOperatorLogo
, SMS
->SMS
[0].Text
+7, &Info
->Entries
[0].Bitmap
->Bitmap
[0]);
1760 NOKIA_DecodeNetworkCode(SMS
->SMS
[0].Text
, Info
->Entries
[0].Bitmap
->Bitmap
[0].NetworkCode
);
1762 if (di
.dl
== DL_TEXTALL
|| di
.dl
== DL_TEXTALLDATE
) GSM_PrintBitmap(di
.df
,&Info
->Entries
[0].Bitmap
->Bitmap
[0]);
1768 if (SMS
->SMS
[0].UDH
.Type
== UDH_ConcatenatedMessages
||
1769 SMS
->SMS
[0].UDH
.Type
== UDH_ConcatenatedMessages16bit
) {
1770 for (i
=0;i
<SMS
->Number
;i
++) {
1771 switch (SMS
->SMS
[i
].Coding
) {
1772 case GSM_Coding_8bit
:
1773 memcpy(Info
->Entries
[0].Buffer
+Length
,SMS
->SMS
[i
].Text
,SMS
->SMS
[i
].Length
);
1774 Length
=Length
+SMS
->SMS
[i
].Length
;
1776 case GSM_Coding_Unicode
:
1777 case GSM_Coding_Default
:
1778 memcpy(Info
->Entries
[0].Buffer
+Length
,SMS
->SMS
[i
].Text
,UnicodeLength(SMS
->SMS
[i
].Text
)*2);
1779 Length
=Length
+UnicodeLength(SMS
->SMS
[i
].Text
)*2;
1783 Info
->Entries
[0].Buffer
[Length
] = 0;
1784 Info
->Entries
[0].Buffer
[Length
+1] = 0;
1789 /* Generally Smart Messaging 3.0 decoding */
1790 if (SMS
->SMS
[0].UDH
.Type
== UDH_NokiaProfileLong
) {
1792 for (i
=0;i
<SMS
->Number
;i
++) {
1793 if (SMS
->SMS
[i
].UDH
.Type
!= UDH_NokiaProfileLong
||
1794 SMS
->SMS
[i
].UDH
.Text
[11] != i
+1 ||
1795 SMS
->SMS
[i
].UDH
.Text
[10] != SMS
->Number
)
1799 memcpy(Buffer
+Length
,SMS
->SMS
[i
].Text
,SMS
->SMS
[i
].Length
);
1800 Length
= Length
+ SMS
->SMS
[i
].Length
;
1802 Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
[0] = 0;
1803 Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
[1] = 0;
1806 switch (Buffer
[i
]) {
1808 dbgprintf("ISO 8859-2 text\n");
1810 case SM30_UNICODETEXT
:
1811 dbgprintf("Unicode text\n");
1812 memcpy(Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
,Buffer
+i
+3,Buffer
[i
+1]*256+Buffer
[i
+2]);
1813 Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
[Buffer
[i
+1]*256 + Buffer
[i
+2]] = 0;
1814 Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
[Buffer
[i
+1]*256 + Buffer
[i
+2]+ 1] = 0;
1815 dbgprintf("Unicode Text \"%s\"\n",DecodeUnicodeString(Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
));
1818 dbgprintf("OTA bitmap as Picture Image\n");
1819 PHONE_DecodeBitmap(GSM_NokiaPictureImage
, Buffer
+ i
+ 7, &Info
->Entries
[0].Bitmap
->Bitmap
[0]);
1821 if (di
.dl
== DL_TEXTALL
|| di
.dl
== DL_TEXTALLDATE
) GSM_PrintBitmap(di
.df
,&Info
->Entries
[0].Bitmap
->Bitmap
[0]);
1826 dbgprintf("RTTL ringtone\n");
1828 case SM30_PROFILENAME
:
1829 dbgprintf("Profile Name\n");
1831 case SM30_SCREENSAVER
:
1832 dbgprintf("OTA bitmap as Screen Saver\n");
1833 PHONE_DecodeBitmap(GSM_NokiaPictureImage
, Buffer
+ i
+ 7, &Info
->Entries
[0].Bitmap
->Bitmap
[0]);
1835 if (di
.dl
== DL_TEXTALL
|| di
.dl
== DL_TEXTALLDATE
) GSM_PrintBitmap(di
.df
,&Info
->Entries
[0].Bitmap
->Bitmap
[0]);
1840 i
= i
+ Buffer
[i
+1]*256 + Buffer
[i
+2] + 3;
1841 dbgprintf("%i %i\n",i
,Length
);
1844 if (!Bitmap
) Info
->Entries
[0].Bitmap
= NULL
;
1845 if (!TextBuffer
) Info
->Entries
[0].Buffer
= NULL
;
1846 if (!Ringtone
) Info
->Entries
[0].Ringtone
= NULL
;
1850 GSM_Error
GSM_SortSMS(GSM_MultiSMSMessage
*INPUT
[150], GSM_MultiSMSMessage
*OUTPUT
[150])
1852 bool INPUTSorted
[150],copyit
;
1853 int i
,OUTPUTNum
,j
,z
,loop
;
1855 for (i
=0;i
<150;i
++) INPUTSorted
[i
] = false;
1861 while (INPUT
[i
]!=NULL
) {
1863 /* If this one SMS was sorted earlier, do not touch */
1864 if (INPUTSorted
[i
]) {
1870 * - linked sms returned by phone driver
1871 * - sms without linking
1873 * we copy it to OUTPUT
1875 if (INPUT
[i
]->Number
!= 1 ||
1876 INPUT
[i
]->SMS
[0].UDH
.Type
== UDH_NoUDH
||
1877 INPUT
[i
]->SMS
[0].UDH
.Type
== UDH_UserUDH
||
1878 INPUT
[i
]->SMS
[0].UDH
.PartNumber
== -1) {
1879 OUTPUT
[OUTPUTNum
] = malloc(sizeof(GSM_MultiSMSMessage
));
1880 if (OUTPUT
[OUTPUTNum
] == NULL
) return GE_MOREMEMORY
;
1881 OUTPUT
[OUTPUTNum
+1] = NULL
;
1883 memcpy(OUTPUT
[OUTPUTNum
],INPUT
[i
],sizeof(GSM_MultiSMSMessage
));
1884 INPUTSorted
[i
]=true;
1891 /* We have 1'st part of linked sms. It's single.
1892 * We will try to find other parts
1894 if (INPUT
[i
]->SMS
[0].UDH
.PartNumber
== 1) {
1895 OUTPUT
[OUTPUTNum
] = malloc(sizeof(GSM_MultiSMSMessage
));
1896 if (OUTPUT
[OUTPUTNum
] == NULL
) return GE_MOREMEMORY
;
1897 OUTPUT
[OUTPUTNum
+1] = NULL
;
1899 memcpy(&OUTPUT
[OUTPUTNum
]->SMS
[0],&INPUT
[i
]->SMS
[0],sizeof(GSM_SMSMessage
));
1900 OUTPUT
[OUTPUTNum
]->Number
= 1;
1901 INPUTSorted
[i
]=true;
1903 while (j
!=INPUT
[i
]->SMS
[0].UDH
.AllParts
) {
1905 while(INPUT
[z
]!=NULL
) {
1908 * - non sorted earlier
1910 * - with the same UDH (with the same ID, etc.) to the first sms
1912 if (!INPUTSorted
[z
] &&
1913 INPUT
[z
]->Number
== 1 &&
1914 INPUT
[z
]->SMS
[0].UDH
.Type
== INPUT
[i
]->SMS
[0].UDH
.Type
&&
1915 INPUT
[z
]->SMS
[0].UDH
.ID8bit
== INPUT
[i
]->SMS
[0].UDH
.ID8bit
&&
1916 INPUT
[z
]->SMS
[0].UDH
.ID16bit
== INPUT
[i
]->SMS
[0].UDH
.ID16bit
&&
1917 INPUT
[z
]->SMS
[0].UDH
.AllParts
== INPUT
[i
]->SMS
[0].UDH
.AllParts
&&
1918 INPUT
[z
]->SMS
[0].UDH
.PartNumber
== j
+1) {
1919 /* For SMS_Deliver compare also SMSC and Sender number */
1920 if (INPUT
[z
]->SMS
[0].PDU
== SMS_Deliver
) {
1921 if (!strcmp(DecodeUnicodeString(INPUT
[z
]->SMS
[0].SMSC
.Number
),DecodeUnicodeString(INPUT
[i
]->SMS
[0].SMSC
.Number
)) &&
1922 !strcmp(DecodeUnicodeString(INPUT
[z
]->SMS
[0].Number
),DecodeUnicodeString(INPUT
[i
]->SMS
[0].Number
))) {
1923 if (UnicodeLength(INPUT
[z
]->SMS
[0].SMSC
.Number
)!=0 || UnicodeLength(INPUT
[z
]->SMS
[0].Number
)!=0) {
1926 if (INPUT
[z
]->SMS
[0].DateTime
.Day
== INPUT
[i
]->SMS
[0].DateTime
.Day
&&
1927 INPUT
[z
]->SMS
[0].DateTime
.Month
== INPUT
[i
]->SMS
[0].DateTime
.Month
&&
1928 INPUT
[z
]->SMS
[0].DateTime
.Year
== INPUT
[i
]->SMS
[0].DateTime
.Year
&&
1929 INPUT
[z
]->SMS
[0].DateTime
.Hour
== INPUT
[i
]->SMS
[0].DateTime
.Hour
&&
1930 INPUT
[z
]->SMS
[0].DateTime
.Minute
== INPUT
[i
]->SMS
[0].DateTime
.Minute
&&
1931 INPUT
[z
]->SMS
[0].DateTime
.Second
== INPUT
[i
]->SMS
[0].DateTime
.Second
) {
1939 /* We found correct sms. Copy it */
1941 memcpy(&OUTPUT
[OUTPUTNum
]->SMS
[j
],&INPUT
[z
]->SMS
[0],sizeof(GSM_SMSMessage
));
1942 OUTPUT
[OUTPUTNum
]->Number
++;
1943 INPUTSorted
[z
]=true;
1948 /* Incomplete sequence */
1949 if (OUTPUT
[OUTPUTNum
]->Number
==j
) break;
1960 /* How should editor hadle tabs in this file? Add editor commands here.
1961 * vim: noexpandtab sw=8 ts=8 sts=8: