[PATCH 2/2] move +CRSM parsing to mm_3gpp_parse_crsm_response; add test cases

Thomas Sailer sailer at sailer.dynip.lugs.ch
Sat Feb 13 13:19:13 UTC 2016


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

Signed-off-by: Thomas Sailer <t.sailer at alumni.ethz.ch>
---
 src/mm-base-sim.c              | 117 +++++++++++++----------------------------
 src/mm-modem-helpers.c         |  51 ++++++++++++++++++
 src/mm-modem-helpers.h         |   8 +++
 src/tests/test-modem-helpers.c |  54 +++++++++++++++++++
 4 files changed, 151 insertions(+), 79 deletions(-)

diff --git a/src/mm-base-sim.c b/src/mm-base-sim.c
index 104e7f8..6a79091 100644
--- a/src/mm-base-sim.c
+++ b/src/mm-base-sim.c
@@ -944,36 +944,27 @@ static gchar *
 parse_iccid (const gchar *response,
              GError **error)
 {
-    gchar buf[21];
-    const gchar *str;
-    gint sw1;
-    gint sw2;
-    gboolean success = FALSE;
-
-    memset (buf, 0, sizeof (buf));
-    str = mm_strip_tag (response, "+CRSM:");
-    if (sscanf (str, "%d,%d,\"%20c\"", &sw1, &sw2, (char *) &buf) == 3)
-        success = TRUE;
-    else {
-        /* May not include quotes... */
-        if (sscanf (str, "%d,%d,%20c", &sw1, &sw2, (char *) &buf) == 3)
-            success = TRUE;
-    }
-
-    if (!success) {
-        g_set_error (error,
-                     MM_CORE_ERROR,
-                     MM_CORE_ERROR_FAILED,
-                     "Could not parse the CRSM response");
+    guint sw1 = 0;
+    guint sw2 = 0;
+    gchar *hex = 0;
+    gchar *ret;
+
+    if (!mm_3gpp_parse_crsm_response (response,
+                                      &sw1,
+                                      &sw2,
+                                      &hex,
+                                      error))
         return NULL;
-    }
 
     if ((sw1 == 0x90 && sw2 == 0x00) ||
         (sw1 == 0x91) ||
         (sw1 == 0x92) ||
         (sw1 == 0x9f)) {
-        return mm_3gpp_parse_iccid (buf, error);
+        ret = mm_3gpp_parse_iccid (hex, error);
+        g_free (hex);
+        return ret;
     } else {
+        g_free (hex);
         g_set_error (error,
                      MM_CORE_ERROR,
                      MM_CORE_ERROR_FAILED,
@@ -1101,27 +1092,16 @@ static guint
 parse_mnc_length (const gchar *response,
                   GError **error)
 {
-    gint sw1;
-    gint sw2;
-    gboolean success = FALSE;
-    gchar hex[51];
-
-    memset (hex, 0, sizeof (hex));
-    if (sscanf (response, "+CRSM:%d,%d,\"%50c\"", &sw1, &sw2, (char *) &hex) == 3)
-        success = TRUE;
-    else {
-        /* May not include quotes... */
-        if (sscanf (response, "+CRSM:%d,%d,%50c", &sw1, &sw2, (char *) &hex) == 3)
-            success = TRUE;
-    }
+    guint sw1 = 0;
+    guint sw2 = 0;
+    gchar *hex = 0;
 
-    if (!success) {
-        g_set_error (error,
-                     MM_CORE_ERROR,
-                     MM_CORE_ERROR_FAILED,
-                     "Could not parse the CRSM response");
+    if (!mm_3gpp_parse_crsm_response (response,
+                                      &sw1,
+                                      &sw2,
+                                      &hex,
+                                      error))
         return 0;
-    }
 
     if ((sw1 == 0x90 && sw2 == 0x00) ||
         (sw1 == 0x91) ||
@@ -1131,15 +1111,6 @@ parse_mnc_length (const gchar *response,
         guint32 mnc_len;
         gchar *bin;
 
-        /* Make sure the buffer is only hex characters */
-        while (buflen < sizeof (hex) && hex[buflen]) {
-            if (!isxdigit (hex[buflen])) {
-                hex[buflen] = 0x0;
-                break;
-            }
-            buflen++;
-        }
-
         /* Convert hex string to binary */
         bin = mm_utils_hexstr2bin (hex, &buflen);
         if (!bin || buflen < 4) {
@@ -1149,9 +1120,12 @@ parse_mnc_length (const gchar *response,
                          "SIM returned malformed response '%s'",
                          hex);
             g_free (bin);
+            g_free (hex);
             return 0;
         }
 
+        g_free (hex);
+
         /* MNC length is byte 4 of this SIM file */
         mnc_len = bin[3] & 0xFF;
         if (mnc_len == 2 || mnc_len == 3) {
@@ -1168,6 +1142,7 @@ parse_mnc_length (const gchar *response,
         return 0;
     }
 
+    g_free (hex);
     g_set_error (error,
                  MM_CORE_ERROR,
                  MM_CORE_ERROR_FAILED,
@@ -1238,27 +1213,16 @@ static gchar *
 parse_spn (const gchar *response,
            GError **error)
 {
-    gint sw1;
-    gint sw2;
-    gboolean success = FALSE;
-    gchar hex[51];
-
-    memset (hex, 0, sizeof (hex));
-    if (sscanf (response, "+CRSM:%d,%d,\"%50c\"", &sw1, &sw2, (char *) &hex) == 3)
-        success = TRUE;
-    else {
-        /* May not include quotes... */
-        if (sscanf (response, "+CRSM:%d,%d,%50c", &sw1, &sw2, (char *) &hex) == 3)
-            success = TRUE;
-    }
+    guint sw1 = 0;
+    guint sw2 = 0;
+    gchar *hex = 0;
 
-    if (!success) {
-        g_set_error (error,
-                     MM_CORE_ERROR,
-                     MM_CORE_ERROR_FAILED,
-                     "Could not parse the CRSM response");
+    if (!mm_3gpp_parse_crsm_response (response,
+                                      &sw1,
+                                      &sw2,
+                                      &hex,
+                                      error))
         return NULL;
-    }
 
     if ((sw1 == 0x90 && sw2 == 0x00) ||
         (sw1 == 0x91) ||
@@ -1268,15 +1232,6 @@ parse_spn (const gchar *response,
         gchar *bin;
         gchar *utf8;
 
-        /* Make sure the buffer is only hex characters */
-        while (buflen < sizeof (hex) && hex[buflen]) {
-            if (!isxdigit (hex[buflen])) {
-                hex[buflen] = 0x0;
-                break;
-            }
-            buflen++;
-        }
-
         /* Convert hex string to binary */
         bin = mm_utils_hexstr2bin (hex, &buflen);
         if (!bin) {
@@ -1285,9 +1240,12 @@ parse_spn (const gchar *response,
                          MM_CORE_ERROR_FAILED,
                          "SIM returned malformed response '%s'",
                          hex);
+            g_free (hex);
             return NULL;
         }
 
+        g_free (hex);
+
         /* Remove the FF filler at the end */
         while (buflen > 1 && bin[buflen - 1] == (char)0xff)
             buflen--;
@@ -1298,6 +1256,7 @@ parse_spn (const gchar *response,
         return utf8;
     }
 
+    g_free (hex);
     g_set_error (error,
                  MM_CORE_ERROR,
                  MM_CORE_ERROR_FAILED,
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index dec53c3..ed36578 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -1342,6 +1342,57 @@ done:
     return info;
 }
 
+/*****************************************************************************/
+
+/* AT+CRSM response parser */
+gboolean
+mm_3gpp_parse_crsm_response (const gchar *reply,
+                             guint *sw1,
+                             guint *sw2,
+                             gchar **hex,
+                             GError **error)
+{
+    GRegex *r;
+    GMatchInfo *match_info;
+
+    g_assert (sw1 != NULL);
+    g_assert (sw2 != NULL);
+    g_assert (hex != NULL);
+
+    *sw1 = 0;
+    *sw2 = 0;
+    *hex = NULL;
+
+    if (!reply || !g_str_has_prefix (reply, "+CRSM:")) {
+        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing +CRSM prefix");
+        return FALSE;
+    }
+
+    r = g_regex_new ("\\+CRSM:\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*\"?([0-9a-fA-F]+)\"?",
+                     G_REGEX_RAW, 0, error);
+    if (!r)
+        return FALSE;
+
+    if (g_regex_match_full (r, reply, strlen (reply), 0, 0, &match_info, NULL) &&
+        mm_get_uint_from_match_info (match_info, 1, sw1) &&
+        mm_get_uint_from_match_info (match_info, 2, sw2))
+        *hex = mm_get_string_unquoted_from_match_info (match_info, 3);
+
+    g_match_info_free (match_info);
+    g_regex_unref (r);
+
+    if (*hex == NULL) {
+        g_set_error (error,
+                     MM_CORE_ERROR,
+                     MM_CORE_ERROR_FAILED,
+                     "Failed to parse CRSM query result '%s'",
+                     reply);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
 /*************************************************************************/
 
 static MMSmsStorage
diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h
index 3be7c7b..975a493 100644
--- a/src/mm-modem-helpers.h
+++ b/src/mm-modem-helpers.h
@@ -203,6 +203,14 @@ MM3gppPduInfo *mm_3gpp_parse_cmgr_read_response (const gchar *reply,
                                                  guint index,
                                                  GError **error);
 
+
+/* AT+CRSM response parser */
+gboolean mm_3gpp_parse_crsm_response (const gchar *reply,
+                                      guint *sw1,
+                                      guint *sw2,
+                                      gchar **hex,
+                                      GError **error);
+
 /* Additional 3GPP-specific helpers */
 
 MMModem3gppFacility mm_3gpp_acronym_to_facility (const gchar *str);
diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c
index d1833e5..445515f 100644
--- a/src/tests/test-modem-helpers.c
+++ b/src/tests/test-modem-helpers.c
@@ -2631,6 +2631,58 @@ test_cclk_response (void)
     }
 }
 
+
+/*****************************************************************************/
+/* Test +CRSM responses */
+
+typedef struct {
+    const gchar *str;
+    gboolean ret;
+    guint sw1;
+    guint sw2;
+    gchar *hex;
+} CrsmTest;
+
+static const CrsmTest crsm_tests[] = {
+    { "+CRSM: 144, 0, 0054485552415941FFFFFFFFFFFFFFFFFF", TRUE, 144, 0, "0054485552415941FFFFFFFFFFFFFFFFFF" },
+    { "+CRSM: 144, 0,0054485552415941FFFFFFFFFFFFFFFFFF", TRUE, 144, 0, "0054485552415941FFFFFFFFFFFFFFFFFF" },
+    { "+CRSM: 144, 0, \"0054485552415941FFFFFFFFFFFFFFFFFF\"", TRUE, 144, 0, "0054485552415941FFFFFFFFFFFFFFFFFF" },
+    { "+CRSM: 144, 0,\"0054485552415941FFFFFFFFFFFFFFFFFF\"", TRUE, 144, 0, "0054485552415941FFFFFFFFFFFFFFFFFF" },
+    { NULL, FALSE, 0, 0, NULL }
+};
+
+static void
+test_crsm_response (void)
+{
+    guint i;
+
+    for (i = 0; crsm_tests[i].str; i++) {
+        GError *error = NULL;
+        guint sw1 = 0;
+        guint sw2 = 0;
+        gchar *hex = 0;
+        gboolean ret;
+  
+        ret = mm_3gpp_parse_crsm_response (crsm_tests[i].str,
+                                           &sw1,
+                                           &sw2,
+                                           &hex,
+                                           &error);
+
+        g_assert (ret == crsm_tests[i].ret);
+        g_assert (ret == (error ? FALSE : TRUE));
+
+        g_clear_error (&error);
+
+        g_assert (sw1 == crsm_tests[i].sw1);
+        g_assert (sw2 == crsm_tests[i].sw2);
+        
+        g_assert_cmpstr (crsm_tests[i].hex, ==, hex);
+
+        g_free(hex);
+    }
+}
+
 /*****************************************************************************/
 
 void
@@ -2805,6 +2857,8 @@ int main (int argc, char **argv)
 
     g_test_suite_add (suite, TESTCASE (test_cclk_response, NULL));
 
+    g_test_suite_add (suite, TESTCASE (test_crsm_response, NULL));
+
     result = g_test_run ();
 
     reg_test_data_free (reg_data);
-- 
2.5.0



More information about the ModemManager-devel mailing list