helpers: move +CRSM parsing to mm_3gpp_parse_crsm_response

Also added test cases.

Signed-off-by: Thomas Sailer <t.sailer@alumni.ethz.ch>
This commit is contained in:
Thomas Sailer
2016-02-13 14:19:13 +01:00
committed by Aleksander Morgado
parent a33615d6cb
commit 95876c6f57
4 changed files with 150 additions and 78 deletions

View File

@@ -944,36 +944,27 @@ static gchar *
parse_iccid (const gchar *response,
GError **error)
{
gchar buf[21];
const gchar *str;
gint sw1;
gint sw2;
gboolean success = FALSE;
guint sw1 = 0;
guint sw2 = 0;
gchar *hex = 0;
gchar *ret;
memset (buf, 0, sizeof (buf));
str = mm_strip_tag (response, "+CRSM:");
if (sscanf (str, "%d,%d,\"%20c\"", &sw1, &sw2, (char *) &buf) == 3)
success = TRUE;
else {
/* May not include quotes... */
if (sscanf (str, "%d,%d,%20c", &sw1, &sw2, (char *) &buf) == 3)
success = TRUE;
}
if (!success) {
g_set_error (error,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Could not parse the CRSM response");
if (!mm_3gpp_parse_crsm_response (response,
&sw1,
&sw2,
&hex,
error))
return NULL;
}
if ((sw1 == 0x90 && sw2 == 0x00) ||
(sw1 == 0x91) ||
(sw1 == 0x92) ||
(sw1 == 0x9f)) {
return mm_3gpp_parse_iccid (buf, error);
ret = mm_3gpp_parse_iccid (hex, error);
g_free (hex);
return ret;
} else {
g_free (hex);
g_set_error (error,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
@@ -1101,27 +1092,16 @@ static guint
parse_mnc_length (const gchar *response,
GError **error)
{
gint sw1;
gint sw2;
gboolean success = FALSE;
gchar hex[51];
guint sw1 = 0;
guint sw2 = 0;
gchar *hex = 0;
memset (hex, 0, sizeof (hex));
if (sscanf (response, "+CRSM:%d,%d,\"%50c\"", &sw1, &sw2, (char *) &hex) == 3)
success = TRUE;
else {
/* May not include quotes... */
if (sscanf (response, "+CRSM:%d,%d,%50c", &sw1, &sw2, (char *) &hex) == 3)
success = TRUE;
}
if (!success) {
g_set_error (error,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Could not parse the CRSM response");
if (!mm_3gpp_parse_crsm_response (response,
&sw1,
&sw2,
&hex,
error))
return 0;
}
if ((sw1 == 0x90 && sw2 == 0x00) ||
(sw1 == 0x91) ||
@@ -1131,15 +1111,6 @@ parse_mnc_length (const gchar *response,
guint32 mnc_len;
gchar *bin;
/* Make sure the buffer is only hex characters */
while (buflen < sizeof (hex) && hex[buflen]) {
if (!isxdigit (hex[buflen])) {
hex[buflen] = 0x0;
break;
}
buflen++;
}
/* Convert hex string to binary */
bin = mm_utils_hexstr2bin (hex, &buflen);
if (!bin || buflen < 4) {
@@ -1149,9 +1120,12 @@ parse_mnc_length (const gchar *response,
"SIM returned malformed response '%s'",
hex);
g_free (bin);
g_free (hex);
return 0;
}
g_free (hex);
/* MNC length is byte 4 of this SIM file */
mnc_len = bin[3] & 0xFF;
if (mnc_len == 2 || mnc_len == 3) {
@@ -1168,6 +1142,7 @@ parse_mnc_length (const gchar *response,
return 0;
}
g_free (hex);
g_set_error (error,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
@@ -1238,27 +1213,16 @@ static gchar *
parse_spn (const gchar *response,
GError **error)
{
gint sw1;
gint sw2;
gboolean success = FALSE;
gchar hex[51];
guint sw1 = 0;
guint sw2 = 0;
gchar *hex = 0;
memset (hex, 0, sizeof (hex));
if (sscanf (response, "+CRSM:%d,%d,\"%50c\"", &sw1, &sw2, (char *) &hex) == 3)
success = TRUE;
else {
/* May not include quotes... */
if (sscanf (response, "+CRSM:%d,%d,%50c", &sw1, &sw2, (char *) &hex) == 3)
success = TRUE;
}
if (!success) {
g_set_error (error,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Could not parse the CRSM response");
if (!mm_3gpp_parse_crsm_response (response,
&sw1,
&sw2,
&hex,
error))
return NULL;
}
if ((sw1 == 0x90 && sw2 == 0x00) ||
(sw1 == 0x91) ||
@@ -1268,15 +1232,6 @@ parse_spn (const gchar *response,
gchar *bin;
gchar *utf8;
/* Make sure the buffer is only hex characters */
while (buflen < sizeof (hex) && hex[buflen]) {
if (!isxdigit (hex[buflen])) {
hex[buflen] = 0x0;
break;
}
buflen++;
}
/* Convert hex string to binary */
bin = mm_utils_hexstr2bin (hex, &buflen);
if (!bin) {
@@ -1285,9 +1240,12 @@ parse_spn (const gchar *response,
MM_CORE_ERROR_FAILED,
"SIM returned malformed response '%s'",
hex);
g_free (hex);
return NULL;
}
g_free (hex);
/* Remove the FF filler at the end */
while (buflen > 1 && bin[buflen - 1] == (char)0xff)
buflen--;
@@ -1298,6 +1256,7 @@ parse_spn (const gchar *response,
return utf8;
}
g_free (hex);
g_set_error (error,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,

View File

@@ -1342,6 +1342,57 @@ done:
return info;
}
/*****************************************************************************/
/* AT+CRSM response parser */
gboolean
mm_3gpp_parse_crsm_response (const gchar *reply,
guint *sw1,
guint *sw2,
gchar **hex,
GError **error)
{
GRegex *r;
GMatchInfo *match_info;
g_assert (sw1 != NULL);
g_assert (sw2 != NULL);
g_assert (hex != NULL);
*sw1 = 0;
*sw2 = 0;
*hex = NULL;
if (!reply || !g_str_has_prefix (reply, "+CRSM:")) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing +CRSM prefix");
return FALSE;
}
r = g_regex_new ("\\+CRSM:\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*\"?([0-9a-fA-F]+)\"?",
G_REGEX_RAW, 0, error);
if (!r)
return FALSE;
if (g_regex_match_full (r, reply, strlen (reply), 0, 0, &match_info, NULL) &&
mm_get_uint_from_match_info (match_info, 1, sw1) &&
mm_get_uint_from_match_info (match_info, 2, sw2))
*hex = mm_get_string_unquoted_from_match_info (match_info, 3);
g_match_info_free (match_info);
g_regex_unref (r);
if (*hex == NULL) {
g_set_error (error,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Failed to parse CRSM query result '%s'",
reply);
return FALSE;
}
return TRUE;
}
/*************************************************************************/
static MMSmsStorage

View File

@@ -203,6 +203,14 @@ MM3gppPduInfo *mm_3gpp_parse_cmgr_read_response (const gchar *reply,
guint index,
GError **error);
/* AT+CRSM response parser */
gboolean mm_3gpp_parse_crsm_response (const gchar *reply,
guint *sw1,
guint *sw2,
gchar **hex,
GError **error);
/* Additional 3GPP-specific helpers */
MMModem3gppFacility mm_3gpp_acronym_to_facility (const gchar *str);

View File

@@ -2631,6 +2631,58 @@ test_cclk_response (void)
}
}
/*****************************************************************************/
/* Test +CRSM responses */
typedef struct {
const gchar *str;
gboolean ret;
guint sw1;
guint sw2;
gchar *hex;
} CrsmTest;
static const CrsmTest crsm_tests[] = {
{ "+CRSM: 144, 0, 0054485552415941FFFFFFFFFFFFFFFFFF", TRUE, 144, 0, "0054485552415941FFFFFFFFFFFFFFFFFF" },
{ "+CRSM: 144, 0,0054485552415941FFFFFFFFFFFFFFFFFF", TRUE, 144, 0, "0054485552415941FFFFFFFFFFFFFFFFFF" },
{ "+CRSM: 144, 0, \"0054485552415941FFFFFFFFFFFFFFFFFF\"", TRUE, 144, 0, "0054485552415941FFFFFFFFFFFFFFFFFF" },
{ "+CRSM: 144, 0,\"0054485552415941FFFFFFFFFFFFFFFFFF\"", TRUE, 144, 0, "0054485552415941FFFFFFFFFFFFFFFFFF" },
{ NULL, FALSE, 0, 0, NULL }
};
static void
test_crsm_response (void)
{
guint i;
for (i = 0; crsm_tests[i].str; i++) {
GError *error = NULL;
guint sw1 = 0;
guint sw2 = 0;
gchar *hex = 0;
gboolean ret;
ret = mm_3gpp_parse_crsm_response (crsm_tests[i].str,
&sw1,
&sw2,
&hex,
&error);
g_assert (ret == crsm_tests[i].ret);
g_assert (ret == (error ? FALSE : TRUE));
g_clear_error (&error);
g_assert (sw1 == crsm_tests[i].sw1);
g_assert (sw2 == crsm_tests[i].sw2);
g_assert_cmpstr (crsm_tests[i].hex, ==, hex);
g_free(hex);
}
}
/*****************************************************************************/
void
@@ -2805,6 +2857,8 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_cclk_response, NULL));
g_test_suite_add (suite, TESTCASE (test_crsm_response, NULL));
result = g_test_run ();
reg_test_data_free (reg_data);