aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2016-08-06 19:01:27 +0200
committerAleksander Morgado <aleksander@aleksander.es>2016-10-12 11:29:52 +0200
commit61fbab286c3ab231f7fd16c345cc7e352f33bae4 (patch)
tree145c7f02f3cc137216694068db737b4a904c7f18 /src
parentf2c2a6a05f82450383667eb32dca4fd63488ae4f (diff)
modem-helpers: new CGACT? response parser
Diffstat (limited to 'src')
-rw-r--r--src/mm-modem-helpers.c84
-rw-r--r--src/mm-modem-helpers.h9
-rw-r--r--src/tests/test-modem-helpers.c92
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));