aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/sierra/mm-common-sierra.c95
-rw-r--r--plugins/sierra/mm-sim-sierra.c97
-rw-r--r--plugins/sierra/mm-sim-sierra.h2
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 {