aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mm-modem-helpers.c82
-rw-r--r--src/mm-modem-helpers.h10
-rw-r--r--src/tests/test-modem-helpers.c90
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));