diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-modem-helpers.c | 85 | ||||
-rw-r--r-- | src/mm-modem-helpers.h | 4 | ||||
-rw-r--r-- | src/tests/test-modem-helpers.c | 59 |
3 files changed, 148 insertions, 0 deletions
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c index b2806dfa..dce7e795 100644 --- a/src/mm-modem-helpers.c +++ b/src/mm-modem-helpers.c @@ -4238,3 +4238,88 @@ mm_parse_cclk_response (const char *response, return ret; } + +/*****************************************************************************/ +/* +CSIM response parser */ +#define MM_MIN_SIM_RETRY_HEX 0x63C0 +#define MM_MAX_SIM_RETRY_HEX 0x63CF + +gint +mm_parse_csim_response (const gchar *response, + GError **error) +{ + GMatchInfo *match_info = NULL; + GRegex *r = NULL; + gchar *str_code = NULL; + gint retries = -1; + guint hex_code; + GError *inner_error = NULL; + + r = g_regex_new ("\\+CSIM:\\s*[0-9]+,\\s*\".*([0-9a-fA-F]{4})\"", G_REGEX_RAW, 0, NULL); + g_regex_match (r, response, 0, &match_info); + + if (!g_match_info_matches (match_info)) { + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Could not recognize +CSIM response '%s'", response); + goto out; + } + + str_code = mm_get_string_unquoted_from_match_info (match_info, 1); + if (str_code == NULL) { + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Could not find expected string code in response '%s'", response); + goto out; + } + + if (!mm_get_uint_from_hex_str (str_code, &hex_code)) { + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Could not recognize expected hex code in response '%s'", response); + goto out; + } + + switch (hex_code) { + case 0x6300: + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "SIM verification failed"); + goto out; + case 0x6983: + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "SIM authentication method blocked"); + goto out; + case 0x6984: + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "SIM reference data invalidated"); + goto out; + case 0x6A86: + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Incorrect parameters in SIM request"); + goto out; + case 0x6A88: + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "SIM reference data not found"); + goto out; + default: + break; + } + + if (hex_code < MM_MIN_SIM_RETRY_HEX || hex_code > MM_MAX_SIM_RETRY_HEX) { + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Unknown error returned '0x%04x'", hex_code); + goto out; + } + + retries = (gint)(hex_code - MM_MIN_SIM_RETRY_HEX); + +out: + g_regex_unref (r); + g_match_info_free (match_info); + g_free (str_code); + + if (inner_error) { + g_propagate_error (error, inner_error); + return -1; + } + + g_assert (retries >= 0); + return retries; +} diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h index 524f05ae..db2888b1 100644 --- a/src/mm-modem-helpers.h +++ b/src/mm-modem-helpers.h @@ -394,4 +394,8 @@ gboolean mm_parse_cclk_response (const gchar *response, MMNetworkTimezone **tzp, GError **error); +/* +CSIM response parser */ +gint mm_parse_csim_response (const gchar *response, + GError **error); + #endif /* MM_MODEM_HELPERS_H */ diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c index 52e6302a..c2cc1105 100644 --- a/src/tests/test-modem-helpers.c +++ b/src/tests/test-modem-helpers.c @@ -3667,6 +3667,63 @@ test_cfun_generic_response (void) } } +typedef struct { + gchar *response; + gint result; + gchar *error_message; +} CSIMResponseTest; + +static CSIMResponseTest csim_response_test_list [] = { + /* The parser expects that 2nd arg contains + * substring "63Cx" where x is an HEX string + * representing the retry value */ + {"+CSIM:8,\"000063C1\"", 1, NULL}, + {"+CSIM:8,\"000063CA\"", 10, NULL}, + {"+CSIM:8,\"000063CF\"", 15, NULL}, + /* The parser accepts spaces */ + {"+CSIM:8, \"000063C1\"", 1, NULL}, + {"+CSIM: 8, \"000063C1\"", 1, NULL}, + {"+CSIM: 8, \"000063C1\"", 1, NULL}, + /* the parser expects an int as first argument (2nd arg's length), + * but does not check if it is correct */ + {"+CSIM: 10, \"63CF\"", 15, NULL}, + /* Valid +CSIM Error codes */ + {"+CSIM: 4, \"6300\"", -1, "SIM verification failed"}, + {"+CSIM: 4, \"6983\"", -1, "SIM authentication method blocked"}, + {"+CSIM: 4, \"6984\"", -1, "SIM reference data invalidated"}, + {"+CSIM: 4, \"6A86\"", -1, "Incorrect parameters in SIM request"}, + {"+CSIM: 4, \"6A88\"", -1, "SIM reference data not found"}, + /* Test error: missing first argument */ + {"+CSIM:000063CF\"", -1, "Could not recognize +CSIM response '+CSIM:000063CF\"'"}, + /* Test error: missing quotation mark */ + {"+CSIM: 8, 000063CF", -1, "Could not recognize +CSIM response '+CSIM: 8, 000063CF'"}, + /* Test generic error */ + {"+CSIM: 4, \"63BF\"", -1, "Unknown error returned '0x63bf'"}, + {"+CSIM: 4, \"63D0\"", -1, "Unknown error returned '0x63d0'"} +}; + +static void +test_csim_response (void) +{ + guint i; + gint res; + GError* error = NULL; + + for (i = 0; i < G_N_ELEMENTS (csim_response_test_list); i++) { + res = mm_parse_csim_response (csim_response_test_list[i].response, &error); + + if (csim_response_test_list[i].error_message == NULL) { + g_assert_no_error (error); + } else { + g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED); + g_assert_cmpstr (error->message, ==, csim_response_test_list[i].error_message); + g_clear_error (&error); + } + + g_assert_cmpint (res, ==, csim_response_test_list[i].result); + } +} + /*****************************************************************************/ typedef struct { @@ -3932,6 +3989,8 @@ int main (int argc, char **argv) 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_csim_response, NULL)); + g_test_suite_add (suite, TESTCASE (test_cesq_response, NULL)); g_test_suite_add (suite, TESTCASE (test_cesq_response_to_signal, NULL)); |