modem-helpers: new +CFUN? response parser
This commit is contained in:
@@ -3150,46 +3150,14 @@ cfun_query_ready (MMBaseModem *self,
|
|||||||
GSimpleAsyncResult *simple)
|
GSimpleAsyncResult *simple)
|
||||||
{
|
{
|
||||||
const gchar *result;
|
const gchar *result;
|
||||||
guint state;
|
MMModemPowerState state;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
|
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_take_error (simple, error);
|
||||||
g_simple_async_result_complete (simple);
|
else
|
||||||
g_object_unref (simple);
|
g_simple_async_result_set_op_res_gpointer (simple, GUINT_TO_POINTER (state), NULL);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_simple_async_result_complete (simple);
|
g_simple_async_result_complete (simple);
|
||||||
g_object_unref (simple);
|
g_object_unref (simple);
|
||||||
}
|
}
|
||||||
|
@@ -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
|
static MMSmsStorage
|
||||||
storage_from_str (const gchar *str)
|
storage_from_str (const gchar *str)
|
||||||
{
|
{
|
||||||
|
@@ -253,6 +253,17 @@ gboolean mm_3gpp_parse_cgcontrdp_response (const gchar *response,
|
|||||||
gchar **out_dns_secondary_address,
|
gchar **out_dns_secondary_address,
|
||||||
GError **error);
|
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 */
|
/* Additional 3GPP-specific helpers */
|
||||||
|
|
||||||
MMModem3gppFacility mm_3gpp_acronym_to_facility (const gchar *str);
|
MMModem3gppFacility mm_3gpp_acronym_to_facility (const gchar *str);
|
||||||
|
@@ -3058,6 +3058,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 {
|
typedef struct {
|
||||||
@@ -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_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));
|
g_test_suite_add (suite, TESTCASE (test_parse_uint_list, NULL));
|
||||||
|
|
||||||
result = g_test_run ();
|
result = g_test_run ();
|
||||||
|
Reference in New Issue
Block a user