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:

committed by
Aleksander Morgado

parent
a33615d6cb
commit
95876c6f57
@@ -944,36 +944,27 @@ static gchar *
|
|||||||
parse_iccid (const gchar *response,
|
parse_iccid (const gchar *response,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
gchar buf[21];
|
guint sw1 = 0;
|
||||||
const gchar *str;
|
guint sw2 = 0;
|
||||||
gint sw1;
|
gchar *hex = 0;
|
||||||
gint sw2;
|
gchar *ret;
|
||||||
gboolean success = FALSE;
|
|
||||||
|
|
||||||
memset (buf, 0, sizeof (buf));
|
if (!mm_3gpp_parse_crsm_response (response,
|
||||||
str = mm_strip_tag (response, "+CRSM:");
|
&sw1,
|
||||||
if (sscanf (str, "%d,%d,\"%20c\"", &sw1, &sw2, (char *) &buf) == 3)
|
&sw2,
|
||||||
success = TRUE;
|
&hex,
|
||||||
else {
|
error))
|
||||||
/* 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");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
if ((sw1 == 0x90 && sw2 == 0x00) ||
|
if ((sw1 == 0x90 && sw2 == 0x00) ||
|
||||||
(sw1 == 0x91) ||
|
(sw1 == 0x91) ||
|
||||||
(sw1 == 0x92) ||
|
(sw1 == 0x92) ||
|
||||||
(sw1 == 0x9f)) {
|
(sw1 == 0x9f)) {
|
||||||
return mm_3gpp_parse_iccid (buf, error);
|
ret = mm_3gpp_parse_iccid (hex, error);
|
||||||
|
g_free (hex);
|
||||||
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
|
g_free (hex);
|
||||||
g_set_error (error,
|
g_set_error (error,
|
||||||
MM_CORE_ERROR,
|
MM_CORE_ERROR,
|
||||||
MM_CORE_ERROR_FAILED,
|
MM_CORE_ERROR_FAILED,
|
||||||
@@ -1101,27 +1092,16 @@ static guint
|
|||||||
parse_mnc_length (const gchar *response,
|
parse_mnc_length (const gchar *response,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
gint sw1;
|
guint sw1 = 0;
|
||||||
gint sw2;
|
guint sw2 = 0;
|
||||||
gboolean success = FALSE;
|
gchar *hex = 0;
|
||||||
gchar hex[51];
|
|
||||||
|
|
||||||
memset (hex, 0, sizeof (hex));
|
if (!mm_3gpp_parse_crsm_response (response,
|
||||||
if (sscanf (response, "+CRSM:%d,%d,\"%50c\"", &sw1, &sw2, (char *) &hex) == 3)
|
&sw1,
|
||||||
success = TRUE;
|
&sw2,
|
||||||
else {
|
&hex,
|
||||||
/* May not include quotes... */
|
error))
|
||||||
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");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
if ((sw1 == 0x90 && sw2 == 0x00) ||
|
if ((sw1 == 0x90 && sw2 == 0x00) ||
|
||||||
(sw1 == 0x91) ||
|
(sw1 == 0x91) ||
|
||||||
@@ -1131,15 +1111,6 @@ parse_mnc_length (const gchar *response,
|
|||||||
guint32 mnc_len;
|
guint32 mnc_len;
|
||||||
gchar *bin;
|
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 */
|
/* Convert hex string to binary */
|
||||||
bin = mm_utils_hexstr2bin (hex, &buflen);
|
bin = mm_utils_hexstr2bin (hex, &buflen);
|
||||||
if (!bin || buflen < 4) {
|
if (!bin || buflen < 4) {
|
||||||
@@ -1149,9 +1120,12 @@ parse_mnc_length (const gchar *response,
|
|||||||
"SIM returned malformed response '%s'",
|
"SIM returned malformed response '%s'",
|
||||||
hex);
|
hex);
|
||||||
g_free (bin);
|
g_free (bin);
|
||||||
|
g_free (hex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_free (hex);
|
||||||
|
|
||||||
/* MNC length is byte 4 of this SIM file */
|
/* MNC length is byte 4 of this SIM file */
|
||||||
mnc_len = bin[3] & 0xFF;
|
mnc_len = bin[3] & 0xFF;
|
||||||
if (mnc_len == 2 || mnc_len == 3) {
|
if (mnc_len == 2 || mnc_len == 3) {
|
||||||
@@ -1168,6 +1142,7 @@ parse_mnc_length (const gchar *response,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_free (hex);
|
||||||
g_set_error (error,
|
g_set_error (error,
|
||||||
MM_CORE_ERROR,
|
MM_CORE_ERROR,
|
||||||
MM_CORE_ERROR_FAILED,
|
MM_CORE_ERROR_FAILED,
|
||||||
@@ -1238,27 +1213,16 @@ static gchar *
|
|||||||
parse_spn (const gchar *response,
|
parse_spn (const gchar *response,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
gint sw1;
|
guint sw1 = 0;
|
||||||
gint sw2;
|
guint sw2 = 0;
|
||||||
gboolean success = FALSE;
|
gchar *hex = 0;
|
||||||
gchar hex[51];
|
|
||||||
|
|
||||||
memset (hex, 0, sizeof (hex));
|
if (!mm_3gpp_parse_crsm_response (response,
|
||||||
if (sscanf (response, "+CRSM:%d,%d,\"%50c\"", &sw1, &sw2, (char *) &hex) == 3)
|
&sw1,
|
||||||
success = TRUE;
|
&sw2,
|
||||||
else {
|
&hex,
|
||||||
/* May not include quotes... */
|
error))
|
||||||
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");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
if ((sw1 == 0x90 && sw2 == 0x00) ||
|
if ((sw1 == 0x90 && sw2 == 0x00) ||
|
||||||
(sw1 == 0x91) ||
|
(sw1 == 0x91) ||
|
||||||
@@ -1268,15 +1232,6 @@ parse_spn (const gchar *response,
|
|||||||
gchar *bin;
|
gchar *bin;
|
||||||
gchar *utf8;
|
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 */
|
/* Convert hex string to binary */
|
||||||
bin = mm_utils_hexstr2bin (hex, &buflen);
|
bin = mm_utils_hexstr2bin (hex, &buflen);
|
||||||
if (!bin) {
|
if (!bin) {
|
||||||
@@ -1285,9 +1240,12 @@ parse_spn (const gchar *response,
|
|||||||
MM_CORE_ERROR_FAILED,
|
MM_CORE_ERROR_FAILED,
|
||||||
"SIM returned malformed response '%s'",
|
"SIM returned malformed response '%s'",
|
||||||
hex);
|
hex);
|
||||||
|
g_free (hex);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_free (hex);
|
||||||
|
|
||||||
/* Remove the FF filler at the end */
|
/* Remove the FF filler at the end */
|
||||||
while (buflen > 1 && bin[buflen - 1] == (char)0xff)
|
while (buflen > 1 && bin[buflen - 1] == (char)0xff)
|
||||||
buflen--;
|
buflen--;
|
||||||
@@ -1298,6 +1256,7 @@ parse_spn (const gchar *response,
|
|||||||
return utf8;
|
return utf8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_free (hex);
|
||||||
g_set_error (error,
|
g_set_error (error,
|
||||||
MM_CORE_ERROR,
|
MM_CORE_ERROR,
|
||||||
MM_CORE_ERROR_FAILED,
|
MM_CORE_ERROR_FAILED,
|
||||||
|
@@ -1342,6 +1342,57 @@ done:
|
|||||||
return info;
|
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
|
static MMSmsStorage
|
||||||
|
@@ -203,6 +203,14 @@ MM3gppPduInfo *mm_3gpp_parse_cmgr_read_response (const gchar *reply,
|
|||||||
guint index,
|
guint index,
|
||||||
GError **error);
|
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 */
|
/* Additional 3GPP-specific helpers */
|
||||||
|
|
||||||
MMModem3gppFacility mm_3gpp_acronym_to_facility (const gchar *str);
|
MMModem3gppFacility mm_3gpp_acronym_to_facility (const gchar *str);
|
||||||
|
@@ -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
|
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_cclk_response, NULL));
|
||||||
|
|
||||||
|
g_test_suite_add (suite, TESTCASE (test_crsm_response, NULL));
|
||||||
|
|
||||||
result = g_test_run ();
|
result = g_test_run ();
|
||||||
|
|
||||||
reg_test_data_free (reg_data);
|
reg_test_data_free (reg_data);
|
||||||
|
Reference in New Issue
Block a user