Trying to support PDU mode while receiving SMS messages (untested)

This commit is contained in:
Pierre Pronchery 2010-05-27 11:58:12 +00:00
parent 74d63f15ef
commit f70964a59a
2 changed files with 174 additions and 7 deletions

178
src/gsm.c
View File

@ -83,6 +83,59 @@ struct _GSM
/* variables */ /* variables */
/* conversions */
static struct
{
unsigned char gsm;
unsigned char iso;
} _gsm_conv[] =
{
{ '\0', '@' },
{ 0x01, 163 },
{ 0x02, '$' },
{ 0x03, 165 },
{ 0x04, 232 },
{ 0x05, 233 },
{ 0x06, 249 },
{ 0x07, 236 },
{ 0x08, 242 },
{ 0x09, 199 },
{ 0x0b, 216 },
{ 0x0c, 248 },
{ 0x0e, 197 },
{ 0x0f, 229 },
{ 0x10, ' ' }, /* XXX delta */
{ 0x11, '_' },
{ 0x12, ' ' }, /* XXX phi */
{ 0x13, ' ' }, /* XXX gamma */
{ 0x14, ' ' }, /* XXX lambda */
{ 0x15, ' ' }, /* XXX omega */
{ 0x16, ' ' }, /* XXX pi */
{ 0x17, ' ' }, /* XXX psi */
{ 0x18, ' ' }, /* XXX sigma */
{ 0x19, ' ' }, /* XXX theta */
{ 0x1a, ' ' }, /* XXX xi */
{ 0x1b, ' ' }, /* FIXME escape */
{ 0x1c, 198 },
{ 0x1d, 230 },
{ 0x1e, 223 },
{ 0x1f, 201 },
{ 0x24, 164 },
{ 0x40, 161 },
{ 0x5b, 196 },
{ 0x5c, 214 },
{ 0x5d, 209 },
{ 0x5e, 220 },
{ 0x5f, 167 },
{ 0x60, 191 },
{ 0x7b, 228 },
{ 0x7c, 246 },
{ 0x7d, 241 },
{ 0x7e, 252 },
{ 0x7f, 224 }
};
/* errors */
/* CME ERROR */ /* CME ERROR */
static struct static struct
{ {
@ -154,6 +207,9 @@ static struct
/* prototypes */ /* prototypes */
/* conversions */
static unsigned char _gsm_convert_to_iso(unsigned char c);
/* events */ /* events */
static int _gsm_event_send(GSM * gsm, GSMEventType type); static int _gsm_event_send(GSM * gsm, GSMEventType type);
static int _gsm_event_set_status(GSM * gsm, GSMStatus status); static int _gsm_event_set_status(GSM * gsm, GSMStatus status);
@ -855,6 +911,19 @@ int gsm_send_message(GSM * gsm, char const * number, char const * text)
/* private */ /* private */
/* functions */ /* functions */
/* conversions */
/* gsm_convert_to_iso */
static unsigned char _gsm_convert_to_iso(unsigned char c)
{
size_t i;
for(i = 0; i < sizeof(_gsm_conv) / sizeof(*_gsm_conv); i++)
if(_gsm_conv[i].gsm == c)
return _gsm_conv[i].iso;
return c;
}
/* events */ /* events */
/* gsm_event_send */ /* gsm_event_send */
static int _gsm_event_send(GSM * gsm, GSMEventType type) static int _gsm_event_send(GSM * gsm, GSMEventType type)
@ -1303,6 +1372,8 @@ static int _gsm_trigger_cmgl(GSM * gsm, char const * result)
/* gsm_trigger_cmgr */ /* gsm_trigger_cmgr */
static unsigned char * _cmgr_pdu_parse(char const * pdu);
static int _gsm_trigger_cmgr(GSM * gsm, char const * result) static int _gsm_trigger_cmgr(GSM * gsm, char const * result)
{ {
char buf[32]; char buf[32];
@ -1311,6 +1382,7 @@ static int _gsm_trigger_cmgr(GSM * gsm, char const * result)
unsigned int alpha = 0; unsigned int alpha = 0;
unsigned int * length = &gsm->event.message.length; unsigned int * length = &gsm->event.message.length;
struct tm t; struct tm t;
unsigned char * p;
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result);
@ -1331,18 +1403,114 @@ static int _gsm_trigger_cmgr(GSM * gsm, char const * result)
return 0; /* we need to wait for the next line */ return 0; /* we need to wait for the next line */
} }
/* PDU mode support */ /* PDU mode support */
if(sscanf(result, "%u,%u,%u", &mbox, &alpha, length) == 3 else if(sscanf(result, "%u,%u,%u", &mbox, &alpha, length) != 3
|| sscanf(result, "%u,,%u", &mbox, length) == 2) && sscanf(result, "%u,,%u", &mbox, length) != 2)
return 0; return 0;
/* message content */ /* message content */
if(*length == 0) /* XXX assumes this is text mode */ if(*length == 0) /* XXX assumes this is text mode */
{ {
gsm->event.message.content = result; gsm->event.message.content = result;
*length = strlen(result); *length = strlen(result);
_gsm_event_send(gsm, GSM_EVENT_TYPE_MESSAGE);
} }
else /* FIXME actually parse the PDU */ else if((p = _cmgr_pdu_parse(result)) != NULL)
gsm->event.message.content = result; {
return _gsm_event_send(gsm, GSM_EVENT_TYPE_MESSAGE); gsm->event.message.content = (char *)p;
_gsm_event_send(gsm, GSM_EVENT_TYPE_MESSAGE);
free(p);
}
return 0;
}
/* XXX this function is fat and ugly */
static unsigned char * _cmgr_pdu_parse(char const * pdu)
{
size_t len;
unsigned int smscl;
unsigned int addrl;
unsigned int pid;
unsigned int dcs;
unsigned int datal;
unsigned int u;
unsigned char * p;
char const * q;
size_t i;
size_t j;
unsigned char byte;
unsigned char rest;
int shift;
len = strlen(pdu);
if(sscanf(pdu, "%02X", &smscl) != 1) /* SMSC length */
return NULL;
if((smscl * 2) + 2 > len)
return NULL;
q = pdu + (smscl * 2) + 2;
if(sscanf(q, "%02X", &u) != 1)
return NULL;
if((u & 0x04) != 0x04) /* SMS-DELIVER */
return NULL;
if((smscl * 2) + 4 > len)
return NULL;
q = pdu + (smscl * 2) + 4;
if(sscanf(q, "%02X", &addrl) != 1) /* address length */
return NULL;
if((smscl * 2) + 6 > len)
return NULL;
q = pdu + (smscl * 2) + 6;
if(sscanf(q, "%02X", &u) != 1) /* type of address */
return NULL;
/* FIXME this probably depends on the type of address */
if(addrl % 2 == 1)
addrl++;
if((smscl * 2) + 2 + 4 + addrl + 2 > len)
return NULL;
q = pdu + (smscl * 2) + 2 + 4 + addrl + 2;
if(sscanf(q, "%02X", &pid) != 1) /* PID */
return NULL;
if((smscl * 2) + 2 + 4 + addrl + 4 > len)
return NULL;
q = pdu + (smscl * 2) + 2 + 4 + addrl + 4;
if(sscanf(q, "%02X", &dcs) != 1) /* DCS */
return NULL;
/* FIXME check the DCS */
if((smscl * 2) + 2 + 4 + addrl + 6 > len)
return NULL;
q = pdu + (smscl * 2) + 2 + 4 + addrl + 6;
/* FIXME implement timestamp */
if((smscl * 2) + 2 + 4 + addrl + 6 + 14 > len)
return NULL;
q = pdu + (smscl * 2) + 2 + 4 + addrl + 6 + 14;
if(sscanf(q, "%02X", &datal) != 1) /* data length */
return NULL;
/* XXX check the data length */
if((smscl * 2) + 2 + 4 + addrl + 6 + 16 > len)
return NULL;
q = pdu + (smscl * 2) + 2 + 4 + addrl + 6 + 16;
i = (smscl * 2) + 2 + 4 + addrl + 6 + 16;
if((p = malloc((len - i) * 2)) == NULL)
return NULL;
p[0] = '\0';
for(j = 0, rest = 0, shift = 0; i + 1 < len; i+=2)
{
q = &pdu[i];
if(sscanf(q, "%02X", &u) != 1)
break;
byte = u;
p[j] = (byte << (shift + 1) >> (shift + 1) << shift) & 0x7f;
p[j] |= rest;
p[j] = _gsm_convert_to_iso(p[j]);
j++;
rest = (byte >> (7 - shift)) & 0x7f;
if(++shift == 7)
{
shift = 0;
p[j++] = rest;
rest = 0;
}
}
p[j] = '\0';
return p;
} }

View File

@ -296,8 +296,7 @@ int gsm_modem_get_message(GSMModem * gsmm, unsigned int index)
{ {
char cmd[32]; char cmd[32];
/* FIXME should default to PDU mode */ if(gsm_modem_set_message_format(gsmm, GSM_MESSAGE_FORMAT_PDU) != 0)
if(gsm_modem_set_message_format(gsmm, GSM_MESSAGE_FORMAT_TEXT) != 0)
return 1; return 1;
snprintf(cmd, sizeof(cmd), "%s%u", "AT+CMGR=", index); snprintf(cmd, sizeof(cmd), "%s%u", "AT+CMGR=", index);
/* XXX race condition here if the user forces out of PDU mode */ /* XXX race condition here if the user forces out of PDU mode */