Gammu internals  1.38.0
gsmsms.c File Reference
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <gammu-calendar.h>
#include <gammu-message.h>
#include <gammu-unicode.h>
#include <gammu-debug.h>
#include "../../misc/coding/coding.h"
#include "../../debug.h"
Include dependency graph for gsmsms.c:

Go to the source code of this file.

Functions

static GSM_Error GSM_DecodeSMSDateTime (GSM_Debug_Info *di, GSM_DateTime *DT, const unsigned char *req)
 
void GSM_DecodeUDHHeader (GSM_Debug_Info *di, GSM_UDHHeader *UDH)
 
GSM_Coding_Type GSM_GetMessageCoding (GSM_Debug_Info *di, const char TPDCS)
 
GSM_Error GSM_DecodeSMSFrameText (GSM_Debug_Info *di, GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout)
 
GSM_Error GSM_DecodeSMSStatusReportData (GSM_Debug_Info *di, GSM_SMSMessage *SMS, int TP_ST)
 
GSM_Error GSM_DecodeSMSFrameStatusReportData (GSM_Debug_Info *di, GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout)
 
GSM_Error GSM_DecodePDUFrame (GSM_Debug_Info *di, GSM_SMSMessage *SMS, const unsigned char *buffer, size_t length, size_t *final_pos, gboolean SMSC)
 
GSM_Error GSM_DecodeSMSFrame (GSM_Debug_Info *di, GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout)
 
static GSM_Error GSM_EncodeSMSDateTime (GSM_Debug_Info *di, GSM_DateTime *DT, unsigned char *req)
 
static int GSM_EncodeSMSFrameText (GSM_Debug_Info *di, GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout)
 
GSM_Error GSM_EncodeSMSFrame (GSM_Debug_Info *di, GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout, int *length, gboolean clear)
 
void GSM_SetDefaultReceivedSMSData (GSM_SMSMessage *SMS)
 
void GSM_SetDefaultSMSData (GSM_SMSMessage *SMS)
 
void GSM_EncodeUDHHeader (GSM_Debug_Info *di, GSM_UDHHeader *UDH)
 
gboolean GSM_DecodeSiemensOTASMS (GSM_Debug_Info *di, GSM_SiemensOTASMSInfo *Info, GSM_SMSMessage *SMS)
 
GSM_Coding_Type GSM_StringToSMSCoding (const char *s)
 
const char * GSM_SMSCodingToString (GSM_Coding_Type type)
 

Variables

static GSM_UDHHeader UDHHeaders []
 

Function Documentation

§ GSM_DecodeSMSDateTime()

static GSM_Error GSM_DecodeSMSDateTime ( GSM_Debug_Info di,
GSM_DateTime DT,
const unsigned char *  req 
)
static

Definition at line 89 of file gsmsms.c.

References CheckDate(), CheckTime(), GSM_DateTime::Day, DecodeWithBCDAlphabet(), ERR_NONE, GSM_DateTime::Hour, GSM_DateTime::Minute, GSM_DateTime::Month, OSDateTime(), GSM_DateTime::Second, smfprintf(), GSM_DateTime::Timezone, TRUE, and GSM_DateTime::Year.

Referenced by GSM_DecodePDUFrame(), and GSM_DecodeSMSFrame().

90 {
91  DT->Year = DecodeWithBCDAlphabet(req[0]);
92  if (DT->Year < 90) {
93  DT->Year = DT->Year + 2000;
94  } else {
95  DT->Year = DT->Year + 1990;
96  }
97  DT->Month = DecodeWithBCDAlphabet(req[1]);
98  DT->Day = DecodeWithBCDAlphabet(req[2]);
99  DT->Hour = DecodeWithBCDAlphabet(req[3]);
100  DT->Minute = DecodeWithBCDAlphabet(req[4]);
101  DT->Second = DecodeWithBCDAlphabet(req[5]);
102 
103  /* Base for timezone is GMT. It's in quarters */
104  DT->Timezone = (10 * (req[6] & 0x07) + (req[6] >> 4)) *3600 / 4;
105 
106  if (req[6] & 0x08) {
107  DT->Timezone = -DT->Timezone;
108  }
109 
110  if (!CheckDate(DT) || !CheckTime(DT)) {
111  smfprintf(di, "Invalid date & time!\n");
112  DT->Year = 0;
113  return ERR_NONE;
114  }
115 
116  smfprintf(di, "Decoding date & time: %s\n", OSDateTime(*DT, TRUE));
117 
118  return ERR_NONE;
119 }
gboolean CheckTime(GSM_DateTime *date)
Definition: misc.c:363
int DecodeWithBCDAlphabet(unsigned char value)
Definition: coding.c:323
char * OSDateTime(GSM_DateTime dt, gboolean TimeZone)
Definition: misc.c:264
int smfprintf(GSM_Debug_Info *d, const char *format,...)
Definition: debug.c:240
#define TRUE
Definition: gammu-types.h:28
gboolean CheckDate(GSM_DateTime *date)
Definition: misc.c:349

