diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-iface-modem.c | 128 | ||||
-rw-r--r-- | src/mm-iface-modem.h | 9 |
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); |