Library for parsing and creating Short Messages (SMS).
$Log$
- Revision 1.1.1.1 2001/11/25 21:59:06 short
- :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
-
- Revision 1.13 2001/11/23 22:07:44 machek
- Fix SMS receiving to work, again. Unfortunately, it is not possible to
- reuse much of gsm-sms.c...
-
- Revision 1.12 2001/11/22 17:56:53 pkot
- smslib update. sms sending
-
- Revision 1.11 2001/11/20 16:22:22 pkot
- First attempt to read Picture Messages. They should appear when you enable DEBUG. Nokia seems to break own standards. :/ (Markus Plail)
-
- Revision 1.10 2001/11/19 13:09:40 pkot
- Begin work on sms sending
-
- Revision 1.9 2001/11/18 00:54:32 pkot
- Bugfixes. I18n of the user responses. UDH support in libsms. Business Card UDH Type
-
- Revision 1.8 2001/11/17 20:19:29 pkot
- smslib cleanups, fixes and debugging
-
- Revision 1.7 2001/11/15 12:15:04 pkot
- smslib updates. begin work on sms in 6100 series
-
- Revision 1.6 2001/11/14 18:21:19 pkot
- Fixing some problems with UDH and Unicode, but still doesn't work yet :-(
-
- Revision 1.5 2001/11/14 14:26:18 pkot
- Changed offset of DCS field to the right value in 6210/7110
-
- Revision 1.4 2001/11/14 11:26:18 pkot
- Getting SMS in 6210/7110 does finally work in some cases :)
-
- Revision 1.3 2001/11/13 16:12:20 pkot
- Preparing libsms to get to work. 6210/7110 SMS and SMS Folder updates
-
- Revision 1.2 2001/11/09 14:25:04 pkot
- DEBUG cleanups
+ Revision 1.1.1.8 2002/04/03 00:08:04 short
+ Found in "gnokii-working" directory, some November-patches version
Revision 1.1 2001/11/08 16:23:21 pkot
New version of libsms. Not functional yet, but it reasonably stable API.
*/
#include <stdlib.h>
-#include <string.h>
#include "gsm-common.h"
#include "gsm-encoding.h"
-#include "gsm-bitmaps.h"
struct udh_data {
unsigned int length;
/* User data headers */
static struct udh_data headers[] = {
{ 0x00, "" },
- { 0x05, "\x00\x03\x01\x00\x00" }, /* Concatenated messages */
+ { 0x05, "\x00\x03\x01\x00\x00" }, /* Concatenated messages */
{ 0x06, "\x05\x04\x15\x82\x00\x00" }, /* Operator logos */
- { 0x06, "\x05\x04\x15\x83\x00\x00" }, /* Caller logos */
+ { 0x06, "\x05\x04\x15\x82\x00\x00" }, /* Caller logos */
{ 0x06, "\x05\x04\x15\x81\x00\x00" }, /* Ringtones */
- { 0x04, "\x03\x01\x00\x00" }, /* Voice Messages */
- { 0x04, "\x03\x01\x01\x00" }, /* Fax Messages */
- { 0x04, "\x03\x01\x02\x00" }, /* Email Messages */
- { 0x06, "\x05\x04\x23\xf4\x00\x00" }, /* Business Card */
+ { 0x04, "\x03\x01\x00\x00" }, /* Voice Messages */
+ { 0x04, "\x03\x01\x01\x00" }, /* Fax Messages */
+ { 0x04, "\x03\x01\x02\x00" }, /* Email Messages */
{ 0x00, "" }
};
*** Util functions
***/
-/* This function implements packing of numbers (SMS Center number and
- destination number) for SMS sending function. */
-static int SemiOctetPack(char *Number, unsigned char *Output, SMS_NumberType type)
-{
- unsigned char *IN = Number; /* Pointer to the input number */
- unsigned char *OUT = Output; /* Pointer to the output */
- int count = 0; /* This variable is used to notify us about count of already
- packed numbers. */
-
- /* The first byte in the Semi-octet representation of the address field is
- the Type-of-Address. This field is described in the official GSM
- specification 03.40 version 6.1.0, section 9.1.2.5, page 33. We support
- only international and unknown number. */
-
- *OUT++ = type;
- if (type == SMS_International) IN++; /* Skip '+' */
- if ((type == SMS_Unknown) && (*IN == '+')) IN++; /* Optional '+' in Unknown number type */
-
- /* The next field is the number. It is in semi-octet representation - see
- GSM scpecification 03.40 version 6.1.0, section 9.1.2.3, page 31. */
- while (*IN) {
- if (count & 0x01) {
- *OUT = *OUT | ((*IN - '0') << 4);
- OUT++;
- }
- else
- *OUT = *IN - '0';
- count++; IN++;
- }
-
- /* We should also fill in the most significant bits of the last byte with
- 0x0f (1111 binary) if the number is represented with odd number of
- digits. */
- if (count & 0x01) {
- *OUT = *OUT | 0xf0;
- OUT++;
- }
-
- return (2 * (OUT - Output - 1) - (count % 2));
-}
-
-char *GetBCDNumber(u8 *Number)
+static char *GetBCDNumber(u8 *Number)
{
static char Buffer[20] = "";
- int length = Number[0]; /* This is the length of BCD coded number */
- int count, Digit;
- memset(Buffer, 0, 20);
+ /* This is the length of BCD coded number */
+ int length=Number[0];
+ int count;
+ int Digit;
+
switch (Number[1]) {
- case SMS_Alphanumeric:
+
+ case 0xd0:
Unpack7BitCharacters(0, length, length, Number+2, Buffer);
Buffer[length] = 0;
break;
- case SMS_International:
- sprintf(Buffer, "+");
- case SMS_Unknown:
- case SMS_National:
- case SMS_Network:
- case SMS_Subscriber:
- case SMS_Abbreviated:
default:
+ if (Number[1] == SMS_International)
+ sprintf(Buffer, "+");
+ else
+ Buffer[0] = '\0';
for (count = 0; count < length - 1; count++) {
Digit = Number[count+2] & 0x0f;
if (Digit < 10) sprintf(Buffer, "%s%d", Buffer, Digit);
return Buffer;
}
+#if 0
+char *GetBCDNumber(u8 *Number, int maxdigits, int maxbytes)
+{
+ static char Buffer[22] = "";
+ int length = Number[0]; /* This is the length of BCD coded number */
+ int bytes = 0, digits = 0;
+ int Digit = 0;
+
+ dprintf("%i\n", length);
+
+ if (Number[1] == 0x91) {
+ sprintf(Buffer, "+");
+ } else {
+ Buffer[0] = '\0';
+ }
+
+ while ((Digit < 10) && (bytes < length) && (digits < maxdigits)) {
+ Digit = Number[bytes + 2] & 0x0f;
+ if (Digit < 10) {
+ sprintf(Buffer, "%s%d", Buffer, Digit);
+ digits++;
+ Digit = Number[bytes + 2] >> 4;
+ if (Digit < 10) {
+ sprintf(Buffer, "%s%d", Buffer, Digit);
+ digits++;
+ }
+ }
+ bytes++;
+ }
+
+ return Buffer;
+}
+#endif
+
static char *PrintDateTime(u8 *Number)
{
static char Buffer[23] = "";
memset(Buffer, 0, 23);
- if (Number[0] < 70) sprintf(Buffer, "20");
- else sprintf(Buffer, "19");
- sprintf(Buffer, "%s%d%d-", Buffer, Number[0] & 0x0f, Number[0] >> 4);
+ sprintf(Buffer, "%d%d-", Number[0] & 0x0f, Number[0] >> 4);
sprintf(Buffer, "%s%d%d-", Buffer, Number[1] & 0x0f, Number[1] >> 4);
sprintf(Buffer, "%s%d%d ", Buffer, Number[2] & 0x0f, Number[2] >> 4);
sprintf(Buffer, "%s%d%d:", Buffer, Number[3] & 0x0f, Number[3] >> 4);
return Buffer;
}
-SMS_DateTime *UnpackDateTime(u8 *Number, SMS_DateTime *dt)
+static SMS_DateTime *UnpackDateTime(u8 *Number, SMS_DateTime *dt)
{
dt->Year = 10 * (Number[0] & 0x0f) + (Number[0] >> 4);
- if (dt->Year < 70) dt->Year += 2000;
- else dt->Year += 1900;
dt->Month = 10 * (Number[1] & 0x0f) + (Number[1] >> 4);
dt->Day = 10 * (Number[2] & 0x0f) + (Number[2] >> 4);
dt->Hour = 10 * (Number[3] & 0x0f) + (Number[3] >> 4);
*** ENCODING SMS
***/
-static GSM_Error EncodeData(GSM_SMSMessage *SMS, char *dcs, char *message)
-{
- SMS_AlphabetType al;
- unsigned short length = strlen(SMS->MessageText);
-
- switch (SMS->DCS.Type) {
- case SMS_GeneralDataCoding:
- switch (SMS->DCS.u.General.Class) {
- case 1: dcs[0] |= 0xf0; break;
- case 2: dcs[0] |= 0xf1; break;
- case 3: dcs[0] |= 0xf2; break;
- case 4: dcs[0] |= 0xf3; break;
- default: break;
- }
- if (SMS->DCS.u.General.Compressed) {
- /* Compression not supported yet */
- /* dcs[0] |= 0x20; */
- }
- al = SMS->DCS.u.General.Alphabet;
- break;
- case SMS_MessageWaiting:
- al = SMS->DCS.u.MessageWaiting.Alphabet;
- if (SMS->DCS.u.MessageWaiting.Discard) dcs[0] |= 0xc0;
- else if (SMS->DCS.u.MessageWaiting.Alphabet == SMS_UCS2) dcs[0] |= 0xe0;
- else dcs[0] |= 0xd0;
-
- if (SMS->DCS.u.MessageWaiting.Active) dcs[0] |= 0x08;
- dcs[0] |= (SMS->DCS.u.MessageWaiting.Type & 0x03);
-
- break;
- default:
- return GE_SMSWRONGFORMAT;
- }
- switch (al) {
- case SMS_DefaultAlphabet:
- Pack7BitCharacters((7 - (SMS->UDH_Length % 7)) % 7, SMS->MessageText, message);
- SMS->Length = 8 * SMS->UDH_Length + (7 - (SMS->UDH_Length % 7)) % 7 + length;
- break;
- case SMS_8bit:
- dcs[0] |= 0xf4;
- memcpy(message, SMS->MessageText + 1, SMS->MessageText[0]);
- SMS->Length = SMS->UDH_Length + SMS->MessageText[0];
- break;
- case SMS_UCS2:
- dcs[0] |= 0x08;
- EncodeUnicode(message, SMS->MessageText, length);
- SMS->Length = length;
- break;
- default:
- return GE_SMSWRONGFORMAT;
- }
- return GE_NONE;
-}
-
/* This function encodes the UserDataHeader as described in:
- GSM 03.40 version 6.1.0 Release 1997, section 9.2.3.24
- Smart Messaging Specification, Revision 1.0.0, September 15, 1997
memcpy(UDH+pos+1, headers[UDHi.Type].header, headers[UDHi.Type].length);
break;
default:
- dprintf("Not supported User Data Header type\n");
+ fprintf(stderr, _("Not supported User Data Header type\n"));
break;
}
return GE_NONE;
static GSM_Error EncodeSMSSubmitHeader(GSM_SMSMessage *SMS, char *frame)
{
GSM_Error error = GE_NONE;
+ int i;
- /* Standard Header: */
- memcpy(frame, "\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa9\x00\x00\x00\x00\x00\x00", 24);
+ /* SMS Center */
/* Reply Path */
- if (SMS->ReplyViaSameSMSC) frame[0] |= 0x80;
+ if (SMS->ReplyViaSameSMSC) frame[13] |= 0x80;
- /* User Data Header Indicator */
- if (SMS->UDH_No) frame[0] |= 0x40;
+ /* User Data Header */
+ for (i = 0; SMS->UDH[i].Type != SMS_NoUDH; i++) {
+ frame[13] |= 0x40;
+ error = EncodeUDH(SMS->UDH[i], frame);
+ if (error != GE_NONE) return error;
+ }
/* Status (Delivery) Report Request */
- if (SMS->ReportStatus) frame[0] |= 0x20;
+ if (SMS->Report) frame[13] |= 0x20;
/* Validity Period Format: mask - 0x00, 0x10, 0x08, 0x18 */
- frame[0] |= ((SMS->Validity.VPF & 0x03) << 3);
+ frame[13] |= ((SMS->Validity.VPF & 0x03) << 3);
/* Reject Duplicates */
- if (SMS->RejectDuplicates) frame[0] |= 0x04;
+ if (SMS->RejectDuplicates) frame[13] |= 0x04;
/* Message Type is already set */
/* Protocol Identifier */
/* FIXME: allow to change this in better way.
currently only 0x5f == `Return Call Message' is used */
- if (SMS->PID) frame[3] = SMS->PID;
+ frame[16] = SMS->PID;
/* Data Coding Scheme */
switch (SMS->DCS.Type) {
case SMS_GeneralDataCoding:
- if (SMS->DCS.u.General.Compressed) frame[4] |= 0x20;
- if (SMS->DCS.u.General.Class) frame[4] |= (0x10 | (SMS->DCS.u.General.Class - 1));
- frame[4] |= ((SMS->DCS.u.General.Alphabet & 0x03) << 2);
+ if (SMS->DCS.u.General.Compressed) frame[17] |= 0x20;
+ if (SMS->DCS.u.General.Class) frame[17] |= (0x10 | (SMS->DCS.u.General.Class - 1));
+ frame[17] |= ((SMS->DCS.u.General.Alphabet & 0x03) << 2);
break;
case SMS_MessageWaiting:
- if (SMS->DCS.u.MessageWaiting.Discard) frame[4] |= 0xc0;
- else if (SMS->DCS.u.MessageWaiting.Alphabet == SMS_UCS2) frame[4] |= 0xe0;
- else frame[4] |= 0xd0;
- if (SMS->DCS.u.MessageWaiting.Active) frame[4] |= 0x80;
- frame[4] |= (SMS->DCS.u.MessageWaiting.Type & 0x03);
+ if (SMS->DCS.u.MessageWaiting.Discard) frame[17] |= 0xc0;
+ else if (SMS->DCS.u.MessageWaiting.Alphabet == SMS_UCS2) frame[17] |= 0xe0;
+ else frame[17] |= 0xd0;
+ if (SMS->DCS.u.MessageWaiting.Active) frame[17] |= 0x80;
+ frame[17] |= (SMS->DCS.u.MessageWaiting.Type & 0x03);
break;
default:
- dprintf("Wrong Data Coding Scheme (DCS) format\n");
+ fprintf(stderr, _("Wrong Data Coding Scheme (DCS) format\n"));
return GE_SMSWRONGFORMAT;
}
+ /* User Data Length */
+ /* Will be filled later. */
+
/* Destination Address */
- frame[5] = SemiOctetPack(SMS->RemoteNumber.number, frame + 6, SMS->RemoteNumber.type);
/* Validity Period */
switch (SMS->Validity.VPF) {
break;
}
- return error;
+ return GE_NONE;
}
static GSM_Error EncodeSMSDeliverHeader()
case SMS_Submit: /* we send SMS or save it in Outbox */
return EncodeSMSSubmitHeader(SMS, frame);
case SMS_Deliver: /* we save SMS in Inbox */
- return EncodeSMSDeliverHeader(SMS, frame);
+ return EncodeSMSSubmitHeader(SMS, frame);
default: /* we don't create other formats of SMS */
return GE_SMSWRONGFORMAT;
}
/* This function encodes SMS as described in:
- GSM 03.40 version 6.1.0 Release 1997, section 9
*/
-int EncodePDUSMS(GSM_SMSMessage *SMS, char *message)
+GSM_Error EncodePDUSMS(GSM_SMSMessage *SMS, char *frame)
{
GSM_Error error = GE_NONE;
int i;
- dprintf("Sending SMS to %s via message center %s\n", SMS->RemoteNumber.number, SMS->MessageCenter.Number);
+ /* Short Message Data info element id */
+
+ /* Length of Short Message Data */
+
+ /* Short Message Reference value */
+ if (SMS->Number) frame[3] = SMS->Number;
+
+ /* Short Message status */
+ if (SMS->Status) frame[1] = SMS->Status;
+
+ /* Message Type */
/* SMSC number */
- dprintf("%d %s\n", SMS->MessageCenter.Type, SMS->MessageCenter.Number);
- message[0] = SemiOctetPack(SMS->MessageCenter.Number, message + 1, SMS->MessageCenter.Type);
- if (message[0] % 2) message[0]++;
- message[0] = message[0] / 2 + 1;
+ if (SMS->MessageCenter.Number) {
+// error = GSM->GetSMSCenter(&SMS->MessageCenter);
+
+ if (error != GE_NONE)
+ return error;
+ strcpy(SMS->MessageCenter.Number, "0");
+ }
+ dprintf("Sending SMS to %s via message center %s\n", SMS->Sender, SMS->MessageCenter.Number);
- /* Common Header */
- error = EncodeSMSHeader(SMS, message + 12);
- if (error != GE_NONE) return error;
+ /* Header coding */
+// EncodeUDH(SMS, frame);
+// if (error != GE_NONE) return error;
/* User Data Header - if present */
-// for (i = 0; i < SMS->UDH_No; i++) {
-// error = EncodeUDH(SMS->UDH[i], message + 24);
-// if (error != GE_NONE) return error;
-// }
- SMS->UDH_Length = 0;
+ for (i = 0; SMS->UDH[i].Type != SMS_NoUDH; i++) {
+ error = EncodeUDH(SMS->UDH[i], frame);
+ if (error != GE_NONE) return error;
+ }
/* User Data */
- EncodeData(SMS, message + 14, message + 36 + SMS->UDH_Length);
- message[16] = SMS->Length;
- return SMS->Length + 35;
+ // EncodeData(&(SMS->MessageText), &(SMS->DCS), frame);
+
+ return error;
}
/* This function does simple SMS encoding - no PDU coding */
*** DECODING SMS
***/
-static GSM_Error SMSStatus(unsigned char status, GSM_SMSMessage *SMS)
+static GSM_Error SMSStatus(unsigned char status, GSM_SMSMessage *sms)
{
if (status < 0x03) {
- strcpy(SMS->MessageText, _("Delivered"));
+ strcpy(sms->MessageText, _("Delivered"));
switch (status) {
case 0x00:
- dprintf("SM received by the SME");
+ dprintf(_("SM received by the SME"));
break;
case 0x01:
- dprintf("SM forwarded by the SC to the SME but the SC is unable to confirm delivery");
+ dprintf(_("SM forwarded by the SC to the SME but the SC is unable to confirm delivery"));
break;
case 0x02:
- dprintf("SM replaced by the SC");
+ dprintf(_("SM replaced by the SC"));
break;
}
- SMS->Length = strlen(_("Delivered"));
+ sms->Length = 10;
} else if (status & 0x40) {
- strcpy(SMS->MessageText, _("Failed"));
+ strcpy(sms->MessageText, _("Failed"));
/* more detailed reason only for debug */
if (status & 0x20) {
- dprintf("Temporary error, SC is not making any more transfer attempts\n");
+ dprintf(_("Temporary error, SC is not making any more transfer attempts\n"));
switch (status) {
case 0x60:
- dprintf("Congestion");
+ dprintf(_("Congestion"));
break;
case 0x61:
- dprintf("SME busy");
+ dprintf(_("SME busy"));
break;
case 0x62:
- dprintf("No response from SME");
+ dprintf(_("No response from SME"));
break;
case 0x63:
- dprintf("Service rejected");
+ dprintf(_("Service rejected"));
break;
case 0x64:
- dprintf("Quality of service not aviable");
+ dprintf(_("Quality of service not aviable"));
break;
case 0x65:
- dprintf("Error in SME");
+ dprintf(_("Error in SME"));
break;
default:
- dprintf("Reserved/Specific to SC: %x", status);
+ dprintf(_("Reserved/Specific to SC: %x"), status);
break;
}
} else {
- dprintf("Permanent error, SC is not making any more transfer attempts\n");
+ dprintf(_("Permanent error, SC is not making any more transfer attempts\n"));
switch (status) {
case 0x40:
- dprintf("Remote procedure error");
+ dprintf(_("Remote procedure error"));
break;
case 0x41:
- dprintf("Incompatibile destination");
+ dprintf(_("Incompatibile destination"));
break;
case 0x42:
- dprintf("Connection rejected by SME");
+ dprintf(_("Connection rejected by SME"));
break;
case 0x43:
- dprintf("Not obtainable");
+ dprintf(_("Not obtainable"));
break;
case 0x44:
- dprintf("Quality of service not aviable");
+ dprintf(_("Quality of service not aviable"));
break;
case 0x45:
- dprintf("No internetworking available");
+ dprintf(_("No internetworking available"));
break;
case 0x46:
- dprintf("SM Validity Period Expired");
+ dprintf(_("SM Validity Period Expired"));
break;
case 0x47:
- dprintf("SM deleted by originating SME");
+ dprintf(_("SM deleted by originating SME"));
break;
case 0x48:
- dprintf("SM Deleted by SC Administration");
+ dprintf(_("SM Deleted by SC Administration"));
break;
case 0x49:
- dprintf("SM does not exist");
+ dprintf(_("SM does not exist"));
break;
default:
- dprintf("Reserved/Specific to SC: %x", status);
+ dprintf(_("Reserved/Specific to SC: %x"), status);
break;
}
}
- SMS->Length = strlen(_("Failed"));
+ sms->Length = 6;
} else if (status & 0x20) {
- strcpy(SMS->MessageText, _("Pending"));
+ strcpy(sms->MessageText, _("Pending"));
/* more detailed reason only for debug */
- dprintf("Temporary error, SC still trying to transfer SM\n");
+ dprintf(_("Temporary error, SC still trying to transfer SM\n"));
switch (status) {
case 0x20:
- dprintf("Congestion");
+ dprintf(_("Congestion"));
break;
case 0x21:
- dprintf("SME busy");
+ dprintf(_("SME busy"));
break;
case 0x22:
- dprintf("No response from SME");
+ dprintf(_("No response from SME"));
break;
case 0x23:
- dprintf("Service rejected");
+ dprintf(_("Service rejected"));
break;
case 0x24:
- dprintf("Quality of service not aviable");
+ dprintf(_("Quality of service not aviable"));
break;
case 0x25:
- dprintf("Error in SME");
+ dprintf(_("Error in SME"));
break;
default:
- dprintf("Reserved/Specific to SC: %x", status);
+ dprintf(_("Reserved/Specific to SC: %x"), status);
break;
}
- SMS->Length = strlen(_("Pending"));
+ sms->Length = 7;
} else {
- strcpy(SMS->MessageText, _("Unknown"));
+ strcpy(sms->MessageText, _("Unknown"));
/* more detailed reason only for debug */
- dprintf("Reserved/Specific to SC: %x", status);
- SMS->Length = strlen(_("Unknown"));
+ dprintf(_("Reserved/Specific to SC: %x"), status);
+ sms->Length = 8;
}
- dprintf("\n");
return GE_NONE;
}
-static GSM_Error DecodeData(char *message, char *output, int length, int size, int udhlen, SMS_DataCodingScheme dcs)
+static GSM_Error DecodeData(char *message, char *output, int length, SMS_DataCodingScheme dcs, int udhlen, int size)
{
/* Unicode */
if ((dcs.Type & 0x08) == 0x08) {
- dprintf("Unicode message\n");
length = (length - udhlen)/2;
DecodeUnicode(output, message, length);
+ /* 8bit SMS */
} else {
- /* 8bit SMS */
if ((dcs.Type & 0xf4) == 0xf4) {
- dprintf("8bit message\n");
memcpy(output, message, length);
- /* 7bit SMS */
+ /* 7bit SMS */
} else {
- dprintf("Default Alphabet\n");
- length = length - (udhlen * 8 + ((7-(udhlen%7))%7)) / 7;
+ length = length - (udhlen * 8 + ((7-udhlen)%7)) / 7;
Unpack7BitCharacters((7-udhlen)%7, size, length, message, output);
- DecodeAscii(output, output, length);
}
+ DecodeAscii(output, output, length);
}
dprintf("%s\n", output);
return GE_NONE;
- GSM 03.40 version 6.1.0 Release 1997, section 9.2.3.24
- Smart Messaging Specification, Revision 1.0.0, September 15, 1997
*/
-static GSM_Error DecodeUDH(char *message, GSM_SMSMessage *SMS)
+static GSM_Error DecodeUDH(char *SMSMessage, SMS_UDHInfo **UDHi, GSM_SMSMessage *sms)
{
unsigned char length, pos, nr;
- SMS->UDH_Length = length = message[0] + 1;
+ length = SMSMessage[0];
pos = 1;
nr = 0;
- while (length > 1) {
+ while (length > 0) {
unsigned char udh_length;
- udh_length = message[pos+1];
- switch (message[pos]) {
+ udh_length = SMSMessage[pos+1];
+ switch (SMSMessage[pos]) {
case 0x00: // Concatenated short messages
- dprintf("Concatenated messages\n");
- SMS->UDH[nr].Type = SMS_ConcatenatedMessages;
- SMS->UDH[nr].u.ConcatenatedShortMessage.ReferenceNumber = message[pos + 2];
- SMS->UDH[nr].u.ConcatenatedShortMessage.MaximumNumber = message[pos + 3];
- SMS->UDH[nr].u.ConcatenatedShortMessage.CurrentNumber = message[pos + 4];
+ dprintf("Concat UDH length: %d\n", udh_length);
+ UDHi[nr]->Type = SMS_ConcatenatedMessages;
+ UDHi[nr]->u.ConcatenatedShortMessage.ReferenceNumber = SMSMessage[pos + 3];
+ UDHi[nr]->u.ConcatenatedShortMessage.MaximumNumber = SMSMessage[pos + 4];
+ UDHi[nr]->u.ConcatenatedShortMessage.CurrentNumber = SMSMessage[pos + 5];
break;
case 0x01: // Special SMS Message Indication
- switch (message[pos + 2] & 0x03) {
+ switch (SMSMessage[pos + 3] & 0x03) {
case 0x00:
- dprintf("Voice Message\n");
- SMS->UDH[nr].Type = SMS_VoiceMessage;
+ UDHi[nr]->Type = SMS_VoiceMessage;
break;
case 0x01:
- dprintf("Fax Message\n");
- SMS->UDH[nr].Type = SMS_FaxMessage;
+ UDHi[nr]->Type = SMS_FaxMessage;
break;
case 0x02:
- dprintf("Email Message\n");
- SMS->UDH[nr].Type = SMS_EmailMessage;
+ UDHi[nr]->Type = SMS_EmailMessage;
break;
default:
- dprintf("Unknown\n");
- SMS->UDH[nr].Type = SMS_UnknownUDH;
+ UDHi[nr]->Type = SMS_UnknownUDH;
break;
}
- SMS->UDH[nr].u.SpecialSMSMessageIndication.Store = (message[pos + 2] & 0x80) >> 7;
- SMS->UDH[nr].u.SpecialSMSMessageIndication.MessageCount = message[pos + 3];
+ UDHi[nr]->u.SpecialSMSMessageIndication.Store = (SMSMessage[pos + 3] & 0x80) >> 7;
+ UDHi[nr]->u.SpecialSMSMessageIndication.MessageCount = SMSMessage[pos + 4];
break;
case 0x04: // Application port addression scheme, 8 bit address
break;
case 0x05: // Application port addression scheme, 16 bit address
- switch (((0x00ff & message[pos + 2]) << 8) | (0x00ff & message[pos + 3])) {
- case 0x1581:
- dprintf("Ringtone\n");
- SMS->UDH[nr].Type = SMS_Ringtone;
- break;
- case 0x1582:
- dprintf("Operator Logo\n");
- SMS->UDH[nr].Type = SMS_OpLogo;
- break;
- case 0x1583:
- dprintf("Caller Icon\n");
- SMS->UDH[nr].Type = SMS_CallerIDLogo;
- break;
- case 0x23f4:
- dprintf("Business Card\n");
- SMS->UDH[nr].Type = SMS_BusinessCard;
- break;
- default:
- dprintf("Unknown\n");
- SMS->UDH[nr].Type = SMS_UnknownUDH;
- break;
- }
break;
case 0x06: // SMSC Control Parameters
break;
pos += (udh_length + 2);
nr++;
}
- SMS->UDH_No = nr;
+ sms->UDH_No = nr;
return GE_NONE;
}
-static GSM_Error DecodeSMSHeader(unsigned char *message, GSM_SMSMessage *SMS)
+static GSM_Error DecodeSMSSubmit()
+{
+ return GE_NONE;
+}
+
+static GSM_Error DecodeSMSDeliver()
+{
+ return GE_NONE;
+}
+
+static GSM_Error DecodeSMSHeader(unsigned char *message, GSM_SMSMessage *sms)
{
/* Short Message Type */
- switch (SMS->Type = message[2]) {
+ switch (sms->Type = message[7]) {
case SMS_Deliver:
dprintf("Mobile Terminated message:\n");
break;
case SMS_Delivery_Report:
dprintf("Delivery Report:\n");
- UnpackDateTime(message + 34 + DataOffset[SMS->Type], &(SMS->SMSCTime));
- dprintf("\tDelivery date: %s\n", PrintDateTime(message + 34 + DataOffset[SMS->Type]));
+ UnpackDateTime(message + 39 + DataOffset[sms->Type], &(sms->Time));
+ dprintf("\tDelivery date: %s\n", PrintDateTime(message + 39 + DataOffset[sms->Type]));
break;
case SMS_Submit:
dprintf("Mobile Originated message:\n");
break;
default:
- dprintf("Not supported message type:\n");
+ dprintf("Not supported message:\n");
+ break;
+ }
+ /* Short Message status */
+ sms->Status = message[4];
+ dprintf("\tStatus: ");
+ switch (sms->Status) {
+ case SMS_Read:
+ dprintf("READ\n");
+ break;
+ case SMS_Unread:
+ dprintf("UNREAD\n");
+ break;
+ case SMS_Sent:
+ dprintf("SENT\n");
+ break;
+ case SMS_Unsent:
+ dprintf("UNSENT\n");
+ break;
+ default:
+ dprintf("UNKNOWN\n");
break;
}
/* Short Message location in memory */
- SMS->Number = message[1];
- dprintf("\tLocation: %d\n", SMS->Number);
+ sms->Number = message[6];
+ dprintf("\tLocation: %d\n", sms->Number);
/* Short Message Center */
- strcpy(SMS->MessageCenter.Number, GetBCDNumber(message + 3));
- dprintf("\tSMS center number: %s\n", SMS->MessageCenter.Number);
- SMS->ReplyViaSameSMSC = false;
- if (SMS->RemoteNumber.number[0] == 0 && (message[6] & 0x80)) {
- SMS->ReplyViaSameSMSC = true;
+ strcpy(sms->MessageCenter.Number, GetBCDNumber(message));
+ dprintf("\tSMS center number: %s\n", sms->MessageCenter.Number);
+ sms->ReplyViaSameSMSC = false;
+ if (sms->RemoteNumber.number[0] == 0 && (message[12] & 0x80)) {
+ sms->ReplyViaSameSMSC = true;
}
/* Remote number */
- message[15+DataOffset[SMS->Type]] = ((message[15+DataOffset[SMS->Type]])+1)/2+1;
- dprintf("\tRemote number (recipient or sender): %s\n", GetBCDNumber(message + 15 + DataOffset[SMS->Type]));
- strcpy(SMS->RemoteNumber.number, GetBCDNumber(message + 15 + DataOffset[SMS->Type]));
-
- UnpackDateTime(message + 27 + DataOffset[SMS->Type], &(SMS->Time));
- dprintf("\tDate: %s\n", PrintDateTime(message + 27 + DataOffset[SMS->Type]));
+ message[20+DataOffset[sms->Type]] = ((message[20+DataOffset[sms->Type]])+1)/2+1;
+ dprintf("\tRemote number (recipient or sender): %s\n", GSM_GetBCDNumber(message + 20 + DataOffset[sms->Type]));
+ strcpy(sms->RemoteNumber.number, GetBCDNumber(message + 20 + DataOffset[sms->Type]));
- /* Message length */
- SMS->Length = message[14+DataOffset[SMS->Type]];
+ UnpackDateTime(message + 24 + DataOffset[sms->Type], &(sms->Time));
+ dprintf("\tDate: %s\n", PrintDateTime(message + 24 + DataOffset[sms->Type]));
/* Data Coding Scheme */
- if (SMS->Type != SMS_Delivery_Report && SMS->Type != SMS_Picture)
- SMS->DCS.Type = message[13 + DataOffset[SMS->Type]];
+ if (sms->Type != SMS_Delivery_Report)
+ sms->DCS.Type = message[18 + DataOffset[sms->Type]];
else
- SMS->DCS.Type = 0;
+ sms->DCS.Type = 0;
/* User Data Header */
- if (message[15] & 0x40) { /* UDH header available */
- dprintf("UDH found\n");
- DecodeUDH(message + 34 + DataOffset[SMS->Type], SMS);
- } else { /* No UDH */
- dprintf("No UDH\n");
- SMS->UDH_No = 0;
- }
+ if (message[20] & 0x40) /* UDH header available */
+ DecodeUDH(message + 31 + DataOffset[sms->Type], (SMS_UDHInfo **)sms->UDH, sms);
+ else /* No UDH */
+ sms->UDH_No = 0;
return GE_NONE;
}
*/
GSM_Error DecodePDUSMS(unsigned char *message, GSM_SMSMessage *SMS, int MessageLength)
{
- int size;
- GSM_Bitmap bitmap;
+ int i, udhlen = 0;
DecodeSMSHeader(message, SMS);
- switch (SMS->Type) {
- case SMS_Delivery_Report:
- SMSStatus(message[17], SMS);
- break;
- case SMS_Picture:
- dprintf("Picture!!!\n");
- GSM_ReadSMSBitmap(SMS_Picture, message + 41, NULL, &bitmap);
- GSM_PrintBitmap(&bitmap);
- size = MessageLength - 45 - bitmap.size;
- SMS->Length = message[45 + bitmap.size];
- printf("%d %d %d\n", SMS->Length, bitmap.size, size);
- DecodeData(message + 46 + bitmap.size,
- (unsigned char *)&(SMS->MessageText),
- SMS->Length, size, 0, SMS->DCS);
- SMS->MessageText[SMS->Length] = 0;
- break;
- default:
- size = MessageLength -
- 34 - /* Header Length */
+ for (i = 0; i < SMS->UDH_No; i++) {
+ udhlen += headers[SMS->UDH[i].Type].length;
+ }
+ if (SMS->Type == SMS_Delivery_Report) {
+ SMSStatus(message[22], SMS);
+ } else {
+ int size = MessageLength -
+ 39 - /* Header Length */
DataOffset[SMS->Type] - /* offset */
- SMS->UDH_Length - /* UDH Length */
- 5; /* checksum */
- DecodeData(message + 34 + DataOffset[SMS->Type] + SMS->UDH_Length,
+ udhlen - /* UDH Length */
+ 2; /* checksum */
+ DecodeData(message + 39 + DataOffset[SMS->Type] + udhlen,
(unsigned char *)&(SMS->MessageText),
- SMS->Length, size, SMS->UDH_Length, SMS->DCS);
- /* Just in case */
- SMS->MessageText[SMS->Length] = 0;
- break;
+ SMS->Length, SMS->DCS,
+ udhlen, size);
}
return GE_NONE;
}
/* This function does simple SMS decoding - no PDU coding */
-GSM_Error DecodeTextSMS(unsigned char *message, GSM_SMSMessage *SMS)
+GSM_Error DecodeTextSMS(unsigned char *message, GSM_SMSMessage *sms)
{
+#if 0
+ int w, tmp, i;
+ unsigned char output[161];
+
+ sms->EightBit = false;
+ w = (7 - off) % 7;
+ if (w < 0) w = (14 - off) % 14;
+ sms->Length = message[9 + 11 + offset] - (off * 8 + w) / 7;
+ offset += off;
+ w = (7 - off) % 7;
+ if (w < 0) w = (14 - off) % 14;
+ tmp = Unpack7BitCharacters(w, length-31-9-offset, sms->Length, message+9+31+offset, output);
+ dprintf(" 7 bit SMS, body is (length %i): ",sms->Length);
+ for (i = 0; i < tmp; i++) {
+ dprintf("%c", DecodeWithDefaultAlphabet(output[i]));
+ sms->MessageText[i] = DecodeWithDefaultAlphabet(output[i]);
+ }
+ dprintf("\n");
+#endif
return GE_NONE;
}