diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2012-01-16 19:39:00 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2012-03-15 14:14:51 +0100 |
commit | 03c5f4e6fbb5d5f2750f23deb5832b5eaa5c5197 (patch) | |
tree | 7b35e1f3096c00ea7ed08d97b6392de80a92566e | |
parent | d7f98cf27781babb5fb9b051c1b3be228232177e (diff) |
iface-modem-location: handle enabling/disabling location gathering
-rw-r--r-- | src/mm-iface-modem-location.c | 429 | ||||
-rw-r--r-- | src/mm-iface-modem-location.h | 32 |
2 files changed, 458 insertions, 3 deletions
diff --git a/src/mm-iface-modem-location.c b/src/mm-iface-modem-location.c index 00895e48..51ffea35 100644 --- a/src/mm-iface-modem-location.c +++ b/src/mm-iface-modem-location.c @@ -20,6 +20,10 @@ #include "mm-iface-modem-location.h" #include "mm-log.h" +#define LOCATION_CONTEXT_TAG "location-context-tag" + +static GQuark location_context_quark; + /*****************************************************************************/ void @@ -30,14 +34,177 @@ mm_iface_modem_location_bind_simple_status (MMIfaceModemLocation *self, /*****************************************************************************/ +typedef struct { + MmGdbusModemLocation *skeleton; + GDBusMethodInvocation *invocation; + MMIfaceModemLocation *self; +} DbusCallContext; + +static void +dbus_call_context_free (DbusCallContext *ctx) +{ + g_object_unref (ctx->skeleton); + g_object_unref (ctx->invocation); + g_object_unref (ctx->self); + g_free (ctx); +} + +static DbusCallContext * +dbus_call_context_new (MmGdbusModemLocation *skeleton, + GDBusMethodInvocation *invocation, + MMIfaceModemLocation *self) +{ + DbusCallContext *ctx; + + ctx = g_new (DbusCallContext, 1); + ctx->skeleton = g_object_ref (skeleton); + ctx->invocation = g_object_ref (invocation); + ctx->self = g_object_ref (self); + return ctx; +} + +/*****************************************************************************/ + +typedef struct { + gboolean interface_enabled; +} LocationContext; + +static LocationContext * +get_location_context (MMIfaceModemLocation *self) +{ + LocationContext *ctx; + + if (G_UNLIKELY (!location_context_quark)) + location_context_quark = (g_quark_from_static_string ( + LOCATION_CONTEXT_TAG)); + + ctx = g_object_get_qdata (G_OBJECT (self), location_context_quark); + if (!ctx) { + /* Create context and keep it as object data */ + ctx = g_new0 (LocationContext, 1); + + g_object_set_qdata_full ( + G_OBJECT (self), + location_context_quark, + ctx, + (GDestroyNotify)g_free); + } + + return ctx; +} + +/*****************************************************************************/ + +static void +enable_location_gathering_ready (MMIfaceModemLocation *self, + GAsyncResult *res, + DbusCallContext *ctx) +{ + GError *error = NULL; + + if (!MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->enable_location_gathering_finish (self, + res, + &error)) + g_dbus_method_invocation_take_error (ctx->invocation, error); + else { + mm_gdbus_modem_location_set_enabled (ctx->skeleton, TRUE); + mm_gdbus_modem_location_complete_enable (ctx->skeleton, + ctx->invocation); + } + + dbus_call_context_free (ctx); +} + +static void +disable_location_gathering_ready (MMIfaceModemLocation *self, + GAsyncResult *res, + DbusCallContext *ctx) +{ + GError *error = NULL; + + if (!MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->disable_location_gathering_finish (self, + res, + &error)) + g_dbus_method_invocation_take_error (ctx->invocation, error); + else { + mm_gdbus_modem_location_set_enabled (ctx->skeleton, FALSE); + mm_gdbus_modem_location_complete_enable (ctx->skeleton, + ctx->invocation); + } + + dbus_call_context_free (ctx); +} + static gboolean -handle_enable (MmGdbusModemLocation *object, +handle_enable (MmGdbusModemLocation *skeleton, GDBusMethodInvocation *invocation, gboolean enable, gboolean signal_location, MMIfaceModemLocation *self) { - return FALSE; + LocationContext *ctx; + + ctx = get_location_context (self); + + /* Enabling */ + if (enable) { + mm_dbg ("Enabling location gathering%s...", + signal_location ? " (with signaling)" : ""); + + /* Update the new signal location value */ + if (mm_gdbus_modem_location_get_signals_location (skeleton) != signal_location) { + mm_dbg ("%s location signaling", + signal_location ? "Enabling" : "Disabling"); + mm_gdbus_modem_location_set_signals_location (skeleton, signal_location); + if (!signal_location) + /* If disabling, cleanup currently available value */ + mm_gdbus_modem_location_set_location (skeleton, NULL); + } + + /* If already enabled, just done */ + if (mm_gdbus_modem_location_get_enabled (skeleton)) + mm_gdbus_modem_location_complete_enable (skeleton, invocation); + /* Plugins can run custom actions to enable location gathering */ + else if (ctx->interface_enabled && + MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->enable_location_gathering && + MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->enable_location_gathering_finish) + MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->enable_location_gathering ( + self, + (GAsyncReadyCallback)enable_location_gathering_ready, + dbus_call_context_new (skeleton, + invocation, + self)); + else { + /* If no plugin-specific setup needed or interface not yet enabled, just done */ + mm_gdbus_modem_location_set_enabled (skeleton, TRUE); + mm_gdbus_modem_location_complete_enable (skeleton, invocation); + } + } + /* Disabling */ + else { + mm_dbg ("Disabling location gathering..."); + + /* If already disabled, just done */ + if (!mm_gdbus_modem_location_get_enabled (skeleton)) + mm_gdbus_modem_location_complete_enable (skeleton, invocation); + /* Plugins can run custom actions to disable location gathering */ + else if (ctx->interface_enabled && + MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->disable_location_gathering && + MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->disable_location_gathering_finish) + MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->disable_location_gathering ( + self, + (GAsyncReadyCallback)disable_location_gathering_ready, + dbus_call_context_new (skeleton, + invocation, + self)); + else { + /* If no plugin-specific setup needed, or interface not yet enabled, just done */ + mm_gdbus_modem_location_set_enabled (skeleton, FALSE); + mm_gdbus_modem_location_complete_enable (skeleton, invocation); + } + } + + return TRUE; } /*****************************************************************************/ @@ -52,6 +219,262 @@ handle_get_location (MmGdbusModemLocation *object, /*****************************************************************************/ +typedef struct _DisablingContext DisablingContext; +static void interface_disabling_step (DisablingContext *ctx); + +typedef enum { + DISABLING_STEP_FIRST, + DISABLING_STEP_DISABLE_GATHERING, + DISABLING_STEP_LAST +} DisablingStep; + +struct _DisablingContext { + MMIfaceModemLocation *self; + MMAtSerialPort *primary; + DisablingStep step; + GSimpleAsyncResult *result; + MmGdbusModemLocation *skeleton; +}; + +static DisablingContext * +disabling_context_new (MMIfaceModemLocation *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + DisablingContext *ctx; + + ctx = g_new0 (DisablingContext, 1); + ctx->self = g_object_ref (self); + ctx->primary = g_object_ref (mm_base_modem_get_port_primary (MM_BASE_MODEM (self))); + ctx->result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + disabling_context_new); + ctx->step = DISABLING_STEP_FIRST; + g_object_get (ctx->self, + MM_IFACE_MODEM_LOCATION_DBUS_SKELETON, &ctx->skeleton, + NULL); + g_assert (ctx->skeleton != NULL); + + return ctx; +} + +static void +disabling_context_complete_and_free (DisablingContext *ctx) +{ + g_simple_async_result_complete_in_idle (ctx->result); + g_object_unref (ctx->self); + g_object_unref (ctx->primary); + g_object_unref (ctx->result); + g_object_unref (ctx->skeleton); + g_free (ctx); +} + +gboolean +mm_iface_modem_location_disable_finish (MMIfaceModemLocation *self, + GAsyncResult *res, + GError **error) +{ + return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); +} + +static void +disabling_location_gathering_ready (MMIfaceModemLocation *self, + GAsyncResult *res, + DisablingContext *ctx) +{ + GError *error = NULL; + + if (!MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->disable_location_gathering_finish (self, + res, + &error)) { + g_simple_async_result_take_error (ctx->result, error); + disabling_context_complete_and_free (ctx); + return; + } + + mm_gdbus_modem_location_set_enabled (ctx->skeleton, FALSE); + + /* Go on to next step */ + ctx->step++; + interface_disabling_step (ctx); +} + +static void +interface_disabling_step (DisablingContext *ctx) +{ + LocationContext *location_context; + + location_context = get_location_context (ctx->self); + + switch (ctx->step) { + case DISABLING_STEP_FIRST: + /* Fall down to next step */ + ctx->step++; + + case DISABLING_STEP_DISABLE_GATHERING: + if (mm_gdbus_modem_location_get_enabled (ctx->skeleton) && + MM_IFACE_MODEM_LOCATION_GET_INTERFACE (ctx->self)->disable_location_gathering && + MM_IFACE_MODEM_LOCATION_GET_INTERFACE (ctx->self)->disable_location_gathering_finish) { + MM_IFACE_MODEM_LOCATION_GET_INTERFACE (ctx->self)->disable_location_gathering ( + ctx->self, + (GAsyncReadyCallback)disabling_location_gathering_ready, + ctx); + return; + } + /* Fall down to next step */ + ctx->step++; + + case DISABLING_STEP_LAST: + /* We are done without errors! */ + location_context->interface_enabled = FALSE; + g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); + disabling_context_complete_and_free (ctx); + return; + } + + g_assert_not_reached (); +} + +void +mm_iface_modem_location_disable (MMIfaceModemLocation *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + interface_disabling_step (disabling_context_new (self, + callback, + user_data)); +} + +/*****************************************************************************/ + +typedef struct _EnablingContext EnablingContext; +static void interface_enabling_step (EnablingContext *ctx); + +typedef enum { + ENABLING_STEP_FIRST, + ENABLING_STEP_ENABLE_GATHERING, + ENABLING_STEP_LAST +} EnablingStep; + +struct _EnablingContext { + MMIfaceModemLocation *self; + MMAtSerialPort *primary; + EnablingStep step; + GSimpleAsyncResult *result; + MmGdbusModemLocation *skeleton; +}; + +static EnablingContext * +enabling_context_new (MMIfaceModemLocation *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + EnablingContext *ctx; + + ctx = g_new0 (EnablingContext, 1); + ctx->self = g_object_ref (self); + ctx->primary = g_object_ref (mm_base_modem_get_port_primary (MM_BASE_MODEM (self))); + ctx->result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + enabling_context_new); + ctx->step = ENABLING_STEP_FIRST; + g_object_get (ctx->self, + MM_IFACE_MODEM_LOCATION_DBUS_SKELETON, &ctx->skeleton, + NULL); + g_assert (ctx->skeleton != NULL); + + return ctx; +} + +static void +enabling_context_complete_and_free (EnablingContext *ctx) +{ + g_simple_async_result_complete_in_idle (ctx->result); + g_object_unref (ctx->self); + g_object_unref (ctx->primary); + g_object_unref (ctx->result); + g_object_unref (ctx->skeleton); + g_free (ctx); +} + +gboolean +mm_iface_modem_location_enable_finish (MMIfaceModemLocation *self, + GAsyncResult *res, + GError **error) +{ + return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); +} + +static void +enabling_location_gathering_ready (MMIfaceModemLocation *self, + GAsyncResult *res, + EnablingContext *ctx) +{ + GError *error = NULL; + + if (!MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->enable_location_gathering_finish (self, + res, + &error)) { + g_simple_async_result_take_error (ctx->result, error); + enabling_context_complete_and_free (ctx); + return; + } + + /* Go on to next step */ + ctx->step++; + interface_enabling_step (ctx); +} + +static void +interface_enabling_step (EnablingContext *ctx) +{ + LocationContext *location_context; + + location_context = get_location_context (ctx->self); + + switch (ctx->step) { + case ENABLING_STEP_FIRST: + /* Fall down to next step */ + ctx->step++; + + case ENABLING_STEP_ENABLE_GATHERING: + if (mm_gdbus_modem_location_get_enabled (ctx->skeleton) && + MM_IFACE_MODEM_LOCATION_GET_INTERFACE (ctx->self)->enable_location_gathering && + MM_IFACE_MODEM_LOCATION_GET_INTERFACE (ctx->self)->enable_location_gathering_finish) { + MM_IFACE_MODEM_LOCATION_GET_INTERFACE (ctx->self)->enable_location_gathering ( + ctx->self, + (GAsyncReadyCallback)enabling_location_gathering_ready, + ctx); + return; + } + /* Fall down to next step */ + ctx->step++; + + case ENABLING_STEP_LAST: + /* We are done without errors! */ + location_context->interface_enabled = TRUE; + g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); + enabling_context_complete_and_free (ctx); + return; + } + + g_assert_not_reached (); +} + +void +mm_iface_modem_location_enable (MMIfaceModemLocation *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + interface_enabling_step (enabling_context_new (self, + callback, + user_data)); +} + +/*****************************************************************************/ + typedef struct _InitializationContext InitializationContext; static void interface_initialization_step (InitializationContext *ctx); @@ -220,8 +643,8 @@ mm_iface_modem_location_initialize (MMIfaceModemLocation *self, /* Set all initial property defaults */ mm_gdbus_modem_location_set_capabilities (skeleton, MM_MODEM_LOCATION_SOURCE_NONE); mm_gdbus_modem_location_set_enabled (skeleton, TRUE); - mm_gdbus_modem_location_set_location (skeleton, NULL); mm_gdbus_modem_location_set_signals_location (skeleton, FALSE); + mm_gdbus_modem_location_set_location (skeleton, NULL); g_object_set (self, MM_IFACE_MODEM_LOCATION_DBUS_SKELETON, skeleton, diff --git a/src/mm-iface-modem-location.h b/src/mm-iface-modem-location.h index 72220535..f332d139 100644 --- a/src/mm-iface-modem-location.h +++ b/src/mm-iface-modem-location.h @@ -40,6 +40,22 @@ struct _MMIfaceModemLocation { MMModemLocationSource (*load_capabilities_finish) (MMIfaceModemLocation *self, GAsyncResult *res, GError **error); + + /* Enable location gathering (async) */ + void (* enable_location_gathering) (MMIfaceModemLocation *self, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (*enable_location_gathering_finish) (MMIfaceModemLocation *self, + GAsyncResult *res, + GError **error); + + /* Disable location gathering (async) */ + void (* disable_location_gathering) (MMIfaceModemLocation *self, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (*disable_location_gathering_finish) (MMIfaceModemLocation *self, + GAsyncResult *res, + GError **error); }; GType mm_iface_modem_location_get_type (void); @@ -53,6 +69,22 @@ gboolean mm_iface_modem_location_initialize_finish (MMIfaceModemLocation *self, GAsyncResult *res, GError **error); +/* Enable Location interface (async) */ +void mm_iface_modem_location_enable (MMIfaceModemLocation *self, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean mm_iface_modem_location_enable_finish (MMIfaceModemLocation *self, + GAsyncResult *res, + GError **error); + +/* Disable Location interface (async) */ +void mm_iface_modem_location_disable (MMIfaceModemLocation *self, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean mm_iface_modem_location_disable_finish (MMIfaceModemLocation *self, + GAsyncResult *res, + GError **error); + /* Shutdown Location interface */ void mm_iface_modem_location_shutdown (MMIfaceModemLocation *self); |