aboutsummaryrefslogtreecommitdiff
path: root/src/mm-sim.c
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/mm-sim.c
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/mm-sim.c')
-rw-r--r--src/mm-sim.c119
1 files changed, 73 insertions, 46 deletions
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