aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dan@ioncontrol.co>2025-05-23 14:11:58 -0500
committerDan Williams <dan@ioncontrol.co>2025-05-23 14:11:58 -0500
commit9cc5582bf28ba6cc30bc000f1f759fe530b6be55 (patch)
tree7df1d08d24db68b12b202d7bf2f658e0c8787b69
parentc5a2cd3157854b9f368717f72ebc852d6d8de954 (diff)
parent5c1fcbfe4a6ee9e89f8b859e26d7d0f74106178d (diff)
Merge request !1355 from 'mtk-unlock-required'
mtk-legacy: read IMSI if CPIN response is an error https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1355 Closes #980
-rw-r--r--src/mm-broadband-modem.c61
-rw-r--r--src/mm-modem-helpers.c64
-rw-r--r--src/mm-modem-helpers.h5
-rw-r--r--src/plugins/mtk/mm-broadband-modem-mtk-legacy.c97
-rw-r--r--src/plugins/simtech/mm-broadband-modem-simtech.c39
-rw-r--r--src/tests/test-modem-helpers.c33
6 files changed, 207 insertions, 92 deletions
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index e0f277fe..3d02553d 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -1505,32 +1505,6 @@ modem_load_own_numbers (MMIfaceModem *self,
/*****************************************************************************/
/* Check if unlock required (Modem interface) */
-typedef struct {
- const gchar *result;
- MMModemLock code;
-} CPinResult;
-
-static CPinResult unlock_results[] = {
- /* Longer entries first so we catch the correct one with strcmp() */
- { "READY", MM_MODEM_LOCK_NONE },
- { "SIM PIN2", MM_MODEM_LOCK_SIM_PIN2 },
- { "SIM PUK2", MM_MODEM_LOCK_SIM_PUK2 },
- { "SIM PIN", MM_MODEM_LOCK_SIM_PIN },
- { "SIM PUK", MM_MODEM_LOCK_SIM_PUK },
- { "PH-NETSUB PIN", MM_MODEM_LOCK_PH_NETSUB_PIN },
- { "PH-NETSUB PUK", MM_MODEM_LOCK_PH_NETSUB_PUK },
- { "PH-FSIM PIN", MM_MODEM_LOCK_PH_FSIM_PIN },
- { "PH-FSIM PUK", MM_MODEM_LOCK_PH_FSIM_PUK },
- { "PH-CORP PIN", MM_MODEM_LOCK_PH_CORP_PIN },
- { "PH-CORP PUK", MM_MODEM_LOCK_PH_CORP_PUK },
- { "PH-SIM PIN", MM_MODEM_LOCK_PH_SIM_PIN },
- { "PH-NET PIN", MM_MODEM_LOCK_PH_NET_PIN },
- { "PH-NET PUK", MM_MODEM_LOCK_PH_NET_PUK },
- { "PH-SP PIN", MM_MODEM_LOCK_PH_SP_PIN },
- { "PH-SP PUK", MM_MODEM_LOCK_PH_SP_PUK },
- { NULL }
-};
-
static MMModemLock
modem_load_unlock_required_finish (MMIfaceModem *self,
GAsyncResult *res,
@@ -1553,42 +1527,19 @@ cpin_query_ready (MMIfaceModem *self,
GTask *task)
{
- MMModemLock lock = MM_MODEM_LOCK_UNKNOWN;
+ MMModemLock lock = MM_MODEM_LOCK_UNKNOWN;
const gchar *result;
- GError *error = NULL;
+ GError *error = NULL;
result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
if (error) {
g_task_return_error (task, error);
- g_object_unref (task);
- return;
- }
-
- if (result &&
- strstr (result, "+CPIN:")) {
- CPinResult *iter = &unlock_results[0];
- const gchar *str;
-
- str = strstr (result, "+CPIN:") + 6;
- /* Skip possible whitespaces after '+CPIN:' and before the response */
- while (*str == ' ')
- str++;
-
- /* Some phones (Motorola EZX models) seem to quote the response */
- if (str[0] == '"')
- str++;
-
- /* Translate the reply */
- while (iter->result) {
- if (g_str_has_prefix (str, iter->result)) {
- lock = iter->code;
- break;
- }
- iter++;
- }
+ } else {
+ if (result)
+ lock = mm_parse_cpin_response (result, TRUE);
+ g_task_return_int (task, lock);
}
- g_task_return_int (task, lock);
g_object_unref (task);
}
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index d69951be..a79ca956 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -5807,3 +5807,67 @@ mm_string_uint_map_lookup (const MMStringUintMap *map,
}
return default_value;
}
+
+/*****************************************************************************/
+
+typedef struct {
+ const gchar *result;
+ const MMModemLock code;
+} CPinResult;
+
+static const CPinResult unlock_results[] = {
+ /* Longer entries first so we catch the correct one with strcmp() */
+ { "READY", MM_MODEM_LOCK_NONE },
+ { "SIM PIN2", MM_MODEM_LOCK_SIM_PIN2 },
+ { "SIM PUK2", MM_MODEM_LOCK_SIM_PUK2 },
+ { "SIM PIN", MM_MODEM_LOCK_SIM_PIN },
+ { "SIM PUK", MM_MODEM_LOCK_SIM_PUK },
+ { "PH-NETSUB PIN", MM_MODEM_LOCK_PH_NETSUB_PIN },
+ { "PH-NETSUB PUK", MM_MODEM_LOCK_PH_NETSUB_PUK },
+ { "PH-FSIM PIN", MM_MODEM_LOCK_PH_FSIM_PIN },
+ { "PH-FSIM PUK", MM_MODEM_LOCK_PH_FSIM_PUK },
+ { "PH-CORP PIN", MM_MODEM_LOCK_PH_CORP_PIN },
+ { "PH-CORP PUK", MM_MODEM_LOCK_PH_CORP_PUK },
+ { "PH-SIM PIN", MM_MODEM_LOCK_PH_SIM_PIN },
+ { "PH-NET PIN", MM_MODEM_LOCK_PH_NET_PIN },
+ { "PH-NET PUK", MM_MODEM_LOCK_PH_NET_PUK },
+ { "PH-SP PIN", MM_MODEM_LOCK_PH_SP_PIN },
+ { "PH-SP PUK", MM_MODEM_LOCK_PH_SP_PUK },
+ { NULL }
+};
+
+MMModemLock
+mm_parse_cpin_response (const gchar *response,
+ gboolean expect_cpin_prefix)
+{
+ const CPinResult *iter = &unlock_results[0];
+
+ if (expect_cpin_prefix) {
+ const gchar *p;
+
+ p = strstr (response, "+CPIN:");
+ if (!p)
+ return MM_MODEM_LOCK_UNKNOWN;
+
+ /* Advance past the +CPIN: */
+ response = p + 6;
+ }
+
+ /* Skip possible whitespaces after '+CPIN:' and before the response */
+ while (*response == ' ')
+ response++;
+
+ /* Some phones (Motorola EZX models) seem to quote the response */
+ if (response[0] == '"')
+ response++;
+
+ /* Translate the reply */
+ while (iter->result) {
+ if (g_str_has_prefix (response, iter->result)) {
+ return iter->code;
+ }
+ iter++;
+ }
+
+ return MM_MODEM_LOCK_UNKNOWN;
+}
diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h
index 73203c8b..eb62a551 100644
--- a/src/mm-modem-helpers.h
+++ b/src/mm-modem-helpers.h
@@ -638,4 +638,9 @@ guint mm_string_uint_map_lookup (const MMStringUintMap *map,
const gchar *str,
const guint default_value);
+/*****************************************************************************/
+
+MMModemLock mm_parse_cpin_response (const gchar *response,
+ gboolean expect_cpin_prefix);
+
#endif /* MM_MODEM_HELPERS_H */
diff --git a/src/plugins/mtk/mm-broadband-modem-mtk-legacy.c b/src/plugins/mtk/mm-broadband-modem-mtk-legacy.c
index 36121d0e..fe1f48cb 100644
--- a/src/plugins/mtk/mm-broadband-modem-mtk-legacy.c
+++ b/src/plugins/mtk/mm-broadband-modem-mtk-legacy.c
@@ -55,6 +55,101 @@ struct _MMBroadbandModemMtkLegacyPrivate {
};
/*****************************************************************************/
+/* Check unlock required (Modem interface) */
+
+static MMModemLock
+load_unlock_required_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ GError *inner_error = NULL;
+ gssize value;
+
+ value = g_task_propagate_int (G_TASK (res), &inner_error);
+ if (inner_error) {
+ g_propagate_error (error, inner_error);
+ return MM_MODEM_LOCK_UNKNOWN;
+ }
+ return (MMModemLock)value;
+}
+
+static void
+unlock_required_cimi_query_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GError *error = NULL;
+
+ mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
+ if (error)
+ g_task_return_error (task, error);
+ else {
+ /* Assume unlocked if we can successfully read the IMSI */
+ g_task_return_int (task, MM_MODEM_LOCK_NONE);
+ }
+ g_object_unref (task);
+}
+
+static void
+cpin_query_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ MMModemLock lock = MM_MODEM_LOCK_UNKNOWN;
+ const gchar *result;
+ GError *error = NULL;
+
+ result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
+ if (error) {
+ /* Some older MTK-based phones reply to +CPIN with CME ERROR 100,
+ * but to even boot up they require the SIM PIN and so must be
+ * unlocked. Double-check by reading the IMSI though.
+ */
+ if (g_error_matches (error,
+ MM_MOBILE_EQUIPMENT_ERROR,
+ MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN)) {
+ mm_base_modem_at_command (MM_BASE_MODEM (self),
+ "+CIMI",
+ 10,
+ FALSE,
+ (GAsyncReadyCallback)unlock_required_cimi_query_ready,
+ task);
+ return;
+ }
+
+ /* Otherwise just return the error */
+ g_task_return_error (task, error);
+ } else {
+ if (result)
+ lock = mm_parse_cpin_response (result, TRUE);
+ g_task_return_int (task, lock);
+ }
+
+ g_object_unref (task);
+}
+
+static void
+load_unlock_required (MMIfaceModem *self,
+ gboolean last_attempt,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+
+ mm_obj_dbg (self, "checking if unlock required...");
+ mm_base_modem_at_command (MM_BASE_MODEM (self),
+ "+CPIN?",
+ 10,
+ FALSE,
+ (GAsyncReadyCallback)cpin_query_ready,
+ task);
+}
+
+/*****************************************************************************/
+
static gboolean
modem_after_sim_unlock_finish (MMIfaceModem *self,
GAsyncResult *res,
@@ -835,6 +930,8 @@ iface_modem_init (MMIfaceModemInterface *iface)
{
iface_modem_parent = g_type_interface_peek_parent (iface);
+ iface->load_unlock_required = load_unlock_required;
+ iface->load_unlock_required_finish = load_unlock_required_finish;
iface->modem_after_sim_unlock = modem_after_sim_unlock;
iface->modem_after_sim_unlock_finish = modem_after_sim_unlock_finish;
iface->load_supported_modes = load_supported_modes;
diff --git a/src/plugins/simtech/mm-broadband-modem-simtech.c b/src/plugins/simtech/mm-broadband-modem-simtech.c
index cdc822d8..a390a88f 100644
--- a/src/plugins/simtech/mm-broadband-modem-simtech.c
+++ b/src/plugins/simtech/mm-broadband-modem-simtech.c
@@ -72,31 +72,6 @@ struct _MMBroadbandModemSimtechPrivate {
MMModemLock sim_lock;
};
-typedef struct {
- const gchar *result;
- MMModemLock code;
-} CPinResult;
-
-static CPinResult unlock_results[] = {
- { "READY", MM_MODEM_LOCK_NONE },
- { "SIM PIN2", MM_MODEM_LOCK_SIM_PIN2 },
- { "SIM PUK2", MM_MODEM_LOCK_SIM_PUK2 },
- { "SIM PIN", MM_MODEM_LOCK_SIM_PIN },
- { "SIM PUK", MM_MODEM_LOCK_SIM_PUK },
- { "PH-NETSUB PIN", MM_MODEM_LOCK_PH_NETSUB_PIN },
- { "PH-NETSUB PUK", MM_MODEM_LOCK_PH_NETSUB_PUK },
- { "PH-FSIM PIN", MM_MODEM_LOCK_PH_FSIM_PIN },
- { "PH-FSIM PUK", MM_MODEM_LOCK_PH_FSIM_PUK },
- { "PH-CORP PIN", MM_MODEM_LOCK_PH_CORP_PIN },
- { "PH-CORP PUK", MM_MODEM_LOCK_PH_CORP_PUK },
- { "PH-SIM PIN", MM_MODEM_LOCK_PH_SIM_PIN },
- { "PH-NET PIN", MM_MODEM_LOCK_PH_NET_PIN },
- { "PH-NET PUK", MM_MODEM_LOCK_PH_NET_PUK },
- { "PH-SP PIN", MM_MODEM_LOCK_PH_SP_PIN },
- { "PH-SP PUK", MM_MODEM_LOCK_PH_SP_PUK },
- { NULL }
-};
-
/*****************************************************************************/
/* Setup/Cleanup unsolicited events (3GPP interface) */
@@ -158,20 +133,10 @@ simtech_cpin_changed (MMPortSerialAt *port,
MMBroadbandModemSimtech *self)
{
g_autofree gchar *str = NULL;
- CPinResult *iter;
str = mm_get_string_unquoted_from_match_info (match_info, 1);
- if (str) {
- iter = &unlock_results[0];
- /* Translate the reply */
- while (iter->result) {
- if (g_str_has_prefix (str, iter->result)) {
- self->priv->sim_lock = iter->code;
- return;
- }
- iter++;
- }
- }
+ if (str)
+ self->priv->sim_lock = mm_parse_cpin_response (str, FALSE);
}
static void
diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c
index a3a42ad8..3421921b 100644
--- a/src/tests/test-modem-helpers.c
+++ b/src/tests/test-modem-helpers.c
@@ -5089,6 +5089,37 @@ test_string_to_access_tech (void)
/*****************************************************************************/
+typedef struct {
+ const gchar *str;
+ const gboolean expect_prefix;
+ const MMModemLock expected_lock;
+} TestCpinResponse;
+
+static const TestCpinResponse test_cpin_responses[] = {
+ { "+CME ERROR: 100", TRUE, MM_MODEM_LOCK_UNKNOWN },
+ { "+CPIN: SIM PIN", TRUE, MM_MODEM_LOCK_SIM_PIN },
+ { "+CPIN: SIM PUK2", TRUE, MM_MODEM_LOCK_SIM_PUK2 },
+ { " SIM PUK", FALSE, MM_MODEM_LOCK_SIM_PUK },
+ { " SIM PUK2", FALSE, MM_MODEM_LOCK_SIM_PUK2 },
+ { "+CPIN: \"SIM PIN\"", TRUE, MM_MODEM_LOCK_SIM_PIN },
+ { "+CPIN: PH-NET PIN", TRUE, MM_MODEM_LOCK_PH_NET_PIN },
+};
+
+static void
+test_cpin_response (void)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (test_cpin_responses); i++) {
+ MMModemLock lock;
+
+ lock = mm_parse_cpin_response (test_cpin_responses[i].str, test_cpin_responses[i].expect_prefix);
+ g_assert_cmpint (lock, ==, test_cpin_responses[i].expected_lock);
+ }
+}
+
+/*****************************************************************************/
+
#define TESTCASE(t, d) g_test_create_case (#t, 0, d, NULL, (GTestFixtureFunc) t, NULL)
int main (int argc, char **argv)
@@ -5351,6 +5382,8 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_string_to_access_tech, NULL));
+ g_test_suite_add (suite, TESTCASE (test_cpin_response, NULL));
+
result = g_test_run ();
reg_test_data_free (reg_data);