summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlaforge <laforge@99fdad57-331a-0410-800a-d7fa5415bdb3>2007-08-16 04:20:03 +0000
committerlaforge <laforge@99fdad57-331a-0410-800a-d7fa5415bdb3>2007-08-16 04:20:03 +0000
commitf5423c22b8e60bd9ddd05695135ed0713ae07143 (patch)
tree5438dc32053b6f2927ac0c096a4b12215007ad4b
parent66ddffab0a8fe2f517d83859ffb20467acd0cbe6 (diff)
From 5b7c50fd08b8f76f761958c8a8243e6c23118fa3 Mon Sep 17 00:00:00 2001
From: Andrzej Zaborowski <balrog@zabor.org> Date: Thu, 12 Jul 2007 14:26:46 +0200 Subject: [PATCH] Incoming SMS events This is a proposed patch to emit a gsmd event when a new SMS arrives, also modifies libgsmd-tool to display the notification. It makes sms_cb.c compile but only really implements the bits necessary to make it build and for the notifications to work. I chose AT+CNMI mode 1 (i.e. store messages in memory and report the location through +CMTI, rather than print the message right away through +CMT) because the parser doesn't support multiline unsolicited responses - in fact it can't support those because in a situation when a normal command is executing and an unsolicited response comes in (which is the case when sending a message to yourself) it is impossible for the parser to distinguish whether the line after the unsolicited response is part of that response or part of the command's response. git-svn-id: http://svn.openmoko.org/trunk/src/target/gsm@2711 99fdad57-331a-0410-800a-d7fa5415bdb3
-rw-r--r--include/gsmd/sms.h2
-rw-r--r--include/gsmd/usock.h23
-rw-r--r--src/gsmd/Makefile.am2
-rw-r--r--src/gsmd/gsmd.c4
-rw-r--r--src/gsmd/sms_cb.c201
-rw-r--r--src/gsmd/sms_pdu.c2
-rw-r--r--src/gsmd/usock.c2
-rw-r--r--src/util/event.c8
8 files changed, 206 insertions, 38 deletions
diff --git a/include/gsmd/sms.h b/include/gsmd/sms.h
index 145b585..ac16509 100644
--- a/include/gsmd/sms.h
+++ b/include/gsmd/sms.h
@@ -5,6 +5,8 @@
#include <gsmd/gsmd.h>
+int sms_cb_init(struct gsmd *gsmd);
+
int sms_pdu_make_smssubmit(char *dest, const struct gsmd_sms_submit *src);
int sms_pdu_to_msg(struct gsmd_sms_list *dst, const u_int8_t *src,
int pdulen, int len);
diff --git a/include/gsmd/usock.h b/include/gsmd/usock.h
index 631238a..f42a766 100644
--- a/include/gsmd/usock.h
+++ b/include/gsmd/usock.h
@@ -55,6 +55,11 @@ enum gsmd_msg_phone {
GSMD_PHONE_POWERDOWN = 2,
};
+enum gsmd_msg_cb {
+ GSMD_CB_SUBSCRIBE = 1,
+ GSMD_CB_UNSUBSCRIBE = 2,
+};
+
enum gsmd_msg_network {
GSMD_NETWORK_REGISTER = 1,
GSMD_NETWORK_SIGQ_GET = 2,
@@ -65,11 +70,15 @@ enum gsmd_msg_network {
};
enum gsmd_msg_sms {
- GSMD_SMS_LIST = 1,
- GSMD_SMS_READ = 2,
- GSMD_SMS_SEND = 3,
- GSMD_SMS_WRITE = 4,
- GSMD_SMS_DELETE = 5,
+ GSMD_SMS_LIST = 1,
+ GSMD_SMS_READ = 2,
+ GSMD_SMS_SEND = 3,
+ GSMD_SMS_WRITE = 4,
+ GSMD_SMS_DELETE = 5,
+ GSMD_SMS_GET_MSG_STORAGE = 6,
+ GSMD_SMS_SET_MSG_STORAGE = 7,
+ GSMD_SMS_GET_SERVICE_CENTRE = 8,
+ GSMD_SMS_SET_SERVICE_CENTRE = 9,
};
/* SMS stat from 3GPP TS 07.05, Clause 3.1 */
@@ -248,8 +257,8 @@ struct gsmd_evt_auxdata {
struct gsmd_addr addr;
} colp;
struct {
- /* TBD */
- struct gsmd_addr addr;
+ u_int8_t memtype;
+ int index;
} sms;
struct {
enum gsmd_pin_type type;
diff --git a/src/gsmd/Makefile.am b/src/gsmd/Makefile.am
index 6b25812..1ff1970 100644
--- a/src/gsmd/Makefile.am
+++ b/src/gsmd/Makefile.am
@@ -7,7 +7,7 @@ sbin_PROGRAMS = gsmd
gsmd_CFLAGS = -D PLUGINDIR=\"$(plugindir)\"
gsmd_SOURCES = gsmd.c atcmd.c select.c machine.c vendor.c unsolicited.c log.c \
usock.c talloc.c timer.c operator_cache.c ext_response.c \
- sms_pdu.c
+ sms_cb.c sms_pdu.c
gsmd_LDADD = -ldl
gsmd_LDFLAGS = -Wl,--export-dynamic
diff --git a/src/gsmd/gsmd.c b/src/gsmd/gsmd.c
index 734620e..5e9b046 100644
--- a/src/gsmd/gsmd.c
+++ b/src/gsmd/gsmd.c
@@ -185,7 +185,9 @@ static int gsmd_initsettings2(struct gsmd *gsmd)
#if 0
/* Select TE character set */
rc |= gsmd_simplecmd(gsmd, "AT+CSCS=\"UCS2\"");
-#endif
+#endif
+
+ sms_cb_init(gsmd);
if (gsmd->vendorpl && gsmd->vendorpl->initsettings)
return gsmd->vendorpl->initsettings(gsmd);
diff --git a/src/gsmd/sms_cb.c b/src/gsmd/sms_cb.c
index 22bf613..9884bfb 100644
--- a/src/gsmd/sms_cb.c
+++ b/src/gsmd/sms_cb.c
@@ -36,11 +36,11 @@
#include <gsmd/select.h>
#include <gsmd/atcmd.h>
#include <gsmd/usock.h>
+#include <gsmd/unsolicited.h>
enum ts0705_mem_type {
GSM0705_MEMTYPE_NONE,
GSM0705_MEMTYPE_BROADCAST,
- GSM0705_MEMTYPE_BROADCAST,
GSM0705_MEMTYPE_ME_MESSAGE,
GSM0705_MEMTYPE_MT,
GSM0705_MEMTYPE_SIM,
@@ -48,7 +48,7 @@ enum ts0705_mem_type {
GSM0705_MEMTYPE_SR,
};
-static const char *ts0705_memtype_name = {
+static const char *ts0705_memtype_name[] = {
[GSM0705_MEMTYPE_NONE] = "NONE",
[GSM0705_MEMTYPE_BROADCAST] = "BM",
[GSM0705_MEMTYPE_ME_MESSAGE] = "ME",
@@ -70,9 +70,10 @@ static inline int parse_memtype(char *memtype)
return GSM0705_MEMTYPE_NONE;
}
+/* TODO: move to headers */
struct __gsmd_sms_storage {
- u_int8 memtype;
- u_int8_t pad[3]
+ u_int8_t memtype;
+ u_int8_t pad[3];
u_int16_t used;
u_int16_t total;
} __attribute__ ((packed));
@@ -85,21 +86,34 @@ static int usock_cpms_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
{
struct gsmd_user *gu = ctx;
struct gsmd_ucmd *ucmd = ucmd_alloc(sizeof(struct gsmd_sms_storage));
+ struct gsmd_sms_storage *gss = (typeof(gss)) ucmd->buf;
+ char buf[3][3];
DEBUGP("entering(cmd=%p, gu=%p)\n", cmd, gu);
if (!ucmd)
return -ENOMEM;
-
-
-
ucmd->hdr.version = GSMD_PROTO_VERSION;
ucmd->hdr.msg_type = GSMD_MSG_SMS;
- ucmd->hdr.msg_subtype = GSMD_SMS_GETMSG_STORAGE;
- ucmd->hdr.len = ...;
+ ucmd->hdr.msg_subtype = GSMD_SMS_GET_MSG_STORAGE;
+ ucmd->hdr.len = sizeof(struct gsmd_sms_storage);
ucmd->hdr.id = cmd->id;
-
+
+ if (sscanf(resp, "+CPMS: \"%2[A-Z]\",%hi,%hi,"
+ "\"%2[A-Z]\",%hi,%hi,\"%2[A-Z]\",%hi,%hi",
+ buf[0], &gss->mem[0].used, &gss->mem[0].total,
+ buf[1], &gss->mem[1].used, &gss->mem[1].total,
+ buf[2], &gss->mem[2].used, &gss->mem[2].total)
+ < 9) {
+ talloc_free(ucmd);
+ return -EINVAL;
+ }
+
+ gss->mem[0].memtype = parse_memtype(buf[0]);
+ gss->mem[1].memtype = parse_memtype(buf[1]);
+ gss->mem[2].memtype = parse_memtype(buf[2]);
+
usock_cmd_enqueue(ucmd, gu);
return 0;
@@ -113,14 +127,13 @@ static int usock_rcv_sms(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
switch (gph->msg_subtype) {
case GSMD_SMS_GET_SERVICE_CENTRE:
-
- break;
+ return;
case GSMD_SMS_SET_SERVICE_CENTRE:
- break;
+ return;
case GSMD_SMS_SET_MSG_STORAGE:
- break;
+ return;
case GSMD_SMS_GET_MSG_STORAGE:
- cmd = atcmd_fill("AT+CPMS?", 8, ...);
+ cmd = atcmd_fill("AT+CPMS?", 8 + 1, usock_cpms_cb, gu, 0);
break;
}
@@ -131,7 +144,6 @@ static int usock_rcv_sms(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
static int usock_rcv_cb(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
int len)
{
-
switch (gph->msg_subtype) {
case GSMD_CB_SUBSCRIBE:
break;
@@ -139,44 +151,158 @@ static int usock_rcv_cb(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
break;
}
- return
+ return -ENOSYS;
}
-
/* Unsolicited messages related to SMS / CB */
static int cmti_parse(char *buf, int len, const char *param,
struct gsmd *gsmd)
{
+ char memstr[3];
+ struct gsmd_ucmd *ucmd = ucmd_alloc(sizeof(struct gsmd_evt_auxdata));
+ struct gsmd_evt_auxdata *aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+
+ if (!ucmd)
+ return -ENOMEM;
+
+ ucmd->hdr.version = GSMD_PROTO_VERSION;
+ ucmd->hdr.msg_type = GSMD_MSG_EVENT;
+ ucmd->hdr.msg_subtype = GSMD_EVT_IN_SMS;
+ ucmd->hdr.len = sizeof(*aux);
+
+ if (sscanf(param, "\"%2[A-Z]\",%i", memstr, &aux->u.sms.index) < 2) {
+ talloc_free(ucmd);
+ return -EINVAL;
+ }
+
+ aux->u.sms.memtype = parse_memtype(memstr);
+
+ return usock_evt_send(gsmd, ucmd, GSMD_EVT_IN_SMS);
}
static int cmt_parse(char *buf, int len, const char *param,
struct gsmd *gsmd)
{
+ /* TODO: TEXT mode */
+ u_int8_t pdu[180];
+ const char *comma = strchr(param, ',');
+ char *cr;
+ int i;
+ struct gsmd_sms_list msg;
+
+ if (!comma)
+ return -EINVAL;
+ len = strtoul(comma + 1, &cr, 10);
+ if (cr[0] != '\n')
+ return -EINVAL;
+
+ cr ++;
+ for (i = 0; cr[0] >= '0' && cr[1] >= '0' && i < 180; i ++) {
+ if (sscanf(cr, "%2hhX", &pdu[i]) < 1) {
+ gsmd_log(GSMD_DEBUG, "malformed input (%i)\n", i);
+ return -EINVAL;
+ }
+ cr += 2;
+ }
+ if (sms_pdu_to_msg(&msg, pdu, len, i)) {
+ gsmd_log(GSMD_DEBUG, "malformed PDU\n");
+ return -EINVAL;
+ }
+
+ /* FIXME: generate some kind of event */
+ return -ENOSYS;
}
static int cbmi_parse(char *buf, int len, const char *param,
struct gsmd *gsmd)
{
+ char memstr[3];
+ int memtype, index;
+
+ if (sscanf(param, "\"%2[A-Z]\",%i", memstr, &index) < 2)
+ return -EINVAL;
+
+ memtype = parse_memtype(memstr);
+ /* FIXME: generate some kind of event */
+ return -ENOSYS;
}
static int cbm_parse(char *buf, int len, const char *param,
struct gsmd *gsmd)
{
+ /* TODO: TEXT mode */
+ u_int8_t pdu[180];
+ char *cr;
+ int i;
+ struct gsmd_sms_list msg;
+
+ len = strtoul(param, &cr, 10);
+ if (cr[0] != '\n')
+ return -EINVAL;
+
+ cr ++;
+ for (i = 0; cr[0] >= '0' && cr[1] >= '0' && i < 180; i ++) {
+ if (sscanf(cr, "%2hhX", &pdu[i]) < 1) {
+ gsmd_log(GSMD_DEBUG, "malformed input (%i)\n", i);
+ return -EINVAL;
+ }
+ cr += 2;
+ }
+ if (sms_pdu_to_msg(&msg, pdu, len, i)) {
+ gsmd_log(GSMD_DEBUG, "malformed PDU\n");
+ return -EINVAL;
+ }
+
+ /* FIXME: generate some kind of event */
+ return -ENOSYS;
}
static int cdsi_parse(char *buf, int len, const char *param,
struct gsmd *gsmd)
{
+ char memstr[3];
+ int memtype, index;
+
+ if (sscanf(param, "\"%2[A-Z]\",%i", memstr, &index) < 2)
+ return -EINVAL;
+
+ memtype = parse_memtype(memstr);
+ /* FIXME: generate some kind of event */
+ return -ENOSYS;
}
static int cds_parse(char *buf, int len, const char *param,
struct gsmd *gsmd)
{
-}
+ /* TODO: TEXT mode */
+ u_int8_t pdu[180];
+ char *cr;
+ int i;
+ struct gsmd_sms_list msg;
+
+ len = strtoul(param, &cr, 10);
+ if (cr[0] != '\n')
+ return -EINVAL;
+
+ cr ++;
+ for (i = 0; cr[0] >= '0' && cr[1] >= '0' && i < 180; i ++) {
+ if (sscanf(cr, "%2hhX", &pdu[i]) < 1) {
+ gsmd_log(GSMD_DEBUG, "malformed input (%i)\n", i);
+ return -EINVAL;
+ }
+ cr += 2;
+ }
+ if (sms_pdu_to_msg(&msg, pdu, len, i)) {
+ gsmd_log(GSMD_DEBUG, "malformed PDU\n");
+ return -EINVAL;
+ }
+ /* FIXME: generate some kind of event */
+ return -ENOSYS;
+}
-static const struct gsmd_unsolocit gsm0705_unsolicit[] = {
- { "+CMTI", &cmti_parse }, /* SMS Deliver Index (stored in ME/TA) */
+static const struct gsmd_unsolicit gsm0705_unsolicit[] = {
+ { "+CMTI", &cmti_parse }, /* SMS Deliver Index (stored in ME/TA)*/
{ "+CMT", &cmt_parse }, /* SMS Deliver to TE */
{ "+CBMI", &cbmi_parse }, /* Cell Broadcast Message Index */
{ "+CBM", &cbm_parse }, /* Cell Broadcast Message */
@@ -189,24 +315,43 @@ int sms_cb_init(struct gsmd *gsmd)
struct gsmd_atcmd *atcmd;
char buffer[10];
- atcmd = atcmd_fill("AT+CSMS=0", NULL, gu, 0);
+ atcmd = atcmd_fill("AT+CSMS=0", 9 + 1, NULL, gsmd, 0);
+ if (!atcmd)
+ return -ENOMEM;
+ atcmd_submit(gsmd, atcmd);
+
+ /* Store and notify */
+ atcmd = atcmd_fill("AT+CNMI=1,1,1", 13 + 1, NULL, gsmd, 0);
+ if (!atcmd)
+ return -ENOMEM;
+ atcmd_submit(gsmd, atcmd);
+
+ /* Store into ME/TA and notify */
+ atcmd = atcmd_fill("AT+CSBS=1", 9 + 1, NULL, gsmd, 0);
+ if (!atcmd)
+ return -ENOMEM;
+ atcmd_submit(gsmd, atcmd);
+
+ /* Store into ME/TA and notify */
+ atcmd = atcmd_fill("AT+CSDS=2", 9 + 1, NULL, gsmd, 0);
if (!atcmd)
return -ENOMEM;
atcmd_submit(gsmd, atcmd);
/* If text mode, set the encoding */
- if (gu->gsmd->flags & GSMD_FLAG_SMS_FMT_TEXT) {
- atcmd = atcmd_fill("AT+CSCS=\"IRA\"", 13, NULL, gu, 0);
+ if (gsmd->flags & GSMD_FLAG_SMS_FMT_TEXT) {
+ atcmd = atcmd_fill("AT+CSCS=\"IRA\"", 13 + 1, NULL, gsmd, 0);
if (!atcmd)
return -ENOMEM;
atcmd_submit(gsmd, atcmd);
}
/* Switch into desired mode (Section 3.2.3) */
- snprintf(buffer, sizeof(buffer), "AT+CMGF=%i",
- (gu->gsmd->flags & GSMD_FLAG_SMS_FMT_TEXT) ?
- GSMD_SMS_FMT_TEXT : GSMD_SMS_FMT_PDU);
- atcmd = atcmd_fill(buffer, strlen(buffer) + 1, NULL, gu, 0);
+ atcmd = atcmd_fill(buffer, snprintf(buffer, sizeof(buffer),
+ "AT+CMGF=%i",
+ (gsmd->flags & GSMD_FLAG_SMS_FMT_TEXT) ?
+ GSMD_SMS_FMT_TEXT : GSMD_SMS_FMT_PDU) + 1,
+ NULL, gsmd, 0);
if (!atcmd)
return -ENOMEM;
diff --git a/src/gsmd/sms_pdu.c b/src/gsmd/sms_pdu.c
index 1ec3202..c9b9327 100644
--- a/src/gsmd/sms_pdu.c
+++ b/src/gsmd/sms_pdu.c
@@ -179,6 +179,8 @@ int sms_pdu_to_msg(struct gsmd_sms_list *dst,
memset(dst->time_stamp, 0, 7);
break;
+ case GSMD_SMS_TP_MTI_STATUS_REPORT:
+ /* TODO */
default:
/* Unknown PDU type */
return 1;
diff --git a/src/gsmd/usock.c b/src/gsmd/usock.c
index be8aee8..8496dd1 100644
--- a/src/gsmd/usock.c
+++ b/src/gsmd/usock.c
@@ -532,7 +532,7 @@ static int sms_send_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
struct gsmd_ucmd *ucmd;
int msgref;
- if (cmd->ret == 0) {
+ if (cmd->ret == 0 || cmd->ret == -255) {
if (sscanf(resp, "+CMGS: %i", &msgref) < 1)
return -EINVAL;
} else
diff --git a/src/util/event.c b/src/util/event.c
index 0fe6472..209d34b 100644
--- a/src/util/event.c
+++ b/src/util/event.c
@@ -34,6 +34,13 @@ static int incall_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxda
return 0;
}
+static int insms_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata *aux)
+{
+ printf("EVENT: Incoming SMS stored at location %i\n", aux->u.sms.index);
+
+ return 0;
+}
+
static int clip_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata *aux)
{
printf("EVENT: Incoming call clip = %s\n", aux->u.clip.addr.number);
@@ -131,6 +138,7 @@ int event_init(struct lgsm_handle *lh)
rc = lgsm_evt_handler_register(lh, GSMD_EVT_IN_CALL, &incall_handler);
rc |= lgsm_evt_handler_register(lh, GSMD_EVT_IN_CLIP, &clip_handler);
+ rc |= lgsm_evt_handler_register(lh, GSMD_EVT_IN_SMS, &insms_handler);
rc |= lgsm_evt_handler_register(lh, GSMD_EVT_OUT_COLP, &colp_handler);
rc |= lgsm_evt_handler_register(lh, GSMD_EVT_NETREG, &netreg_handler);
rc |= lgsm_evt_handler_register(lh, GSMD_EVT_SIGNAL, &sigq_handler);
personal git repositories of Harald Welte. Your mileage may vary