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