aboutsummaryrefslogtreecommitdiff
path: root/src/mm-iface-modem.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mm-iface-modem.c')
-rw-r--r--src/mm-iface-modem.c146
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;
}