aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mm-iface-modem.c128
-rw-r--r--src/mm-iface-modem.h9
2 files changed, 137 insertions, 0 deletions
diff --git a/src/mm-iface-modem.c b/src/mm-iface-modem.c
index 27ac2572..b8ff43f4 100644
--- a/src/mm-iface-modem.c
+++ b/src/mm-iface-modem.c
@@ -75,6 +75,134 @@ mm_iface_modem_bind_simple_status (MMIfaceModem *self,
}
/*****************************************************************************/
+/* Helper method to wait for a final state */
+
+#define MODEM_STATE_IS_INTERMEDIATE(state) \
+ (state == MM_MODEM_STATE_INITIALIZING || \
+ state == MM_MODEM_STATE_INITIALIZING || \
+ state == MM_MODEM_STATE_INITIALIZING || \
+ state == MM_MODEM_STATE_INITIALIZING || \
+ state == MM_MODEM_STATE_INITIALIZING)
+
+typedef struct {
+ MMIfaceModem *self;
+ MMModemState final_state;
+ GSimpleAsyncResult *result;
+ gulong state_changed_id;
+ guint state_changed_wait_id;
+} WaitForFinalStateContext;
+
+static void
+wait_for_final_state_context_complete_and_free (WaitForFinalStateContext *ctx)
+{
+ g_simple_async_result_complete (ctx->result);
+ g_object_unref (ctx->result);
+ g_signal_handler_disconnect (ctx->self, ctx->state_changed_id);
+ g_source_remove (ctx->state_changed_wait_id);
+ g_object_unref (ctx->self);
+ g_slice_free (WaitForFinalStateContext, ctx);
+}
+
+MMModemState
+mm_iface_modem_wait_for_final_state_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return MM_MODEM_STATE_UNKNOWN;
+
+ return (MMModemState)GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
+}
+
+static gboolean
+state_changed_wait_expired (WaitForFinalStateContext *ctx)
+{
+ g_simple_async_result_set_error (
+ ctx->result,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_RETRY,
+ "Too much time waiting to get to a final state");
+ wait_for_final_state_context_complete_and_free (ctx);
+ return FALSE;
+}
+
+static void
+state_changed (MMIfaceModem *self,
+ GParamSpec *spec,
+ WaitForFinalStateContext *ctx)
+{
+ MMModemState state = MM_MODEM_STATE_UNKNOWN;
+
+ g_object_get (self,
+ MM_IFACE_MODEM_STATE, &state,
+ NULL);
+
+ /* Are we in a final state already? */
+ if (MODEM_STATE_IS_INTERMEDIATE (state))
+ return;
+
+ /* If we want a specific final state and this is not the one we were
+ * looking for, then skip */
+ if (ctx->final_state != MM_MODEM_STATE_UNKNOWN &&
+ state != MM_MODEM_STATE_UNKNOWN &&
+ state != ctx->final_state)
+ return;
+
+ /* Done! */
+ g_simple_async_result_set_op_res_gpointer (ctx->result, GUINT_TO_POINTER (state), NULL);
+ wait_for_final_state_context_complete_and_free (ctx);
+}
+
+void
+mm_iface_modem_wait_for_final_state (MMIfaceModem *self,
+ MMModemState final_state,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ MMModemState state = MM_MODEM_STATE_UNKNOWN;
+ WaitForFinalStateContext *ctx;
+ GSimpleAsyncResult *result;
+
+ result = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ mm_iface_modem_wait_for_final_state);
+
+ g_object_get (self,
+ MM_IFACE_MODEM_STATE, &state,
+ NULL);
+
+ /* Are we in a final state already? */
+ if (!MODEM_STATE_IS_INTERMEDIATE (state)) {
+ /* Is this the state we actually wanted? */
+ if (final_state == MM_MODEM_STATE_UNKNOWN ||
+ (state != MM_MODEM_STATE_UNKNOWN && state == final_state)) {
+ g_simple_async_result_set_op_res_gpointer (result, GUINT_TO_POINTER (state), NULL);
+ g_simple_async_result_complete_in_idle (result);
+ g_object_unref (result);
+ return;
+ }
+
+ /* Otherwise, we'll need to wait for the exact one we want */
+ }
+
+ ctx = g_slice_new0 (WaitForFinalStateContext);
+ ctx->result = result;
+ ctx->self = g_object_ref (self);
+ ctx->final_state = final_state;
+
+ /* Want to get notified when modem state changes */
+ ctx->state_changed_id = g_signal_connect (ctx->self,
+ "notify::" MM_IFACE_MODEM_STATE,
+ G_CALLBACK (state_changed),
+ ctx);
+ /* But we don't want to wait forever */
+ ctx->state_changed_wait_id = g_timeout_add_seconds (10,
+ (GSourceFunc)state_changed_wait_expired,
+ ctx);
+}
+
+/*****************************************************************************/
static MMModemState get_current_consolidated_state (MMIfaceModem *self);
diff --git a/src/mm-iface-modem.h b/src/mm-iface-modem.h
index b5e7ddc4..a6bd9046 100644
--- a/src/mm-iface-modem.h
+++ b/src/mm-iface-modem.h
@@ -437,6 +437,15 @@ MMBearer *mm_iface_modem_create_bearer_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error);
+/* Helper method to wait for a final state */
+void mm_iface_modem_wait_for_final_state (MMIfaceModem *self,
+ MMModemState final_state,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+MMModemState mm_iface_modem_wait_for_final_state_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error);
+
void mm_iface_modem_bind_simple_status (MMIfaceModem *self,
MMSimpleStatus *status);