diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2012-03-26 19:24:25 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2012-03-29 09:17:53 +0200 |
commit | ceefa2c356ae270c7dda4b5e771d225502d4913d (patch) | |
tree | 5caa9ef50a9d633d00a91a371f165b0af72acd86 | |
parent | 090e3492095cf6d663bfb3f83b3ed0cb19121f1a (diff) |
location: rework to allow multiple location sources
Location sources can now be enabled or disabled by using the mask of sources
given in Setup() (similar previous Enable()).
-rw-r--r-- | cli/mmcli-modem-location.c | 77 | ||||
-rw-r--r-- | introspection/org.freedesktop.ModemManager1.Modem.Location.xml | 25 | ||||
-rw-r--r-- | libmm-glib/mm-modem-location.c | 87 | ||||
-rw-r--r-- | libmm-glib/mm-modem-location.h | 39 | ||||
-rw-r--r-- | src/mm-iface-modem-location.c | 515 | ||||
-rw-r--r-- | src/mm-iface-modem-location.h | 2 |
6 files changed, 478 insertions, 267 deletions
diff --git a/cli/mmcli-modem-location.c b/cli/mmcli-modem-location.c index 22e7aa1a..d4f8b171 100644 --- a/cli/mmcli-modem-location.c +++ b/cli/mmcli-modem-location.c @@ -16,6 +16,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Copyright (C) 2012 Google, Inc. + * Copyright (C) 2012 Lanedo GmbH <aleksander@lanedo.com> */ #include "config.h" @@ -43,17 +44,17 @@ typedef struct { static Context *ctx; /* Options */ -static gboolean enable_flag; -static gboolean disable_flag; +static gboolean enable_3gpp_flag; +static gboolean disable_3gpp_flag; static gboolean get_3gpp_flag; static GOptionEntry entries[] = { - { "location-enable", 0, 0, G_OPTION_ARG_NONE, &enable_flag, - "Enable location gathering.", + { "location-enable-3gpp", 0, 0, G_OPTION_ARG_NONE, &enable_3gpp_flag, + "Enable 3GPP location gathering.", NULL }, - { "location-disable", 0, 0, G_OPTION_ARG_NONE, &disable_flag, - "Disable location gathering.", + { "location-disable-3gpp", 0, 0, G_OPTION_ARG_NONE, &disable_3gpp_flag, + "Disable 3GPP location gathering.", NULL }, { "location-get-3gpp", 0, 0, G_OPTION_ARG_NONE, &get_3gpp_flag, @@ -87,8 +88,8 @@ mmcli_modem_location_options_enabled (void) if (checked) return !!n_actions; - n_actions = (enable_flag + - disable_flag + + n_actions = (enable_3gpp_flag + + disable_3gpp_flag + get_3gpp_flag); if (n_actions > 1) { @@ -159,7 +160,7 @@ enable_ready (MMModemLocation *modem_location, gboolean operation_result; GError *error = NULL; - operation_result = mm_modem_location_enable_finish (modem_location, result, &error); + operation_result = mm_modem_location_setup_finish (modem_location, result, &error); enable_process_reply (operation_result, error); mmcli_async_operation_done (); @@ -185,7 +186,7 @@ disable_ready (MMModemLocation *modem_location, gboolean operation_result; GError *error = NULL; - operation_result = mm_modem_location_disable_finish (modem_location, result, &error); + operation_result = mm_modem_location_setup_finish (modem_location, result, &error); disable_process_reply (operation_result, error); mmcli_async_operation_done (); @@ -238,24 +239,28 @@ get_modem_ready (GObject *source, ensure_modem_location (); /* Request to enable location gathering? */ - if (enable_flag) { - g_debug ("Asynchronously enabling location gathering..."); - - mm_modem_location_enable (ctx->modem_location, - ctx->cancellable, - (GAsyncReadyCallback)enable_ready, - NULL); + if (enable_3gpp_flag) { + g_debug ("Asynchronously enabling 3GPP location gathering..."); + + mm_modem_location_setup (ctx->modem_location, + mm_modem_location_get_capabilities (ctx->modem_location) | MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI, + mm_modem_location_signals_location (ctx->modem_location), + ctx->cancellable, + (GAsyncReadyCallback)enable_ready, + NULL); return; } /* Request to disable location gathering? */ - if (disable_flag) { - g_debug ("Asynchronously enabling location gathering..."); - - mm_modem_location_disable (ctx->modem_location, - ctx->cancellable, - (GAsyncReadyCallback)disable_ready, - NULL); + if (disable_3gpp_flag) { + g_debug ("Asynchronously disabling 3GPP location gathering..."); + + mm_modem_location_setup (ctx->modem_location, + mm_modem_location_get_capabilities (ctx->modem_location) & ~MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI, + mm_modem_location_signals_location (ctx->modem_location), + ctx->cancellable, + (GAsyncReadyCallback)disable_ready, + NULL); return; } @@ -305,27 +310,31 @@ mmcli_modem_location_run_synchronous (GDBusConnection *connection) ensure_modem_location (); /* Request to enable location gathering? */ - if (enable_flag) { + if (enable_3gpp_flag) { gboolean result; - g_debug ("Asynchronously enabling location gathering..."); + g_debug ("Asynchronously enabling 3GPP location gathering..."); - result = mm_modem_location_enable_sync (ctx->modem_location, - NULL, - &error); + result = mm_modem_location_setup_sync (ctx->modem_location, + mm_modem_location_get_capabilities (ctx->modem_location) | MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI, + mm_modem_location_signals_location (ctx->modem_location), + NULL, + &error); enable_process_reply (result, error); return; } /* Request to disable location gathering? */ - if (disable_flag) { + if (disable_3gpp_flag) { gboolean result; - g_debug ("Asynchronously enabling location gathering..."); + g_debug ("Asynchronously disabling 3GPP location gathering..."); - result = mm_modem_location_disable_sync (ctx->modem_location, - NULL, - &error); + result = mm_modem_location_setup_sync (ctx->modem_location, + mm_modem_location_get_capabilities (ctx->modem_location) & ~MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI, + mm_modem_location_signals_location (ctx->modem_location), + NULL, + &error); disable_process_reply (result, error); return; } diff --git a/introspection/org.freedesktop.ModemManager1.Modem.Location.xml b/introspection/org.freedesktop.ModemManager1.Modem.Location.xml index 4673a28a..b19283e1 100644 --- a/introspection/org.freedesktop.ModemManager1.Modem.Location.xml +++ b/introspection/org.freedesktop.ModemManager1.Modem.Location.xml @@ -23,12 +23,13 @@ <interface name="org.freedesktop.ModemManager1.Modem.Location"> <!-- - Enable: - @enable: %TRUE to enable location information gathering, %FALSE to disable. + Setup: + @sources: Bitmask of <link linkend="MMModemLocationSource">MMModemLocationSource</link> flags, specifying which sources should get enabled or disabled. <link linkend="MM-MODEM-LOCATION-SOURCE-NONE:CAPS">MM_MODEM_LOCATION_SOURCE_NONE</link> will disable all location gathering. @signal_location: Flag to control whether the device emits signals with the new location information. This argument is ignored when disabling location information gathering. - Enable or disable location information gathering. This method may - require the client to authenticate itself. + Configure the location sources to use when gathering location + information. Also enable or disable location information gathering. + This method may require the client to authenticate itself. When signals are emitted, any client application (including malicious ones!) can listen for location updates unless D-Bus permissions restrict @@ -40,8 +41,8 @@ ) to get location information. --> - <method name="Enable"> - <arg name="enable" type="b" direction="in" /> + <method name="Setup"> + <arg name="sources" type="u" direction="in" /> <arg name="signal_location" type="b" direction="in" /> </method> @@ -64,18 +65,18 @@ Capabilities: Bitmask of <link linkend="MMModemLocationSource">MMModemLocationSource</link> - values, specifying the location retrieval capabilities of the device. + values, specifying the supported location sources. --> <property name="Capabilities" type="u" access="read" /> <!-- Enabled: - %TRUE if location information gathering is enabled for this device, - %FALSE if it is disabled. When disabled, the device will not provide - location information. + Bitmask specifying which of the supported + <link linkend="MMModemLocationSource">MMModemLocationSource</link> + location sources is currently enabled in the device. --> - <property name="Enabled" type="b" access="read" /> + <property name="Enabled" type="u" access="read" /> <!-- SignalsLocation: @@ -84,7 +85,7 @@ location updates will not be emitted. See the - <link linkend="gdbus-method-org-freedesktop-ModemManager1-Modem-Location.Enable">Enable()</link> + <link linkend="gdbus-method-org-freedesktop-ModemManager1-Modem-Location.Setup">Setup()</link> method for more information. --> <property name="SignalsLocation" type="b" access="read" /> diff --git a/libmm-glib/mm-modem-location.c b/libmm-glib/mm-modem-location.c index c800fa3b..4f88d7ee 100644 --- a/libmm-glib/mm-modem-location.c +++ b/libmm-glib/mm-modem-location.c @@ -18,6 +18,7 @@ * Boston, MA 02110-1301 USA. * * Copyright (C) 2012 Google, Inc. + * Copyright (C) 2012 Lanedo GmbH <aleksander@lanedo.com> */ #include <gio/gio.h> @@ -72,92 +73,64 @@ mm_modem_location_get_capabilities (MMModemLocation *self) return (MMModemLocationSource) mm_gdbus_modem_location_get_capabilities (self); } -gboolean +MMModemLocationSource mm_modem_location_get_enabled (MMModemLocation *self) { g_return_val_if_fail (MM_GDBUS_IS_MODEM_LOCATION (self), FALSE); - return mm_gdbus_modem_location_get_enabled (self); + return (MMModemLocationSource) mm_gdbus_modem_location_get_enabled (self); } gboolean -mm_modem_location_disable_finish (MMModemLocation *self, - GAsyncResult *res, - GError **error) +mm_modem_location_signals_location (MMModemLocation *self) { g_return_val_if_fail (MM_GDBUS_IS_MODEM_LOCATION (self), FALSE); - return mm_gdbus_modem_location_call_enable_finish (self, res, error); -} - -void -mm_modem_location_disable (MMModemLocation *self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_return_if_fail (MM_GDBUS_IS_MODEM_LOCATION (self)); - - mm_gdbus_modem_location_call_enable (self, - FALSE, - FALSE, - cancellable, - callback, - user_data); + return mm_gdbus_modem_location_get_signals_location (self); } gboolean -mm_modem_location_disable_sync (MMModemLocation *self, - GCancellable *cancellable, +mm_modem_location_setup_finish (MMModemLocation *self, + GAsyncResult *res, GError **error) { g_return_val_if_fail (MM_GDBUS_IS_MODEM_LOCATION (self), FALSE); - return mm_gdbus_modem_location_call_enable_sync (self, - FALSE, - FALSE, - cancellable, - error); -} - -gboolean -mm_modem_location_enable_finish (MMModemLocation *self, - GAsyncResult *res, - GError **error) -{ - g_return_val_if_fail (MM_GDBUS_IS_MODEM_LOCATION (self), FALSE); - - return mm_gdbus_modem_location_call_enable_finish (self, res, error); + return mm_gdbus_modem_location_call_setup_finish (self, res, error); } void -mm_modem_location_enable (MMModemLocation *self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +mm_modem_location_setup (MMModemLocation *self, + MMModemLocationSource sources, + gboolean signal_location, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { g_return_if_fail (MM_GDBUS_IS_MODEM_LOCATION (self)); - mm_gdbus_modem_location_call_enable (self, - TRUE, - FALSE /* signal_location */, - cancellable, - callback, - user_data); + mm_gdbus_modem_location_call_setup (self, + sources, + signal_location, + cancellable, + callback, + user_data); } gboolean -mm_modem_location_enable_sync (MMModemLocation *self, - GCancellable *cancellable, - GError **error) +mm_modem_location_setup_sync (MMModemLocation *self, + MMModemLocationSource sources, + gboolean signal_location, + GCancellable *cancellable, + GError **error) { g_return_val_if_fail (MM_GDBUS_IS_MODEM_LOCATION (self), FALSE); - return mm_gdbus_modem_location_call_enable_sync (self, - TRUE, - FALSE /* signal_location */, - cancellable, - error); + return mm_gdbus_modem_location_call_setup_sync (self, + sources, + signal_location, + cancellable, + error); } static MMLocation3gpp * diff --git a/libmm-glib/mm-modem-location.h b/libmm-glib/mm-modem-location.h index b92040db..216704c0 100644 --- a/libmm-glib/mm-modem-location.h +++ b/libmm-glib/mm-modem-location.h @@ -18,6 +18,7 @@ * Boston, MA 02110-1301 USA. * * Copyright (C) 2012 Google, Inc. + * Copyright (C) 2012 Lanedo GmbH <aleksander@lanedo.com> */ #ifndef _MM_MODEM_LOCATION_H_ @@ -37,29 +38,23 @@ const gchar *mm_modem_location_get_path (MMModemLocation *self); gchar *mm_modem_location_dup_path (MMModemLocation *self); MMModemLocationSource mm_modem_location_get_capabilities (MMModemLocation *self); -gboolean mm_modem_location_get_enabled (MMModemLocation *self); +MMModemLocationSource mm_modem_location_get_enabled (MMModemLocation *self); +gboolean mm_modem_location_signals_location (MMModemLocation *self); -void mm_modem_location_enable (MMModemLocation *self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_modem_location_enable_finish (MMModemLocation *self, - GAsyncResult *res, - GError **error); -gboolean mm_modem_location_enable_sync (MMModemLocation *self, - GCancellable *cancellable, - GError **error); - -void mm_modem_location_disable (MMModemLocation *self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_modem_location_disable_finish (MMModemLocation *self, - GAsyncResult *res, - GError **error); -gboolean mm_modem_location_disable_sync (MMModemLocation *self, - GCancellable *cancellable, - GError **error); +void mm_modem_location_setup (MMModemLocation *self, + MMModemLocationSource sources, + gboolean signal_location, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean mm_modem_location_setup_finish (MMModemLocation *self, + GAsyncResult *res, + GError **error); +gboolean mm_modem_location_setup_sync (MMModemLocation *self, + MMModemLocationSource sources, + gboolean signal_location, + GCancellable *cancellable, + GError **error); void mm_modem_location_get_3gpp (MMModemLocation *self, GCancellable *cancellable, diff --git a/src/mm-iface-modem-location.c b/src/mm-iface-modem-location.c index 2003943d..dc5e0805 100644 --- a/src/mm-iface-modem-location.c +++ b/src/mm-iface-modem-location.c @@ -11,6 +11,7 @@ * GNU General Public License for more details: * * Copyright (C) 2012 Google, Inc. + * Copyright (C) 2012 Lanedo GmbH <aleksander@lanedo.com> */ #include <ModemManager.h> @@ -141,12 +142,10 @@ mm_iface_modem_location_3gpp_update_mcc_mnc (MMIfaceModemLocation *self, MM_IFACE_MODEM_LOCATION_DBUS_SKELETON, &skeleton, NULL); - if (mm_gdbus_modem_location_get_enabled (skeleton)) { + if (mm_gdbus_modem_location_get_enabled (skeleton) & MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI) { guint changed = 0; - if (G_UNLIKELY (!ctx->location_3gpp)) - ctx->location_3gpp = mm_location_3gpp_new (); - + g_assert (ctx->location_3gpp != NULL); changed += mm_location_3gpp_set_mobile_country_code (ctx->location_3gpp, mobile_country_code); changed += mm_location_3gpp_set_mobile_network_code (ctx->location_3gpp, @@ -171,12 +170,10 @@ mm_iface_modem_location_3gpp_update_lac_ci (MMIfaceModemLocation *self, MM_IFACE_MODEM_LOCATION_DBUS_SKELETON, &skeleton, NULL); - if (mm_gdbus_modem_location_get_enabled (skeleton)) { + if (mm_gdbus_modem_location_get_enabled (skeleton) & MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI) { guint changed = 0; - if (G_UNLIKELY (!ctx->location_3gpp)) - ctx->location_3gpp = mm_location_3gpp_new (); - + g_assert (ctx->location_3gpp != NULL); changed += mm_location_3gpp_set_location_area_code (ctx->location_3gpp, location_area_code); changed += mm_location_3gpp_set_cell_id (ctx->location_3gpp, @@ -199,12 +196,10 @@ mm_iface_modem_location_3gpp_clear (MMIfaceModemLocation *self) MM_IFACE_MODEM_LOCATION_DBUS_SKELETON, &skeleton, NULL); - if (mm_gdbus_modem_location_get_enabled (skeleton)) { + if (mm_gdbus_modem_location_get_enabled (skeleton) & MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI) { guint changed = 0; - if (G_UNLIKELY (!ctx->location_3gpp)) - ctx->location_3gpp = mm_location_3gpp_new (); - + g_assert (ctx->location_3gpp != NULL); changed += mm_location_3gpp_set_location_area_code (ctx->location_3gpp, 0); changed += mm_location_3gpp_set_cell_id (ctx->location_3gpp, 0); changed += mm_location_3gpp_set_mobile_country_code (ctx->location_3gpp, 0); @@ -218,164 +213,394 @@ mm_iface_modem_location_3gpp_clear (MMIfaceModemLocation *self) /*****************************************************************************/ +static void +update_location_source_status (MMIfaceModemLocation *self, + MMModemLocationSource source, + gboolean enabled) +{ + MMModemLocationSource mask; + MmGdbusModemLocation *skeleton = NULL; + LocationContext *ctx; + + g_object_get (self, + MM_IFACE_MODEM_LOCATION_DBUS_SKELETON, &skeleton, + NULL); + g_assert (skeleton != NULL); + + /* Update status in the interface */ + mask = mm_gdbus_modem_location_get_enabled (skeleton); + if (enabled) + mask |= source; + else + mask &= ~source; + + /* Update status in the context */ + ctx = get_location_context (self); + + switch (source) { + case MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI: + if (enabled) { + if (!ctx->location_3gpp) + ctx->location_3gpp = mm_location_3gpp_new (); + } else + g_clear_object (&ctx->location_3gpp); + break; + default: + break; + } + + mm_gdbus_modem_location_set_enabled (skeleton, mask); + + g_object_unref (skeleton); +} + +/*****************************************************************************/ + typedef struct { - MmGdbusModemLocation *skeleton; - GDBusMethodInvocation *invocation; MMIfaceModemLocation *self; - gboolean enable; - gboolean signal_location; -} HandleEnableContext; + MmGdbusModemLocation *skeleton; + GSimpleAsyncResult *result; + MMModemLocationSource to_enable; + MMModemLocationSource to_disable; + MMModemLocationSource current; +} SetupGatheringContext; + +static void setup_gathering_step (SetupGatheringContext *ctx); static void -handle_enable_context_free (HandleEnableContext *ctx) +setup_gathering_context_complete_and_free (SetupGatheringContext *ctx) { + g_simple_async_result_complete_in_idle (ctx->result); + g_object_unref (ctx->result); g_object_unref (ctx->skeleton); - g_object_unref (ctx->invocation); g_object_unref (ctx->self); g_free (ctx); } +static gboolean +setup_gathering_finish (MMIfaceModemLocation *self, + GAsyncResult *res, + GError **error) +{ + return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); +} + static void enable_location_gathering_ready (MMIfaceModemLocation *self, GAsyncResult *res, - HandleEnableContext *ctx) + SetupGatheringContext *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); + if (!MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->enable_location_gathering_finish (self, res, &error)) { + gchar *str; + + str = mm_modem_location_source_build_string_from_mask (ctx->current); + g_prefix_error (&error, + "Couldn't enable location '%s' gathering: ", + str); + g_simple_async_result_take_error (ctx->result, error); + setup_gathering_context_complete_and_free (ctx); + g_free (str); + return; } - handle_enable_context_free (ctx); + update_location_source_status (self, ctx->current, TRUE); + + /* Keep on with next ones... */ + ctx->current = ctx->current << 1; + setup_gathering_step (ctx); } static void disable_location_gathering_ready (MMIfaceModemLocation *self, GAsyncResult *res, - HandleEnableContext *ctx) + SetupGatheringContext *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 { - clear_location_context (self); - mm_gdbus_modem_location_set_enabled (ctx->skeleton, FALSE); - mm_gdbus_modem_location_complete_enable (ctx->skeleton, - ctx->invocation); + if (!MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->disable_location_gathering_finish (self, res, &error)) { + gchar *str; + + str = mm_modem_location_source_build_string_from_mask (ctx->current); + g_prefix_error (&error, + "Couldn't disable location '%s' gathering: ", + str); + g_simple_async_result_take_error (ctx->result, error); + setup_gathering_context_complete_and_free (ctx); + g_free (str); + return; } - handle_enable_context_free (ctx); + update_location_source_status (self, ctx->current, FALSE); + + /* Keep on with next ones... */ + ctx->current = ctx->current << 1; + setup_gathering_step (ctx); } static void -handle_enable_auth_ready (MMBaseModem *self, - GAsyncResult *res, - HandleEnableContext *ctx) +setup_gathering_step (SetupGatheringContext *ctx) { - GError *error = NULL; - - if (!mm_base_modem_authorize_finish (self, res, &error)) { - g_dbus_method_invocation_take_error (ctx->invocation, error); - handle_enable_context_free (ctx); + /* Are we done? */ + if (ctx->to_enable == MM_MODEM_LOCATION_SOURCE_NONE && + ctx->to_disable == MM_MODEM_LOCATION_SOURCE_NONE) { + g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); + setup_gathering_context_complete_and_free (ctx); return; } - /* Enabling */ - if (ctx->enable) { - LocationContext *location_ctx; - - location_ctx = get_location_context (ctx->self); - mm_dbg ("Enabling location gathering%s...", - ctx->signal_location ? " (with signaling)" : ""); - - /* Update the new signal location value */ - if (mm_gdbus_modem_location_get_signals_location (ctx->skeleton) != ctx->signal_location) { - mm_dbg ("%s location signaling", - ctx->signal_location ? "Enabling" : "Disabling"); - mm_gdbus_modem_location_set_signals_location (ctx->skeleton, - ctx->signal_location); - mm_gdbus_modem_location_set_location (ctx->skeleton, - build_location_dictionary (ctx->signal_location ? - location_ctx->location_3gpp : - NULL)); + while (ctx->current <= MM_MODEM_LOCATION_SOURCE_GPS_NMEA) { + gchar *source_str; + + if (ctx->to_enable & ctx->current) { + /* Remove from mask */ + ctx->to_enable &= ~ctx->current; + + /* Plugins can run custom actions to enable location gathering */ + if (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 ( + MM_IFACE_MODEM_LOCATION (ctx->self), + ctx->current, + (GAsyncReadyCallback)enable_location_gathering_ready, + ctx); + return; + } + + update_location_source_status (ctx->self, ctx->current, TRUE); + + source_str = mm_modem_location_source_build_string_from_mask (ctx->current); + mm_dbg ("Enabled location '%s' gathering...", source_str); + g_free (source_str); + } else if (ctx->to_disable & ctx->current) { + /* Remove from mask */ + ctx->to_disable &= ~ctx->current; + + /* Plugins can run custom actions to disable location gathering */ + if (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 ( + MM_IFACE_MODEM_LOCATION (ctx->self), + ctx->current, + (GAsyncReadyCallback)disable_location_gathering_ready, + ctx); + return; + } + + update_location_source_status (ctx->self, ctx->current, FALSE); + + source_str = mm_modem_location_source_build_string_from_mask (ctx->current); + mm_dbg ("Disabled location '%s' gathering...", source_str); + g_free (source_str); } - /* If already enabled, just done */ - if (mm_gdbus_modem_location_get_enabled (ctx->skeleton)) { - mm_gdbus_modem_location_complete_enable (ctx->skeleton, ctx->invocation); - handle_enable_context_free (ctx); - return; - } + /* go on... */ + ctx->current = ctx->current << 1; + } - /* Plugins can run custom actions to enable location gathering */ - if (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 ( - MM_IFACE_MODEM_LOCATION (self), - (GAsyncReadyCallback)enable_location_gathering_ready, - ctx); - return; + /* We just need to finish now */ + g_assert (ctx->to_enable == MM_MODEM_LOCATION_SOURCE_NONE); + g_assert (ctx->to_disable == MM_MODEM_LOCATION_SOURCE_NONE); + setup_gathering_step (ctx); +} + +static void +setup_gathering (MMIfaceModemLocation *self, + MMModemLocationSource mask, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SetupGatheringContext *ctx; + MMModemLocationSource currently_enabled; + MMModemLocationSource source; + gchar *str; + + ctx = g_new (SetupGatheringContext, 1); + ctx->self = g_object_ref (self); + ctx->result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + setup_gathering); + g_object_get (self, + MM_IFACE_MODEM_LOCATION_DBUS_SKELETON, &ctx->skeleton, + NULL); + g_assert (ctx->skeleton != NULL); + + /* Get current list of enabled sources */ + currently_enabled = mm_gdbus_modem_location_get_enabled (ctx->skeleton); + + /* Reset the list of sources to enable or disable */ + ctx->to_enable = MM_MODEM_LOCATION_SOURCE_NONE; + ctx->to_disable = MM_MODEM_LOCATION_SOURCE_NONE; + + /* Loop through all known bits in the bitmask to enable/disable specific location sources */ + for (source = MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI; + source <= MM_MODEM_LOCATION_SOURCE_GPS_NMEA; + source = source << 1) { + /* skip unsupported sources */ + if (!(mm_gdbus_modem_location_get_capabilities (ctx->skeleton) & source)) + continue; + + str = mm_modem_location_source_build_string_from_mask (source); + + if (mask & source) { + /* Source set in mask, need to enable if disabled */ + if (currently_enabled & source) + mm_dbg ("Location '%s' gathering is already enabled...", str); + else + ctx->to_enable |= source; + } else { + /* Source unset in mask, need to disable if enabled */ + if (currently_enabled & source) + ctx->to_disable |= source; + else + mm_dbg ("Location '%s' gathering is already disabled...", str); } - /* If no plugin-specific setup needed or interface not yet enabled, just done */ - mm_gdbus_modem_location_set_enabled (ctx->skeleton, TRUE); - mm_gdbus_modem_location_complete_enable (ctx->skeleton, ctx->invocation); - handle_enable_context_free (ctx); - return; + g_free (str); + } + + if (ctx->to_enable != MM_MODEM_LOCATION_SOURCE_NONE) { + str = mm_modem_location_source_build_string_from_mask (ctx->to_enable); + mm_dbg ("Need to enable the following location sources: '%s'", str); + g_free (str); + } + + if (ctx->to_disable != MM_MODEM_LOCATION_SOURCE_NONE) { + str = mm_modem_location_source_build_string_from_mask (ctx->to_disable); + mm_dbg ("Need to disable the following location sources: '%s'", str); + g_free (str); } - /* Disabling */ - mm_dbg ("Disabling location gathering..."); + /* Start enabling/disabling location sources */ + ctx->current = MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI; + setup_gathering_step (ctx); +} + +/*****************************************************************************/ + +typedef struct { + MmGdbusModemLocation *skeleton; + GDBusMethodInvocation *invocation; + MMIfaceModemLocation *self; + guint32 sources; + gboolean signal_location; +} HandleSetupContext; + +static void +handle_setup_context_free (HandleSetupContext *ctx) +{ + g_object_unref (ctx->skeleton); + g_object_unref (ctx->invocation); + g_object_unref (ctx->self); + g_free (ctx); +} + +static void +setup_gathering_ready (MMIfaceModemLocation *self, + GAsyncResult *res, + HandleSetupContext *ctx) +{ + GError *error = NULL; + + if (!setup_gathering_finish (self, res, &error)) + g_dbus_method_invocation_take_error (ctx->invocation, error); + else + mm_gdbus_modem_location_complete_setup (ctx->skeleton, ctx->invocation); + + handle_setup_context_free (ctx); +} + +static void +handle_setup_auth_ready (MMBaseModem *self, + GAsyncResult *res, + HandleSetupContext *ctx) +{ + GError *error = NULL; + MMModemState modem_state; + MMModemLocationSource not_supported; + LocationContext *location_ctx; + gchar *str; - /* If already disabled, just done */ - if (!mm_gdbus_modem_location_get_enabled (ctx->skeleton)) { - mm_gdbus_modem_location_complete_enable (ctx->skeleton, ctx->invocation); - handle_enable_context_free (ctx); + if (!mm_base_modem_authorize_finish (self, res, &error)) { + g_dbus_method_invocation_take_error (ctx->invocation, error); + handle_setup_context_free (ctx); return; } - /* Plugins can run custom actions to disable location gathering */ - if (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 ( - MM_IFACE_MODEM_LOCATION (self), - (GAsyncReadyCallback)disable_location_gathering_ready, - ctx); + modem_state = MM_MODEM_STATE_UNKNOWN; + g_object_get (self, + MM_IFACE_MODEM_STATE, &modem_state, + NULL); + if (modem_state < MM_MODEM_STATE_ENABLED) { + g_dbus_method_invocation_return_error (ctx->invocation, + MM_CORE_ERROR, + MM_CORE_ERROR_WRONG_STATE, + "Cannot setup location: " + "device not yet enabled"); + handle_setup_context_free (ctx); return; } - /* If no plugin-specific setup needed, or interface not yet enabled, just done */ - clear_location_context (ctx->self); - mm_gdbus_modem_location_set_enabled (ctx->skeleton, FALSE); - mm_gdbus_modem_location_complete_enable (ctx->skeleton, ctx->invocation); - handle_enable_context_free (ctx); + /* If any of the location sources being enabled is NOT supported, set error */ + not_supported = ((mm_gdbus_modem_location_get_capabilities (ctx->skeleton) ^ ctx->sources) & ctx->sources); + if (not_supported != MM_MODEM_LOCATION_SOURCE_NONE) { + str = mm_modem_location_source_build_string_from_mask (not_supported); + g_dbus_method_invocation_return_error (ctx->invocation, + MM_CORE_ERROR, + MM_CORE_ERROR_UNSUPPORTED, + "Cannot enable unsupported location sources: '%s'", + str); + handle_setup_context_free (ctx); + g_free (str); + return; + } + + /* Enable/disable location signaling */ + location_ctx = get_location_context (ctx->self); + if (mm_gdbus_modem_location_get_signals_location (ctx->skeleton) != ctx->signal_location) { + mm_dbg ("%s location signaling", + ctx->signal_location ? "Enabling" : "Disabling"); + mm_gdbus_modem_location_set_signals_location (ctx->skeleton, + ctx->signal_location); + mm_gdbus_modem_location_set_location (ctx->skeleton, + build_location_dictionary (ctx->signal_location ? + location_ctx->location_3gpp : + NULL)); + } + + str = mm_modem_location_source_build_string_from_mask (ctx->sources); + mm_dbg ("Setting up location sources: '%s'", str); + g_free (str); + + /* Go on to enable or disable the requested sources */ + setup_gathering (ctx->self, + ctx->sources, + (GAsyncReadyCallback)setup_gathering_ready, + ctx); } static gboolean -handle_enable (MmGdbusModemLocation *skeleton, - GDBusMethodInvocation *invocation, - gboolean enable, - gboolean signal_location, - MMIfaceModemLocation *self) +handle_setup (MmGdbusModemLocation *skeleton, + GDBusMethodInvocation *invocation, + guint32 sources, + gboolean signal_location, + MMIfaceModemLocation *self) { - HandleEnableContext *ctx; + HandleSetupContext *ctx; - ctx = g_new (HandleEnableContext, 1); + ctx = g_new (HandleSetupContext, 1); ctx->skeleton = g_object_ref (skeleton); ctx->invocation = g_object_ref (invocation); ctx->self = g_object_ref (self); - ctx->enable = enable; + ctx->sources = sources; ctx->signal_location = signal_location; mm_base_modem_authorize (MM_BASE_MODEM (self), invocation, MM_AUTHORIZATION_DEVICE_CONTROL, - (GAsyncReadyCallback)handle_enable_auth_ready, + (GAsyncReadyCallback)handle_setup_auth_ready, ctx); return TRUE; } @@ -402,6 +627,7 @@ handle_get_location_auth_ready (MMBaseModem *self, GAsyncResult *res, HandleGetLocationContext *ctx) { + MMModemState modem_state; LocationContext *location_ctx; GError *error = NULL; @@ -411,6 +637,20 @@ handle_get_location_auth_ready (MMBaseModem *self, return; } + modem_state = MM_MODEM_STATE_UNKNOWN; + g_object_get (self, + MM_IFACE_MODEM_STATE, &modem_state, + NULL); + if (modem_state < MM_MODEM_STATE_ENABLED) { + g_dbus_method_invocation_return_error (ctx->invocation, + MM_CORE_ERROR, + MM_CORE_ERROR_WRONG_STATE, + "Cannot get location: " + "device not yet enabled"); + handle_get_location_context_free (ctx); + return; + } + location_ctx = get_location_context (ctx->self); mm_gdbus_modem_location_complete_get_location ( ctx->skeleton, @@ -503,16 +743,12 @@ disabling_location_gathering_ready (MMIfaceModemLocation *self, { GError *error = NULL; - if (!MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->disable_location_gathering_finish (self, - res, - &error)) { + if (!setup_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); @@ -527,20 +763,15 @@ interface_disabling_step (DisablingContext *ctx) 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++; + setup_gathering (ctx->self, + MM_MODEM_LOCATION_SOURCE_NONE, + (GAsyncReadyCallback)disabling_location_gathering_ready, + ctx); + return; case DISABLING_STEP_LAST: /* We are done without errors! */ + clear_location_context (ctx->self); g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); disabling_context_complete_and_free (ctx); return; @@ -642,9 +873,7 @@ enabling_location_gathering_ready (MMIfaceModemLocation *self, { GError *error = NULL; - if (!MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->enable_location_gathering_finish (self, - res, - &error)) { + if (!setup_gathering_finish (self, res, &error)) { g_simple_async_result_take_error (ctx->result, error); enabling_context_complete_and_free (ctx); return; @@ -667,18 +896,20 @@ interface_enabling_step (EnablingContext *ctx) /* 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_ENABLE_GATHERING: { + MMModemLocationSource default_sources; + + /* By default, we'll enable all NON-GPS sources + * (so, only 3GPP-LAC-CI if available) */ + default_sources = mm_gdbus_modem_location_get_capabilities (ctx->skeleton); + default_sources &= ~(MM_MODEM_LOCATION_SOURCE_GPS_RAW | MM_MODEM_LOCATION_SOURCE_GPS_NMEA); + + setup_gathering (ctx->self, + default_sources, + (GAsyncReadyCallback)enabling_location_gathering_ready, + ctx); + return; + } case ENABLING_STEP_LAST: /* We are done without errors! */ @@ -839,8 +1070,8 @@ interface_initialization_step (InitializationContext *ctx) /* Handle method invocations */ g_signal_connect (ctx->skeleton, - "handle-enable", - G_CALLBACK (handle_enable), + "handle-setup", + G_CALLBACK (handle_setup), ctx->self); g_signal_connect (ctx->skeleton, "handle-get-location", @@ -889,7 +1120,7 @@ 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_enabled (skeleton, MM_MODEM_LOCATION_SOURCE_NONE); mm_gdbus_modem_location_set_signals_location (skeleton, FALSE); mm_gdbus_modem_location_set_location (skeleton, build_location_dictionary (NULL)); diff --git a/src/mm-iface-modem-location.h b/src/mm-iface-modem-location.h index 2346c0f4..19f760e4 100644 --- a/src/mm-iface-modem-location.h +++ b/src/mm-iface-modem-location.h @@ -43,6 +43,7 @@ struct _MMIfaceModemLocation { /* Enable location gathering (async) */ void (* enable_location_gathering) (MMIfaceModemLocation *self, + MMModemLocationSource source, GAsyncReadyCallback callback, gpointer user_data); gboolean (*enable_location_gathering_finish) (MMIfaceModemLocation *self, @@ -51,6 +52,7 @@ struct _MMIfaceModemLocation { /* Disable location gathering (async) */ void (* disable_location_gathering) (MMIfaceModemLocation *self, + MMModemLocationSource source, GAsyncReadyCallback callback, gpointer user_data); gboolean (*disable_location_gathering_finish) (MMIfaceModemLocation *self, |