aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mm-broadband-modem.c40
-rw-r--r--src/mm-modem-helpers.c79
-rw-r--r--src/mm-modem-helpers.h11
-rw-r--r--src/tests/test-modem-helpers.c68
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 ();