aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mm-broadband-modem.c17
-rw-r--r--src/mm-modem-helpers.c73
-rw-r--r--src/mm-modem-helpers.h5
-rw-r--r--src/mm-sms-part-3gpp.h2
-rw-r--r--src/tests/test-modem-helpers.c64
5 files changed, 148 insertions, 13 deletions
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index 611a80aa..90b5780d 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -5614,8 +5614,7 @@ sms_part_ready (MMBroadbandModem *self,
SmsPartContext *ctx)
{
MMSmsPart *part;
- gint rv, status, tpdu_len;
- gchar pdu[MM_SMS_PART_3GPP_MAX_PDU_LEN + 1];
+ MM3gppPduInfo *info;
const gchar *response;
GError *error = NULL;
@@ -5633,19 +5632,16 @@ sms_part_ready (MMBroadbandModem *self,
return;
}
- rv = sscanf (response, "+CMGR: %d,,%d %" G_STRINGIFY (MM_SMS_PART_3GPP_MAX_PDU_LEN) "s",
- &status, &tpdu_len, pdu);
- if (rv != 3) {
- error = g_error_new (MM_CORE_ERROR,
- MM_CORE_ERROR_FAILED,
- "Failed to parse CMGR response (parsed %d items)", rv);
- mm_warn ("Couldn't retrieve SMS part: '%s'", error->message);
+ info = mm_3gpp_parse_cmgr_read_response (response, ctx->idx, &error);
+ if (!info) {
+ mm_warn ("Couldn't parse SMS part: '%s'",
+ error->message);
g_simple_async_result_take_error (ctx->result, error);
sms_part_context_complete_and_free (ctx);
return;
}
- part = mm_sms_part_3gpp_new_from_pdu (ctx->idx, pdu, &error);
+ part = mm_sms_part_3gpp_new_from_pdu (info->index, info->pdu, &error);
if (part) {
mm_dbg ("Correctly parsed PDU (%d)", ctx->idx);
mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self),
@@ -5659,6 +5655,7 @@ sms_part_ready (MMBroadbandModem *self,
}
/* All done */
+ mm_3gpp_pdu_info_free (info);
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
sms_part_context_complete_and_free (ctx);
}
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index fb0b7fa1..5c9c269c 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -1201,6 +1201,77 @@ mm_3gpp_parse_cmgf_test_response (const gchar *reply,
/*************************************************************************/
+MM3gppPduInfo *
+mm_3gpp_parse_cmgr_read_response (const gchar *reply,
+ guint index,
+ GError **error)
+{
+ GRegex *r;
+ GMatchInfo *match_info;
+ gint count;
+ gint status;
+ gchar *pdu;
+ MM3gppPduInfo *info = NULL;
+
+ /* +CMGR: <stat>,<alpha>,<length>(whitespace)<pdu> */
+ /* The <alpha> and <length> fields are matched, but not currently used */
+ r = g_regex_new ("\\+CMGR:\\s*(\\d+)\\s*,([^,]*),\\s*(\\d+)\\s*([^\\r\\n]*)", 0, 0, NULL);
+ g_assert (r);
+
+ if (!g_regex_match_full (r, reply, strlen (reply), 0, 0, &match_info, NULL)) {
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Failed to parse CMGR read result: response didn't match '%s'",
+ reply);
+ goto done;
+ }
+
+ /* g_match_info_get_match_count includes match #0 */
+ if ((count = g_match_info_get_match_count (match_info)) != 5) {
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Failed to match CMGR fields (matched %d) '%s'",
+ count,
+ reply);
+ goto done;
+ }
+
+ if (!mm_get_int_from_match_info (match_info, 1, &status)) {
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Failed to extract CMGR status field '%s'",
+ reply);
+ goto done;
+ }
+
+
+ pdu = mm_get_string_unquoted_from_match_info (match_info, 4);
+ if (!pdu) {
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Failed to extract CMGR pdu field '%s'",
+ reply);
+ goto done;
+ }
+
+ info = g_new0 (MM3gppPduInfo, 1);
+ info->index = index;
+ info->status = status;
+ info->pdu = pdu;
+
+done:
+ g_match_info_free (match_info);
+ g_regex_unref (r);
+
+ return info;
+}
+
+/*************************************************************************/
+
static MMSmsStorage
storage_from_str (const gchar *str)
{
@@ -1698,7 +1769,7 @@ done:
/*************************************************************************/
-static void
+void
mm_3gpp_pdu_info_free (MM3gppPduInfo *info)
{
g_free (info->pdu);
diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h
index 9fabd6aa..e92b6c0a 100644
--- a/src/mm-modem-helpers.h
+++ b/src/mm-modem-helpers.h
@@ -191,10 +191,15 @@ typedef struct {
gint status;
gchar *pdu;
} MM3gppPduInfo;
+void mm_3gpp_pdu_info_free (MM3gppPduInfo *info);
void mm_3gpp_pdu_info_list_free (GList *info_list);
GList *mm_3gpp_parse_pdu_cmgl_response (const gchar *str,
GError **error);
+/* AT+CMGR (Read message) response parser */
+MM3gppPduInfo *mm_3gpp_parse_cmgr_read_response (const gchar *reply,
+ guint index,
+ GError **error);
/* Additional 3GPP-specific helpers */
diff --git a/src/mm-sms-part-3gpp.h b/src/mm-sms-part-3gpp.h
index 82709a2f..a21d7347 100644
--- a/src/mm-sms-part-3gpp.h
+++ b/src/mm-sms-part-3gpp.h
@@ -22,8 +22,6 @@
#include "mm-sms-part.h"
-#define MM_SMS_PART_3GPP_MAX_PDU_LEN 344
-
MMSmsPart *mm_sms_part_3gpp_new_from_pdu (guint index,
const gchar *hexpdu,
GError **error);
diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c
index 9fd25016..dfced5ea 100644
--- a/src/tests/test-modem-helpers.c
+++ b/src/tests/test-modem-helpers.c
@@ -196,6 +196,67 @@ test_cmgl_response_pantech_multiple (void *f, gpointer d)
}
/*****************************************************************************/
+/* Test CMGR responses */
+
+static void
+test_cmgr_response (const gchar *str,
+ const MM3gppPduInfo *expected)
+{
+ MM3gppPduInfo *info;
+ GError *error = NULL;
+
+ info = mm_3gpp_parse_cmgr_read_response (str, 0, &error);
+ g_assert_no_error (error);
+ g_assert (info != NULL);
+
+ /* Ignore index, it is not included in CMGR response */
+ g_assert_cmpint (info->status, ==, expected->status);
+ g_assert_cmpstr (info->pdu, ==, expected->pdu);
+}
+
+static void
+test_cmgr_response_generic (void *f, gpointer d)
+{
+ const gchar *str =
+ "+CMGR: 1,,147 07914306073011F00405812261F700003130916191314095C27"
+ "4D96D2FBBD3E437280CB2BEC961F3DB5D76818EF2F0381D9E83E06F39A8CC2E9FD372F"
+ "77BEE0249CBE37A594E0E83E2F532085E2F93CB73D0B93CA7A7DFEEB01C447F93DF731"
+ "0BD3E07CDCB727B7A9C7ECF41E432C8FC96B7C32079189E26874179D0F8DD7E93C3A0B"
+ "21B246AA641D637396C7EBBCB22D0FD7E77B5D376B3AB3C07";
+
+ const MM3gppPduInfo expected = {
+ .index = 0,
+ .status = 1,
+ .pdu = "07914306073011F00405812261F700003130916191314095C27"
+ "4D96D2FBBD3E437280CB2BEC961F3DB5D76818EF2F0381D9E83E06F39A8CC2E9FD372F"
+ "77BEE0249CBE37A594E0E83E2F532085E2F93CB73D0B93CA7A7DFEEB01C447F93DF731"
+ "0BD3E07CDCB727B7A9C7ECF41E432C8FC96B7C32079189E26874179D0F8DD7E93C3A0B"
+ "21B246AA641D637396C7EBBCB22D0FD7E77B5D376B3AB3C07"
+ };
+
+ test_cmgr_response (str, &expected);
+}
+
+/* Telit HE910 places empty quotation marks in the <alpha> field and a CR+LF
+ * before the PDU */
+static void
+test_cmgr_response_telit (void *f, gpointer d)
+{
+ const gchar *str =
+ "+CMGR: 0,\"\",50\r\n07916163838428F9040B916121021021F7000051905141642"
+ "20A23C4B0BCFD5E8740C4B0BCFD5E83C26E3248196687C9A0301D440DBBC3677918";
+
+ const MM3gppPduInfo expected = {
+ .index = 0,
+ .status = 0,
+ .pdu = "07916163838428F9040B916121021021F7000051905141642"
+ "20A23C4B0BCFD5E8740C4B0BCFD5E83C26E3248196687C9A0301D440DBBC3677918"
+ };
+
+ test_cmgr_response (str, &expected);
+}
+
+/*****************************************************************************/
/* Test COPS responses */
static void
@@ -2568,6 +2629,9 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_cmgl_response_pantech, NULL));
g_test_suite_add (suite, TESTCASE (test_cmgl_response_pantech_multiple, NULL));
+ g_test_suite_add (suite, TESTCASE (test_cmgr_response_generic, NULL));
+ g_test_suite_add (suite, TESTCASE (test_cmgr_response_telit, NULL));
+
g_test_suite_add (suite, TESTCASE (test_supported_mode_filter, NULL));
g_test_suite_add (suite, TESTCASE (test_supported_capability_filter, NULL));