summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/atmodem/sms.c125
1 files changed, 125 insertions, 0 deletions
diff --git a/drivers/atmodem/sms.c b/drivers/atmodem/sms.c
index 2e03ff2e..11d2ff20 100644
--- a/drivers/atmodem/sms.c
+++ b/drivers/atmodem/sms.c
@@ -48,10 +48,12 @@ static const char *cmgf_prefix[] = { "+CMGF:", NULL };
static const char *cpms_prefix[] = { "+CPMS:", NULL };
static const char *cnmi_prefix[] = { "+CNMI:", NULL };
static const char *cmgs_prefix[] = { "+CMGS:", NULL };
+static const char *cmgl_prefix[] = { "+CMGL:", NULL };
static const char *none_prefix[] = { NULL };
static gboolean set_cmgf(gpointer user_data);
static gboolean set_cpms(gpointer user_data);
+static void at_cmgl_set_cpms(struct ofono_sms *sms, int store);
#define MAX_CMGF_RETRIES 10
#define MAX_CPMS_RETRIES 10
@@ -499,6 +501,123 @@ err:
ofono_error("Unable to parse CMTI notification");
}
+static void at_cmgl_done(struct ofono_sms *sms)
+{
+ struct sms_data *data = ofono_sms_get_data(sms);
+
+ if (data->incoming == MT_STORE && data->store == ME_STORE)
+ at_cmgl_set_cpms(sms, SM_STORE);
+}
+
+static void at_cmgl_notify(GAtResult *result, gpointer user_data)
+{
+ struct ofono_sms *sms = user_data;
+ struct sms_data *data = ofono_sms_get_data(sms);
+ GAtResultIter iter;
+ const char *hexpdu;
+ unsigned char pdu[164];
+ long pdu_len;
+ int tpdu_len;
+ int index;
+ int status;
+ char buf[16];
+
+ dump_response("at_cmgl_notify", TRUE, result);
+
+ g_at_result_iter_init(&iter, result);
+
+ while (g_at_result_iter_next(&iter, "+CMGL:")) {
+ if (!g_at_result_iter_next_number(&iter, &index))
+ goto err;
+
+ if (!g_at_result_iter_next_number(&iter, &status))
+ goto err;
+
+ if (!g_at_result_iter_skip_next(&iter))
+ goto err;
+
+ if (!g_at_result_iter_next_number(&iter, &tpdu_len))
+ goto err;
+
+ /* Only MT messages */
+ if (status != 0 && status != 1)
+ continue;
+
+ hexpdu = g_at_result_pdu(result);
+
+ ofono_debug("Found an old SMS PDU: %s, with len: %d",
+ hexpdu, tpdu_len);
+
+ decode_hex_own_buf(hexpdu, -1, &pdu_len, 0, pdu);
+ ofono_sms_deliver_notify(sms, pdu, pdu_len, tpdu_len);
+
+ /* We don't buffer SMS on the SIM/ME, send along a CMGD */
+ sprintf(buf, "AT+CMGD=%d", index);
+ g_at_chat_send(data->chat, buf, none_prefix,
+ at_cmgd_cb, NULL, NULL);
+ }
+ return;
+
+err:
+ ofono_error("Unable to parse CMGL response");
+}
+
+static void at_cmgl_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+ struct ofono_sms *sms = user_data;
+
+ if (!ok)
+ ofono_error("Initial listing SMS storage failed!");
+
+ at_cmgl_done(sms);
+}
+
+static void at_cmgl_cpms_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+ struct cpms_request *req = user_data;
+ struct ofono_sms *sms = req->sms;
+ struct sms_data *data = ofono_sms_get_data(sms);
+
+ if (!ok) {
+ ofono_error("Initial CPMS request failed");
+ at_cmgl_done(sms);
+ return;
+ }
+
+ data->store = req->store;
+
+ g_at_chat_send_pdu_listing(data->chat, "AT+CMGL=4", cmgl_prefix,
+ at_cmgl_notify, at_cmgl_cb, sms, NULL);
+}
+
+static void at_cmgl_set_cpms(struct ofono_sms *sms, int store)
+{
+ struct sms_data *data = ofono_sms_get_data(sms);
+
+ if (store == data->store) {
+ struct cpms_request req;
+
+ req.sms = sms;
+ req.store = store;
+
+ at_cmgl_cpms_cb(TRUE, NULL, &req);
+ } else {
+ char buf[128];
+ const char *readwrite = storages[store];
+ const char *incoming = storages[data->incoming];
+ struct cpms_request *req = g_new(struct cpms_request, 1);
+
+ req->sms = sms;
+ req->store = store;
+
+ sprintf(buf, "AT+CPMS=\"%s\",\"%s\",\"%s\"",
+ readwrite, readwrite, incoming);
+
+ g_at_chat_send(data->chat, buf, cpms_prefix, at_cmgl_cpms_cb,
+ req, g_free);
+ }
+}
+
static void at_sms_initialized(struct ofono_sms *sms)
{
struct sms_data *data = ofono_sms_get_data(sms);
@@ -516,6 +635,12 @@ static void at_sms_initialized(struct ofono_sms *sms)
g_at_chat_register(data->chat, "+CMGR:", at_cmgr_notify, TRUE,
sms, NULL);
+ /* Inspect and free the incoming SMS storage */
+ if (data->incoming == MT_STORE)
+ at_cmgl_set_cpms(sms, ME_STORE);
+ else
+ at_cmgl_set_cpms(sms, data->incoming);
+
ofono_sms_register(sms);
}