diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2016-08-06 19:01:27 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2016-10-12 11:29:52 +0200 |
commit | 61fbab286c3ab231f7fd16c345cc7e352f33bae4 (patch) | |
tree | 145c7f02f3cc137216694068db737b4a904c7f18 | |
parent | f2c2a6a05f82450383667eb32dca4fd63488ae4f (diff) |
modem-helpers: new CGACT? response parser
-rw-r--r-- | src/mm-modem-helpers.c | 84 | ||||
-rw-r--r-- | src/mm-modem-helpers.h | 9 | ||||
-rw-r--r-- | src/tests/test-modem-helpers.c | 92 |
3 files changed, 185 insertions, 0 deletions
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c index ff3aab8f..e6e158cc 100644 --- a/src/mm-modem-helpers.c +++ b/src/mm-modem-helpers.c @@ -1101,6 +1101,90 @@ mm_3gpp_parse_cgdcont_read_response (const gchar *reply, /*************************************************************************/ +static void +mm_3gpp_pdp_context_active_free (MM3gppPdpContextActive *pdp_active) +{ + g_slice_free (MM3gppPdpContextActive, pdp_active); +} + +void +mm_3gpp_pdp_context_active_list_free (GList *pdp_active_list) +{ + g_list_free_full (pdp_active_list, (GDestroyNotify) mm_3gpp_pdp_context_active_free); +} + +static gint +mm_3gpp_pdp_context_active_cmp (MM3gppPdpContextActive *a, + MM3gppPdpContextActive *b) +{ + return (a->cid - b->cid); +} + +GList * +mm_3gpp_parse_cgact_read_response (const gchar *reply, + GError **error) +{ + GError *inner_error = NULL; + GRegex *r; + GMatchInfo *match_info; + GList *list; + + if (!reply || !reply[0]) + /* Nothing configured, all done */ + return NULL; + + list = NULL; + r = g_regex_new ("\\+CGACT:\\s*(\\d+),(\\d+)", + G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, 0, &inner_error); + g_assert (r); + + g_regex_match_full (r, reply, strlen (reply), 0, 0, &match_info, &inner_error); + while (!inner_error && g_match_info_matches (match_info)) { + MM3gppPdpContextActive *pdp_active; + guint cid = 0; + guint aux = 0; + + if (!mm_get_uint_from_match_info (match_info, 1, &cid)) { + inner_error = g_error_new (MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Couldn't parse CID from reply: '%s'", + reply); + break; + } + if (!mm_get_uint_from_match_info (match_info, 2, &aux) || (aux != 0 && aux != 1)) { + inner_error = g_error_new (MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Couldn't parse context status from reply: '%s'", + reply); + break; + } + + pdp_active = g_slice_new0 (MM3gppPdpContextActive); + pdp_active->cid = cid; + pdp_active->active = (gboolean) aux; + list = g_list_prepend (list, pdp_active); + + g_match_info_next (match_info, &inner_error); + } + + if (match_info) + g_match_info_free (match_info); + g_regex_unref (r); + + if (inner_error) { + mm_3gpp_pdp_context_active_list_free (list); + g_propagate_error (error, inner_error); + g_prefix_error (error, "Couldn't properly parse list of active/inactive PDP contexts. "); + return NULL; + } + + list = g_list_sort (list, (GCompareFunc) mm_3gpp_pdp_context_active_cmp); + + return list; +} + +/*************************************************************************/ + static gulong parse_uint (char *str, int base, glong nmin, glong nmax, gboolean *valid) { diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h index 00536889..c7aba903 100644 --- a/src/mm-modem-helpers.h +++ b/src/mm-modem-helpers.h @@ -144,6 +144,15 @@ void mm_3gpp_pdp_context_list_free (GList *pdp_list); GList *mm_3gpp_parse_cgdcont_read_response (const gchar *reply, GError **error); +/* AT+CGACT? (active PDP context query) response parser */ +typedef struct { + guint cid; + gboolean active; +} MM3gppPdpContextActive; +void mm_3gpp_pdp_context_active_list_free (GList *pdp_active_list); +GList *mm_3gpp_parse_cgact_read_response (const gchar *reply, + GError **error); + /* CREG/CGREG response/unsolicited message parser */ gboolean mm_3gpp_parse_creg_response (GMatchInfo *info, MMModem3gppRegistrationState *out_reg_state, diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c index 054b087e..c6fef40a 100644 --- a/src/tests/test-modem-helpers.c +++ b/src/tests/test-modem-helpers.c @@ -1994,6 +1994,93 @@ test_cgdcont_read_response_samsung (void *f, gpointer d) } /*****************************************************************************/ +/* Test CGDCONT read responses */ + +static void +test_cgact_read_results (const gchar *desc, + const gchar *reply, + MM3gppPdpContextActive *expected_results, + guint32 expected_results_len) +{ + GList *l; + GError *error = NULL; + GList *results; + + trace ("\nTesting %s +CGACT response...\n", desc); + + results = mm_3gpp_parse_cgact_read_response (reply, &error); + g_assert_no_error (error); + if (expected_results_len) { + g_assert (results); + g_assert_cmpuint (g_list_length (results), ==, expected_results_len); + } + + for (l = results; l; l = g_list_next (l)) { + MM3gppPdpContextActive *pdp = l->data; + gboolean found = FALSE; + guint i; + + for (i = 0; !found && i < expected_results_len; i++) { + MM3gppPdpContextActive *expected; + + expected = &expected_results[i]; + if (pdp->cid == expected->cid) { + found = TRUE; + g_assert_cmpuint (pdp->active, ==, expected->active); + } + } + + g_assert (found == TRUE); + } + + mm_3gpp_pdp_context_active_list_free (results); +} + +static void +test_cgact_read_response_none (void) +{ + test_cgact_read_results ("none", "", NULL, 0); +} + +static void +test_cgact_read_response_single_inactive (void) +{ + const gchar *reply = "+CGACT: 1,0\r\n"; + static MM3gppPdpContextActive expected[] = { + { 1, FALSE }, + }; + + test_cgact_read_results ("single inactive", reply, &expected[0], G_N_ELEMENTS (expected)); +} + +static void +test_cgact_read_response_single_active (void) +{ + const gchar *reply = "+CGACT: 1,1\r\n"; + static MM3gppPdpContextActive expected[] = { + { 1, TRUE }, + }; + + test_cgact_read_results ("single active", reply, &expected[0], G_N_ELEMENTS (expected)); +} + +static void +test_cgact_read_response_multiple (void) +{ + const gchar *reply = + "+CGACT: 1,0\r\n" + "+CGACT: 4,1\r\n" + "+CGACT: 5,0\r\n"; + static MM3gppPdpContextActive expected[] = { + { 1, FALSE }, + { 4, TRUE }, + { 5, FALSE }, + }; + + test_cgact_read_results ("multiple", reply, &expected[0], G_N_ELEMENTS (expected)); +} + +/*****************************************************************************/ /* Test CPMS responses */ static gboolean @@ -3123,6 +3210,11 @@ int main (int argc, char **argv) g_test_suite_add (suite, TESTCASE (test_cgdcont_read_response_nokia, NULL)); g_test_suite_add (suite, TESTCASE (test_cgdcont_read_response_samsung, NULL)); + g_test_suite_add (suite, TESTCASE (test_cgact_read_response_none, NULL)); + g_test_suite_add (suite, TESTCASE (test_cgact_read_response_single_inactive, NULL)); + g_test_suite_add (suite, TESTCASE (test_cgact_read_response_single_active, NULL)); + g_test_suite_add (suite, TESTCASE (test_cgact_read_response_multiple, NULL)); + g_test_suite_add (suite, TESTCASE (test_cnum_response_generic, NULL)); g_test_suite_add (suite, TESTCASE (test_cnum_response_generic_without_detail, NULL)); g_test_suite_add (suite, TESTCASE (test_cnum_response_generic_detail_unquoted, NULL)); |