diff options
-rw-r--r-- | plugins/sierra/mm-common-sierra.c | 95 | ||||
-rw-r--r-- | plugins/sierra/mm-sim-sierra.c | 97 | ||||
-rw-r--r-- | plugins/sierra/mm-sim-sierra.h | 2 |
3 files changed, 190 insertions, 4 deletions
diff --git a/plugins/sierra/mm-common-sierra.c b/plugins/sierra/mm-common-sierra.c index d0bde95c..3bfbf2ca 100644 --- a/plugins/sierra/mm-common-sierra.c +++ b/plugins/sierra/mm-common-sierra.c @@ -32,12 +32,99 @@ mm_common_sierra_modem_power_up_finish (MMIfaceModem *self, return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); } +static void +send_pin_ready (MMSim *sim, + GAsyncResult *res, + GSimpleAsyncResult *simple) +{ + GError *error = NULL; + + if (!MM_SIM_GET_CLASS (sim)->send_pin_finish (sim, res, &error)) { + mm_warn ("Error sending cached SIM PIN after power-up: '%s'", error->message); + + /* If the error is because PIN wasn't found, we need to fully reset the + * modem and re-start the state machine from the beginning, so that we + * ask the user for the PIN while in locked state. */ + if (g_error_matches (error, + MM_CORE_ERROR, + MM_CORE_ERROR_NOT_FOUND)) { + MMBroadbandModem *self = NULL; + + self = MM_BROADBAND_MODEM (g_async_result_get_source_object (G_ASYNC_RESULT (simple))); + /* Launch modem reset... if possible */ + if (MM_IFACE_MODEM_GET_INTERFACE (MM_IFACE_MODEM (self))->reset && + MM_IFACE_MODEM_GET_INTERFACE (MM_IFACE_MODEM (self))->reset_finish) { + mm_warn ("Launching modem reset..."); + MM_IFACE_MODEM_GET_INTERFACE (MM_IFACE_MODEM (self))->reset (MM_IFACE_MODEM (self), NULL, NULL); + } + g_object_unref (self); + } + + g_simple_async_result_take_error (simple, error); + } else { + mm_dbg ("Assuming we got unlocked after power-up"); + /* Assume we're done */ + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + } + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +static void +unlock_check_ready (MMIfaceModem *self, + GAsyncResult *res, + GSimpleAsyncResult *simple) +{ + MMModemLock lock; + GError *error = NULL; + + lock = MM_IFACE_MODEM_GET_INTERFACE (self)->load_unlock_required_finish (self, res, &error); + if (error) { + mm_dbg ("Couldn't check lock status after power up: '%s'", error->message); + g_error_free (error); + } else if (lock == MM_MODEM_LOCK_SIM_PIN) { + MMSim *sim = NULL; + + /* If we need SIM PIN unlocking, re-send the cached one */ + g_object_get (self, + MM_IFACE_MODEM_SIM, &sim, + NULL); + if (sim) { + mm_dbg ("Sending cached SIM PIN..."); + /* On the Sierra-specific SIM implementation, we do allow passing a + * NULL pin. It just means 'try to use the last cached one'. + * NOTE: do not call mm_sim_send_pin(), as that may ignore the errors. */ + MM_SIM_GET_CLASS (sim)->send_pin (sim, + NULL, + (GAsyncReadyCallback)send_pin_ready, + simple); + g_object_unref (sim); + return; + } + mm_dbg ("No SIM found, assuming we won't need re-unlock"); + } else + mm_info ("Modem is locked with '%s' after power-up", mm_modem_lock_get_string (lock)); + + /* On error, or READY, or other lock, or no SIM, just go on */ + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + static gboolean -sierra_power_up_wait_cb (GSimpleAsyncResult *result) +sierra_power_up_wait_cb (GSimpleAsyncResult *simple) { - g_simple_async_result_set_op_res_gboolean (result, TRUE); - g_simple_async_result_complete (result); - g_object_unref (result); + MMBroadbandModem *self; + + self = MM_BROADBAND_MODEM (g_async_result_get_source_object (G_ASYNC_RESULT (simple))); + + /* Some modems may actually need to unlock the SIM PIN again after powering up... + * We'll call the Modem inteface method of the modem directly */ + MM_IFACE_MODEM_GET_INTERFACE (MM_IFACE_MODEM (self))->load_unlock_required (MM_IFACE_MODEM (self), + (GAsyncReadyCallback)unlock_check_ready, + simple); + g_object_unref (self); return FALSE; } diff --git a/plugins/sierra/mm-sim-sierra.c b/plugins/sierra/mm-sim-sierra.c index 1b741de6..de5fa09e 100644 --- a/plugins/sierra/mm-sim-sierra.c +++ b/plugins/sierra/mm-sim-sierra.c @@ -33,6 +33,82 @@ G_DEFINE_TYPE (MMSimSierra, mm_sim_sierra, MM_TYPE_SIM); +struct _MMSimSierraPrivate { + gchar *cached_pin; +}; + +/*****************************************************************************/ +/* Send SIM PIN */ + +static gboolean +send_pin_finish (MMSim *self, + GAsyncResult *res, + GError **error) +{ + return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); +} + +static void +parent_send_pin_ready (MMSim *_self, + GAsyncResult *res, + GSimpleAsyncResult *simple) +{ + MMSimSierra *self = MM_SIM_SIERRA (_self); + GError *error = NULL; + + if (!MM_SIM_CLASS (mm_sim_sierra_parent_class)->send_pin_finish (_self, res, &error)) { + /* Clear cached PIN if sending PIN fails */ + g_free (self->priv->cached_pin); + self->priv->cached_pin = NULL; + g_simple_async_result_take_error (simple, error); + } else + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +static void +send_pin (MMSim *_self, + const gchar *pin, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MMSimSierra *self = MM_SIM_SIERRA (_self); + GSimpleAsyncResult *result; + + result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + send_pin); + + /* We allow passing NULL pin, when we want to use the last cached one. + * This will only happen when re-unlocking the SIM after powering up + * the modem, so it means that if any PIN was introduced already, + * it would be the correct one. */ + if (!pin) { + if (!self->priv->cached_pin) { + g_simple_async_result_set_error (result, + MM_CORE_ERROR, + MM_CORE_ERROR_NOT_FOUND, + "No cached PIN found"); + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); + return; + } + } else { + /* Update cached PIN */ + g_free (self->priv->cached_pin); + self->priv->cached_pin = g_strdup (pin); + } + + /* Call parent's PIN sending code */ + MM_SIM_CLASS (mm_sim_sierra_parent_class)->send_pin (_self, + self->priv->cached_pin, + (GAsyncReadyCallback)parent_send_pin_ready, + result); +} + /*****************************************************************************/ /* SIM identifier loading */ @@ -179,13 +255,34 @@ mm_sim_sierra_new (MMBaseModem *modem, static void mm_sim_sierra_init (MMSimSierra *self) { + /* Initialize private data */ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + MM_TYPE_SIM_SIERRA, + MMSimSierraPrivate); +} + +static void +finalize (GObject *object) +{ + MMSimSierra *self = MM_SIM_SIERRA (object); + + g_free (self->priv->cached_pin); + + G_OBJECT_CLASS (mm_sim_sierra_parent_class)->finalize (object); } static void mm_sim_sierra_class_init (MMSimSierraClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS (klass); MMSimClass *sim_class = MM_SIM_CLASS (klass); + g_type_class_add_private (object_class, sizeof (MMSimSierraPrivate)); + + object_class->finalize = finalize; + sim_class->load_sim_identifier = load_sim_identifier; sim_class->load_sim_identifier_finish = load_sim_identifier_finish; + sim_class->send_pin = send_pin; + sim_class->send_pin_finish = send_pin_finish; } diff --git a/plugins/sierra/mm-sim-sierra.h b/plugins/sierra/mm-sim-sierra.h index 3595bd94..d89df35a 100644 --- a/plugins/sierra/mm-sim-sierra.h +++ b/plugins/sierra/mm-sim-sierra.h @@ -32,9 +32,11 @@ typedef struct _MMSimSierra MMSimSierra; typedef struct _MMSimSierraClass MMSimSierraClass; +typedef struct _MMSimSierraPrivate MMSimSierraPrivate; struct _MMSimSierra { MMSim parent; + MMSimSierraPrivate *priv; }; struct _MMSimSierraClass { |