aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2016-01-30 20:14:23 -0800
committerAleksander Morgado <aleksander@aleksander.es>2016-02-11 10:51:43 +0100
commit7ded4f3c3be0a437d39777f38dfd58df4b570c07 (patch)
tree384ab8f7df7b8857422428bb101ba2f39d2b3cf0 /src
parent6a675536d678d1855859b5d5dd07fe22e0ceef88 (diff)
broadband-modem-qmi: implement unlock retries loading with UIM service
Newer modems like the MC7455 don't implement the "DMS UIM" commands in the DMS service, and therefore these modems need to use the UIM service directly.
Diffstat (limited to 'src')
-rw-r--r--src/mm-broadband-modem-qmi.c357
1 files changed, 236 insertions, 121 deletions
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index b5cf403f..bd6e2a8b 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -1467,13 +1467,16 @@ modem_load_unlock_required_finish (MMIfaceModem *self,
static void load_unlock_required_context_step (LoadUnlockRequiredContext *ctx);
-static void
-uim_get_card_status_ready (QmiClientUim *client,
- GAsyncResult *res,
- LoadUnlockRequiredContext *ctx)
+/* Used also when loading unlock retries left */
+static gboolean
+uim_get_card_status_output_parse (QmiMessageUimGetCardStatusOutput *output,
+ MMModemLock *o_lock,
+ guint *o_pin1_retries,
+ guint *o_puk1_retries,
+ guint *o_pin2_retries,
+ guint *o_puk2_retries,
+ GError **error)
{
- QmiMessageUimGetCardStatusOutput *output;
- GError *error = NULL;
GArray *cards;
QmiMessageUimGetCardStatusOutputCardStatusCardsElement *card;
QmiMessageUimGetCardStatusOutputCardStatusCardsElementApplicationsElement *app;
@@ -1489,20 +1492,9 @@ uim_get_card_status_ready (QmiClientUim *client,
* purposes, we're going to consider as the SIM to use the first card present
* with a SIM/USIM application. */
- output = qmi_client_uim_get_card_status_finish (client, res, &error);
- if (!output) {
- g_prefix_error (&error, "QMI operation failed: ");
- g_simple_async_result_take_error (ctx->result, error);
- load_unlock_required_context_complete_and_free (ctx);
- return;
- }
-
- if (!qmi_message_uim_get_card_status_output_get_result (output, &error)) {
- g_prefix_error (&error, "QMI operation failed: ");
- g_simple_async_result_take_error (ctx->result, error);
- qmi_message_uim_get_card_status_output_unref (output);
- load_unlock_required_context_complete_and_free (ctx);
- return;
+ if (!qmi_message_uim_get_card_status_output_get_result (output, error)) {
+ g_prefix_error (error, "QMI operation failed: ");
+ return FALSE;
}
qmi_message_uim_get_card_status_output_get_card_status (
@@ -1515,11 +1507,9 @@ uim_get_card_status_ready (QmiClientUim *client,
NULL);
if (cards->len == 0) {
- g_simple_async_result_set_error (ctx->result, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
- "No cards reported");
- qmi_message_uim_get_card_status_output_unref (output);
- load_unlock_required_context_complete_and_free (ctx);
- return;
+ g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
+ "No cards reported");
+ return FALSE;
}
if (cards->len > 1)
@@ -1598,24 +1588,22 @@ uim_get_card_status_ready (QmiClientUim *client,
if (card_i < 0 || application_j < 0) {
/* If not a single card found, report SIM not inserted */
if (n_absent > 0 && !n_error && !n_invalid)
- g_simple_async_result_set_error (ctx->result,
- MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_SIM_NOT_INSERTED,
- "No card found");
+ g_set_error (error,
+ MM_MOBILE_EQUIPMENT_ERROR,
+ MM_MOBILE_EQUIPMENT_ERROR_SIM_NOT_INSERTED,
+ "No card found");
else if (n_error > 0)
- g_simple_async_result_set_error (ctx->result,
- MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_SIM_WRONG,
- "Card error");
+ g_set_error (error,
+ MM_MOBILE_EQUIPMENT_ERROR,
+ MM_MOBILE_EQUIPMENT_ERROR_SIM_WRONG,
+ "Card error");
else
- g_simple_async_result_set_error (ctx->result,
- MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_SIM_FAILURE,
- "Card failure: %u absent, %u errors, %u invalid",
- n_absent, n_error, n_invalid);
- qmi_message_uim_get_card_status_output_unref (output);
- load_unlock_required_context_complete_and_free (ctx);
- return;
+ g_set_error (error,
+ MM_MOBILE_EQUIPMENT_ERROR,
+ MM_MOBILE_EQUIPMENT_ERROR_SIM_FAILURE,
+ "Card failure: %u absent, %u errors, %u invalid",
+ n_absent, n_error, n_invalid);
+ return FALSE;
}
/* Get card/app to use */
@@ -1630,27 +1618,36 @@ uim_get_card_status_ready (QmiClientUim *client,
app->state != QMI_UIM_CARD_APPLICATION_STATE_PUK1_OR_UPIN_PUK_REQUIRED &&
app->state != QMI_UIM_CARD_APPLICATION_STATE_PIN1_BLOCKED) {
g_debug ("Neither SIM nor USIM are ready");
- g_simple_async_result_set_error (ctx->result,
- MM_CORE_ERROR,
- MM_CORE_ERROR_RETRY,
- "SIM not ready yet (retry)");
- qmi_message_uim_get_card_status_output_unref (output);
- load_unlock_required_context_complete_and_free (ctx);
- return;
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_RETRY,
+ "SIM not ready yet (retry)");
+ return FALSE;
}
+ /* Report retries if requested to do so */
+ if (o_pin1_retries)
+ *o_pin1_retries = app->pin1_retries;
+ if (o_puk1_retries)
+ *o_puk1_retries = app->puk1_retries;
+ if (o_pin2_retries)
+ *o_pin2_retries = app->pin2_retries;
+ if (o_puk2_retries)
+ *o_puk2_retries = app->puk2_retries;
+
+ /* Early bail out if lock status isn't wanted at this point, so that we
+ * don't fail with an error the unlock retries check */
+ if (!o_lock)
+ return TRUE;
+
/* Card is ready, what's the lock status? */
/* PIN1 */
switch (app->pin1_state) {
case QMI_UIM_PIN_STATE_PERMANENTLY_BLOCKED:
- g_simple_async_result_set_error (ctx->result,
- MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_SIM_WRONG,
- "SIM PIN/PUK permanently blocked");
- qmi_message_uim_get_card_status_output_unref (output);
- load_unlock_required_context_complete_and_free (ctx);
- return;
+ g_set_error (error,
+ MM_MOBILE_EQUIPMENT_ERROR,
+ MM_MOBILE_EQUIPMENT_ERROR_SIM_WRONG,
+ "SIM PIN/PUK permanently blocked");
+ return FALSE;
case QMI_UIM_PIN_STATE_ENABLED_NOT_VERIFIED:
lock = MM_MODEM_LOCK_SIM_PIN;
@@ -1666,13 +1663,11 @@ uim_get_card_status_ready (QmiClientUim *client,
break;
default:
- g_simple_async_result_set_error (ctx->result,
- MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_SIM_WRONG,
- "Unknown SIM PIN/PUK status");
- qmi_message_uim_get_card_status_output_unref (output);
- load_unlock_required_context_complete_and_free (ctx);
- return;
+ g_set_error (error,
+ MM_MOBILE_EQUIPMENT_ERROR,
+ MM_MOBILE_EQUIPMENT_ERROR_SIM_WRONG,
+ "Unknown SIM PIN/PUK status");
+ return FALSE;
}
/* PIN2 */
@@ -1698,7 +1693,36 @@ uim_get_card_status_ready (QmiClientUim *client,
}
}
- g_simple_async_result_set_op_res_gpointer (ctx->result, GUINT_TO_POINTER (lock), NULL);
+ *o_lock = lock;
+ return TRUE;
+}
+
+static void
+unlock_required_uim_get_card_status_ready (QmiClientUim *client,
+ GAsyncResult *res,
+ LoadUnlockRequiredContext *ctx)
+{
+ QmiMessageUimGetCardStatusOutput *output;
+ GError *error = NULL;
+ MMModemLock lock = MM_MODEM_LOCK_UNKNOWN;
+
+ output = qmi_client_uim_get_card_status_finish (client, res, &error);
+ if (!output) {
+ g_prefix_error (&error, "QMI operation failed: ");
+ g_simple_async_result_take_error (ctx->result, error);
+ load_unlock_required_context_complete_and_free (ctx);
+ return;
+ }
+
+ if (!uim_get_card_status_output_parse (output,
+ &lock,
+ NULL, NULL, NULL, NULL,
+ &error)) {
+ g_prefix_error (&error, "QMI operation failed: ");
+ g_simple_async_result_take_error (ctx->result, error);
+ } else
+ g_simple_async_result_set_op_res_gpointer (ctx->result, GUINT_TO_POINTER (lock), NULL);
+
qmi_message_uim_get_card_status_output_unref (output);
load_unlock_required_context_complete_and_free (ctx);
}
@@ -1844,7 +1868,7 @@ load_unlock_required_context_step (LoadUnlockRequiredContext *ctx)
NULL,
5,
NULL,
- (GAsyncReadyCallback) uim_get_card_status_ready,
+ (GAsyncReadyCallback) unlock_required_uim_get_card_status_ready,
ctx);
return;
}
@@ -1872,93 +1896,184 @@ modem_load_unlock_required (MMIfaceModem *self,
/* Check if unlock retries (Modem interface) */
static MMUnlockRetries *
-modem_load_unlock_retries_finish (MMIfaceModem *self,
- GAsyncResult *res,
- GError **error)
+modem_load_unlock_retries_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
{
- if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
- return NULL;
-
- return MM_UNLOCK_RETRIES (g_object_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res))));
+ return MM_UNLOCK_RETRIES (g_task_propagate_pointer (G_TASK (res), error));
}
static void
-retry_count_dms_uim_get_pin_status_ready (QmiClientDms *client,
+unlock_retries_uim_get_card_status_ready (QmiClientUim *client,
GAsyncResult *res,
- GSimpleAsyncResult *simple)
+ GTask *task)
+{
+ QmiMessageUimGetCardStatusOutput *output;
+ GError *error = NULL;
+ guint pin1_retries = 0;
+ guint puk1_retries = 0;
+ guint pin2_retries = 0;
+ guint puk2_retries = 0;
+ MMUnlockRetries *retries;
+
+ output = qmi_client_uim_get_card_status_finish (client, res, &error);
+ if (!output) {
+ g_prefix_error (&error, "QMI operation failed: ");
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ if (!uim_get_card_status_output_parse (output,
+ NULL,
+ &pin1_retries, &puk1_retries,
+ &pin2_retries, &puk2_retries,
+ &error)) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ retries = mm_unlock_retries_new ();
+ mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN, pin1_retries);
+ mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK, puk1_retries);
+ mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN2, pin2_retries);
+ mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK2, puk2_retries);
+
+ qmi_message_uim_get_card_status_output_unref (output);
+
+ g_task_return_pointer (task, retries, g_object_unref);
+ g_object_unref (task);
+}
+
+static void
+uim_load_unlock_retries (MMBroadbandModemQmi *self,
+ GTask *task)
+{
+ QmiClient *client;
+ GError *error = NULL;
+
+ client = peek_qmi_client (self, QMI_SERVICE_UIM, &error);
+ if (!client) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ qmi_client_uim_get_card_status (QMI_CLIENT_UIM (client),
+ NULL,
+ 5,
+ NULL,
+ (GAsyncReadyCallback) unlock_retries_uim_get_card_status_ready,
+ task);
+}
+
+static void
+unlock_retries_dms_uim_get_pin_status_ready (QmiClientDms *client,
+ GAsyncResult *res,
+ GTask *task)
{
QmiMessageDmsUimGetPinStatusOutput *output;
GError *error = NULL;
+ MMBroadbandModemQmi *self;
+ MMUnlockRetries *retries;
+ guint8 verify_retries_left;
+ guint8 unblock_retries_left;
+
+ self = g_task_get_source_object (task);
output = qmi_client_dms_uim_get_pin_status_finish (client, res, &error);
if (!output) {
g_prefix_error (&error, "QMI operation failed: ");
- g_simple_async_result_take_error (simple, error);
- } else if (!qmi_message_dms_uim_get_pin_status_output_get_result (output, &error)) {
- g_prefix_error (&error, "Couldn't get unlock retries: ");
- g_simple_async_result_take_error (simple, error);
- } else {
- MMUnlockRetries *retries;
- guint8 verify_retries_left;
- guint8 unblock_retries_left;
-
- retries = mm_unlock_retries_new ();
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
- if (qmi_message_dms_uim_get_pin_status_output_get_pin1_status (
- output,
- NULL, /* current_status */
- &verify_retries_left,
- &unblock_retries_left,
- NULL)) {
- mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN, verify_retries_left);
- mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK, unblock_retries_left);
+ if (!qmi_message_dms_uim_get_pin_status_output_get_result (output, &error)) {
+ qmi_message_dms_uim_get_pin_status_output_unref (output);
+ /* We get InvalidQmiCommand on newer devices which don't like the legacy way */
+ if (g_error_matches (error,
+ QMI_PROTOCOL_ERROR,
+ QMI_PROTOCOL_ERROR_INVALID_QMI_COMMAND)) {
+ g_error_free (error);
+ /* Flag that the command is unsupported, and try with the new way */
+ self->priv->dms_uim_get_pin_status_supported = FALSE;
+ uim_load_unlock_retries (self, task);
+ return;
}
+ g_prefix_error (&error, "Couldn't get unlock retries: ");
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
- if (qmi_message_dms_uim_get_pin_status_output_get_pin2_status (
- output,
- NULL, /* current_status */
- &verify_retries_left,
- &unblock_retries_left,
- NULL)) {
- mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN2, verify_retries_left);
- mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK2, unblock_retries_left);
- }
+ retries = mm_unlock_retries_new ();
- g_simple_async_result_set_op_res_gpointer (simple, retries, g_object_unref);
+ if (qmi_message_dms_uim_get_pin_status_output_get_pin1_status (
+ output,
+ NULL, /* current_status */
+ &verify_retries_left,
+ &unblock_retries_left,
+ NULL)) {
+ mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN, verify_retries_left);
+ mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK, unblock_retries_left);
}
- if (output)
- qmi_message_dms_uim_get_pin_status_output_unref (output);
+ if (qmi_message_dms_uim_get_pin_status_output_get_pin2_status (
+ output,
+ NULL, /* current_status */
+ &verify_retries_left,
+ &unblock_retries_left,
+ NULL)) {
+ mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN2, verify_retries_left);
+ mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK2, unblock_retries_left);
+ }
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
+ qmi_message_dms_uim_get_pin_status_output_unref (output);
+
+ g_task_return_pointer (task, retries, g_object_unref);
+ g_object_unref (task);
}
static void
-modem_load_unlock_retries (MMIfaceModem *self,
- GAsyncReadyCallback callback,
- gpointer user_data)
+dms_uim_load_unlock_retries (MMBroadbandModemQmi *self,
+ GTask *task)
{
- GSimpleAsyncResult *result;
- QmiClient *client = NULL;
+ QmiClient *client;
- if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self),
- QMI_SERVICE_DMS, &client,
- callback, user_data))
+ client = peek_qmi_client (self, QMI_SERVICE_DMS, NULL);
+ if (!client) {
+ /* Very unlikely that this will ever happen, but anyway, try with
+ * UIM service instead */
+ uim_load_unlock_retries (self, task);
return;
+ }
- result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- modem_load_unlock_retries);
-
- mm_dbg ("loading unlock retries...");
qmi_client_dms_uim_get_pin_status (QMI_CLIENT_DMS (client),
NULL,
5,
NULL,
- (GAsyncReadyCallback)retry_count_dms_uim_get_pin_status_ready,
- result);
+ (GAsyncReadyCallback) unlock_retries_dms_uim_get_pin_status_ready,
+ task);
+}
+
+static void
+modem_load_unlock_retries (MMIfaceModem *_self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ MMBroadbandModemQmi *self;
+ GTask *task;
+
+ self = MM_BROADBAND_MODEM_QMI (_self);
+ task = g_task_new (self, NULL, callback, user_data);
+
+ mm_dbg ("loading unlock retries...");
+ if (self->priv->dms_uim_get_pin_status_supported)
+ dms_uim_load_unlock_retries (MM_BROADBAND_MODEM_QMI (self), task);
+ else
+ uim_load_unlock_retries (MM_BROADBAND_MODEM_QMI (self), task);
}
/*****************************************************************************/