diff options
-rw-r--r-- | src/mm-modem-helpers.c | 82 | ||||
-rw-r--r-- | src/mm-modem-helpers.h | 10 | ||||
-rw-r--r-- | src/tests/test-modem-helpers.c | 90 |
3 files changed, 182 insertions, 0 deletions
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c index c4640d42..46265d04 100644 --- a/src/mm-modem-helpers.c +++ b/src/mm-modem-helpers.c @@ -644,6 +644,88 @@ mm_3gpp_parse_cops_test_response (const gchar *reply, /*************************************************************************/ + +static void +mm_3gpp_pdp_context_format_free (MM3gppPdpContextFormat *format) +{ + g_slice_free (MM3gppPdpContextFormat, format); +} + +void +mm_3gpp_pdp_context_format_list_free (GList *pdp_format_list) +{ + g_list_free_full (pdp_format_list, (GDestroyNotify) mm_3gpp_pdp_context_format_free); +} + +GList * +mm_3gpp_parse_cgdcont_test_response (const gchar *response, + GError **error) +{ + GRegex *r; + GMatchInfo *match_info; + GError *inner_error = NULL; + GList *list = NULL; + + if (!response || !g_str_has_prefix (response, "+CGDCONT:")) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing +CGDCONT prefix"); + return NULL; + } + + r = g_regex_new ("\\+CGDCONT:\\s*\\((\\d+)-(\\d+)\\),\\(?\"(\\S+)\"", + G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, + 0, &inner_error); + g_assert (r != NULL); + + g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); + while (!inner_error && g_match_info_matches (match_info)) { + gchar *pdp_type_str; + guint min_cid; + guint max_cid; + MMBearerIpFamily pdp_type; + + /* Read PDP type */ + pdp_type_str = mm_get_string_unquoted_from_match_info (match_info, 3); + pdp_type = mm_3gpp_get_ip_family_from_pdp_type (pdp_type_str); + if (pdp_type == MM_BEARER_IP_FAMILY_NONE) + mm_dbg ("Unhandled PDP type in CGDCONT=? reply: '%s'", pdp_type_str); + else { + /* Read min CID */ + if (!mm_get_uint_from_match_info (match_info, 1, &min_cid)) + mm_warn ("Invalid min CID in CGDCONT=? reply for PDP type '%s'", pdp_type_str); + else { + /* Read max CID */ + if (!mm_get_uint_from_match_info (match_info, 2, &max_cid)) + mm_warn ("Invalid max CID in CGDCONT=? reply for PDP type '%s'", pdp_type_str); + else { + MM3gppPdpContextFormat *format; + + format = g_slice_new (MM3gppPdpContextFormat); + format->pdp_type = pdp_type; + format->min_cid = min_cid; + format->max_cid = max_cid; + + list = g_list_prepend (list, format); + } + } + } + + g_free (pdp_type_str); + g_match_info_next (match_info, &inner_error); + } + + g_match_info_free (match_info); + g_regex_unref (r); + + if (inner_error) { + mm_warn ("Unexpected error matching +CGDCONT response: '%s'", inner_error->message); + g_error_free (inner_error); + } + + return list; +} + +/*************************************************************************/ + static void mm_3gpp_pdp_context_free (MM3gppPdpContext *pdp) { diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h index 5a8ba493..80c31691 100644 --- a/src/mm-modem-helpers.h +++ b/src/mm-modem-helpers.h @@ -98,6 +98,16 @@ void mm_3gpp_network_info_list_free (GList *info_list); GList *mm_3gpp_parse_cops_test_response (const gchar *reply, GError **error); +/* AT+CGDCONT=? (PDP context format) test parser */ +typedef struct { + guint min_cid; + guint max_cid; + MMBearerIpFamily pdp_type; +} MM3gppPdpContextFormat; +void mm_3gpp_pdp_context_format_list_free (GList *pdp_format_list); +GList *mm_3gpp_parse_cgdcont_test_response (const gchar *reply, + GError **error); + /* AT+CGDCONT? (PDP context query) response parser */ typedef struct { guint cid; diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c index 8453840b..0d245b29 100644 --- a/src/tests/test-modem-helpers.c +++ b/src/tests/test-modem-helpers.c @@ -1456,6 +1456,92 @@ test_cind_response_moto_v3m (void *f, gpointer d) } /*****************************************************************************/ +/* Test CGDCONT test responses */ + +static void +test_cgdcont_test_results (const gchar *desc, + const gchar *reply, + MM3gppPdpContextFormat *expected_results, + guint32 expected_results_len) +{ + GList *l; + GError *error = NULL; + GList *results; + + g_print ("\nTesting %s +CGDCONT test response...\n", desc); + + results = mm_3gpp_parse_cgdcont_test_response (reply, &error); + g_assert (results); + g_assert_no_error (error); + g_assert_cmpuint (g_list_length (results), ==, expected_results_len); + + for (l = results; l; l = g_list_next (l)) { + MM3gppPdpContextFormat *format = l->data; + gboolean found = FALSE; + guint i; + + for (i = 0; !found && i < expected_results_len; i++) { + MM3gppPdpContextFormat *expected; + + expected = &expected_results[i]; + if (format->pdp_type == expected->pdp_type) { + found = TRUE; + + g_assert_cmpuint (format->min_cid, ==, expected->min_cid); + g_assert_cmpuint (format->max_cid, ==, expected->max_cid); + } + } + + g_assert (found == TRUE); + } + + mm_3gpp_pdp_context_format_list_free (results); +} + +static void +test_cgdcont_test_response_single (void *f, gpointer d) +{ + const gchar *reply = "+CGDCONT: (1-10),\"IP\",,,(0,1),(0,1)"; + static MM3gppPdpContextFormat expected[] = { + { 1, 10, MM_BEARER_IP_FAMILY_IPV4 } + }; + + test_cgdcont_test_results ("Single", reply, &expected[0], G_N_ELEMENTS (expected)); +} + +static void +test_cgdcont_test_response_multiple (void *f, gpointer d) +{ + const gchar *reply = + "+CGDCONT: (1-10),\"IP\",,,(0,1),(0,1)\r\n" + "+CGDCONT: (1-10),\"IPV6\",,,(0,1),(0,1)\r\n" + "+CGDCONT: (1-10),\"IPV4V6\",,,(0,1),(0,1)\r\n"; + static MM3gppPdpContextFormat expected[] = { + { 1, 10, MM_BEARER_IP_FAMILY_IPV4 }, + { 1, 10, MM_BEARER_IP_FAMILY_IPV6 }, + { 1, 10, MM_BEARER_IP_FAMILY_IPV4V6 } + }; + + test_cgdcont_test_results ("Multiple", reply, &expected[0], G_N_ELEMENTS (expected)); +} + +static void +test_cgdcont_test_response_multiple_and_ignore (void *f, gpointer d) +{ + const gchar *reply = + "+CGDCONT: (1-16),\"IP\",,,(0-2),(0-4)\r\n" + "+CGDCONT: (1-16),\"PPP\",,,(0-2),(0-4)\r\n" + "+CGDCONT: (1-16),\"IPV6\",,,(0-2),(0-4)\r\n"; + static MM3gppPdpContextFormat expected[] = { + { 1, 16, MM_BEARER_IP_FAMILY_IPV4 }, + /* PPP is ignored */ + { 1, 16, MM_BEARER_IP_FAMILY_IPV6 } + }; + + test_cgdcont_test_results ("Multiple and Ignore", reply, &expected[0], G_N_ELEMENTS (expected)); +} + +/*****************************************************************************/ /* Test CGDCONT read responses */ static void @@ -1950,6 +2036,10 @@ int main (int argc, char **argv) g_test_suite_add (suite, TESTCASE (test_cpms_response_cinterion, 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_read_response_nokia, NULL)); g_test_suite_add (suite, TESTCASE (test_cgdcont_read_response_samsung, NULL)); |