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()).
This commit is contained in:
Aleksander Morgado
2012-03-26 19:24:25 +02:00
parent 090e349209
commit ceefa2c356
6 changed files with 486 additions and 275 deletions

View File

@@ -16,6 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
* Copyright (C) 2012 Google, Inc. * Copyright (C) 2012 Google, Inc.
* Copyright (C) 2012 Lanedo GmbH <aleksander@lanedo.com>
*/ */
#include "config.h" #include "config.h"
@@ -43,17 +44,17 @@ typedef struct {
static Context *ctx; static Context *ctx;
/* Options */ /* Options */
static gboolean enable_flag; static gboolean enable_3gpp_flag;
static gboolean disable_flag; static gboolean disable_3gpp_flag;
static gboolean get_3gpp_flag; static gboolean get_3gpp_flag;
static GOptionEntry entries[] = { static GOptionEntry entries[] = {
{ "location-enable", 0, 0, G_OPTION_ARG_NONE, &enable_flag, { "location-enable-3gpp", 0, 0, G_OPTION_ARG_NONE, &enable_3gpp_flag,
"Enable location gathering.", "Enable 3GPP location gathering.",
NULL NULL
}, },
{ "location-disable", 0, 0, G_OPTION_ARG_NONE, &disable_flag, { "location-disable-3gpp", 0, 0, G_OPTION_ARG_NONE, &disable_3gpp_flag,
"Disable location gathering.", "Disable 3GPP location gathering.",
NULL NULL
}, },
{ "location-get-3gpp", 0, 0, G_OPTION_ARG_NONE, &get_3gpp_flag, { "location-get-3gpp", 0, 0, G_OPTION_ARG_NONE, &get_3gpp_flag,
@@ -87,8 +88,8 @@ mmcli_modem_location_options_enabled (void)
if (checked) if (checked)
return !!n_actions; return !!n_actions;
n_actions = (enable_flag + n_actions = (enable_3gpp_flag +
disable_flag + disable_3gpp_flag +
get_3gpp_flag); get_3gpp_flag);
if (n_actions > 1) { if (n_actions > 1) {
@@ -159,7 +160,7 @@ enable_ready (MMModemLocation *modem_location,
gboolean operation_result; gboolean operation_result;
GError *error = NULL; 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); enable_process_reply (operation_result, error);
mmcli_async_operation_done (); mmcli_async_operation_done ();
@@ -185,7 +186,7 @@ disable_ready (MMModemLocation *modem_location,
gboolean operation_result; gboolean operation_result;
GError *error = NULL; 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); disable_process_reply (operation_result, error);
mmcli_async_operation_done (); mmcli_async_operation_done ();
@@ -238,24 +239,28 @@ get_modem_ready (GObject *source,
ensure_modem_location (); ensure_modem_location ();
/* Request to enable location gathering? */ /* Request to enable location gathering? */
if (enable_flag) { if (enable_3gpp_flag) {
g_debug ("Asynchronously enabling location gathering..."); g_debug ("Asynchronously enabling 3GPP location gathering...");
mm_modem_location_enable (ctx->modem_location, mm_modem_location_setup (ctx->modem_location,
ctx->cancellable, mm_modem_location_get_capabilities (ctx->modem_location) | MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI,
(GAsyncReadyCallback)enable_ready, mm_modem_location_signals_location (ctx->modem_location),
NULL); ctx->cancellable,
(GAsyncReadyCallback)enable_ready,
NULL);
return; return;
} }
/* Request to disable location gathering? */ /* Request to disable location gathering? */
if (disable_flag) { if (disable_3gpp_flag) {
g_debug ("Asynchronously enabling location gathering..."); g_debug ("Asynchronously disabling 3GPP location gathering...");
mm_modem_location_disable (ctx->modem_location, mm_modem_location_setup (ctx->modem_location,
ctx->cancellable, mm_modem_location_get_capabilities (ctx->modem_location) & ~MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI,
(GAsyncReadyCallback)disable_ready, mm_modem_location_signals_location (ctx->modem_location),
NULL); ctx->cancellable,
(GAsyncReadyCallback)disable_ready,
NULL);
return; return;
} }
@@ -305,27 +310,31 @@ mmcli_modem_location_run_synchronous (GDBusConnection *connection)
ensure_modem_location (); ensure_modem_location ();
/* Request to enable location gathering? */ /* Request to enable location gathering? */
if (enable_flag) { if (enable_3gpp_flag) {
gboolean result; gboolean result;
g_debug ("Asynchronously enabling location gathering..."); g_debug ("Asynchronously enabling 3GPP location gathering...");
result = mm_modem_location_enable_sync (ctx->modem_location, result = mm_modem_location_setup_sync (ctx->modem_location,
NULL, mm_modem_location_get_capabilities (ctx->modem_location) | MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI,
&error); mm_modem_location_signals_location (ctx->modem_location),
NULL,
&error);
enable_process_reply (result, error); enable_process_reply (result, error);
return; return;
} }
/* Request to disable location gathering? */ /* Request to disable location gathering? */
if (disable_flag) { if (disable_3gpp_flag) {
gboolean result; gboolean result;
g_debug ("Asynchronously enabling location gathering..."); g_debug ("Asynchronously disabling 3GPP location gathering...");
result = mm_modem_location_disable_sync (ctx->modem_location, result = mm_modem_location_setup_sync (ctx->modem_location,
NULL, mm_modem_location_get_capabilities (ctx->modem_location) & ~MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI,
&error); mm_modem_location_signals_location (ctx->modem_location),
NULL,
&error);
disable_process_reply (result, error); disable_process_reply (result, error);
return; return;
} }

View File

@@ -23,12 +23,13 @@
<interface name="org.freedesktop.ModemManager1.Modem.Location"> <interface name="org.freedesktop.ModemManager1.Modem.Location">
<!-- <!--
Enable: Setup:
@enable: %TRUE to enable location information gathering, %FALSE to disable. @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. @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 Configure the location sources to use when gathering location
require the client to authenticate itself. 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 When signals are emitted, any client application (including malicious
ones!) can listen for location updates unless D-Bus permissions restrict ones!) can listen for location updates unless D-Bus permissions restrict
@@ -40,8 +41,8 @@
) to get ) to get
location information. location information.
--> -->
<method name="Enable"> <method name="Setup">
<arg name="enable" type="b" direction="in" /> <arg name="sources" type="u" direction="in" />
<arg name="signal_location" type="b" direction="in" /> <arg name="signal_location" type="b" direction="in" />
</method> </method>
@@ -64,18 +65,18 @@
Capabilities: Capabilities:
Bitmask of <link linkend="MMModemLocationSource">MMModemLocationSource</link> 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" /> <property name="Capabilities" type="u" access="read" />
<!-- <!--
Enabled: Enabled:
%TRUE if location information gathering is enabled for this device, Bitmask specifying which of the supported
%FALSE if it is disabled. When disabled, the device will not provide <link linkend="MMModemLocationSource">MMModemLocationSource</link>
location information. location sources is currently enabled in the device.
--> -->
<property name="Enabled" type="b" access="read" /> <property name="Enabled" type="u" access="read" />
<!-- <!--
SignalsLocation: SignalsLocation:
@@ -84,7 +85,7 @@
location updates will not be emitted. location updates will not be emitted.
See the 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. method for more information.
--> -->
<property name="SignalsLocation" type="b" access="read" /> <property name="SignalsLocation" type="b" access="read" />

View File

@@ -18,6 +18,7 @@
* Boston, MA 02110-1301 USA. * Boston, MA 02110-1301 USA.
* *
* Copyright (C) 2012 Google, Inc. * Copyright (C) 2012 Google, Inc.
* Copyright (C) 2012 Lanedo GmbH <aleksander@lanedo.com>
*/ */
#include <gio/gio.h> #include <gio/gio.h>
@@ -72,92 +73,64 @@ mm_modem_location_get_capabilities (MMModemLocation *self)
return (MMModemLocationSource) mm_gdbus_modem_location_get_capabilities (self); return (MMModemLocationSource) mm_gdbus_modem_location_get_capabilities (self);
} }
gboolean MMModemLocationSource
mm_modem_location_get_enabled (MMModemLocation *self) mm_modem_location_get_enabled (MMModemLocation *self)
{ {
g_return_val_if_fail (MM_GDBUS_IS_MODEM_LOCATION (self), FALSE); 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 gboolean
mm_modem_location_disable_finish (MMModemLocation *self, mm_modem_location_signals_location (MMModemLocation *self)
GAsyncResult *res,
GError **error)
{ {
g_return_val_if_fail (MM_GDBUS_IS_MODEM_LOCATION (self), FALSE); 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_get_signals_location (self);
}
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);
} }
gboolean gboolean
mm_modem_location_disable_sync (MMModemLocation *self, mm_modem_location_setup_finish (MMModemLocation *self,
GCancellable *cancellable, GAsyncResult *res,
GError **error) GError **error)
{ {
g_return_val_if_fail (MM_GDBUS_IS_MODEM_LOCATION (self), FALSE); g_return_val_if_fail (MM_GDBUS_IS_MODEM_LOCATION (self), FALSE);
return mm_gdbus_modem_location_call_enable_sync (self, return mm_gdbus_modem_location_call_setup_finish (self, res, error);
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);
} }
void void
mm_modem_location_enable (MMModemLocation *self, mm_modem_location_setup (MMModemLocation *self,
GCancellable *cancellable, MMModemLocationSource sources,
GAsyncReadyCallback callback, gboolean signal_location,
gpointer user_data) GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{ {
g_return_if_fail (MM_GDBUS_IS_MODEM_LOCATION (self)); g_return_if_fail (MM_GDBUS_IS_MODEM_LOCATION (self));
mm_gdbus_modem_location_call_enable (self, mm_gdbus_modem_location_call_setup (self,
TRUE, sources,
FALSE /* signal_location */, signal_location,
cancellable, cancellable,
callback, callback,
user_data); user_data);
} }
gboolean gboolean
mm_modem_location_enable_sync (MMModemLocation *self, mm_modem_location_setup_sync (MMModemLocation *self,
GCancellable *cancellable, MMModemLocationSource sources,
GError **error) gboolean signal_location,
GCancellable *cancellable,
GError **error)
{ {
g_return_val_if_fail (MM_GDBUS_IS_MODEM_LOCATION (self), FALSE); g_return_val_if_fail (MM_GDBUS_IS_MODEM_LOCATION (self), FALSE);
return mm_gdbus_modem_location_call_enable_sync (self, return mm_gdbus_modem_location_call_setup_sync (self,
TRUE, sources,
FALSE /* signal_location */, signal_location,
cancellable, cancellable,
error); error);
} }
static MMLocation3gpp * static MMLocation3gpp *

View File

@@ -18,6 +18,7 @@
* Boston, MA 02110-1301 USA. * Boston, MA 02110-1301 USA.
* *
* Copyright (C) 2012 Google, Inc. * Copyright (C) 2012 Google, Inc.
* Copyright (C) 2012 Lanedo GmbH <aleksander@lanedo.com>
*/ */
#ifndef _MM_MODEM_LOCATION_H_ #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); gchar *mm_modem_location_dup_path (MMModemLocation *self);
MMModemLocationSource mm_modem_location_get_capabilities (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, void mm_modem_location_setup (MMModemLocation *self,
GCancellable *cancellable, MMModemLocationSource sources,
GAsyncReadyCallback callback, gboolean signal_location,
gpointer user_data); GCancellable *cancellable,
gboolean mm_modem_location_enable_finish (MMModemLocation *self, GAsyncReadyCallback callback,
GAsyncResult *res, gpointer user_data);
GError **error); gboolean mm_modem_location_setup_finish (MMModemLocation *self,
gboolean mm_modem_location_enable_sync (MMModemLocation *self, GAsyncResult *res,
GCancellable *cancellable, GError **error);
GError **error); gboolean mm_modem_location_setup_sync (MMModemLocation *self,
MMModemLocationSource sources,
void mm_modem_location_disable (MMModemLocation *self, gboolean signal_location,
GCancellable *cancellable, GCancellable *cancellable,
GAsyncReadyCallback callback, GError **error);
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_get_3gpp (MMModemLocation *self, void mm_modem_location_get_3gpp (MMModemLocation *self,
GCancellable *cancellable, GCancellable *cancellable,

View File

@@ -11,6 +11,7 @@
* GNU General Public License for more details: * GNU General Public License for more details:
* *
* Copyright (C) 2012 Google, Inc. * Copyright (C) 2012 Google, Inc.
* Copyright (C) 2012 Lanedo GmbH <aleksander@lanedo.com>
*/ */
#include <ModemManager.h> #include <ModemManager.h>
@@ -141,12 +142,10 @@ mm_iface_modem_location_3gpp_update_mcc_mnc (MMIfaceModemLocation *self,
MM_IFACE_MODEM_LOCATION_DBUS_SKELETON, &skeleton, MM_IFACE_MODEM_LOCATION_DBUS_SKELETON, &skeleton,
NULL); 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; guint changed = 0;
if (G_UNLIKELY (!ctx->location_3gpp)) g_assert (ctx->location_3gpp != NULL);
ctx->location_3gpp = mm_location_3gpp_new ();
changed += mm_location_3gpp_set_mobile_country_code (ctx->location_3gpp, changed += mm_location_3gpp_set_mobile_country_code (ctx->location_3gpp,
mobile_country_code); mobile_country_code);
changed += mm_location_3gpp_set_mobile_network_code (ctx->location_3gpp, 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, MM_IFACE_MODEM_LOCATION_DBUS_SKELETON, &skeleton,
NULL); 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; guint changed = 0;
if (G_UNLIKELY (!ctx->location_3gpp)) g_assert (ctx->location_3gpp != NULL);
ctx->location_3gpp = mm_location_3gpp_new ();
changed += mm_location_3gpp_set_location_area_code (ctx->location_3gpp, changed += mm_location_3gpp_set_location_area_code (ctx->location_3gpp,
location_area_code); location_area_code);
changed += mm_location_3gpp_set_cell_id (ctx->location_3gpp, 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, MM_IFACE_MODEM_LOCATION_DBUS_SKELETON, &skeleton,
NULL); 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; guint changed = 0;
if (G_UNLIKELY (!ctx->location_3gpp)) g_assert (ctx->location_3gpp != NULL);
ctx->location_3gpp = mm_location_3gpp_new ();
changed += mm_location_3gpp_set_location_area_code (ctx->location_3gpp, 0); 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_cell_id (ctx->location_3gpp, 0);
changed += mm_location_3gpp_set_mobile_country_code (ctx->location_3gpp, 0); changed += mm_location_3gpp_set_mobile_country_code (ctx->location_3gpp, 0);
@@ -218,16 +213,283 @@ 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 {
MMIfaceModemLocation *self;
MmGdbusModemLocation *skeleton;
GSimpleAsyncResult *result;
MMModemLocationSource to_enable;
MMModemLocationSource to_disable;
MMModemLocationSource current;
} SetupGatheringContext;
static void setup_gathering_step (SetupGatheringContext *ctx);
static void
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->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,
SetupGatheringContext *ctx)
{
GError *error = NULL;
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;
}
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,
SetupGatheringContext *ctx)
{
GError *error = NULL;
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;
}
update_location_source_status (self, ctx->current, FALSE);
/* Keep on with next ones... */
ctx->current = ctx->current << 1;
setup_gathering_step (ctx);
}
static void
setup_gathering_step (SetupGatheringContext *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;
}
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);
}
/* go on... */
ctx->current = ctx->current << 1;
}
/* 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);
}
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);
}
/* Start enabling/disabling location sources */
ctx->current = MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI;
setup_gathering_step (ctx);
}
/*****************************************************************************/
typedef struct { typedef struct {
MmGdbusModemLocation *skeleton; MmGdbusModemLocation *skeleton;
GDBusMethodInvocation *invocation; GDBusMethodInvocation *invocation;
MMIfaceModemLocation *self; MMIfaceModemLocation *self;
gboolean enable; guint32 sources;
gboolean signal_location; gboolean signal_location;
} HandleEnableContext; } HandleSetupContext;
static void static void
handle_enable_context_free (HandleEnableContext *ctx) handle_setup_context_free (HandleSetupContext *ctx)
{ {
g_object_unref (ctx->skeleton); g_object_unref (ctx->skeleton);
g_object_unref (ctx->invocation); g_object_unref (ctx->invocation);
@@ -236,146 +498,109 @@ handle_enable_context_free (HandleEnableContext *ctx)
} }
static void static void
enable_location_gathering_ready (MMIfaceModemLocation *self, setup_gathering_ready (MMIfaceModemLocation *self,
GAsyncResult *res, GAsyncResult *res,
HandleEnableContext *ctx) HandleSetupContext *ctx)
{ {
GError *error = NULL; 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_dbus_method_invocation_take_error (ctx->invocation, error); g_dbus_method_invocation_take_error (ctx->invocation, error);
else { else
mm_gdbus_modem_location_set_enabled (ctx->skeleton, TRUE); mm_gdbus_modem_location_complete_setup (ctx->skeleton, ctx->invocation);
mm_gdbus_modem_location_complete_enable (ctx->skeleton,
ctx->invocation);
}
handle_enable_context_free (ctx); handle_setup_context_free (ctx);
} }
static void static void
disable_location_gathering_ready (MMIfaceModemLocation *self, handle_setup_auth_ready (MMBaseModem *self,
GAsyncResult *res, GAsyncResult *res,
HandleEnableContext *ctx) HandleSetupContext *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);
}
handle_enable_context_free (ctx);
}
static void
handle_enable_auth_ready (MMBaseModem *self,
GAsyncResult *res,
HandleEnableContext *ctx)
{ {
GError *error = NULL; GError *error = NULL;
MMModemState modem_state;
MMModemLocationSource not_supported;
LocationContext *location_ctx;
gchar *str;
if (!mm_base_modem_authorize_finish (self, res, &error)) { if (!mm_base_modem_authorize_finish (self, res, &error)) {
g_dbus_method_invocation_take_error (ctx->invocation, error); g_dbus_method_invocation_take_error (ctx->invocation, error);
handle_enable_context_free (ctx); handle_setup_context_free (ctx);
return; return;
} }
/* Enabling */ modem_state = MM_MODEM_STATE_UNKNOWN;
if (ctx->enable) { g_object_get (self,
LocationContext *location_ctx; MM_IFACE_MODEM_STATE, &modem_state,
NULL);
location_ctx = get_location_context (ctx->self); if (modem_state < MM_MODEM_STATE_ENABLED) {
mm_dbg ("Enabling location gathering%s...", g_dbus_method_invocation_return_error (ctx->invocation,
ctx->signal_location ? " (with signaling)" : ""); MM_CORE_ERROR,
MM_CORE_ERROR_WRONG_STATE,
/* Update the new signal location value */ "Cannot setup location: "
if (mm_gdbus_modem_location_get_signals_location (ctx->skeleton) != ctx->signal_location) { "device not yet enabled");
mm_dbg ("%s location signaling", handle_setup_context_free (ctx);
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));
}
/* 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;
}
/* 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;
}
/* 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; return;
} }
/* Disabling */ /* If any of the location sources being enabled is NOT supported, set error */
mm_dbg ("Disabling location gathering..."); not_supported = ((mm_gdbus_modem_location_get_capabilities (ctx->skeleton) ^ ctx->sources) & ctx->sources);
if (not_supported != MM_MODEM_LOCATION_SOURCE_NONE) {
/* If already disabled, just done */ str = mm_modem_location_source_build_string_from_mask (not_supported);
if (!mm_gdbus_modem_location_get_enabled (ctx->skeleton)) { g_dbus_method_invocation_return_error (ctx->invocation,
mm_gdbus_modem_location_complete_enable (ctx->skeleton, ctx->invocation); MM_CORE_ERROR,
handle_enable_context_free (ctx); MM_CORE_ERROR_UNSUPPORTED,
"Cannot enable unsupported location sources: '%s'",
str);
handle_setup_context_free (ctx);
g_free (str);
return; return;
} }
/* Plugins can run custom actions to disable location gathering */ /* Enable/disable location signaling */
if (MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->disable_location_gathering && location_ctx = get_location_context (ctx->self);
MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->disable_location_gathering_finish) { if (mm_gdbus_modem_location_get_signals_location (ctx->skeleton) != ctx->signal_location) {
MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->disable_location_gathering ( mm_dbg ("%s location signaling",
MM_IFACE_MODEM_LOCATION (self), ctx->signal_location ? "Enabling" : "Disabling");
(GAsyncReadyCallback)disable_location_gathering_ready, mm_gdbus_modem_location_set_signals_location (ctx->skeleton,
ctx); ctx->signal_location);
return; mm_gdbus_modem_location_set_location (ctx->skeleton,
build_location_dictionary (ctx->signal_location ?
location_ctx->location_3gpp :
NULL));
} }
/* If no plugin-specific setup needed, or interface not yet enabled, just done */ str = mm_modem_location_source_build_string_from_mask (ctx->sources);
clear_location_context (ctx->self); mm_dbg ("Setting up location sources: '%s'", str);
mm_gdbus_modem_location_set_enabled (ctx->skeleton, FALSE); g_free (str);
mm_gdbus_modem_location_complete_enable (ctx->skeleton, ctx->invocation);
handle_enable_context_free (ctx); /* Go on to enable or disable the requested sources */
setup_gathering (ctx->self,
ctx->sources,
(GAsyncReadyCallback)setup_gathering_ready,
ctx);
} }
static gboolean static gboolean
handle_enable (MmGdbusModemLocation *skeleton, handle_setup (MmGdbusModemLocation *skeleton,
GDBusMethodInvocation *invocation, GDBusMethodInvocation *invocation,
gboolean enable, guint32 sources,
gboolean signal_location, gboolean signal_location,
MMIfaceModemLocation *self) MMIfaceModemLocation *self)
{ {
HandleEnableContext *ctx; HandleSetupContext *ctx;
ctx = g_new (HandleEnableContext, 1); ctx = g_new (HandleSetupContext, 1);
ctx->skeleton = g_object_ref (skeleton); ctx->skeleton = g_object_ref (skeleton);
ctx->invocation = g_object_ref (invocation); ctx->invocation = g_object_ref (invocation);
ctx->self = g_object_ref (self); ctx->self = g_object_ref (self);
ctx->enable = enable; ctx->sources = sources;
ctx->signal_location = signal_location; ctx->signal_location = signal_location;
mm_base_modem_authorize (MM_BASE_MODEM (self), mm_base_modem_authorize (MM_BASE_MODEM (self),
invocation, invocation,
MM_AUTHORIZATION_DEVICE_CONTROL, MM_AUTHORIZATION_DEVICE_CONTROL,
(GAsyncReadyCallback)handle_enable_auth_ready, (GAsyncReadyCallback)handle_setup_auth_ready,
ctx); ctx);
return TRUE; return TRUE;
} }
@@ -402,6 +627,7 @@ handle_get_location_auth_ready (MMBaseModem *self,
GAsyncResult *res, GAsyncResult *res,
HandleGetLocationContext *ctx) HandleGetLocationContext *ctx)
{ {
MMModemState modem_state;
LocationContext *location_ctx; LocationContext *location_ctx;
GError *error = NULL; GError *error = NULL;
@@ -411,6 +637,20 @@ handle_get_location_auth_ready (MMBaseModem *self,
return; 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); location_ctx = get_location_context (ctx->self);
mm_gdbus_modem_location_complete_get_location ( mm_gdbus_modem_location_complete_get_location (
ctx->skeleton, ctx->skeleton,
@@ -503,16 +743,12 @@ disabling_location_gathering_ready (MMIfaceModemLocation *self,
{ {
GError *error = NULL; GError *error = NULL;
if (!MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->disable_location_gathering_finish (self, if (!setup_gathering_finish (self, res, &error)) {
res,
&error)) {
g_simple_async_result_take_error (ctx->result, error); g_simple_async_result_take_error (ctx->result, error);
disabling_context_complete_and_free (ctx); disabling_context_complete_and_free (ctx);
return; return;
} }
mm_gdbus_modem_location_set_enabled (ctx->skeleton, FALSE);
/* Go on to next step */ /* Go on to next step */
ctx->step++; ctx->step++;
interface_disabling_step (ctx); interface_disabling_step (ctx);
@@ -527,20 +763,15 @@ interface_disabling_step (DisablingContext *ctx)
ctx->step++; ctx->step++;
case DISABLING_STEP_DISABLE_GATHERING: case DISABLING_STEP_DISABLE_GATHERING:
if (mm_gdbus_modem_location_get_enabled (ctx->skeleton) && setup_gathering (ctx->self,
MM_IFACE_MODEM_LOCATION_GET_INTERFACE (ctx->self)->disable_location_gathering && MM_MODEM_LOCATION_SOURCE_NONE,
MM_IFACE_MODEM_LOCATION_GET_INTERFACE (ctx->self)->disable_location_gathering_finish) { (GAsyncReadyCallback)disabling_location_gathering_ready,
MM_IFACE_MODEM_LOCATION_GET_INTERFACE (ctx->self)->disable_location_gathering ( ctx);
ctx->self, return;
(GAsyncReadyCallback)disabling_location_gathering_ready,
ctx);
return;
}
/* Fall down to next step */
ctx->step++;
case DISABLING_STEP_LAST: case DISABLING_STEP_LAST:
/* We are done without errors! */ /* We are done without errors! */
clear_location_context (ctx->self);
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
disabling_context_complete_and_free (ctx); disabling_context_complete_and_free (ctx);
return; return;
@@ -642,9 +873,7 @@ enabling_location_gathering_ready (MMIfaceModemLocation *self,
{ {
GError *error = NULL; GError *error = NULL;
if (!MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->enable_location_gathering_finish (self, if (!setup_gathering_finish (self, res, &error)) {
res,
&error)) {
g_simple_async_result_take_error (ctx->result, error); g_simple_async_result_take_error (ctx->result, error);
enabling_context_complete_and_free (ctx); enabling_context_complete_and_free (ctx);
return; return;
@@ -667,18 +896,20 @@ interface_enabling_step (EnablingContext *ctx)
/* Fall down to next step */ /* Fall down to next step */
ctx->step++; ctx->step++;
case ENABLING_STEP_ENABLE_GATHERING: case ENABLING_STEP_ENABLE_GATHERING: {
if (mm_gdbus_modem_location_get_enabled (ctx->skeleton) && MMModemLocationSource default_sources;
MM_IFACE_MODEM_LOCATION_GET_INTERFACE (ctx->self)->enable_location_gathering &&
MM_IFACE_MODEM_LOCATION_GET_INTERFACE (ctx->self)->enable_location_gathering_finish) { /* By default, we'll enable all NON-GPS sources
MM_IFACE_MODEM_LOCATION_GET_INTERFACE (ctx->self)->enable_location_gathering ( * (so, only 3GPP-LAC-CI if available) */
ctx->self, default_sources = mm_gdbus_modem_location_get_capabilities (ctx->skeleton);
(GAsyncReadyCallback)enabling_location_gathering_ready, default_sources &= ~(MM_MODEM_LOCATION_SOURCE_GPS_RAW | MM_MODEM_LOCATION_SOURCE_GPS_NMEA);
ctx);
return; setup_gathering (ctx->self,
} default_sources,
/* Fall down to next step */ (GAsyncReadyCallback)enabling_location_gathering_ready,
ctx->step++; ctx);
return;
}
case ENABLING_STEP_LAST: case ENABLING_STEP_LAST:
/* We are done without errors! */ /* We are done without errors! */
@@ -839,8 +1070,8 @@ interface_initialization_step (InitializationContext *ctx)
/* Handle method invocations */ /* Handle method invocations */
g_signal_connect (ctx->skeleton, g_signal_connect (ctx->skeleton,
"handle-enable", "handle-setup",
G_CALLBACK (handle_enable), G_CALLBACK (handle_setup),
ctx->self); ctx->self);
g_signal_connect (ctx->skeleton, g_signal_connect (ctx->skeleton,
"handle-get-location", "handle-get-location",
@@ -889,7 +1120,7 @@ mm_iface_modem_location_initialize (MMIfaceModemLocation *self,
/* Set all initial property defaults */ /* Set all initial property defaults */
mm_gdbus_modem_location_set_capabilities (skeleton, MM_MODEM_LOCATION_SOURCE_NONE); 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_signals_location (skeleton, FALSE);
mm_gdbus_modem_location_set_location (skeleton, mm_gdbus_modem_location_set_location (skeleton,
build_location_dictionary (NULL)); build_location_dictionary (NULL));

View File

@@ -43,6 +43,7 @@ struct _MMIfaceModemLocation {
/* Enable location gathering (async) */ /* Enable location gathering (async) */
void (* enable_location_gathering) (MMIfaceModemLocation *self, void (* enable_location_gathering) (MMIfaceModemLocation *self,
MMModemLocationSource source,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data); gpointer user_data);
gboolean (*enable_location_gathering_finish) (MMIfaceModemLocation *self, gboolean (*enable_location_gathering_finish) (MMIfaceModemLocation *self,
@@ -51,6 +52,7 @@ struct _MMIfaceModemLocation {
/* Disable location gathering (async) */ /* Disable location gathering (async) */
void (* disable_location_gathering) (MMIfaceModemLocation *self, void (* disable_location_gathering) (MMIfaceModemLocation *self,
MMModemLocationSource source,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data); gpointer user_data);
gboolean (*disable_location_gathering_finish) (MMIfaceModemLocation *self, gboolean (*disable_location_gathering_finish) (MMIfaceModemLocation *self,