[PATCH 1/2] modem response parsing updates needed for thuraya

Thomas Sailer sailer at sailer.dynip.lugs.ch
Tue Feb 2 17:13:49 UTC 2016


From: Thomas Sailer <t.sailer at alumni.ethz.ch>

Signed-off-by: Thomas Sailer <t.sailer at alumni.ethz.ch>
---
 src/mm-modem-helpers.c         | 86 ++++++++++++++++++++++++++++++++++++++----
 src/tests/test-modem-helpers.c | 81 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 158 insertions(+), 9 deletions(-)

diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index 17ad8d2..a9b1c71 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -131,6 +131,58 @@ mm_split_string_groups (const gchar *str)
 
 /*****************************************************************************/
 
+static gchar **
+mm_split_string_groups_space (const gchar *str)
+{
+    GPtrArray *array;
+    const gchar *start;
+    const gchar *next;
+
+    array = g_ptr_array_new ();
+
+    /*
+     * Manually parse splitting groups. Groups are separated by space
+     */
+
+    /* Iterate string splitting groups */
+    for (start = str; start; start = next) {
+        gchar *item;
+        gssize len = -1;
+
+        /* skip leading whitespaces */
+        while (*start == ' ')
+            start++;
+
+        if (!*start)
+            break;
+
+        next = strchr (start, ' ');
+        if (next) {
+            len = next - start;
+            if (next[-1] == ',')
+                len--;
+            next++;
+        }
+
+        if (len < 0)
+            item = g_strdup (start);
+        else
+            item = g_strndup (start, len);
+
+        g_ptr_array_add (array, item);
+    }
+
+    if (array->len > 0) {
+        g_ptr_array_add (array, NULL);
+        return (gchar **) g_ptr_array_free (array, FALSE);
+    }
+
+    g_ptr_array_unref (array);
+    return NULL;
+}
+
+/*****************************************************************************/
+
 guint
 mm_count_bits_set (gulong number)
 {
@@ -434,6 +486,7 @@ mm_voice_clip_regex_get (void)
 
 /* +CREG: <stat>,<lac>,<ci>           (GSM 07.07 CREG=2 unsolicited) */
 #define CREG3 "\\+(CREG|CGREG|CEREG):\\s*0*([0-9]),\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)"
+#define CREG11 "\\+(CREG|CGREG|CEREG):\\s*0*([0-9]),\\s*(\"[^\"\\s]*\")\\s*,\\s*(\"[^\"\\s]*\")"
 
 /* +CREG: <n>,<stat>,<lac>,<ci>       (GSM 07.07 solicited and some CREG=2 unsolicited) */
 #define CREG4 "\\+(CREG|CGREG|CEREG):\\s*([0-9]),\\s*([0-9])\\s*,\\s*([^,]*)\\s*,\\s*([^,\\s]*)"
@@ -545,6 +598,14 @@ mm_3gpp_creg_regex_get (gboolean solicited)
     g_assert (regex);
     g_ptr_array_add (array, regex);
 
+    /* #11 */
+    if (solicited)
+        regex = g_regex_new (CREG11 "$", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+    else
+        regex = g_regex_new ("\\r\\n" CREG11 "\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+    g_assert (regex);
+    g_ptr_array_add (array, regex);
+
     /* CEREG #1 */
     if (solicited)
         regex = g_regex_new (CEREG1 "$", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
@@ -867,7 +928,7 @@ mm_3gpp_parse_cgdcont_test_response (const gchar *response,
         return NULL;
     }
 
-    r = g_regex_new ("\\+CGDCONT:\\s*\\((\\d+)-?(\\d+)?\\),\\(?\"(\\S+)\"",
+    r = g_regex_new ("\\+CGDCONT:\\s*\\(\\s*(\\d+)\\s*-?\\s*(\\d+)?\\s*\\)\\s*,\\s*\\(?\"(\\S+)\"",
                      G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW,
                      0, &inner_error);
     g_assert (r != NULL);
@@ -955,7 +1016,7 @@ mm_3gpp_parse_cgdcont_read_response (const gchar *reply,
         return NULL;
 
     list = NULL;
-    r = g_regex_new ("\\+CGDCONT:\\s*(\\d+)\\s*,([^,\\)]*),([^,\\)]*),([^,\\)]*)",
+    r = g_regex_new ("\\+CGDCONT:\\s*(\\d+)\\s*,([^, \\)]*)\\s*,([^, \\)]*)\\s*,([^, \\)]*)",
                      G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW,
                      0, &inner_error);
     if (r) {
@@ -1359,12 +1420,14 @@ mm_3gpp_parse_cpms_test_response (const gchar *reply,
                                   GArray **mem2,
                                   GArray **mem3)
 {
+    const gchar *reply_notag;
     GRegex *r;
     gchar **split;
     guint i;
     GArray *tmp1 = NULL;
     GArray *tmp2 = NULL;
     GArray *tmp3 = NULL;
+    guint n_groups;
 
     g_assert (mem1 != NULL);
     g_assert (mem2 != NULL);
@@ -1372,15 +1435,24 @@ mm_3gpp_parse_cpms_test_response (const gchar *reply,
 
 #define N_EXPECTED_GROUPS 3
 
-    split = mm_split_string_groups (mm_strip_tag (reply, "+CPMS:"));
+    reply_notag = mm_strip_tag (reply, "+CPMS:");
+    split = mm_split_string_groups (reply_notag);
     if (!split)
         return FALSE;
 
-    if (g_strv_length (split) != N_EXPECTED_GROUPS) {
-        mm_warn ("Cannot parse +CPMS test response: invalid number of groups (%u != %u)",
-                 g_strv_length (split), N_EXPECTED_GROUPS);
+    n_groups = g_strv_length (split);
+    if (n_groups != N_EXPECTED_GROUPS) {
         g_strfreev (split);
-        return FALSE;
+        split = mm_split_string_groups_space (reply_notag);
+        if (split && g_strv_length (split) != N_EXPECTED_GROUPS) {
+            g_strfreev (split);
+            split = 0;
+        }
+        if (!split) {
+            mm_warn ("Cannot parse +CPMS test response: invalid number of groups (%u != %u)",
+                     n_groups, N_EXPECTED_GROUPS);
+            return FALSE;
+        }
     }
 
     r = g_regex_new ("\\s*\"([^,\\)]+)\"\\s*", 0, 0, NULL);
diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c
index bd7f688..a85709a 100644
--- a/src/tests/test-modem-helpers.c
+++ b/src/tests/test-modem-helpers.c
@@ -1135,7 +1135,7 @@ test_cereg2_novatel_lte_solicited (void *f, gpointer d)
 {
     RegTestData *data = (RegTestData *) d;
     const char *reply = "\r\n+CEREG: 2,1, 1F00, 20 ,79D903 ,7\r\n";
-    const CregResult result = { 1, 0x1F00, 0x79D903, MM_MODEM_ACCESS_TECHNOLOGY_LTE, 12, FALSE, TRUE };
+    const CregResult result = { 1, 0x1F00, 0x79D903, MM_MODEM_ACCESS_TECHNOLOGY_LTE, 13, FALSE, TRUE };
 
     test_creg_match ("Novatel LTE E362 CEREG=2", TRUE, reply, data, &result);
 }
@@ -1145,11 +1145,31 @@ test_cereg2_novatel_lte_unsolicited (void *f, gpointer d)
 {
     RegTestData *data = (RegTestData *) d;
     const char *reply = "\r\n+CEREG: 1, 1F00, 20 ,79D903 ,7\r\n";
-    const CregResult result = { 1, 0x1F00, 0x79D903, MM_MODEM_ACCESS_TECHNOLOGY_LTE, 11, FALSE, TRUE };
+    const CregResult result = { 1, 0x1F00, 0x79D903, MM_MODEM_ACCESS_TECHNOLOGY_LTE, 12, FALSE, TRUE };
 
     test_creg_match ("Novatel LTE E362 CEREG=2", FALSE, reply, data, &result);
 }
 
+static void
+test_cgreg2_thuraya_solicited (void *f, gpointer d)
+{
+    RegTestData *data = (RegTestData *) d;
+    const char *reply = "+CGREG: 1, \"0426\", \"F0,0F\"";
+    const CregResult result = { 1, 0x0426, 0x00F0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 11, TRUE, FALSE };
+
+    test_creg_match ("Thuraya solicited CREG=2", TRUE, reply, data, &result);
+}
+
+static void
+test_cgreg2_thuraya_unsolicited (void *f, gpointer d)
+{
+    RegTestData *data = (RegTestData *) d;
+    const char *reply = "\r\n+CGREG: 1, \"0426\", \"F0,0F\"\r\n";
+    const CregResult result = { 1, 0x0426, 0x00F0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 11, TRUE, FALSE };
+
+    test_creg_match ("Thuraya unsolicited CREG=2", FALSE, reply, data, &result);
+}
+
 /*****************************************************************************/
 /* Test CSCS responses */
 
@@ -1798,6 +1818,19 @@ test_cgdcont_test_response_single_context (void *f, gpointer d)
     test_cgdcont_test_results ("Single Context", reply, &expected[0], G_N_ELEMENTS (expected));
 }
 
+static void
+test_cgdcont_test_response_thuraya (void *f, gpointer d)
+{
+    const gchar *reply =
+        "+CGDCONT: ( 1 ) , \"IP\" ,,, (0-2),(0-3)\r\n"
+        "+CGDCONT: , \"PPP\" ,,, (0-2),(0-3)\r\n";
+    static MM3gppPdpContextFormat expected[] = {
+        { 1, 1, MM_BEARER_IP_FAMILY_IPV4 }
+    };
+
+    test_cgdcont_test_results ("Thuraya", reply, &expected[0], G_N_ELEMENTS (expected));
+}
+
 /*****************************************************************************/
 /* Test CGDCONT read responses */
 
@@ -2037,6 +2070,46 @@ test_cpms_response_empty_fields (void *f, gpointer d)
     g_array_unref (mem3);
 }
 
+static void
+test_cpms_response_thuraya (void *f, gpointer d)
+{
+    /*
+     * First:    ("ME","MT")  2-item group
+     * Second:   "ME"         1 item
+     * Third:    ("SM")       1-item group
+     */
+    const gchar *reply = "+CPMS: \"MT\",\"SM\",\"BM\",\"ME\",\"SR\", \"MT\",\"SM\",\"BM\",\"ME\",\"SR\", \"MT\",\"SM\",\"BM\",\"ME\",\"SR\" ";
+    GArray *mem1 = NULL;
+    GArray *mem2 = NULL;
+    GArray *mem3 = NULL;
+
+    trace ("\nTesting thuraya +CPMS=? response...\n");
+
+    g_assert (mm_3gpp_parse_cpms_test_response (reply, &mem1, &mem2, &mem3));
+    g_assert_cmpuint (mem1->len, ==, 5);
+    g_assert (is_storage_supported (mem1, MM_SMS_STORAGE_MT));
+    g_assert (is_storage_supported (mem1, MM_SMS_STORAGE_SM));
+    g_assert (is_storage_supported (mem1, MM_SMS_STORAGE_BM));
+    g_assert (is_storage_supported (mem1, MM_SMS_STORAGE_ME));
+    g_assert (is_storage_supported (mem1, MM_SMS_STORAGE_SR));
+    g_assert_cmpuint (mem2->len, ==, 5);
+    g_assert (is_storage_supported (mem2, MM_SMS_STORAGE_MT));
+    g_assert (is_storage_supported (mem2, MM_SMS_STORAGE_SM));
+    g_assert (is_storage_supported (mem2, MM_SMS_STORAGE_BM));
+    g_assert (is_storage_supported (mem2, MM_SMS_STORAGE_ME));
+    g_assert (is_storage_supported (mem2, MM_SMS_STORAGE_SR));
+    g_assert_cmpuint (mem3->len, ==, 5);
+    g_assert (is_storage_supported (mem3, MM_SMS_STORAGE_MT));
+    g_assert (is_storage_supported (mem3, MM_SMS_STORAGE_SM));
+    g_assert (is_storage_supported (mem3, MM_SMS_STORAGE_BM));
+    g_assert (is_storage_supported (mem3, MM_SMS_STORAGE_ME));
+    g_assert (is_storage_supported (mem3, MM_SMS_STORAGE_SR));
+
+    g_array_unref (mem1);
+    g_array_unref (mem2);
+    g_array_unref (mem3);
+}
+
 /*****************************************************************************/
 /* Test CNUM responses */
 
@@ -2693,6 +2766,8 @@ int main (int argc, char **argv)
     g_test_suite_add (suite, TESTCASE (test_cgreg2_md400_unsolicited, reg_data));
     g_test_suite_add (suite, TESTCASE (test_cgreg2_x220_unsolicited, reg_data));
     g_test_suite_add (suite, TESTCASE (test_cgreg2_unsolicited_with_rac, reg_data));
+    g_test_suite_add (suite, TESTCASE (test_cgreg2_thuraya_solicited, reg_data));
+    g_test_suite_add (suite, TESTCASE (test_cgreg2_thuraya_unsolicited, reg_data));
 
     g_test_suite_add (suite, TESTCASE (test_cereg1_solicited, reg_data));
     g_test_suite_add (suite, TESTCASE (test_cereg1_unsolicited, reg_data));
@@ -2734,11 +2809,13 @@ int main (int argc, char **argv)
     g_test_suite_add (suite, TESTCASE (test_cpms_response_mixed,        NULL));
     g_test_suite_add (suite, TESTCASE (test_cpms_response_mixed_spaces, NULL));
     g_test_suite_add (suite, TESTCASE (test_cpms_response_empty_fields, NULL));
+    g_test_suite_add (suite, TESTCASE (test_cpms_response_thuraya,      NULL));
 
     g_test_suite_add (suite, TESTCASE (test_cgdcont_test_response_single, NULL));
     g_test_suite_add (suite, TESTCASE (test_cgdcont_test_response_multiple, NULL));
     g_test_suite_add (suite, TESTCASE (test_cgdcont_test_response_multiple_and_ignore, NULL));
     g_test_suite_add (suite, TESTCASE (test_cgdcont_test_response_single_context, NULL));
+    g_test_suite_add (suite, TESTCASE (test_cgdcont_test_response_thuraya, NULL));
 
     g_test_suite_add (suite, TESTCASE (test_cgdcont_read_response_nokia, NULL));
     g_test_suite_add (suite, TESTCASE (test_cgdcont_read_response_samsung, NULL));
-- 
2.5.0



More information about the ModemManager-devel mailing list