aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2013-06-23 11:22:00 +0200
committerAleksander Morgado <aleksander@lanedo.com>2013-06-24 19:40:58 +0200
commite227d4af39d2c09ef1e8a8818d2558fba210f334 (patch)
treeac386c8340fda1fc935a93b353b5538ff763382b
parentbcb00df1422b8a3a6d0fafbefe8ac3fcc9011b97 (diff)
iface-modem: don't rely on the cached current power state value
The real power state value of the modem may be changed by other means, e.g. rfkill. So when changing power state of the modem in MM, we better recheck which the current power status is. A better full approach would be to follow rfkill changes, but this fix should help until that is done. https://bugzilla.gnome.org/show_bug.cgi?id=702838
-rw-r--r--src/mm-iface-modem.c136
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 */