summaryrefslogtreecommitdiff
path: root/src/gsmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/gsmd')
-rw-r--r--src/gsmd/atcmd.c26
-rw-r--r--src/gsmd/sms_cb.c73
-rw-r--r--src/gsmd/unsolicited.c8
-rw-r--r--src/gsmd/usock.c21
4 files changed, 90 insertions, 38 deletions
diff --git a/src/gsmd/atcmd.c b/src/gsmd/atcmd.c
index 506f7b8..9d45588 100644
--- a/src/gsmd/atcmd.c
+++ b/src/gsmd/atcmd.c
@@ -197,6 +197,7 @@ static int ml_parse(const char *buf, int len, void *ctx)
static char mlbuf[MLPARSE_BUF_SIZE];
int rc = 0;
static int mlbuf_len;
+ static int mlunsolicited = 0;
int cme_error = 0;
DEBUGP("buf=`%s'(%d)\n", buf, len);
@@ -272,6 +273,16 @@ static int ml_parse(const char *buf, int len, void *ctx)
if (colon > buf+len)
colon = NULL;
rc = unsolicited_parse(g, buf, len, colon);
+ if (rc == -EAGAIN) {
+ /* The parser wants one more line of
+ * input. Wait for the next line, concatenate
+ * and resumbit to unsolicited_parse(). */
+ DEBUGP("Multiline unsolicited code\n");
+ mlbuf_len = len;
+ memcpy(mlbuf, buf, len);
+ mlunsolicited = 1;
+ return 0;
+ }
/* if unsolicited parser didn't handle this 'reply', then we
* need to continue and try harder and see what it is */
if (rc != -ENOENT) {
@@ -356,6 +367,21 @@ static int ml_parse(const char *buf, int len, void *ctx)
len = sizeof(mlbuf) - mlbuf_len;
memcpy(mlbuf + mlbuf_len, buf, len);
mlbuf_len += len;
+
+ if (mlunsolicited) {
+ rc = unsolicited_parse(g, mlbuf, mlbuf_len,
+ strchr(mlbuf, ':') + 1);
+ if (rc == -EAGAIN) {
+ /* The parser wants one more line of
+ * input. Wait for the next line, concatenate
+ * and resumbit to unsolicited_parse(). */
+ DEBUGP("Multiline unsolicited code\n");
+ return 0;
+ }
+ mlunsolicited = 0;
+ mlbuf_len = 0;
+ return rc;
+ }
return 0;
final_cb:
diff --git a/src/gsmd/sms_cb.c b/src/gsmd/sms_cb.c
index 9aed070..1ae337e 100644
--- a/src/gsmd/sms_cb.c
+++ b/src/gsmd/sms_cb.c
@@ -498,7 +498,7 @@ static int cmt_parse(char *buf, int len, const char *param, struct gsmd *gsmd)
len = strtoul(comma + 1, &cr, 10);
if (cr[0] != '\n') {
talloc_free(ucmd);
- return -EINVAL;
+ return -EAGAIN;
}
cr ++;
@@ -567,8 +567,10 @@ static int cbm_parse(char *buf, int len, const char *param, struct gsmd *gsmd)
msg = (struct gsmd_sms_list *) aux->data;
len = strtoul(param, &cr, 10);
- if (cr[0] != '\n')
- return -EINVAL;
+ if (cr[0] != '\n') {
+ talloc_free(ucmd);
+ return -EAGAIN;
+ }
cr ++;
for (i = 0; cr[0] >= '0' && cr[1] >= '0' && i < MAX_PDU_SIZE; i ++) {
@@ -631,8 +633,10 @@ static int cds_parse(char *buf, int len, const char *param, struct gsmd *gsmd)
msg = (struct gsmd_sms_list *) aux->data;
len = strtoul(param, &cr, 10);
- if (cr[0] != '\n')
- return -EINVAL;
+ if (cr[0] != '\n') {
+ talloc_free(ucmd);
+ return -EAGAIN;
+ }
cr ++;
for (i = 0; cr[0] >= '0' && cr[1] >= '0' && i < MAX_PDU_SIZE; i ++) {
@@ -671,37 +675,6 @@ int sms_cb_init(struct gsmd *gsmd)
unsolicited_register_array(gsm0705_unsolicit,
ARRAY_SIZE(gsm0705_unsolicit));
- atcmd = atcmd_fill("AT+CSMS=0", 9 + 1, NULL, gsmd, 0);
- if (!atcmd)
- return -ENOMEM;
- atcmd_submit(gsmd, atcmd);
-
- /*
- * 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);
-
- /* 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 (gsmd->flags & GSMD_FLAG_SMS_FMT_TEXT) {
atcmd = atcmd_fill("AT+CSCS=\"IRA\"", 13 + 1, NULL, gsmd, 0);
@@ -721,3 +694,31 @@ int sms_cb_init(struct gsmd *gsmd)
return atcmd_submit(gsmd, atcmd);
}
+
+/* Called everytime the phone registers to the network and we want to start
+ * receiving messages. */
+int sms_cb_network_init(struct gsmd *gsmd)
+{
+ int ret = 0;
+
+ ret |= gsmd_simplecmd(gsmd, "AT+CSMS=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.
+ */
+ ret |= gsmd_simplecmd(gsmd, "AT+CNMI=2,1,2,1,0");
+
+ /* Store into ME/TA and notify */
+ ret |= gsmd_simplecmd(gsmd, "AT+CSBS=1");
+
+ /* Store into ME/TA and notify */
+ ret |= gsmd_simplecmd(gsmd, "AT+CSDS=2");
+
+ return ret;
+}
diff --git a/src/gsmd/unsolicited.c b/src/gsmd/unsolicited.c
index 82a4f17..0cef5ca 100644
--- a/src/gsmd/unsolicited.c
+++ b/src/gsmd/unsolicited.c
@@ -163,6 +163,12 @@ static int creg_parse(char *buf, int len, const char *param,
} else
aux->u.netreg.lac = aux->u.netreg.ci = 0;
+ /* Intialise things that depend on network registration */
+ if (aux->u.netreg.state == GSMD_NETREG_REG_HOME ||
+ aux->u.netreg.state == GSMD_NETREG_REG_ROAMING) {
+ sms_cb_network_init(gsmd);
+ }
+
return usock_evt_send(gsmd, ucmd, GSMD_EVT_NETREG);
}
@@ -378,6 +384,8 @@ int unsolicited_parse(struct gsmd *g, char *buf, int len, const char *param)
colon = NULL;
rc = i->parse(buf, len, colon, g);
+ if (rc == -EAGAIN)
+ return rc;
if (rc < 0)
gsmd_log(GSMD_ERROR, "error %d during parsing of "
"an unsolicied response `%s'\n",
diff --git a/src/gsmd/usock.c b/src/gsmd/usock.c
index 08563cf..5224f92 100644
--- a/src/gsmd/usock.c
+++ b/src/gsmd/usock.c
@@ -239,6 +239,24 @@ static int usock_rcv_pin(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
return atcmd_submit(gu->gsmd, cmd);
}
+static int phone_powerup_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+
+ /* We need to verify if there is some error */
+ switch (cmd->ret) {
+ case 0:
+ gsmd_log(GSMD_DEBUG, "Radio powered-up\n");
+ gu->gsmd->dev_state.on = 1;
+ break;
+ default:
+ /* something went wrong */
+ gsmd_log(GSMD_DEBUG, "Radio power-up failed\n");
+ break;
+ }
+ return 0;
+}
+
static int usock_rcv_phone(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
int len)
{
@@ -247,8 +265,7 @@ static int usock_rcv_phone(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
switch (gph->msg_subtype) {
case GSMD_PHONE_POWERUP:
cmd = atcmd_fill("AT+CFUN=1", 9+1,
- &null_cmd_cb, gu, 0);
- gu->gsmd->dev_state.on = 1;
+ &phone_powerup_cb, gu, 0);
break;
case GSMD_PHONE_POWERDOWN:
personal git repositories of Harald Welte. Your mileage may vary