diff options
Diffstat (limited to 'src/mm-iface-modem.c')
-rw-r--r-- | src/mm-iface-modem.c | 146 |
1 files changed, 105 insertions, 41 deletions
diff --git a/src/mm-iface-modem.c b/src/mm-iface-modem.c index c4b808c..f0f10ce 100644 --- a/src/mm-iface-modem.c +++ b/src/mm-iface-modem.c @@ -2983,7 +2983,8 @@ typedef struct { GSimpleAsyncResult *result; MmGdbusModem *skeleton; MMModemPowerState power_state; - MMModemPowerState previous_power_state; + MMModemPowerState previous_cached_power_state; + MMModemPowerState previous_real_power_state; } SetPowerStateContext; static void @@ -3029,6 +3030,9 @@ modem_power_up_ready (MMIfaceModem *self, MM_IFACE_MODEM_GET_INTERFACE (self)->modem_power_up_finish (self, res, &error); if (error) { + /* If the real and cached ones are different, set the real one */ + if (ctx->previous_cached_power_state != ctx->previous_real_power_state) + mm_gdbus_modem_set_power_state (ctx->skeleton, ctx->previous_real_power_state); g_simple_async_result_take_error (ctx->result, error); set_power_state_context_complete_and_free (ctx); return; @@ -3060,9 +3064,12 @@ modem_power_down_ready (MMIfaceModem *self, GError *error = NULL; MM_IFACE_MODEM_GET_INTERFACE (self)->modem_power_down_finish (self, res, &error); - if (error) + if (error) { + /* If the real and cached ones are different, set the real one */ + if (ctx->previous_cached_power_state != ctx->previous_real_power_state) + mm_gdbus_modem_set_power_state (ctx->skeleton, ctx->previous_real_power_state); g_simple_async_result_take_error (ctx->result, error); - else { + } else { mm_dbg ("Modem set in low-power mode..."); mm_gdbus_modem_set_power_state (ctx->skeleton, ctx->power_state); g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); @@ -3071,38 +3078,16 @@ modem_power_down_ready (MMIfaceModem *self, set_power_state_context_complete_and_free (ctx); } -void -mm_iface_modem_set_power_state (MMIfaceModem *self, - MMModemPowerState power_state, - GAsyncReadyCallback callback, - gpointer user_data) +static void +set_power_state (SetPowerStateContext *ctx) { - SetPowerStateContext *ctx; - - ctx = g_slice_new0 (SetPowerStateContext); - ctx->self = g_object_ref (self); - ctx->result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - mm_iface_modem_set_power_state); - ctx->power_state = power_state; - g_object_get (ctx->self, - MM_IFACE_MODEM_DBUS_SKELETON, &ctx->skeleton, - NULL); - if (!ctx->skeleton) { - g_simple_async_result_set_error (ctx->result, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't get interface skeleton"); - set_power_state_context_complete_and_free (ctx); - return; - } - ctx->previous_power_state = mm_gdbus_modem_get_power_state (ctx->skeleton); - /* Already done if we're in the desired power state */ - if (ctx->previous_power_state == ctx->power_state) { + if (ctx->previous_real_power_state == ctx->power_state) { mm_dbg ("No need to change power state: already in '%s' power state", mm_modem_power_state_get_string (ctx->power_state)); + /* If the real and cached ones are different, set the real one */ + if (ctx->previous_cached_power_state != ctx->previous_real_power_state) + mm_gdbus_modem_set_power_state (ctx->skeleton, ctx->previous_real_power_state); g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); set_power_state_context_complete_and_free (ctx); return; @@ -3116,8 +3101,8 @@ mm_iface_modem_set_power_state (MMIfaceModem *self, /* Going into low power mode? */ if (ctx->power_state == MM_MODEM_POWER_STATE_LOW) { /* Error if unsupported */ - if (!MM_IFACE_MODEM_GET_INTERFACE (self)->modem_power_down || - !MM_IFACE_MODEM_GET_INTERFACE (self)->modem_power_down_finish) { + if (!MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->modem_power_down || + !MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->modem_power_down_finish) { g_simple_async_result_set_error (ctx->result, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, @@ -3126,17 +3111,18 @@ mm_iface_modem_set_power_state (MMIfaceModem *self, return; } - MM_IFACE_MODEM_GET_INTERFACE (self)->modem_power_down (MM_IFACE_MODEM (self), - (GAsyncReadyCallback)modem_power_down_ready, - ctx); + MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->modem_power_down ( + MM_IFACE_MODEM (ctx->self), + (GAsyncReadyCallback)modem_power_down_ready, + ctx); return; } /* Going out of low power mode? */ if (ctx->power_state == MM_MODEM_POWER_STATE_ON) { /* Error if unsupported */ - if (!MM_IFACE_MODEM_GET_INTERFACE (self)->modem_power_up || - !MM_IFACE_MODEM_GET_INTERFACE (self)->modem_power_up_finish) { + if (!MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->modem_power_up || + !MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->modem_power_up_finish) { g_simple_async_result_set_error (ctx->result, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, @@ -3145,15 +3131,83 @@ mm_iface_modem_set_power_state (MMIfaceModem *self, return; } - MM_IFACE_MODEM_GET_INTERFACE (self)->modem_power_up (MM_IFACE_MODEM (self), - (GAsyncReadyCallback)modem_power_up_ready, - ctx); + MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->modem_power_up ( + MM_IFACE_MODEM (ctx->self), + (GAsyncReadyCallback)modem_power_up_ready, + ctx); return; } g_assert_not_reached (); } +static void +set_power_state_load_ready (MMIfaceModem *self, + GAsyncResult *res, + SetPowerStateContext *ctx) +{ + GError *error = NULL; + + ctx->previous_real_power_state = MM_IFACE_MODEM_GET_INTERFACE (self)->load_power_state_finish (self, res, &error); + if (error) { + g_debug ("Couldn't reload current power state: %s", error->message); + g_error_free (error); + /* Default to the cached one */ + ctx->previous_real_power_state = ctx->previous_cached_power_state; + } + + /* And keep on */ + set_power_state (ctx); +} + +void +mm_iface_modem_set_power_state (MMIfaceModem *self, + MMModemPowerState power_state, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SetPowerStateContext *ctx; + + ctx = g_slice_new0 (SetPowerStateContext); + ctx->self = g_object_ref (self); + ctx->result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + mm_iface_modem_set_power_state); + ctx->power_state = power_state; + g_object_get (ctx->self, + MM_IFACE_MODEM_DBUS_SKELETON, &ctx->skeleton, + NULL); + if (!ctx->skeleton) { + g_simple_async_result_set_error (ctx->result, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Couldn't get interface skeleton"); + set_power_state_context_complete_and_free (ctx); + return; + } + + ctx->previous_cached_power_state = mm_gdbus_modem_get_power_state (ctx->skeleton); + + /* We cannot really rely on the power state value that we had cached before, + * as the real power status of the modem may also be changed by rfkill. So, + * before updating the current power state, re-check which is the real power + * state. */ + if (MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_power_state && + MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_power_state_finish) { + MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_power_state ( + ctx->self, + (GAsyncReadyCallback)set_power_state_load_ready, + ctx); + return; + } + + /* If there is no way to load power state, just keep on assuming the cached + * one is also the real one */ + ctx->previous_real_power_state = ctx->previous_cached_power_state; + set_power_state (ctx); +} + /*****************************************************************************/ /* MODEM DISABLING */ @@ -3965,6 +4019,15 @@ interface_initialization_step (InitializationContext *ctx) g_assert (primary != NULL); mm_gdbus_modem_set_primary_port (ctx->skeleton, mm_port_get_device (primary)); } + /* Load ports if not done before */ + if (!mm_gdbus_modem_get_ports (ctx->skeleton)) { + MMModemPortInfo *port_infos; + guint n_port_infos; + + port_infos = mm_base_modem_get_port_infos (MM_BASE_MODEM (ctx->self), &n_port_infos); + mm_gdbus_modem_set_ports (ctx->skeleton, mm_common_ports_array_to_variant (port_infos, n_port_infos)); + mm_modem_port_info_array_free (port_infos, n_port_infos); + } /* Fall down to next step */ ctx->step++; @@ -4004,6 +4067,7 @@ interface_initialization_step (InitializationContext *ctx) ctx->self, (GAsyncReadyCallback)load_supported_capabilities_ready, ctx); + g_array_unref (supported_capabilities); return; } |