§ GSM_DecodeSMSStatusReportData()

GSM_Error GSM_DecodeSMSStatusReportData ( GSM_Debug_Info di,
GSM_SMSMessage SMS,
int  TP_ST 
)

Definition at line 384 of file gsmsms.c.

References GSM_SMSMessage::Coding, GSM_SMSMessage::DeliveryStatus, EncodeUnicode(), ERR_NONE, GSM_SMSMessage::Length, smfprintf(), SMS_Coding_Unicode_No_Compression, and GSM_SMSMessage::Text.

Referenced by GSM_DecodePDUFrame(), and GSM_DecodeSMSFrameStatusReportData().

385 {
386  SMS->DeliveryStatus = TP_ST;
388 
389  if (TP_ST < 0x03) {
390  EncodeUnicode(SMS->Text,"Delivered",9);
391  SMS->Length = 9;
392  } else if (TP_ST & 0x40) {
393  EncodeUnicode(SMS->Text,"Failed",6);
394  SMS->Length = 6;
395  } else if (TP_ST & 0x20) {
396  EncodeUnicode(SMS->Text,"Pending",7);
397  SMS->Length = 7;
398  } else {
399  EncodeUnicode(SMS->Text,"Unknown",7);
400  SMS->Length = 7;
401  }
402 
403 #ifdef DEBUG
404  /* See GSM 03.40 section 9.2.3.15 (TP-Status) */
405  if (TP_ST & 0x40) {
406  if (TP_ST & 0x20) {
407  /* 0x60, 0x61, ... */
408  smfprintf(di, "Temporary error, SC is not making any more transfer attempts\n");
409  } else {
410  /* 0x40, 0x41, ... */
411  smfprintf(di, "Permanent error, SC is not making any more transfer attempts\n");
412  }
413  } else if (TP_ST & 0x20) {
414  /* 0x20, 0x21, ... */
415  smfprintf(di, "Temporary error, SC still trying to transfer SM\n");
416  }
417  switch (TP_ST) {
418  case 0x00:
419  smfprintf(di, "SM received by the SME");
420  break;
421  case 0x01:
422  smfprintf(di, "SM forwarded by the SC to the SME but the SC is unable to confirm delivery");
423  break;
424  case 0x02:
425  smfprintf(di, "SM replaced by the SC");
426  break;
427  case 0x20:
428  smfprintf(di, "Congestion");
429  break;
430  case 0x21:
431  smfprintf(di, "SME busy");
432  break;
433  case 0x22:
434  smfprintf(di, "No response from SME");
435  break;
436  case 0x23:
437  smfprintf(di, "Service rejected");
438  break;
439  case 0x24:
440  smfprintf(di, "Quality of service not available");
441  break;
442  case 0x25:
443  smfprintf(di, "Error in SME");
444  break;
445  case 0x40:
446  smfprintf(di, "Remote procedure error");
447  break;
448  case 0x41:
449  smfprintf(di, "Incompatible destination");
450  break;
451  case 0x42:
452  smfprintf(di, "Connection rejected by SME");
453  break;
454  case 0x43:
455  smfprintf(di, "Not obtainable");
456  break;
457  case 0x44:
458  smfprintf(di, "Quality of service not available");
459  break;
460  case 0x45:
461  smfprintf(di, "No internetworking available");
462  break;
463  case 0x46:
464  smfprintf(di, "SM Validity Period Expired");
465  break;
466  case 0x47:
467  smfprintf(di, "SM deleted by originating SME");
468  break;
469  case 0x48:
470  smfprintf(di, "SM Deleted by SC Administration");
471  break;
472  case 0x49:
473  smfprintf(di, "SM does not exist");
474  break;
475  case 0x60:
476  smfprintf(di, "Congestion");
477  break;
478  case 0x61:
479  smfprintf(di, "SME busy");
480  break;
481  case 0x62:
482  smfprintf(di, "No response from SME");
483  break;
484  case 0x63:
485  smfprintf(di, "Service rejected");
486  break;
487  case 0x64:
488  smfprintf(di, "Quality of service not available");
489  break;
490  case 0x65:
491  smfprintf(di, "Error in SME");
492  break;
493  default:
494  smfprintf(di, "Reserved/Specific to SC: %x",TP_ST);
495  break;
496  }
497  smfprintf(di, "\n");
498 #endif
499 
500  return ERR_NONE;
501 }
unsigned char Text[(GSM_MAX_SMS_LENGTH+1) *2]
unsigned char DeliveryStatus
GSM_Coding_Type Coding
void EncodeUnicode(unsigned char *dest, const char *src, size_t len)
Definition: coding.c:301
int smfprintf(GSM_Debug_Info *d, const char *format,...)
Definition: debug.c:240

