diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2016-10-11 16:27:51 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2016-10-12 11:29:52 +0200 |
commit | aca6bb1c02ddc16d88fb8c9fd934466eb7debf5c (patch) | |
tree | 157c9d96d8331e00dfe3b090a89b084e71e98886 /src | |
parent | b34f147ba27b9d328a17bee092d0d21bd20eb200 (diff) |
modem-helpers: new +CFUN? response parser
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-broadband-modem.c | 40 | ||||
-rw-r--r-- | src/mm-modem-helpers.c | 79 | ||||
-rw-r--r-- | src/mm-modem-helpers.h | 11 | ||||
-rw-r--r-- | src/tests/test-modem-helpers.c | 68 |
4 files changed, 162 insertions, 36 deletions
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 6b3b8e40..86b80ca2 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -3150,46 +3150,14 @@ cfun_query_ready (MMBaseModem *self, GSimpleAsyncResult *simple) { const gchar *result; - guint state; + MMModemPowerState state; GError *error = NULL; result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!result) { + if (!result || !mm_3gpp_parse_cfun_query_generic_response (result, &state, &error)) g_simple_async_result_take_error (simple, error); - g_simple_async_result_complete (simple); - g_object_unref (simple); - return; - } - - /* Parse power state reply */ - result = mm_strip_tag (result, "+CFUN:"); - if (!mm_get_uint_from_str (result, &state)) { - g_simple_async_result_set_error (simple, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse +CFUN? response '%s'", - result); - } else { - switch (state) { - case 0: - g_simple_async_result_set_op_res_gpointer (simple, GUINT_TO_POINTER (MM_MODEM_POWER_STATE_OFF), NULL); - break; - case 1: - g_simple_async_result_set_op_res_gpointer (simple, GUINT_TO_POINTER (MM_MODEM_POWER_STATE_ON), NULL); - break; - case 4: - g_simple_async_result_set_op_res_gpointer (simple, GUINT_TO_POINTER (MM_MODEM_POWER_STATE_LOW), NULL); - break; - default: - g_simple_async_result_set_error (simple, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unhandled power state: '%u'", - state); - break; - } - } - + else + g_simple_async_result_set_op_res_gpointer (simple, GUINT_TO_POINTER (state), NULL); g_simple_async_result_complete (simple); g_object_unref (simple); } diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c index 8b4f0f08..8f208000 100644 --- a/src/mm-modem-helpers.c +++ b/src/mm-modem-helpers.c @@ -1858,6 +1858,85 @@ out: /*************************************************************************/ +gboolean +mm_3gpp_parse_cfun_query_response (const gchar *response, + guint *out_state, + GError **error) +{ + GRegex *r; + GMatchInfo *match_info; + GError *inner_error = NULL; + guint state = G_MAXUINT; + + g_assert (out_state != NULL); + + /* Response may be e.g.: + * +CFUN: 1,0 + * ..but we don't care about the second number + */ + r = g_regex_new ("\\+CFUN: (\\d+)(?:,(?:\\d+))?(?:\\r\\n)?", 0, 0, NULL); + g_assert (r != NULL); + + g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); + if (inner_error) + goto out; + + if (!g_match_info_matches (match_info)) { + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Couldn't parse +CFUN response: %s", response); + goto out; + } + + if (!mm_get_uint_from_match_info (match_info, 1, &state)) { + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Couldn't read power state value"); + goto out; + } + + *out_state = state; + +out: + if (match_info) + g_match_info_free (match_info); + g_regex_unref (r); + + if (inner_error) { + g_propagate_error (error, inner_error); + return FALSE; + } + + return TRUE; +} + +gboolean +mm_3gpp_parse_cfun_query_generic_response (const gchar *response, + MMModemPowerState *out_state, + GError **error) +{ + guint state; + + if (!mm_3gpp_parse_cfun_query_response (response, &state, error)) + return FALSE; + + switch (state) { + case 0: + *out_state = MM_MODEM_POWER_STATE_OFF; + return TRUE; + case 1: + *out_state = MM_MODEM_POWER_STATE_ON; + return TRUE; + case 4: + *out_state = MM_MODEM_POWER_STATE_LOW; + return TRUE; + default: + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Unknown +CFUN state: %u", state); + return FALSE; + } +} + +/*************************************************************************/ + static MMSmsStorage storage_from_str (const gchar *str) { diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h index 21794646..b25b2055 100644 --- a/src/mm-modem-helpers.h +++ b/src/mm-modem-helpers.h @@ -253,6 +253,17 @@ gboolean mm_3gpp_parse_cgcontrdp_response (const gchar *response, gchar **out_dns_secondary_address, GError **error); +/* CFUN? response parser + * Note: a custom method with values not translated into MMModemPowerState is + * provided, because they may be vendor specific. + */ +gboolean mm_3gpp_parse_cfun_query_response (const gchar *response, + guint *out_state, + GError **error); +gboolean mm_3gpp_parse_cfun_query_generic_response (const gchar *response, + MMModemPowerState *out_state, + GError **error); + /* Additional 3GPP-specific helpers */ MMModem3gppFacility mm_3gpp_acronym_to_facility (const gchar *str); diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c index 14f32961..0d70f051 100644 --- a/src/tests/test-modem-helpers.c +++ b/src/tests/test-modem-helpers.c @@ -3059,6 +3059,71 @@ test_cgcontrdp_response (void) } /*****************************************************************************/ +/* Test CFUN? response */ + +typedef struct { + const gchar *str; + guint state; +} CfunQueryTest; + +static const CfunQueryTest cfun_query_tests[] = { + { "+CFUN: 1", 1 }, + { "+CFUN: 1,0", 1 }, + { "+CFUN: 0", 0 }, + { "+CFUN: 0,0", 0 }, + { "+CFUN: 19", 19 }, + { "+CFUN: 19,0", 19 }, +}; + +static void +test_cfun_response (void) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS (cfun_query_tests); i++) { + GError *error = NULL; + gboolean success; + guint state = G_MAXUINT; + + success = mm_3gpp_parse_cfun_query_response (cfun_query_tests[i].str, &state, &error); + g_assert_no_error (error); + g_assert (success); + g_assert_cmpuint (cfun_query_tests[i].state, ==, state); + } +} + +typedef struct { + const gchar *str; + MMModemPowerState state; +} CfunQueryGenericTest; + +static const CfunQueryGenericTest cfun_query_generic_tests[] = { + { "+CFUN: 1", MM_MODEM_POWER_STATE_ON }, + { "+CFUN: 1,0", MM_MODEM_POWER_STATE_ON }, + { "+CFUN: 0", MM_MODEM_POWER_STATE_OFF }, + { "+CFUN: 0,0", MM_MODEM_POWER_STATE_OFF }, + { "+CFUN: 4", MM_MODEM_POWER_STATE_LOW }, + { "+CFUN: 4,0", MM_MODEM_POWER_STATE_LOW }, +}; + +static void +test_cfun_generic_response (void) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS (cfun_query_generic_tests); i++) { + GError *error = NULL; + gboolean success; + MMModemPowerState state = MM_MODEM_POWER_STATE_UNKNOWN; + + success = mm_3gpp_parse_cfun_query_generic_response (cfun_query_generic_tests[i].str, &state, &error); + g_assert_no_error (error); + g_assert (success); + g_assert_cmpuint (cfun_query_generic_tests[i].state, ==, state); + } +} + +/*****************************************************************************/ typedef struct { gchar *str; @@ -3288,6 +3353,9 @@ int main (int argc, char **argv) g_test_suite_add (suite, TESTCASE (test_cgcontrdp_response, NULL)); + g_test_suite_add (suite, TESTCASE (test_cfun_response, NULL)); + g_test_suite_add (suite, TESTCASE (test_cfun_generic_response, NULL)); + g_test_suite_add (suite, TESTCASE (test_parse_uint_list, NULL)); result = g_test_run (); |