modem-helpers: new CGACT? response parser

This commit is contained in:
Aleksander Morgado
2016-08-06 19:01:27 +02:00
parent f2c2a6a05f
commit 61fbab286c
3 changed files with 185 additions and 0 deletions

View File

@@ -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 static gulong
parse_uint (char *str, int base, glong nmin, glong nmax, gboolean *valid) parse_uint (char *str, int base, glong nmin, glong nmax, gboolean *valid)
{ {

View File

@@ -144,6 +144,15 @@ void mm_3gpp_pdp_context_list_free (GList *pdp_list);
GList *mm_3gpp_parse_cgdcont_read_response (const gchar *reply, GList *mm_3gpp_parse_cgdcont_read_response (const gchar *reply,
GError **error); 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 */ /* CREG/CGREG response/unsolicited message parser */
gboolean mm_3gpp_parse_creg_response (GMatchInfo *info, gboolean mm_3gpp_parse_creg_response (GMatchInfo *info,
MMModem3gppRegistrationState *out_reg_state, MMModem3gppRegistrationState *out_reg_state,

View File

@@ -1993,6 +1993,93 @@ test_cgdcont_read_response_samsung (void *f, gpointer d)
test_cgdcont_read_results ("Samsung", reply, &expected[0], G_N_ELEMENTS (expected)); test_cgdcont_read_results ("Samsung", reply, &expected[0], G_N_ELEMENTS (expected));
} }
/*****************************************************************************/
/* 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 */ /* Test CPMS responses */
@@ -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_nokia, NULL));
g_test_suite_add (suite, TESTCASE (test_cgdcont_read_response_samsung, 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, NULL));
g_test_suite_add (suite, TESTCASE (test_cnum_response_generic_without_detail, 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)); g_test_suite_add (suite, TESTCASE (test_cnum_response_generic_detail_unquoted, NULL));