From f5423c22b8e60bd9ddd05695135ed0713ae07143 Mon Sep 17 00:00:00 2001 From: laforge Date: Thu, 16 Aug 2007 04:20:03 +0000 Subject: From 5b7c50fd08b8f76f761958c8a8243e6c23118fa3 Mon Sep 17 00:00:00 2001 From: Andrzej Zaborowski 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 --- src/gsmd/Makefile.am | 2 +- src/gsmd/gsmd.c | 4 +- src/gsmd/sms_cb.c | 201 ++++++++++++++++++++++++++++++++++++++++++++------- src/gsmd/sms_pdu.c | 2 + src/gsmd/usock.c | 2 +- src/util/event.c | 8 ++ 6 files changed, 188 insertions(+), 31 deletions(-) (limited to 'src') 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 #include #include +#include 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); -- cgit v1.2.3