diff options
-rw-r--r-- | src/mm-iface-modem.c | 136 |
1 files changed, 95 insertions, 41 deletions
diff --git a/src/mm-iface-modem.c b/src/mm-iface-modem.c index c4b808c2..e4103ffe 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 */ |