summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/gsmd/event.h2
-rw-r--r--include/gsmd/sms.h5
-rw-r--r--include/gsmd/usock.h19
-rw-r--r--include/libgsmd/sms.h7
-rw-r--r--src/gsmd/sms_cb.c555
-rw-r--r--src/gsmd/unsolicited.c2
-rw-r--r--src/gsmd/usock.c7
-rw-r--r--src/libgsmd/libgsmd_sms.c10
8 files changed, 542 insertions, 65 deletions
diff --git a/include/gsmd/event.h b/include/gsmd/event.h
index 15d070d..395c488 100644
--- a/include/gsmd/event.h
+++ b/include/gsmd/event.h
@@ -16,6 +16,8 @@ enum gsmd_events {
GSMD_EVT_TIMEZONE = 11, /* Timezone change */
GSMD_EVT_SUBSCRIPTIONS = 12, /* To which events are we subscribed to */
GSMD_EVT_CIPHER = 13, /* Chiphering Information */
+ GSMD_EVT_IN_CBM = 14, /* Incoming Cell Broadcat message */
+ GSMD_EVT_IN_DS = 15, /* SMS Status Report */
__NUM_GSMD_EVT
};
diff --git a/include/gsmd/sms.h b/include/gsmd/sms.h
index 3192472..f4def25 100644
--- a/include/gsmd/sms.h
+++ b/include/gsmd/sms.h
@@ -7,12 +7,13 @@
int sms_cb_init(struct gsmd *gsmd);
+#define MAX_PDU_SIZE 180
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);
-extern const char *ts0705_memtype_name[];
-int parse_memtype(char *memtype);
+int usock_rcv_sms(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len);
+int usock_rcv_cb(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len);
#endif /* __GSMD__ */
diff --git a/include/gsmd/usock.h b/include/gsmd/usock.h
index bcff129..18ffa5e 100644
--- a/include/gsmd/usock.h
+++ b/include/gsmd/usock.h
@@ -22,6 +22,7 @@ enum gsmd_msg_type {
GSMD_MSG_PHONE = 7,
GSMD_MSG_PIN = 8,
GSMD_MSG_SMS = 9,
+ GSMD_MSG_CB = 10,
__NUM_GSMD_MSGS
};
@@ -259,10 +260,21 @@ struct gsmd_evt_auxdata {
struct gsmd_addr addr;
} colp;
struct {
+ int inlined;
u_int8_t memtype;
int index;
} sms;
struct {
+ int inlined;
+ u_int8_t memtype;
+ int index;
+ } cbm;
+ struct {
+ int inlined;
+ u_int8_t memtype;
+ int index;
+ } ds;
+ struct {
enum gsmd_pin_type type;
} pin;
struct {
@@ -289,7 +301,8 @@ struct gsmd_evt_auxdata {
u_int16_t net_state_gprs;
} cipher;
} u;
-} __attribute__((packed));
+ u_int8_t data[0];
+} __attribute__ ((packed));
/* Refer to GSM 07.05 subclause 3.5.4 */
struct gsmd_sms_delete {
@@ -431,8 +444,10 @@ struct gsmd_ucmd {
extern struct gsmd_ucmd *ucmd_alloc(int extra_size);
extern int usock_init(struct gsmd *g);
extern void usock_cmd_enqueue(struct gsmd_ucmd *ucmd, struct gsmd_user *gu);
-extern struct gsmd_ucmd *usock_build_event(u_int8_t type, u_int8_t subtype, u_int8_t len);
+extern struct gsmd_ucmd *usock_build_event(u_int8_t type, u_int8_t subtype, u_int16_t len);
extern int usock_evt_send(struct gsmd *gsmd, struct gsmd_ucmd *ucmd, u_int32_t evt);
+extern struct gsmd_ucmd *gsmd_ucmd_fill(int len, u_int8_t msg_type,
+ u_int8_t msg_subtype, u_int16_t id);
#endif /* __GSMD__ */
diff --git a/include/libgsmd/sms.h b/include/libgsmd/sms.h
index d389b21..69363e7 100644
--- a/include/libgsmd/sms.h
+++ b/include/libgsmd/sms.h
@@ -109,5 +109,10 @@ extern int packing_UCS2_82(char *src, char *dest);
/* Refer to 3GPP TS 11.11 Annex B */
extern int unpacking_UCS2_82(char *src, char *dest);
-#endif
+/* This phone wants to receive Cell Broadcast Messages */
+extern int lgsm_cb_subscribe(struct lgsm_handle *lh);
+
+/* This phone wants no more Cell Broadcast Messages */
+extern int lgsm_cb_unsubscribe(struct lgsm_handle *lh);
+#endif
diff --git a/src/gsmd/sms_cb.c b/src/gsmd/sms_cb.c
index 97141c1..9aed070 100644
--- a/src/gsmd/sms_cb.c
+++ b/src/gsmd/sms_cb.c
@@ -18,7 +18,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
- */
+ */
#include <stdlib.h>
#include <stdio.h>
@@ -37,8 +37,9 @@
#include <gsmd/atcmd.h>
#include <gsmd/usock.h>
#include <gsmd/unsolicited.h>
+#include <gsmd/sms.h>
-const char *ts0705_memtype_name[] = {
+static const char *ts0705_memtype_name[] = {
[GSM0705_MEMTYPE_NONE] = "NONE",
[GSM0705_MEMTYPE_BROADCAST] = "BM",
[GSM0705_MEMTYPE_ME_MESSAGE] = "ME",
@@ -48,7 +49,7 @@ const char *ts0705_memtype_name[] = {
[GSM0705_MEMTYPE_SR] = "SR",
};
-inline int parse_memtype(char *memtype)
+static inline int parse_memtype(char *memtype)
{
int i;
@@ -60,165 +61,597 @@ inline int parse_memtype(char *memtype)
return GSM0705_MEMTYPE_NONE;
}
+static int sms_list_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+ struct gsmd_sms_list msg;
+ int i, idx, stat, len, cr;
+ u_int8_t pdu[MAX_PDU_SIZE];
+
+ if (cmd->ret && cmd->ret != -255)
+ return 0;
+
+ /* FIXME: TEXT mode */
+ if (
+ sscanf(resp, "+CMGL: %i,%i,,%i\n%n",
+ &idx, &stat, &len, &cr) < 3 &&
+ sscanf(resp, "+CMGL: %i,%i,\"%*[^\"]\",%i\n%n",
+ &idx, &stat, &len, &cr) < 3)
+ return -EINVAL;
+ if (len > 164)
+ return -EINVAL;
+
+ msg.index = idx;
+ msg.stat = stat;
+ msg.is_last = (cmd->ret == 0);
+ for (i = 0; resp[cr] >= '0' && resp[cr + 1] >= '0' &&
+ i < MAX_PDU_SIZE; i ++) {
+ if (sscanf(resp + 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;
+ }
+
+ ucmd = gsmd_ucmd_fill(sizeof(msg), GSMD_MSG_SMS,
+ GSMD_SMS_LIST, cmd->id);
+ if (!ucmd)
+ return -ENOMEM;
+ memcpy(ucmd->buf, &msg, sizeof(msg));
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int sms_read_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+ struct gsmd_sms_list msg;
+ int i, stat, len, cr;
+ u_int8_t pdu[MAX_PDU_SIZE];
+
+ if (cmd->ret)
+ return 0;
+
+ /* FIXME: TEXT mode */
+ if (
+ sscanf(resp, "+CMGR: %i,,%i\n%n",
+ &stat, &len, &cr) < 2 &&
+ sscanf(resp, "+CMGR: %i,%*i,%i\n%n",
+ &stat, &len, &cr) < 2)
+ return -EINVAL;
+ if (len > 164)
+ return -EINVAL;
+
+ msg.index = 0;
+ msg.stat = stat;
+ msg.is_last = 1;
+ for (i = 0; resp[cr] >= '0' && resp[cr + 1] >= '0' &&
+ i < MAX_PDU_SIZE; i ++) {
+ if (sscanf(resp + 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;
+ }
+
+ ucmd = gsmd_ucmd_fill(sizeof(msg), GSMD_MSG_SMS,
+ GSMD_SMS_READ, cmd->id);
+ if (!ucmd)
+ return -ENOMEM;
+ memcpy(ucmd->buf, &msg, sizeof(msg));
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int sms_send_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+ int msgref;
+
+ if (cmd->ret == 0 || cmd->ret == -255) {
+ if (sscanf(resp, "+CMGS: %i", &msgref) < 1)
+ return -EINVAL;
+ } else
+ msgref = -cmd->ret;
+
+ ucmd = gsmd_ucmd_fill(sizeof(int), GSMD_MSG_SMS,
+ GSMD_SMS_SEND, cmd->id);
+ if (!ucmd)
+ return -ENOMEM;
+ *(int *) ucmd->buf = msgref;
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int sms_write_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+ int result;
+
+ if (cmd->ret == 0) {
+ if (sscanf(resp, "+CMGW: %i", &result) < 1)
+ return -EINVAL;
+ } else
+ result = -cmd->ret;
+
+ ucmd = gsmd_ucmd_fill(sizeof(int), GSMD_MSG_SMS,
+ GSMD_SMS_WRITE, cmd->id);
+ if (!ucmd)
+ return -ENOMEM;
+ *(int *) ucmd->buf = result;
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int sms_delete_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+ int *result;
+
+ ucmd = gsmd_ucmd_fill(sizeof(int), GSMD_MSG_SMS,
+ GSMD_SMS_DELETE, cmd->id);
+ if (!ucmd)
+ return -ENOMEM;
+
+ result = (int *) ucmd->buf;
+ *result = cmd->ret;
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+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_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;
+}
+
+static int usock_get_smsc_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+ struct gsmd_addr *ga;
+
+ ucmd = gsmd_ucmd_fill(sizeof(struct gsmd_addr), GSMD_MSG_SMS,
+ GSMD_SMS_GET_SERVICE_CENTRE, cmd->id);
+ if (!ucmd)
+ return -ENOMEM;
+
+ ga = (struct gsmd_addr *) ucmd->buf;
+ if (sscanf(resp, "+CSCA: \"%31[^\"]\",%hhi",
+ ga->number, &ga->type) < 2) {
+ talloc_free(ucmd);
+ return -EINVAL;
+ }
+
+ usock_cmd_enqueue(ucmd, gu);
+ return 0;
+}
+
+static const char *gsmd_cmgl_stat[] = {
+ "REC UNREAD", "REC READ", "STO UNSENT", "STO SENT", "ALL",
+};
+
+/* main unix socket Short Message receiver */
+int usock_rcv_sms(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len)
+{
+ /* FIXME: TEXT mode support!! */
+ struct gsmd_atcmd *cmd = NULL;
+ struct gsmd_sms_delete *gsd;
+ struct gsmd_sms_submit *gss;
+ struct gsmd_sms_write *gsw;
+ struct gsmd_addr *ga;
+ enum ts0705_mem_type *storage;
+ int *stat, *index;
+ int atcmd_len;
+ char buf[1024];
+
+ switch (gph->msg_subtype) {
+ case GSMD_SMS_LIST:
+ if(len < sizeof(*gph) + sizeof(int))
+ return -EINVAL;
+ stat = (int *) ((void *)gph + sizeof(*gph));
+ if (*stat < 0 || *stat > 4)
+ return -EINVAL;
+
+ if (gu->gsmd->flags & GSMD_FLAG_SMS_FMT_TEXT)
+ atcmd_len = sprintf(buf, "AT+CMGL=\"%s\"",
+ gsmd_cmgl_stat[*stat]);
+ else
+ atcmd_len = sprintf(buf, "AT+CMGL=%i", *stat);
+
+ cmd = atcmd_fill(buf, atcmd_len + 1,
+ &sms_list_cb, gu, gph->id);
+ break;
+
+ case GSMD_SMS_READ:
+ if(len < sizeof(*gph) + sizeof(int))
+ return -EINVAL;
+ index = (int *) ((void *)gph + sizeof(*gph));
+
+ atcmd_len = sprintf(buf, "AT+CMGR=%i", *index);
+
+ cmd = atcmd_fill(buf, atcmd_len + 1,
+ &sms_read_cb, gu, gph->id);
+ break;
+
+ case GSMD_SMS_SEND:
+ if (len < sizeof(*gph) + sizeof(*gss))
+ return -EINVAL;
+ gss = (struct gsmd_sms_submit *) ((void *) gph + sizeof(*gph));
+
+ if (gu->gsmd->flags & GSMD_FLAG_SMS_FMT_TEXT) {
+ atcmd_len = sprintf(buf, "AT+CMGS=\"%s\"\n%.*s",
+ gss->addr.number,
+ gss->payload.length,
+ gss->payload.data); /* FIXME */
+ } else {
+ atcmd_len = sprintf(buf, "AT+CMGS=%i\n",
+ sms_pdu_make_smssubmit(NULL, gss) - 1);
+ atcmd_len += sms_pdu_make_smssubmit(buf + atcmd_len,
+ gss) * 2;
+ }
+ buf[atcmd_len ++] = 26; /* ^Z ends the message */
+ buf[atcmd_len ++] = 0;
+
+ cmd = atcmd_fill(buf, atcmd_len, &sms_send_cb, gu, gph->id);
+ break;
+
+ case GSMD_SMS_WRITE:
+ if (len < sizeof(*gph) + sizeof(*gsw))
+ return -EINVAL;
+ gsw = (struct gsmd_sms_write *) ((void *) gph + sizeof(*gph));
+ if (gsw->stat > 4)
+ return -EINVAL;
+
+ if (gu->gsmd->flags & GSMD_FLAG_SMS_FMT_TEXT) {
+ atcmd_len = sprintf(buf, "AT+CMGW=\"%s\"\n%.*s",
+ gsw->sms.addr.number,
+ gsw->sms.payload.length,
+ gsw->sms.payload.data); /* FIXME */
+ } else {
+ atcmd_len = sprintf(buf, "AT+CMGW=%i,%i\n",
+ sms_pdu_make_smssubmit(NULL,
+ &gsw->sms) - 1, gsw->stat);
+ atcmd_len += sms_pdu_make_smssubmit(buf + atcmd_len,
+ &gsw->sms) * 2;
+ }
+ buf[atcmd_len ++] = 26; /* ^Z ends the message */
+ buf[atcmd_len ++] = 0;
+
+ cmd = atcmd_fill(buf, atcmd_len, &sms_write_cb, gu, gph->id);
+ break;
+
+ case GSMD_SMS_DELETE:
+ if(len < sizeof(*gph) + sizeof(*gsd))
+ return -EINVAL;
+ gsd = (struct gsmd_sms_delete *) ((void *)gph + sizeof(*gph));
+
+ atcmd_len = sprintf(buf, "AT+CMGD=%d,%d",
+ gsd->index, gsd->delflg);
+
+ cmd = atcmd_fill(buf, atcmd_len + 1,
+ &sms_delete_cb, gu, gph->id);
+ break;
+
+ case GSMD_SMS_GET_MSG_STORAGE:
+ cmd = atcmd_fill("AT+CPMS?", 8 + 1, usock_cpms_cb, gu, 0);
+ break;
+
+ case GSMD_SMS_SET_MSG_STORAGE:
+ if (len < sizeof(*gph) + 3 * sizeof(enum ts0705_mem_type))
+ return -EINVAL;
+ storage = (enum ts0705_mem_type *)
+ ((void *) gph + sizeof(*gph));
+ atcmd_len = sprintf(buf, "AT+CPMS=\"%s\",\"%s\",\"%s\"",
+ ts0705_memtype_name[storage[0]],
+ ts0705_memtype_name[storage[1]],
+ ts0705_memtype_name[storage[2]]);
+ cmd = atcmd_fill(buf, atcmd_len + 1, NULL, gu, gph->id);
+ break;
+
+ case GSMD_SMS_GET_SERVICE_CENTRE:
+ cmd = atcmd_fill("AT+CSCA?", 8 + 1, &usock_get_smsc_cb, gu, 0);
+ break;
+
+ case GSMD_SMS_SET_SERVICE_CENTRE:
+ if (len < sizeof(*gph) + sizeof(struct gsmd_addr))
+ return -EINVAL;
+ ga = (struct gsmd_addr *) ((void *) gph + sizeof(*gph));
+ atcmd_len = sprintf(buf, "AT+CSCA=\"%s\",%i",
+ ga->number, ga->type);
+ cmd = atcmd_fill(buf, atcmd_len + 1, NULL, gu, gph->id);
+ break;
+
+ default:
+ return -ENOSYS;
+ }
+
+ if (!cmd)
+ return -ENOMEM;
+
+ gsmd_log(GSMD_DEBUG, "%s\n", cmd ? cmd->buf : 0);
+ return atcmd_submit(gu->gsmd, cmd);
+}
+
/* main unix socket Cell Broadcast receiver */
-static int usock_rcv_cb(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
- int len)
+int usock_rcv_cb(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len)
{
+ struct gsmd_atcmd *cmd;
+
switch (gph->msg_subtype) {
case GSMD_CB_SUBSCRIBE:
+ cmd = atcmd_fill("AT+CSCB=1", 9 + 1, NULL, gu->gsmd, 0);
break;
case GSMD_CB_UNSUBSCRIBE:
+ cmd = atcmd_fill("AT+CSCB=0", 9 + 1, NULL, gu->gsmd, 0);
break;
+ default:
+ return -ENOSYS;
}
- return -ENOSYS;
+ if (!cmd)
+ return -ENOMEM;
+
+ return atcmd_submit(gu->gsmd, cmd);
}
/* Unsolicited messages related to SMS / CB */
-static int cmti_parse(char *buf, int len, const char *param,
- struct gsmd *gsmd)
+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;
+ struct gsmd_evt_auxdata *aux;
+ struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT,
+ GSMD_EVT_IN_SMS, sizeof(struct gsmd_evt_auxdata));
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);
-
+ aux = (struct gsmd_evt_auxdata *) ucmd->buf;
if (sscanf(param, "\"%2[A-Z]\",%i", memstr, &aux->u.sms.index) < 2) {
talloc_free(ucmd);
return -EINVAL;
}
+ aux->u.sms.inlined = 0;
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)
+static int cmt_parse(char *buf, int len, const char *param, struct gsmd *gsmd)
{
/* TODO: TEXT mode */
- u_int8_t pdu[180];
+ u_int8_t pdu[MAX_PDU_SIZE];
const char *comma = strchr(param, ',');
char *cr;
int i;
- struct gsmd_sms_list msg;
+ struct gsmd_evt_auxdata *aux;
+ struct gsmd_sms_list *msg;
+ struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT,
+ GSMD_EVT_IN_SMS, sizeof(struct gsmd_evt_auxdata) +
+ sizeof(struct gsmd_sms_list));
+
+ if (!ucmd)
+ return -ENOMEM;
- if (!comma)
+ aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+ msg = (struct gsmd_sms_list *) aux->data;
+
+ if (!comma) {
+ talloc_free(ucmd);
return -EINVAL;
+ }
len = strtoul(comma + 1, &cr, 10);
- if (cr[0] != '\n')
+ if (cr[0] != '\n') {
+ talloc_free(ucmd);
return -EINVAL;
+ }
cr ++;
- for (i = 0; cr[0] >= '0' && cr[1] >= '0' && i < 180; i ++) {
+ for (i = 0; cr[0] >= '0' && cr[1] >= '0' && i < MAX_PDU_SIZE; i ++) {
if (sscanf(cr, "%2hhX", &pdu[i]) < 1) {
gsmd_log(GSMD_DEBUG, "malformed input (%i)\n", i);
+ talloc_free(ucmd);
return -EINVAL;
}
cr += 2;
}
- if (sms_pdu_to_msg(&msg, pdu, len, i)) {
+
+ aux->u.sms.inlined = 1;
+ if (sms_pdu_to_msg(msg, pdu, len, i)) {
gsmd_log(GSMD_DEBUG, "malformed PDU\n");
+ talloc_free(ucmd);
return -EINVAL;
}
- /* FIXME: generate some kind of event */
- return -ENOSYS;
+ return usock_evt_send(gsmd, ucmd, GSMD_EVT_IN_SMS);
}
-static int cbmi_parse(char *buf, int len, const char *param,
- struct gsmd *gsmd)
+static int cbmi_parse(char *buf, int len, const char *param, struct gsmd *gsmd)
{
char memstr[3];
- int memtype, index;
+ struct gsmd_evt_auxdata *aux;
+ struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT,
+ GSMD_EVT_IN_CBM, sizeof(struct gsmd_evt_auxdata));
+
+ if (!ucmd)
+ return -ENOMEM;
+
+ ucmd->hdr.version = GSMD_PROTO_VERSION;
+ ucmd->hdr.msg_type = GSMD_MSG_EVENT;
+ ucmd->hdr.msg_subtype = GSMD_EVT_IN_CBM;
+ ucmd->hdr.len = sizeof(*aux);
- if (sscanf(param, "\"%2[A-Z]\",%i", memstr, &index) < 2)
+ aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+ if (sscanf(param, "\"%2[A-Z]\",%i", memstr, &aux->u.cbm.index) < 2) {
+ talloc_free(ucmd);
return -EINVAL;
+ }
+
+ aux->u.cbm.inlined = 0;
+ aux->u.cbm.memtype = parse_memtype(memstr);
- memtype = parse_memtype(memstr);
- /* FIXME: generate some kind of event */
- return -ENOSYS;
+ return usock_evt_send(gsmd, ucmd, GSMD_EVT_IN_CBM);
}
-static int cbm_parse(char *buf, int len, const char *param,
- struct gsmd *gsmd)
+static int cbm_parse(char *buf, int len, const char *param, struct gsmd *gsmd)
{
/* TODO: TEXT mode */
- u_int8_t pdu[180];
+ u_int8_t pdu[MAX_PDU_SIZE];
char *cr;
int i;
- struct gsmd_sms_list msg;
+ struct gsmd_evt_auxdata *aux;
+ struct gsmd_sms_list *msg;
+ struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT,
+ GSMD_EVT_IN_CBM, sizeof(struct gsmd_evt_auxdata) +
+ sizeof(struct gsmd_sms_list));
+
+ if (!ucmd)
+ return -ENOMEM;
+
+ aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+ msg = (struct gsmd_sms_list *) aux->data;
len = strtoul(param, &cr, 10);
if (cr[0] != '\n')
return -EINVAL;
cr ++;
- for (i = 0; cr[0] >= '0' && cr[1] >= '0' && i < 180; i ++) {
+ for (i = 0; cr[0] >= '0' && cr[1] >= '0' && i < MAX_PDU_SIZE; i ++) {
if (sscanf(cr, "%2hhX", &pdu[i]) < 1) {
gsmd_log(GSMD_DEBUG, "malformed input (%i)\n", i);
+ talloc_free(ucmd);
return -EINVAL;
}
cr += 2;
}
- if (sms_pdu_to_msg(&msg, pdu, len, i)) {
+
+ aux->u.cbm.inlined = 1;
+ if (sms_pdu_to_msg(msg, pdu, len, i)) {
gsmd_log(GSMD_DEBUG, "malformed PDU\n");
+ talloc_free(ucmd);
return -EINVAL;
}
- /* FIXME: generate some kind of event */
- return -ENOSYS;
+ return usock_evt_send(gsmd, ucmd, GSMD_EVT_IN_CBM);
}
-static int cdsi_parse(char *buf, int len, const char *param,
- struct gsmd *gsmd)
+static int cdsi_parse(char *buf, int len, const char *param, struct gsmd *gsmd)
{
char memstr[3];
- int memtype, index;
+ struct gsmd_evt_auxdata *aux;
+ struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT,
+ GSMD_EVT_IN_DS, sizeof(struct gsmd_evt_auxdata));
+
+ if (!ucmd)
+ return -ENOMEM;
- if (sscanf(param, "\"%2[A-Z]\",%i", memstr, &index) < 2)
+ aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+ if (sscanf(param, "\"%2[A-Z]\",%i", memstr, &aux->u.ds.index) < 2) {
+ talloc_free(ucmd);
return -EINVAL;
+ }
- memtype = parse_memtype(memstr);
- /* FIXME: generate some kind of event */
- return -ENOSYS;
+ aux->u.ds.inlined = 0;
+ aux->u.ds.memtype = parse_memtype(memstr);
+
+ return usock_evt_send(gsmd, ucmd, GSMD_EVT_IN_DS);
}
-static int cds_parse(char *buf, int len, const char *param,
- struct gsmd *gsmd)
+static int cds_parse(char *buf, int len, const char *param, struct gsmd *gsmd)
{
/* TODO: TEXT mode */
- u_int8_t pdu[180];
+ u_int8_t pdu[MAX_PDU_SIZE];
char *cr;
int i;
- struct gsmd_sms_list msg;
+ struct gsmd_evt_auxdata *aux;
+ struct gsmd_sms_list *msg;
+ struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT,
+ GSMD_EVT_IN_DS, sizeof(struct gsmd_evt_auxdata) +
+ sizeof(struct gsmd_sms_list));
+
+ if (!ucmd)
+ return -ENOMEM;
+
+ aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+ msg = (struct gsmd_sms_list *) aux->data;
len = strtoul(param, &cr, 10);
if (cr[0] != '\n')
return -EINVAL;
cr ++;
- for (i = 0; cr[0] >= '0' && cr[1] >= '0' && i < 180; i ++) {
+ for (i = 0; cr[0] >= '0' && cr[1] >= '0' && i < MAX_PDU_SIZE; i ++) {
if (sscanf(cr, "%2hhX", &pdu[i]) < 1) {
gsmd_log(GSMD_DEBUG, "malformed input (%i)\n", i);
+ talloc_free(ucmd);
return -EINVAL;
}
cr += 2;
}
- if (sms_pdu_to_msg(&msg, pdu, len, i)) {
+
+ aux->u.ds.inlined = 1;
+ if (sms_pdu_to_msg(msg, pdu, len, i)) {
gsmd_log(GSMD_DEBUG, "malformed PDU\n");
+ talloc_free(ucmd);
return -EINVAL;
}
- /* FIXME: generate some kind of event */
- return -ENOSYS;
+ return usock_evt_send(gsmd, ucmd, GSMD_EVT_IN_DS);
}
static const struct gsmd_unsolicit gsm0705_unsolicit[] = {
@@ -243,8 +676,16 @@ int sms_cb_init(struct gsmd *gsmd)
return -ENOMEM;
atcmd_submit(gsmd, atcmd);
- /* Store and notify */
- atcmd = atcmd_fill("AT+CNMI=1,1,1", 13 + 1, NULL, gsmd, 0);
+ /*
+ * Set the New Message Indications properties to values that are
+ * likely supported. We will get a:
+ * +CMTI on a new incoming SMS,
+ * +CBM on a new incoming CB,
+ * +CDS on an SMS status report.
+ *
+ * FIXME: ask for supported +CNMI values first.
+ */
+ atcmd = atcmd_fill("AT+CNMI=2,1,2,1,0", 17 + 1, NULL, gsmd, 0);
if (!atcmd)
return -ENOMEM;
atcmd_submit(gsmd, atcmd);
diff --git a/src/gsmd/unsolicited.c b/src/gsmd/unsolicited.c
index 4bf4833..82a4f17 100644
--- a/src/gsmd/unsolicited.c
+++ b/src/gsmd/unsolicited.c
@@ -36,7 +36,7 @@
#include <gsmd/unsolicited.h>
#include <gsmd/talloc.h>
-struct gsmd_ucmd *usock_build_event(u_int8_t type, u_int8_t subtype, u_int8_t len)
+struct gsmd_ucmd *usock_build_event(u_int8_t type, u_int8_t subtype, u_int16_t len)
{
struct gsmd_ucmd *ucmd = ucmd_alloc(len);
diff --git a/src/gsmd/usock.c b/src/gsmd/usock.c
index 543c3cf..08563cf 100644
--- a/src/gsmd/usock.c
+++ b/src/gsmd/usock.c
@@ -319,8 +319,8 @@ out_free_einval:
return -EINVAL;
}
-static struct gsmd_ucmd *gsmd_ucmd_fill(int len, u_int8_t msg_type, u_int8_t msg_subtype,
- u_int16_t id)
+struct gsmd_ucmd *gsmd_ucmd_fill(int len, u_int8_t msg_type,
+ u_int8_t msg_subtype, u_int16_t id)
{
struct gsmd_ucmd *ucmd;
@@ -511,6 +511,7 @@ static int usock_rcv_network(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
return atcmd_submit(gu->gsmd, cmd);
}
+#if 0
static int sms_list_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
{
struct gsmd_user *gu = ctx;
@@ -876,6 +877,7 @@ static int usock_rcv_sms(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
gsmd_log(GSMD_DEBUG, "%s\n", cmd ? cmd->buf : 0);
return atcmd_submit(gu->gsmd, cmd);
}
+#endif
#if 0
static int phonebook_find_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
@@ -1127,6 +1129,7 @@ static usock_msg_handler *pcmd_type_handlers[__NUM_GSMD_MSGS] = {
[GSMD_MSG_PHONE] = &usock_rcv_phone,
[GSMD_MSG_NETWORK] = &usock_rcv_network,
[GSMD_MSG_SMS] = &usock_rcv_sms,
+ [GSMD_MSG_CB] = &usock_rcv_cb,
//[GSMD_MSG_PHONEBOOK] = &usock_rcv_phonebook,
};
diff --git a/src/libgsmd/libgsmd_sms.c b/src/libgsmd/libgsmd_sms.c
index 29b92fb..72723c0 100644
--- a/src/libgsmd/libgsmd_sms.c
+++ b/src/libgsmd/libgsmd_sms.c
@@ -318,3 +318,13 @@ int unpacking_UCS2_82(char *src, char *dest)
{
return 0;
}
+
+int lgsm_cb_subscribe(struct lgsm_handle *lh)
+{
+ return lgsm_send_simple(lh, GSMD_MSG_CB, GSMD_CB_SUBSCRIBE);
+}
+
+int lgsm_cb_unsubscribe(struct lgsm_handle *lh)
+{
+ return lgsm_send_simple(lh, GSMD_MSG_CB, GSMD_CB_UNSUBSCRIBE);
+}
personal git repositories of Harald Welte. Your mileage may vary