aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2012-12-18 23:38:42 +0100
committerAleksander Morgado <aleksander@lanedo.com>2013-01-08 18:40:47 +0100
commit1372933345b197d89a7e4ae0d5bdcec1fd1e1b2e (patch)
tree908c7103dcf66afcb9090900ada612a6fc66c851 /src
parent959bb9d2ffb8bd7a3d701c21ec2cb58cab3717d9 (diff)
iface-modem,sim: improve lock info update logic
The logic to handle the lock information (current lock and unlock retry count) wasn't handling all possible cases properly, e.g.: * When PIN is incorrectly entered too many times, a SIM-PUK error may happen. In this case we need to directly assume SIM-PUK is the current lock (some modems, like Option HSO ones, would incorrectly reply SIM-PIN if CPIN? asked just after the SIM-PUK error). * After every operation acting in SIM locks, we need to update the current unlock retry count. This change tries to cover those cases, by: * The logic to check current lock is extended to also load the unlock retry count when needed. * Whenever a SIM-PUK error happens in the SIM operations, we directly assume that SIM-PUK is required, without re-asking CPIN?. * The overall logic of lock checking is now handled by a state machine, which is much easier to understand.
Diffstat (limited to 'src')
-rw-r--r--src/mm-iface-modem-simple.c15
-rw-r--r--src/mm-iface-modem.c447
-rw-r--r--src/mm-iface-modem.h26
-rw-r--r--src/mm-sim.c119
4 files changed, 310 insertions, 297 deletions
diff --git a/src/mm-iface-modem-simple.c b/src/mm-iface-modem-simple.c
index 2c2c58ff..12aa1520 100644
--- a/src/mm-iface-modem-simple.c
+++ b/src/mm-iface-modem-simple.c
@@ -437,15 +437,15 @@ send_pin_ready (MMSim *sim,
}
static void
-unlock_check_ready (MMIfaceModem *self,
- GAsyncResult *res,
- ConnectionContext *ctx)
+update_lock_info_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ ConnectionContext *ctx)
{
GError *error = NULL;
MMModemLock lock;
MMSim *sim;
- lock = mm_iface_modem_unlock_check_finish (self, res, &error);
+ lock = mm_iface_modem_update_lock_info_finish (self, res, &error);
if (error) {
g_dbus_method_invocation_take_error (ctx->invocation, error);
connection_context_free (ctx);
@@ -524,9 +524,10 @@ connection_step (ConnectionContext *ctx)
case CONNECTION_STEP_UNLOCK_CHECK:
mm_info ("Simple connect state (%d/%d): Unlock check",
ctx->step, CONNECTION_STEP_LAST);
- mm_iface_modem_unlock_check (MM_IFACE_MODEM (ctx->self),
- (GAsyncReadyCallback)unlock_check_ready,
- ctx);
+ mm_iface_modem_update_lock_info (MM_IFACE_MODEM (ctx->self),
+ MM_MODEM_LOCK_UNKNOWN, /* ask */
+ (GAsyncReadyCallback)update_lock_info_ready,
+ ctx);
return;
case CONNECTION_STEP_WAIT_FOR_INITIALIZED:
diff --git a/src/mm-iface-modem.c b/src/mm-iface-modem.c
index e94bc42a..9b5f8dcd 100644
--- a/src/mm-iface-modem.c
+++ b/src/mm-iface-modem.c
@@ -2225,26 +2225,6 @@ handle_set_allowed_modes (MmGdbusModem *skeleton,
/*****************************************************************************/
-typedef struct {
- MMIfaceModem *self;
- guint pin_check_tries;
- guint pin_check_timeout_id;
- GSimpleAsyncResult *result;
- MmGdbusModem *skeleton;
- MMModemLock lock;
-} UnlockCheckContext;
-
-static void
-unlock_check_context_complete_and_free (UnlockCheckContext *ctx)
-{
- g_simple_async_result_complete_in_idle (ctx->result);
- g_object_unref (ctx->result);
- g_object_unref (ctx->self);
- if (ctx->skeleton)
- g_object_unref (ctx->skeleton);
- g_free (ctx);
-}
-
static void
reinitialize_ready (MMBaseModem *self,
GAsyncResult *res)
@@ -2303,10 +2283,78 @@ set_lock_status (MMIfaceModem *self,
}
}
+static void
+update_unlock_retries (MMIfaceModem *self,
+ MMUnlockRetries *unlock_retries)
+{
+ MmGdbusModem *skeleton = NULL;
+ GError *error = NULL;
+ GVariant *previous_dictionary;
+ MMUnlockRetries *previous_unlock_retries;
+
+ g_object_get (self,
+ MM_IFACE_MODEM_DBUS_SKELETON, &skeleton,
+ NULL);
+ if (!skeleton)
+ return;
+
+ previous_dictionary = mm_gdbus_modem_get_unlock_retries (skeleton);
+ previous_unlock_retries = mm_unlock_retries_new_from_dictionary (previous_dictionary);
+
+ if (error) {
+ mm_warn ("Couldn't build previous unlock retries: '%s'", error->message);
+ g_error_free (error);
+ } else {
+ /* If they are different, update */
+ if (!mm_unlock_retries_cmp (unlock_retries, previous_unlock_retries)) {
+ GVariant *new_dictionary;
+
+ new_dictionary = mm_unlock_retries_get_dictionary (unlock_retries);
+ mm_gdbus_modem_set_unlock_retries (skeleton, new_dictionary);
+ g_variant_unref (new_dictionary);
+ }
+ }
+
+ g_object_unref (previous_unlock_retries);
+ g_object_unref (skeleton);
+}
+
+typedef enum {
+ UPDATE_LOCK_INFO_CONTEXT_STEP_FIRST = 0,
+ UPDATE_LOCK_INFO_CONTEXT_STEP_LOCK,
+ UPDATE_LOCK_INFO_CONTEXT_STEP_RETRIES,
+ UPDATE_LOCK_INFO_CONTEXT_STEP_AFTER_UNLOCK,
+ UPDATE_LOCK_INFO_CONTEXT_STEP_LAST
+} UpdateLockInfoContextStep;
+
+typedef struct {
+ MMIfaceModem *self;
+ UpdateLockInfoContextStep step;
+ guint pin_check_tries;
+ guint pin_check_timeout_id;
+ GSimpleAsyncResult *result;
+ MmGdbusModem *skeleton;
+ MMModemLock lock;
+ GError *saved_error;
+} UpdateLockInfoContext;
+
+static void
+update_lock_info_context_complete_and_free (UpdateLockInfoContext *ctx)
+{
+ g_assert (ctx->saved_error == NULL);
+
+ g_simple_async_result_complete_in_idle (ctx->result);
+ g_object_unref (ctx->result);
+ g_object_unref (ctx->self);
+ if (ctx->skeleton)
+ g_object_unref (ctx->skeleton);
+ g_slice_free (UpdateLockInfoContext, ctx);
+}
+
MMModemLock
-mm_iface_modem_unlock_check_finish (MMIfaceModem *self,
- GAsyncResult *res,
- GError **error)
+mm_iface_modem_update_lock_info_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
{
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
return MM_MODEM_LOCK_UNKNOWN;
@@ -2314,48 +2362,61 @@ mm_iface_modem_unlock_check_finish (MMIfaceModem *self,
return (MMModemLock) GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
}
-static void unlock_check_ready (MMIfaceModem *self,
- GAsyncResult *res,
- UnlockCheckContext *ctx);
+static void update_lock_info_context_step (UpdateLockInfoContext *ctx);
-static gboolean
-unlock_check_again (UnlockCheckContext *ctx)
+static void
+load_unlock_retries_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ UpdateLockInfoContext *ctx)
{
- ctx->pin_check_timeout_id = 0;
+ GError *error = NULL;
+ MMUnlockRetries *unlock_retries;
- MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_unlock_required (
- ctx->self,
- (GAsyncReadyCallback)unlock_check_ready,
- ctx);
- return FALSE;
+ unlock_retries = MM_IFACE_MODEM_GET_INTERFACE (self)->load_unlock_retries_finish (self, res, &error);
+ if (!unlock_retries) {
+ mm_warn ("Couldn't load unlock retries: '%s'", error->message);
+ g_error_free (error);
+ } else {
+ /* Update the dictionary in the DBus interface */
+ update_unlock_retries (self, unlock_retries);
+ g_object_unref (unlock_retries);
+ }
+
+ /* Go on to next step */
+ ctx->step++;
+ update_lock_info_context_step (ctx);
}
static void
modem_after_sim_unlock_ready (MMIfaceModem *self,
GAsyncResult *res,
- UnlockCheckContext *ctx)
+ UpdateLockInfoContext *ctx)
{
GError *error = NULL;
if (!MM_IFACE_MODEM_GET_INTERFACE (self)->modem_after_sim_unlock_finish (self, res, &error)) {
- /* Complete anyway */
mm_warn ("After SIM unlock failed setup: '%s'", error->message);
g_error_free (error);
}
- /* Update lock status and modem status if needed */
- set_lock_status (self, ctx->skeleton, ctx->lock);
+ /* Go on to next step */
+ ctx->step++;
+ update_lock_info_context_step (ctx);
+}
- g_simple_async_result_set_op_res_gpointer (ctx->result,
- GUINT_TO_POINTER (ctx->lock),
- NULL);
- unlock_check_context_complete_and_free (ctx);
+static gboolean
+load_unlock_required_again (UpdateLockInfoContext *ctx)
+{
+ ctx->pin_check_timeout_id = 0;
+ /* Retry the step */
+ update_lock_info_context_step (ctx);
+ return FALSE;
}
static void
-unlock_check_ready (MMIfaceModem *self,
- GAsyncResult *res,
- UnlockCheckContext *ctx)
+load_unlock_required_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ UpdateLockInfoContext *ctx)
{
GError *error = NULL;
@@ -2377,13 +2438,13 @@ unlock_check_ready (MMIfaceModem *self,
g_error_matches (error,
MM_MOBILE_EQUIPMENT_ERROR,
MM_MOBILE_EQUIPMENT_ERROR_SIM_WRONG)) {
- g_simple_async_result_take_error (ctx->result, error);
- unlock_check_context_complete_and_free (ctx);
+ ctx->saved_error = error;
+ ctx->step = UPDATE_LOCK_INFO_CONTEXT_STEP_LAST;
+ update_lock_info_context_step (ctx);
return;
}
- mm_dbg ("Couldn't check if unlock required: '%s'",
- error->message);
+ mm_dbg ("Couldn't check if unlock required: '%s'", error->message);
g_error_free (error);
/* Retry up to 6 times */
@@ -2394,7 +2455,7 @@ unlock_check_ready (MMIfaceModem *self,
g_source_remove (ctx->pin_check_timeout_id);
ctx->pin_check_timeout_id = g_timeout_add_seconds (
2,
- (GSourceFunc)unlock_check_again,
+ (GSourceFunc)load_unlock_required_again,
ctx);
return;
}
@@ -2403,177 +2464,131 @@ unlock_check_ready (MMIfaceModem *self,
ctx->lock = MM_MODEM_LOCK_UNKNOWN;
}
- /* If we get that no lock is required, run the after SIM unlock step
- * in order to wait for the SIM to get ready */
- if (ctx->lock == MM_MODEM_LOCK_NONE ||
- ctx->lock == MM_MODEM_LOCK_SIM_PIN2 ||
- ctx->lock == MM_MODEM_LOCK_SIM_PUK2) {
- if (MM_IFACE_MODEM_GET_INTERFACE (self)->modem_after_sim_unlock != NULL &&
- MM_IFACE_MODEM_GET_INTERFACE (self)->modem_after_sim_unlock_finish != NULL) {
- mm_dbg ("SIM is ready, running after SIM unlock step...");
- MM_IFACE_MODEM_GET_INTERFACE (self)->modem_after_sim_unlock(
- self,
- (GAsyncReadyCallback)modem_after_sim_unlock_ready,
- ctx);
- return;
- }
-
- /* If no way to run after SIM unlock step, we're done */
- mm_dbg ("SIM is ready, and no need for the after SIM unlock step...");
- }
-
- /* Update lock status and modem status if needed */
- set_lock_status (self, ctx->skeleton, ctx->lock);
-
- g_simple_async_result_set_op_res_gpointer (ctx->result,
- GUINT_TO_POINTER (ctx->lock),
- NULL);
- unlock_check_context_complete_and_free (ctx);
+ /* Go on to next step */
+ ctx->step++;
+ update_lock_info_context_step (ctx);
}
-void
-mm_iface_modem_unlock_check (MMIfaceModem *self,
- GAsyncReadyCallback callback,
- gpointer user_data)
+static void
+update_lock_info_context_step (UpdateLockInfoContext *ctx)
{
- UnlockCheckContext *ctx;
+ switch (ctx->step) {
+ case UPDATE_LOCK_INFO_CONTEXT_STEP_FIRST:
+ /* We need the skeleton around */
+ if (!ctx->skeleton) {
+ ctx->saved_error = g_error_new (MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Couldn't get interface skeleton");
+ ctx->step = UPDATE_LOCK_INFO_CONTEXT_STEP_LAST;
+ update_lock_info_context_step (ctx);
+ return;
+ }
- ctx = g_new0 (UnlockCheckContext, 1);
- ctx->self = g_object_ref (self);
- ctx->result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- mm_iface_modem_unlock_check);
- g_object_get (ctx->self,
- MM_IFACE_MODEM_DBUS_SKELETON, &ctx->skeleton,
- NULL);
- if (!ctx->skeleton) {
- g_simple_async_result_set_error (ctx->result,
- MM_CORE_ERROR,
- MM_CORE_ERROR_FAILED,
- "Couldn't get interface skeleton");
- unlock_check_context_complete_and_free (ctx);
- return;
- }
+ /* Fall down to next step */
+ ctx->step++;
- /* If we're already unlocked, we're done */
- if (mm_gdbus_modem_get_unlock_required (ctx->skeleton) != MM_MODEM_LOCK_NONE &&
- MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_unlock_required &&
- MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_unlock_required_finish) {
- MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_unlock_required (
- self,
- (GAsyncReadyCallback)unlock_check_ready,
- ctx);
- return;
- }
+ case UPDATE_LOCK_INFO_CONTEXT_STEP_LOCK:
+ /* Don't re-ask if already known */
+ if (ctx->lock == MM_MODEM_LOCK_UNKNOWN) {
+ /* If we're already unlocked, we're done */
+ if (mm_gdbus_modem_get_unlock_required (ctx->skeleton) != MM_MODEM_LOCK_NONE &&
+ MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_unlock_required &&
+ MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_unlock_required_finish) {
+ MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_unlock_required (
+ ctx->self,
+ (GAsyncReadyCallback)load_unlock_required_ready,
+ ctx);
+ return;
+ }
- /* Just assume that no lock is required */
- g_simple_async_result_set_op_res_gpointer (ctx->result,
- GUINT_TO_POINTER (MM_MODEM_LOCK_NONE),
- NULL);
- unlock_check_context_complete_and_free (ctx);
-}
+ /* Just assume that no lock is required */
+ ctx->lock = MM_MODEM_LOCK_NONE;
+ }
-/*****************************************************************************/
-/* Unlock retry count */
+ /* Fall down to next step */
+ ctx->step++;
-gboolean
-mm_iface_modem_update_unlock_retries_finish (MMIfaceModem *self,
- GAsyncResult *res,
- GError **error)
-{
- if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
- return FALSE;
+ case UPDATE_LOCK_INFO_CONTEXT_STEP_RETRIES:
+ /* Load unlock retries if possible */
+ if (MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_unlock_retries &&
+ MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_unlock_retries_finish) {
+ MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_unlock_retries (
+ ctx->self,
+ (GAsyncReadyCallback)load_unlock_retries_ready,
+ ctx);
+ return;
+ }
- return g_simple_async_result_get_op_res_gboolean (G_SIMPLE_ASYNC_RESULT (res));
-}
+ /* Fall down to next step */
+ ctx->step++;
-static void
-update_unlock_retries (MMIfaceModem *self,
- MMUnlockRetries *unlock_retries)
-{
- MmGdbusModem *skeleton = NULL;
- GError *error = NULL;
- GVariant *previous_dictionary;
- MMUnlockRetries *previous_unlock_retries;
+ case UPDATE_LOCK_INFO_CONTEXT_STEP_AFTER_UNLOCK:
+ /* If we get that no lock is required, run the after SIM unlock step
+ * in order to wait for the SIM to get ready */
+ if (ctx->lock == MM_MODEM_LOCK_NONE ||
+ ctx->lock == MM_MODEM_LOCK_SIM_PIN2 ||
+ ctx->lock == MM_MODEM_LOCK_SIM_PUK2) {
+ if (MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->modem_after_sim_unlock != NULL &&
+ MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->modem_after_sim_unlock_finish != NULL) {
+ mm_dbg ("SIM is ready, running after SIM unlock step...");
+ MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->modem_after_sim_unlock (
+ ctx->self,
+ (GAsyncReadyCallback)modem_after_sim_unlock_ready,
+ ctx);
+ return;
+ }
- g_object_get (self,
- MM_IFACE_MODEM_DBUS_SKELETON, &skeleton,
- NULL);
- if (!skeleton)
- return;
+ /* If no way to run after SIM unlock step, we're done */
+ mm_dbg ("SIM is ready, and no need for the after SIM unlock step...");
+ }
- previous_dictionary = mm_gdbus_modem_get_unlock_retries (skeleton);
- previous_unlock_retries = mm_unlock_retries_new_from_dictionary (previous_dictionary);
+ /* Fall down to next step */
+ ctx->step++;
- if (error) {
- mm_warn ("Couldn't build previous unlock retries: '%s'", error->message);
- g_error_free (error);
- } else {
- /* If they are different, update */
- if (!mm_unlock_retries_cmp (unlock_retries, previous_unlock_retries)) {
- GVariant *new_dictionary;
+ case UPDATE_LOCK_INFO_CONTEXT_STEP_LAST:
+ if (ctx->saved_error) {
+ /* Return saved error */
+ g_simple_async_result_take_error (ctx->result, ctx->saved_error);
+ ctx->saved_error = NULL;
+ } else {
+ /* Update lock status and modem status if needed */
+ set_lock_status (ctx->self, ctx->skeleton, ctx->lock);
- new_dictionary = mm_unlock_retries_get_dictionary (unlock_retries);
- mm_gdbus_modem_set_unlock_retries (skeleton, new_dictionary);
- g_variant_unref (new_dictionary);
+ g_simple_async_result_set_op_res_gpointer (ctx->result,
+ GUINT_TO_POINTER (ctx->lock),
+ NULL);
}
- }
-
- g_object_unref (previous_unlock_retries);
- g_object_unref (skeleton);
-}
-
-static void
-unlock_retries_ready (MMIfaceModem *self,
- GAsyncResult *res,
- GSimpleAsyncResult *simple)
-{
- GError *error = NULL;
- MMUnlockRetries *unlock_retries;
- unlock_retries = MM_IFACE_MODEM_GET_INTERFACE (self)->load_unlock_retries_finish (self, res, &error);
- if (!unlock_retries) {
- g_simple_async_result_take_error (simple, error);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
+ update_lock_info_context_complete_and_free (ctx);
return;
- }
-
- /* Update the dictionary in the DBus interface */
- update_unlock_retries (self, unlock_retries);
- g_object_unref (unlock_retries);
- g_simple_async_result_set_op_res_gboolean (simple, TRUE);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
+ default:
+ g_assert_not_reached();
+ }
}
void
-mm_iface_modem_update_unlock_retries (MMIfaceModem *self,
- GAsyncReadyCallback callback,
- gpointer user_data)
+mm_iface_modem_update_lock_info (MMIfaceModem *self,
+ MMModemLock known_lock,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- GSimpleAsyncResult *result;
+ UpdateLockInfoContext *ctx;
- result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- mm_iface_modem_update_unlock_retries);
+ ctx = g_slice_new0 (UpdateLockInfoContext);
+ ctx->self = g_object_ref (self);
+ ctx->result = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ mm_iface_modem_update_lock_info);
+ g_object_get (ctx->self,
+ MM_IFACE_MODEM_DBUS_SKELETON, &ctx->skeleton,
+ NULL);
- if (MM_IFACE_MODEM_GET_INTERFACE (self)->load_unlock_retries &&
- MM_IFACE_MODEM_GET_INTERFACE (self)->load_unlock_retries_finish) {
- MM_IFACE_MODEM_GET_INTERFACE (self)->load_unlock_retries (
- self,
- (GAsyncReadyCallback)unlock_retries_ready,
- result);
- return;
- }
+ /* If the given lock is known, we will avoid re-asking for it */
+ ctx->lock = known_lock;
- /* Return FALSE when we cannot load unlock retries */
- g_simple_async_result_set_op_res_gboolean (result, FALSE);
- g_simple_async_result_complete_in_idle (result);
- g_object_unref (result);
+ update_lock_info_context_step (ctx);
}
/*****************************************************************************/
@@ -3129,7 +3144,6 @@ typedef enum {
INITIALIZATION_STEP_EQUIPMENT_ID,
INITIALIZATION_STEP_DEVICE_ID,
INITIALIZATION_STEP_UNLOCK_REQUIRED,
- INITIALIZATION_STEP_UNLOCK_RETRIES,
INITIALIZATION_STEP_SIM,
INITIALIZATION_STEP_OWN_NUMBERS,
INITIALIZATION_STEP_SUPPORTED_MODES,
@@ -3333,12 +3347,12 @@ load_supported_bands_ready (MMIfaceModem *self,
}
static void
-load_unlock_required_ready (MMIfaceModem *self,
- GAsyncResult *res,
- InitializationContext *ctx)
+modem_update_lock_info_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ InitializationContext *ctx)
{
/* NOTE: we already propagated the lock state, no need to do it again */
- mm_iface_modem_unlock_check_finish (self, res, &ctx->fatal_error);
+ mm_iface_modem_update_lock_info_finish (self, res, &ctx->fatal_error);
if (ctx->fatal_error) {
g_prefix_error (&ctx->fatal_error,
"Couldn't check unlock status: ");
@@ -3352,24 +3366,6 @@ load_unlock_required_ready (MMIfaceModem *self,
}
static void
-update_unlock_retries_ready (MMIfaceModem *self,
- GAsyncResult *res,
- InitializationContext *ctx)
-{
- GError *error = NULL;
-
- mm_iface_modem_update_unlock_retries_finish (self, res, &error);
- if (error) {
- mm_warn ("couldn't update unlock retries: '%s'", error->message);
- g_error_free (error);
- }
-
- /* Go on to next step */
- ctx->step++;
- interface_initialization_step (ctx);
-}
-
-static void
sim_new_ready (GAsyncInitable *initable,
GAsyncResult *res,
InitializationContext *ctx)
@@ -3652,20 +3648,15 @@ interface_initialization_step (InitializationContext *ctx)
case INITIALIZATION_STEP_UNLOCK_REQUIRED:
/* Only check unlock required if we were previously not unlocked */
if (mm_gdbus_modem_get_unlock_required (ctx->skeleton) != MM_MODEM_LOCK_NONE) {
- mm_iface_modem_unlock_check (ctx->self,
- (GAsyncReadyCallback)load_unlock_required_ready,
- ctx);
+ mm_iface_modem_update_lock_info (ctx->self,
+ MM_MODEM_LOCK_UNKNOWN, /* ask */
+ (GAsyncReadyCallback)modem_update_lock_info_ready,
+ ctx);
return;
}
/* Fall down to next step */
ctx->step++;
- case INITIALIZATION_STEP_UNLOCK_RETRIES:
- mm_iface_modem_update_unlock_retries (ctx->self,
- (GAsyncReadyCallback)update_unlock_retries_ready,
- ctx);
- return;
-
case INITIALIZATION_STEP_SIM:
/* If the modem doesn't need any SIM, skip */
if (MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->create_sim &&
diff --git a/src/mm-iface-modem.h b/src/mm-iface-modem.h
index 52b0d8eb..23dac75b 100644
--- a/src/mm-iface-modem.h
+++ b/src/mm-iface-modem.h
@@ -365,23 +365,17 @@ gboolean mm_iface_modem_disable_finish (MMIfaceModem *self,
/* Shutdown Modem interface */
void mm_iface_modem_shutdown (MMIfaceModem *self);
-/* Request unlock recheck.
+/* Request lock info update.
* It will not only return the lock status, but also set the property values
- * in the DBus interface. */
-void mm_iface_modem_unlock_check (MMIfaceModem *self,
- GAsyncReadyCallback callback,
- gpointer user_data);
-MMModemLock mm_iface_modem_unlock_check_finish (MMIfaceModem *self,
- GAsyncResult *res,
- GError **error);
-
-/* Check unlock retries */
-void mm_iface_modem_update_unlock_retries (MMIfaceModem *self,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean mm_iface_modem_update_unlock_retries_finish (MMIfaceModem *self,
- GAsyncResult *res,
- GError **error);
+ * in the DBus interface. If 'known_lock' is given, that lock status will be
+ * assumed. */
+void mm_iface_modem_update_lock_info (MMIfaceModem *self,
+ MMModemLock known_lock,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+MMModemLock mm_iface_modem_update_lock_info_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error);
/* Request signal quality check update.
* It will not only return the signal quality status, but also set the property
diff --git a/src/mm-sim.c b/src/mm-sim.c
index 8f50edd7..436c15d8 100644
--- a/src/mm-sim.c
+++ b/src/mm-sim.c
@@ -143,11 +143,14 @@ typedef struct {
GDBusMethodInvocation *invocation;
gchar *old_pin;
gchar *new_pin;
+ GError *save_error;
} HandleChangePinContext;
static void
handle_change_pin_context_free (HandleChangePinContext *ctx)
{
+ g_assert (ctx->save_error == NULL);
+
g_object_unref (ctx->invocation);
g_object_unref (ctx->self);
g_free (ctx->old_pin);
@@ -156,15 +159,21 @@ handle_change_pin_context_free (HandleChangePinContext *ctx)
}
static void
-after_change_unlock_retries_ready (MMIfaceModem *self,
- GAsyncResult *res,
- HandleChangePinContext *ctx)
+after_change_update_lock_info_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ HandleChangePinContext *ctx)
{
/* We just want to ensure that we tried to update the unlock
* retries, no big issue if it failed */
- mm_iface_modem_update_unlock_retries_finish (self, res, NULL);
+ mm_iface_modem_update_lock_info_finish (self, res, NULL);
+
+ if (ctx->save_error) {
+ g_dbus_method_invocation_take_error (ctx->invocation, ctx->save_error);
+ ctx->save_error = NULL;
+ } else {
+ mm_gdbus_sim_complete_change_pin (MM_GDBUS_SIM (ctx->self), ctx->invocation);
+ }
- mm_gdbus_sim_complete_change_pin (MM_GDBUS_SIM (ctx->self), ctx->invocation);
handle_change_pin_context_free (ctx);
}
@@ -173,20 +182,20 @@ handle_change_pin_ready (MMSim *self,
GAsyncResult *res,
HandleChangePinContext *ctx)
{
- GError *error = NULL;
+ MMModemLock known_lock = MM_MODEM_LOCK_UNKNOWN;
- MM_SIM_GET_CLASS (self)->change_pin_finish (self, res, &error);
- if (error) {
- g_dbus_method_invocation_take_error (ctx->invocation, error);
- handle_change_pin_context_free (ctx);
- return;
+ if (!MM_SIM_GET_CLASS (self)->change_pin_finish (self, res, &ctx->save_error)) {
+ if (g_error_matches (ctx->save_error,
+ MM_MOBILE_EQUIPMENT_ERROR,
+ MM_MOBILE_EQUIPMENT_ERROR_SIM_PUK))
+ known_lock = MM_MODEM_LOCK_SIM_PUK;
}
- /* Before returning success, ensure that we get the unlock retry
- * counts updated properly. */
- mm_iface_modem_update_unlock_retries (MM_IFACE_MODEM (self->priv->modem),
- (GAsyncReadyCallback)after_change_unlock_retries_ready,
- ctx);
+ mm_iface_modem_update_lock_info (
+ MM_IFACE_MODEM (self->priv->modem),
+ known_lock,
+ (GAsyncReadyCallback)after_change_update_lock_info_ready,
+ ctx);
}
static void
@@ -306,11 +315,14 @@ typedef struct {
GDBusMethodInvocation *invocation;
gchar *pin;
gboolean enabled;
+ GError *save_error;
} HandleEnablePinContext;
static void
handle_enable_pin_context_free (HandleEnablePinContext *ctx)
{
+ g_assert (ctx->save_error == NULL);
+
g_object_unref (ctx->invocation);
g_object_unref (ctx->self);
g_free (ctx->pin);
@@ -318,15 +330,23 @@ handle_enable_pin_context_free (HandleEnablePinContext *ctx)
}
static void
-after_enable_unlock_retries_ready (MMIfaceModem *self,
- GAsyncResult *res,
- HandleEnablePinContext *ctx)
+after_enable_update_lock_info_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ HandleEnablePinContext *ctx)
{
/* We just want to ensure that we tried to update the unlock
* retries, no big issue if it failed */
- mm_iface_modem_update_unlock_retries_finish (self, res, NULL);
+ mm_iface_modem_update_lock_info_finish (self, res, NULL);
+
+ if (ctx->save_error) {
+ g_dbus_method_invocation_take_error (ctx->invocation, ctx->save_error);
+ ctx->save_error = NULL;
+ } else {
+ /* Signal about the new lock state */
+ g_signal_emit (self, signals[SIGNAL_PIN_LOCK_ENABLED], 0, ctx->enabled);
+ mm_gdbus_sim_complete_enable_pin (MM_GDBUS_SIM (ctx->self), ctx->invocation);
+ }
- mm_gdbus_sim_complete_enable_pin (MM_GDBUS_SIM (ctx->self), ctx->invocation);
handle_enable_pin_context_free (ctx);
}
@@ -335,23 +355,20 @@ handle_enable_pin_ready (MMSim *self,
GAsyncResult *res,
HandleEnablePinContext *ctx)
{
- GError *error = NULL;
+ MMModemLock known_lock = MM_MODEM_LOCK_UNKNOWN;
- MM_SIM_GET_CLASS (self)->enable_pin_finish (self, res, &error);
- if (error) {
- g_dbus_method_invocation_take_error (ctx->invocation, error);
- handle_enable_pin_context_free (ctx);
- return;
+ if (!MM_SIM_GET_CLASS (self)->enable_pin_finish (self, res, &ctx->save_error)) {
+ if (g_error_matches (ctx->save_error,
+ MM_MOBILE_EQUIPMENT_ERROR,
+ MM_MOBILE_EQUIPMENT_ERROR_SIM_PUK))
+ known_lock = MM_MODEM_LOCK_SIM_PUK;
}
- /* Signal about the new lock state */
- g_signal_emit (self, signals[SIGNAL_PIN_LOCK_ENABLED], 0, ctx->enabled);
-
- /* Before returning success, ensure that we get the unlock retry
- * counts updated properly. */
- mm_iface_modem_update_unlock_retries (MM_IFACE_MODEM (self->priv->modem),
- (GAsyncReadyCallback)after_enable_unlock_retries_ready,
- ctx);
+ mm_iface_modem_update_lock_info (
+ MM_IFACE_MODEM (self->priv->modem),
+ known_lock,
+ (GAsyncReadyCallback)after_enable_update_lock_info_ready,
+ ctx);
}
static void
@@ -555,14 +572,14 @@ mm_sim_send_puk_finish (MMSim *self,
}
static void
-unlock_check_ready (MMIfaceModem *modem,
- GAsyncResult *res,
- SendPinPukContext *ctx)
+update_lock_info_ready (MMIfaceModem *modem,
+ GAsyncResult *res,
+ SendPinPukContext *ctx)
{
GError *error = NULL;
MMModemLock lock;
- lock = mm_iface_modem_unlock_check_finish (modem, res, &error);
+ lock = mm_iface_modem_update_lock_info_finish (modem, res, &error);
/* Even if we may be SIM-PIN2/PUK2 locked, we don't consider this an error
* in the PIN/PUK sending */
if (lock != MM_MODEM_LOCK_NONE &&
@@ -595,12 +612,21 @@ send_pin_ready (MMSim *self,
GAsyncResult *res,
SendPinPukContext *ctx)
{
- MM_SIM_GET_CLASS (self)->send_pin_finish (self, res, &ctx->save_error);
+ MMModemLock known_lock = MM_MODEM_LOCK_UNKNOWN;
+
+ if (!MM_SIM_GET_CLASS (self)->send_pin_finish (self, res, &ctx->save_error)) {
+ if (g_error_matches (ctx->save_error,
+ MM_MOBILE_EQUIPMENT_ERROR,
+ MM_MOBILE_EQUIPMENT_ERROR_SIM_PUK))
+ known_lock = MM_MODEM_LOCK_SIM_PUK;
+ }
/* Once pin/puk has been sent, recheck lock */
- mm_iface_modem_unlock_check (MM_IFACE_MODEM (self->priv->modem),
- (GAsyncReadyCallback)unlock_check_ready,
- ctx);
+ mm_iface_modem_update_lock_info (
+ MM_IFACE_MODEM (self->priv->modem),
+ known_lock,
+ (GAsyncReadyCallback)update_lock_info_ready,
+ ctx);
}
static void
@@ -611,9 +637,10 @@ send_puk_ready (MMSim *self,
MM_SIM_GET_CLASS (self)->send_puk_finish (self, res, &ctx->save_error);
/* Once pin/puk has been sent, recheck lock */
- mm_iface_modem_unlock_check (MM_IFACE_MODEM (self->priv->modem),
- (GAsyncReadyCallback)unlock_check_ready,
- ctx);
+ mm_iface_modem_update_lock_info (MM_IFACE_MODEM (self->priv->modem),
+ MM_MODEM_LOCK_UNKNOWN, /* ask */
+ (GAsyncReadyCallback)update_lock_info_ready,
+ ctx);
}
void