§ GSM_EncodeSMSDateTime()

static GSM_Error GSM_EncodeSMSDateTime ( GSM_Debug_Info di,
GSM_DateTime DT,
unsigned char *  req 
)
static

Definition at line 909 of file gsmsms.c.

References GSM_DateTime::Day, EncodeWithBCDAlphabet(), ERR_NONE, GSM_DateTime::Hour, GSM_DateTime::Minute, GSM_DateTime::Month, OSDate(), GSM_DateTime::Second, smfprintf(), and GSM_DateTime::Year.

Referenced by GSM_EncodeSMSFrame().

910 {
911  int Year;
912 
913  smfprintf(di, "Encoding SMS datetime: %s\n", OSDate(*DT));
914 
915  /* We need to have only two last digits of year */
916  if (DT->Year>1900) {
917  if (DT->Year<2000) Year = DT->Year-1900;
918  else Year = DT->Year-2000;
919  } else Year = DT->Year;
920 
921  req[0]=EncodeWithBCDAlphabet(Year);
922  req[1]=EncodeWithBCDAlphabet(DT->Month);
923  req[2]=EncodeWithBCDAlphabet(DT->Day);
924  req[3]=EncodeWithBCDAlphabet(DT->Hour);
925  req[4]=EncodeWithBCDAlphabet(DT->Minute);
926  req[5]=EncodeWithBCDAlphabet(DT->Second);
927 
928  /* FIXME: do it */
929  req[6]=0; /* TimeZone = +-0 */
930 
931  return ERR_NONE;
932 }
char * OSDate(GSM_DateTime dt)
Definition: misc.c:305
unsigned char EncodeWithBCDAlphabet(int value)
Definition: coding.c:315
int smfprintf(GSM_Debug_Info *d, const char *format,...)
Definition: debug.c:240

§ GSM_EncodeSMSFrameText()

static int GSM_EncodeSMSFrameText ( GSM_Debug_Info di,
GSM_SMSMessage SMS,
unsigned char *  buffer,
GSM_SMSMessageLayout  Layout 
)
static

Definition at line 934 of file gsmsms.c.

References GSM_SMSMessage::Coding, DecodeUnicodeString(), DumpMessageText(), EncodeDefault(), EncodeUnicodeSpecialNOKIAChars(), GSM_SMSMessageLayout::firstbyte, GSM_MAX_8BIT_SMS_LENGTH, GSM_PackSevenBitsToEight(), GSM_UDHHeader::Length, GSM_SMSMessage::Length, MIN, smfprintf(), SMS_Coding_8bit, SMS_Coding_Default_No_Compression, SMS_Coding_Unicode_No_Compression, GSM_UDHHeader::Text, GSM_SMSMessage::Text, GSM_SMSMessageLayout::Text, GSM_SMSMessageLayout::TPDCS, GSM_SMSMessageLayout::TPUDL, TRUE, GSM_UDHHeader::Type, GSM_SMSMessage::UDH, UDH_NoUDH, and UnicodeLength().

Referenced by GSM_EncodeSMSFrame().

