modem-helpers,sim: auto-detect if ICCID response is character swapped

This patch modifies mm_3gpp_parse_iccid() to auto-detect if an ICCID
response is character swapped or not by comparsing the major industry
identifier part of the ICCID response to the known value (89) for
telecommunication purposes. This addresses the issue where the same AT
command (e.g. AT^ICCID used by the huawei plugin) does not report ICCID
in a consistent format.
This commit is contained in:
Ben Chan
2013-09-26 11:07:16 -07:00
committed by Aleksander Morgado
parent b786ac0deb
commit b5ef861d12
6 changed files with 52 additions and 14 deletions

View File

@@ -87,8 +87,7 @@ iccid_read_ready (MMBaseModem *modem,
if (!p) if (!p)
goto error; goto error;
/* Huawei ^ICCID response must be character swapped */ parsed = mm_3gpp_parse_iccid (p, NULL);
parsed = mm_3gpp_parse_iccid (p, TRUE, NULL);
if (parsed) { if (parsed) {
g_simple_async_result_set_op_res_gpointer (simple, parsed, g_free); g_simple_async_result_set_op_res_gpointer (simple, parsed, g_free);
g_simple_async_result_complete (simple); g_simple_async_result_complete (simple);

View File

@@ -82,8 +82,7 @@ iccid_read_ready (MMBaseModem *modem,
return; return;
} }
/* Sierra !ICCID response is already character swapped */ parsed = mm_3gpp_parse_iccid (p, &local);
parsed = mm_3gpp_parse_iccid (p, FALSE, &local);
if (parsed) if (parsed)
g_simple_async_result_set_op_res_gpointer (simple, parsed, g_free); g_simple_async_result_set_op_res_gpointer (simple, parsed, g_free);
else else

View File

@@ -1892,8 +1892,9 @@ mm_3gpp_get_ip_family_from_pdp_type (const gchar *pdp_type)
/*************************************************************************/ /*************************************************************************/
char * char *
mm_3gpp_parse_iccid (const char *raw_iccid, gboolean swap, GError **error) mm_3gpp_parse_iccid (const char *raw_iccid, GError **error)
{ {
gboolean swap;
char *buf, *swapped = NULL; char *buf, *swapped = NULL;
gsize len = 0; gsize len = 0;
int f_pos = -1, i; int f_pos = -1, i;
@@ -1934,6 +1935,22 @@ mm_3gpp_parse_iccid (const char *raw_iccid, gboolean swap, GError **error)
goto error; goto error;
} }
/* The leading two digits of an ICCID is the major industry identifier and
* should be '89' for telecommunication purposes according to ISO/IEC 7812.
*/
if (buf[0] == '8' && buf[1] == '9') {
swap = FALSE;
} else if (buf[0] == '9' && buf[1] == '8') {
swap = TRUE;
} else {
/* FIXME: Instead of erroring out, revisit this solution if we find any SIM
* that doesn't use '89' as the major industry identifier of the ICCID.
*/
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
"Invalid ICCID response (leading two digits are not 89)");
goto error;
}
/* Ensure if there's an 'F' that it's second-to-last if swap = TRUE, /* Ensure if there's an 'F' that it's second-to-last if swap = TRUE,
* otherwise last if swap = FALSE */ * otherwise last if swap = FALSE */
if (f_pos >= 0) { if (f_pos >= 0) {

View File

@@ -204,7 +204,7 @@ gboolean mm_3gpp_parse_operator_id (const gchar *operator_id,
const gchar *mm_3gpp_get_pdp_type_from_ip_family (MMBearerIpFamily family); const gchar *mm_3gpp_get_pdp_type_from_ip_family (MMBearerIpFamily family);
MMBearerIpFamily mm_3gpp_get_ip_family_from_pdp_type (const gchar *pdp_type); MMBearerIpFamily mm_3gpp_get_ip_family_from_pdp_type (const gchar *pdp_type);
char *mm_3gpp_parse_iccid (const char *raw_iccid, gboolean swap, GError **error); char *mm_3gpp_parse_iccid (const char *raw_iccid, GError **error);
/*****************************************************************************/ /*****************************************************************************/
/* CDMA specific helpers and utilities */ /* CDMA specific helpers and utilities */

View File

@@ -973,8 +973,7 @@ parse_iccid (const gchar *response,
(sw1 == 0x91) || (sw1 == 0x91) ||
(sw1 == 0x92) || (sw1 == 0x92) ||
(sw1 == 0x9f)) { (sw1 == 0x9f)) {
/* +CRSM response must be character-swapped */ return mm_3gpp_parse_iccid (buf, error);
return mm_3gpp_parse_iccid (buf, TRUE, error);
} else { } else {
g_set_error (error, g_set_error (error,
MM_CORE_ERROR, MM_CORE_ERROR,

View File

@@ -1533,7 +1533,7 @@ test_iccid_parse_quoted_swap_19_digit (void *f, gpointer d)
char *parsed; char *parsed;
GError *error = NULL; GError *error = NULL;
parsed = mm_3gpp_parse_iccid (raw_iccid, TRUE, &error); parsed = mm_3gpp_parse_iccid (raw_iccid, &error);
g_assert_no_error (error); g_assert_no_error (error);
g_assert_cmpstr (parsed, ==, expected); g_assert_cmpstr (parsed, ==, expected);
} }
@@ -1546,7 +1546,7 @@ test_iccid_parse_unquoted_swap_20_digit (void *f, gpointer d)
char *parsed; char *parsed;
GError *error = NULL; GError *error = NULL;
parsed = mm_3gpp_parse_iccid (raw_iccid, TRUE, &error); parsed = mm_3gpp_parse_iccid (raw_iccid, &error);
g_assert_no_error (error); g_assert_no_error (error);
g_assert_cmpstr (parsed, ==, expected); g_assert_cmpstr (parsed, ==, expected);
} }
@@ -1559,7 +1559,7 @@ test_iccid_parse_unquoted_unswapped_19_digit (void *f, gpointer d)
char *parsed; char *parsed;
GError *error = NULL; GError *error = NULL;
parsed = mm_3gpp_parse_iccid (raw_iccid, FALSE, &error); parsed = mm_3gpp_parse_iccid (raw_iccid, &error);
g_assert_no_error (error); g_assert_no_error (error);
g_assert_cmpstr (parsed, ==, expected); g_assert_cmpstr (parsed, ==, expected);
} }
@@ -1572,7 +1572,7 @@ test_iccid_parse_quoted_unswapped_20_digit (void *f, gpointer d)
char *parsed; char *parsed;
GError *error = NULL; GError *error = NULL;
parsed = mm_3gpp_parse_iccid (raw_iccid, FALSE, &error); parsed = mm_3gpp_parse_iccid (raw_iccid, &error);
g_assert_no_error (error); g_assert_no_error (error);
g_assert_cmpstr (parsed, ==, expected); g_assert_cmpstr (parsed, ==, expected);
} }
@@ -1584,7 +1584,7 @@ test_iccid_parse_short (void *f, gpointer d)
char *parsed; char *parsed;
GError *error = NULL; GError *error = NULL;
parsed = mm_3gpp_parse_iccid (raw_iccid, TRUE, &error); parsed = mm_3gpp_parse_iccid (raw_iccid, &error);
g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED); g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED);
} }
@@ -1595,7 +1595,29 @@ test_iccid_parse_invalid_chars (void *f, gpointer d)
char *parsed; char *parsed;
GError *error = NULL; GError *error = NULL;
parsed = mm_3gpp_parse_iccid (raw_iccid, TRUE, &error); parsed = mm_3gpp_parse_iccid (raw_iccid, &error);
g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED);
}
static void
test_iccid_parse_quoted_invalid_mii (void *f, gpointer d)
{
const char *raw_iccid = "\"0044200053671052499\"";
char *parsed;
GError *error = NULL;
parsed = mm_3gpp_parse_iccid (raw_iccid, &error);
g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED);
}
static void
test_iccid_parse_unquoted_invalid_mii (void *f, gpointer d)
{
const char *raw_iccid = "0044200053671052499";
char *parsed;
GError *error = NULL;
parsed = mm_3gpp_parse_iccid (raw_iccid, &error);
g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED); g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED);
} }
@@ -2398,6 +2420,8 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_iccid_parse_quoted_unswapped_20_digit, NULL)); g_test_suite_add (suite, TESTCASE (test_iccid_parse_quoted_unswapped_20_digit, NULL));
g_test_suite_add (suite, TESTCASE (test_iccid_parse_short, NULL)); g_test_suite_add (suite, TESTCASE (test_iccid_parse_short, NULL));
g_test_suite_add (suite, TESTCASE (test_iccid_parse_invalid_chars, NULL)); g_test_suite_add (suite, TESTCASE (test_iccid_parse_invalid_chars, NULL));
g_test_suite_add (suite, TESTCASE (test_iccid_parse_quoted_invalid_mii, NULL));
g_test_suite_add (suite, TESTCASE (test_iccid_parse_unquoted_invalid_mii, NULL));
while (item->devid) { while (item->devid) {
g_test_suite_add (suite, TESTCASE (test_devid_item, (gconstpointer) item)); g_test_suite_add (suite, TESTCASE (test_devid_item, (gconstpointer) item));