diff options
author | Dan Williams <dan@ioncontrol.co> | 2025-05-15 10:21:13 -0500 |
---|---|---|
committer | Dan Williams <dan@ioncontrol.co> | 2025-05-23 08:31:04 -0500 |
commit | 5c1fcbfe4a6ee9e89f8b859e26d7d0f74106178d (patch) | |
tree | 7df1d08d24db68b12b202d7bf2f658e0c8787b69 | |
parent | 757df26b295a9b9306fe3278b7f3730cc3a9c703 (diff) |
mtk-legacy: read IMSI if CPIN response is an error
Some older MTK-based phones (Tecno T528 NEW) reply to +CPIN with
an error but are (obviously) unlocked, otherwise they wouldn't
be able to boot up to the point of talking to a computer. Since
they are actually unlocked they will happily give out the IMSI
even if +CPIN errors.
To work around the +CPIN issue treat the device as unlocked if we
can successfully read the IMSI.
Fixes: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/980
Signed-off-by: Dan Williams <dan@ioncontrol.co>
-rw-r--r-- | src/plugins/mtk/mm-broadband-modem-mtk-legacy.c | 97 |
1 files changed, 97 insertions, 0 deletions
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; |