935 {
936  int off = 0; /* length of the User Data Header */
937  int size = 0, size2 = 0, w;
938  size_t p;
939  char buff[200];
940 
941  if (SMS->UDH.Type!=UDH_NoUDH) {
942  buffer[Layout.firstbyte] |= 0x40; /* GSM 03.40 section 9.2.3.23 (TP-User-Data-Header-Indicator) */
943  if (SMS->UDH.Length == 0) {
944  /* off - length of the User Data Header w/o data */
945  off = 1 + SMS->UDH.Text[0];
946  smfprintf(di, "UDL passed from API is 0, using UDHL+1 (%i)\n", off);
947  } else {
948  off = SMS->UDH.Length;
949  smfprintf(di, "UDL: %i, UDHL: %i\n", off, SMS->UDH.Text[0]);
950  }
951  memcpy(buffer+Layout.Text, SMS->UDH.Text, off); /* we copy the udh */
952  smfprintf(di, "UDH, length %i\n",off);
953  DumpMessageText(di, SMS->UDH.Text, off);
954  }
955  switch (SMS->Coding) {
956  case SMS_Coding_8bit:
957  /* the mask for the 8-bit data */
958  /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme)
959  * and GSM 03.38 section 4 */
960  buffer[Layout.TPDCS] |= (1 << 2);
961  memcpy(buffer+(Layout.Text+off), SMS->Text, MIN(SMS->Length, 140));
962  size2 = size = SMS->Length+off;
963  smfprintf(di, "8 bit SMS, length %i\n",SMS->Length);
964  DumpMessageText(di, SMS->Text, SMS->Length);
965  break;
967  p = 0;
968  do {
969  p+=7;
970  w=(p-off)%p;
971  } while (w<0);
972  p = MIN(UnicodeLength(SMS->Text), 160);
973  EncodeDefault(buff, SMS->Text, &p, TRUE, NULL);
974  size = GSM_PackSevenBitsToEight(w, buff, buffer+(Layout.Text+off), p);
975  size += off;
976  size2 = (off*8 + w) / 7 + p;
977  smfprintf(di, "7 bit SMS, length %i, %i\n",size,size2);
978  smfprintf(di, "%s\n",DecodeUnicodeString(SMS->Text));
979  if (size > GSM_MAX_8BIT_SMS_LENGTH) {
980  size = 0; size2 = 0;
981  }
982  break;
984  /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme)
985  * and GSM 03.38 section 4 */
986  buffer[Layout.TPDCS] |= (1 << 3);
987  EncodeUnicodeSpecialNOKIAChars(buffer+(Layout.Text+off), SMS->Text, MIN(UnicodeLength(SMS->Text), 70));
988  size=size2=UnicodeLength(buffer+(Layout.Text+off))*2+off;
989  smfprintf(di, "Unicode SMS, length %i\n",(size2-off)/2);
990  DumpMessageText(di, buffer+(Layout.Text+off), size2-off);
991  smfprintf(di, "%s\n",DecodeUnicodeString(buffer+(Layout.Text+off)));
992  break;
993  default:
994  break;
995  }
996 
997  /* GSM 03.40 section 9.2.3.16 (TP-User-Data-Length)
998  * SMS->Length is:
999  - integer representation of the number od octets within the
1000  user data when TP-User-Data is coded using 8 bit data
1001  - the sum of the number of septets in UDH including any padding
1002  and the number of septets in TP-User-Data in other case
1003  */
1004  buffer[Layout.TPUDL] = size2;
1005  return size;
1006 }
unsigned char Text
unsigned char TPUDL
unsigned char Text[(GSM_MAX_SMS_LENGTH+1) *2]
char * DecodeUnicodeString(const unsigned char *src)
Definition: coding.c:245
unsigned char TPDCS
void DumpMessageText(GSM_Debug_Info *d, const unsigned char *message, const size_t messagesize)
Definition: debug.c:371
int GSM_PackSevenBitsToEight(size_t offset, const unsigned char *input, unsigned char *output, size_t length)
Definition: coding.c:993
size_t UnicodeLength(const unsigned char *str)
Definition: coding.c:186
GSM_UDHHeader UDH
GSM_Coding_Type Coding
#define GSM_MAX_8BIT_SMS_LENGTH
Definition: gammu-limits.h:190
unsigned char Text[GSM_MAX_UDH_LENGTH]
unsigned char firstbyte
void EncodeUnicodeSpecialNOKIAChars(unsigned char *dest, const unsigned char *src, size_t len)
Definition: coding.c:1367
int smfprintf(GSM_Debug_Info *d, const char *format,...)
Definition: debug.c:240
#define MIN(a, b)
Definition: gammu-misc.h:70
#define TRUE
Definition: gammu-types.h:28
void EncodeDefault(unsigned char *dest, const unsigned char *src, size_t *len, gboolean UseExtensions, unsigned char *ExtraAlphabet)
Definition: coding.c:831

§ GSM_GetMessageCoding()

GSM_Coding_Type GSM_GetMessageCoding ( GSM_Debug_Info di,
const char  TPDCS 
)

Finds out coding type based on TPDCS header byte as defined by GSM 03.38.

Definition at line 261 of file gsmsms.c.

