Trying to support PDU mode while receiving SMS messages (untested)
This commit is contained in:
parent
74d63f15ef
commit
f70964a59a
178
src/gsm.c
178
src/gsm.c
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user