References smfprintf(), SMS_Coding_8bit, SMS_Coding_Default_Compression, SMS_Coding_Default_No_Compression, SMS_Coding_Unicode_Compression, and SMS_Coding_Unicode_No_Compression.

Referenced by GSM_DecodePDUFrame(), and GSM_DecodeSMSFrame().

261  {
262 
263  /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme) and GSM 03.38 section 4 */
264  if ((TPDCS & 0xC0) == 0 || (TPDCS & 0xC0) == 0x40) {
265  /* 0x40 is marked for automatic deletion, we ignore that bit */
266  /* bits 7..4 set to 00xx */
267  if ((TPDCS & 0xC) == 0xC) {
268  smfprintf(di, "WARNING: reserved alphabet value in TPDCS\n");
269  } else {
270  if (TPDCS == 0) {
272  }
273  if ((TPDCS & 0x2C) == 0x00) {
275  }
276  if ((TPDCS & 0x2C) == 0x20) {
278  }
279  if ((TPDCS & 0x2C) == 0x08) {
281  }
282  if ((TPDCS & 0x2C) == 0x28) {
284  }
285  }
286  } else if ((TPDCS & 0xF0) >= 0x40 &&
287  (TPDCS & 0xF0) <= 0xB0) {
288  /* bits 7..4 set to 0100 ... 1011 */
289  smfprintf(di, "WARNING: reserved coding group in TPDCS\n");
290  } else if (((TPDCS & 0xF0) == 0xC0) ||
291  ((TPDCS & 0xF0) == 0xD0)) {
292  /* bits 7..4 set to 1100 or 1101 */
293  if ((TPDCS & 4) == 4) {
294  smfprintf(di, "WARNING: set reserved bit 2 in TPDCS\n");
295  } else {
297  }
298  } else if ((TPDCS & 0xF0) == 0xE0) {
299  /* bits 7..4 set to 1110 */
300  if ((TPDCS & 4) == 4) {
301  smfprintf(di, "WARNING: set reserved bit 2 in TPDCS\n");
302  } else {
304  }
305  } else if ((TPDCS & 0xF0) == 0xF0) {
306  /* bits 7..4 set to 1111 */
307  if ((TPDCS & 8) == 8) {
308  smfprintf(di, "WARNING: set reserved bit 3 in TPDCS\n");
309  } else {
310  if ((TPDCS & 4) == 0) return SMS_Coding_Default_No_Compression;
311  }
312  }
313  return SMS_Coding_8bit;
314 }
int smfprintf(GSM_Debug_Info *d, const char *format,...)
Definition: debug.c:240

§ GSM_SMSCodingToString()

const char* GSM_SMSCodingToString ( GSM_Coding_Type  type)

Converts SMS coding to string.

Returns
Pointer to static string, NULL on failure.

Definition at line 1284 of file gsmsms.c.

References SMS_Coding_8bit, SMS_Coding_Default_Compression, SMS_Coding_Default_No_Compression, SMS_Coding_Unicode_Compression, and SMS_Coding_Unicode_No_Compression.

1285 {
1286  switch (type) {
1288  return "Unicode_No_Compression";
1290  return "Unicode_Compression";
1292  return "Default_No_Compression";
1294  return "Default_Compression";
1295  case SMS_Coding_8bit:
1296  return "8bit";
1297  }
1298 
1299  return NULL;
1300 }

§ GSM_StringToSMSCoding()

GSM_Coding_Type GSM_StringToSMSCoding ( const char *  s)

Converts SMS coding to type.

Definition at line 1260 of file gsmsms.c.

References SMS_Coding_8bit, SMS_Coding_Default_Compression, SMS_Coding_Default_No_Compression, SMS_Coding_Unicode_Compression, and SMS_Coding_Unicode_No_Compression.

1261 {
1262  /* Maintain those without compression for backward compatibility */
1263  if (s == NULL) {
1265  } else if (strcmp("Unicode", s) == 0) {
1267  } else if (strcmp("Unicode_No_Compression", s) == 0) {
1269  } else if (strcmp("Unicode_Compression", s) == 0) {
1271  } else if (strcmp("Default", s) == 0) {
1273  } else if (strcmp("Default_No_Compression", s) == 0) {
1275  } else if (strcmp("Default_Compression", s) == 0) {
1277  } else if (strcmp("8bit", s) == 0) {
1278  return SMS_Coding_8bit;
1279  }
1280 
1281  return 0;
1282 }

Variable Documentation

§ UDHHeaders

GSM_UDHHeader UDHHeaders[]
static

Definition at line 29 of file gsmsms.c.