aboutsummaryrefslogtreecommitdiff
path: root/src/mm-iface-modem-location.c
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2018-07-02 00:25:54 +0200
committerDan Williams <dcbw@redhat.com>2018-08-21 13:26:08 +0000
commit091bf4dbd811a7e556613397cd0efa7b8998a2cd (patch)
treeecdd13be2c2a4b1ed3b3f14577ae726df9f48952 /src/mm-iface-modem-location.c
parent0798f32362f0a9664e65de13c66d3767fc7ddf6d (diff)
api: support location assistance data
Sometimes SUPL-server based A-GPS is not possible, e.g. if the module doesn't have Internet connectivity. In such cases, the modem may support injecting additional "assistance data" that may be downloaded from the Internet using external means (e.g. WiFi), in order to keep having a quick time to first fix. We now support using this location assistance data, with the following new API elements: * A new mask of supported assistance data types is provided in the SupportedAssistanceData property. * A new list of URLs from where the aassistance data may be downloaded is also provided in a new AssistanceDataServers property. * A new InjectAssistanceData() method is provided, to perform the data injection in the module once it's been downloaded to the host system.
Diffstat (limited to 'src/mm-iface-modem-location.c')
-rw-r--r--src/mm-iface-modem-location.c188
1 files changed, 188 insertions, 0 deletions
diff --git a/src/mm-iface-modem-location.c b/src/mm-iface-modem-location.c
index 4c45ab11..e5aaa43d 100644
--- a/src/mm-iface-modem-location.c
+++ b/src/mm-iface-modem-location.c
@@ -1035,6 +1035,108 @@ handle_set_supl_server (MmGdbusModemLocation *skeleton,
/*****************************************************************************/
typedef struct {
+ MmGdbusModemLocation *skeleton;
+ GDBusMethodInvocation *invocation;
+ MMIfaceModemLocation *self;
+ GVariant *datav;
+} HandleInjectAssistanceDataContext;
+
+static void
+handle_inject_assistance_data_context_free (HandleInjectAssistanceDataContext *ctx)
+{
+ g_object_unref (ctx->skeleton);
+ g_object_unref (ctx->invocation);
+ g_object_unref (ctx->self);
+ g_variant_unref (ctx->datav);
+ g_slice_free (HandleInjectAssistanceDataContext, ctx);
+}
+
+static void
+inject_assistance_data_ready (MMIfaceModemLocation *self,
+ GAsyncResult *res,
+ HandleInjectAssistanceDataContext *ctx)
+{
+ GError *error = NULL;
+
+ if (!MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->inject_assistance_data_finish (self, res, &error))
+ g_dbus_method_invocation_take_error (ctx->invocation, error);
+ else
+ mm_gdbus_modem_location_complete_inject_assistance_data (ctx->skeleton, ctx->invocation);
+
+ handle_inject_assistance_data_context_free (ctx);
+}
+
+static void
+handle_inject_assistance_data_auth_ready (MMBaseModem *self,
+ GAsyncResult *res,
+ HandleInjectAssistanceDataContext *ctx)
+{
+ GError *error = NULL;
+ const guint8 *data;
+ gsize data_size;
+
+ if (!mm_base_modem_authorize_finish (self, res, &error)) {
+ g_dbus_method_invocation_take_error (ctx->invocation, error);
+ handle_inject_assistance_data_context_free (ctx);
+ return;
+ }
+
+ /* If the type is NOT supported, set error */
+ if (mm_gdbus_modem_location_get_supported_assistance_data (ctx->skeleton) == MM_MODEM_LOCATION_ASSISTANCE_DATA_TYPE_NONE) {
+ g_dbus_method_invocation_return_error (ctx->invocation,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNSUPPORTED,
+ "Cannot inject assistance data: ununsupported");
+ handle_inject_assistance_data_context_free (ctx);
+ return;
+ }
+
+ /* Check if plugin implements it */
+ if (!MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->inject_assistance_data ||
+ !MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->inject_assistance_data_finish) {
+ g_dbus_method_invocation_return_error (ctx->invocation,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNSUPPORTED,
+ "Cannot inject assistance data: not implemented");
+ handle_inject_assistance_data_context_free (ctx);
+ return;
+ }
+
+ data = (const guint8 *) g_variant_get_fixed_array (ctx->datav, &data_size, sizeof (guint8));
+
+ /* Request to inject assistance data */
+ MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->inject_assistance_data (ctx->self,
+ data,
+ data_size,
+ (GAsyncReadyCallback)inject_assistance_data_ready,
+ ctx);
+}
+
+static gboolean
+handle_inject_assistance_data (MmGdbusModemLocation *skeleton,
+ GDBusMethodInvocation *invocation,
+ GVariant *datav,
+ MMIfaceModemLocation *self)
+{
+ HandleInjectAssistanceDataContext *ctx;
+
+ ctx = g_slice_new (HandleInjectAssistanceDataContext);
+ ctx->skeleton = g_object_ref (skeleton);
+ ctx->invocation = g_object_ref (invocation);
+ ctx->self = g_object_ref (self);
+ ctx->datav = g_variant_ref (datav);
+
+ mm_base_modem_authorize (MM_BASE_MODEM (self),
+ invocation,
+ MM_AUTHORIZATION_DEVICE_CONTROL,
+ (GAsyncReadyCallback)handle_inject_assistance_data_auth_ready,
+ ctx);
+ return TRUE;
+}
+
+/*****************************************************************************/
+
+typedef struct {
MmGdbusModemLocation *skeleton;
GDBusMethodInvocation *invocation;
MMIfaceModemLocation *self;
@@ -1447,6 +1549,8 @@ typedef enum {
INITIALIZATION_STEP_CAPABILITIES,
INITIALIZATION_STEP_VALIDATE_CAPABILITIES,
INITIALIZATION_STEP_SUPL_SERVER,
+ INITIALIZATION_STEP_SUPPORTED_ASSISTANCE_DATA,
+ INITIALIZATION_STEP_ASSISTANCE_DATA_SERVERS,
INITIALIZATION_STEP_GPS_REFRESH_RATE,
INITIALIZATION_STEP_LAST
} InitializationStep;
@@ -1465,6 +1569,55 @@ initialization_context_free (InitializationContext *ctx)
}
static void
+load_assistance_data_servers_ready (MMIfaceModemLocation *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GError *error = NULL;
+ InitializationContext *ctx;
+ gchar **servers;
+
+ ctx = g_task_get_task_data (task);
+
+ servers = MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->load_assistance_data_servers_finish (self, res, &error);
+ if (error) {
+ mm_warn ("couldn't load assistance data servers: '%s'", error->message);
+ g_error_free (error);
+ }
+
+ mm_gdbus_modem_location_set_assistance_data_servers (ctx->skeleton, (const gchar *const *)servers);
+ g_strfreev (servers);
+
+ /* Go on to next step */
+ ctx->step++;
+ interface_initialization_step (task);
+}
+
+static void
+load_supported_assistance_data_ready (MMIfaceModemLocation *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GError *error = NULL;
+ MMModemLocationAssistanceDataType mask;
+ InitializationContext *ctx;
+
+ ctx = g_task_get_task_data (task);
+
+ mask = MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->load_supported_assistance_data_finish (self, res, &error);
+ if (error) {
+ mm_warn ("couldn't load supported assistance data types: '%s'", error->message);
+ g_error_free (error);
+ }
+
+ mm_gdbus_modem_location_set_supported_assistance_data (ctx->skeleton, (guint32) mask);
+
+ /* Go on to next step */
+ ctx->step++;
+ interface_initialization_step (task);
+}
+
+static void
load_supl_server_ready (MMIfaceModemLocation *self,
GAsyncResult *res,
GTask *task)
@@ -1576,6 +1729,36 @@ interface_initialization_step (GTask *task)
/* Fall down to next step */
ctx->step++;
+ case INITIALIZATION_STEP_SUPPORTED_ASSISTANCE_DATA:
+ /* If the modem supports any GPS-related technology, check assistance data types supported */
+ if ((ctx->capabilities & (MM_MODEM_LOCATION_SOURCE_AGPS |
+ MM_MODEM_LOCATION_SOURCE_GPS_RAW |
+ MM_MODEM_LOCATION_SOURCE_GPS_NMEA)) &&
+ MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->load_supported_assistance_data &&
+ MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->load_supported_assistance_data_finish) {
+ MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->load_supported_assistance_data (
+ self,
+ (GAsyncReadyCallback)load_supported_assistance_data_ready,
+ task);
+ return;
+ }
+ /* Fall down to next step */
+ ctx->step++;
+
+ case INITIALIZATION_STEP_ASSISTANCE_DATA_SERVERS:
+ /* If any assistance data supported, load servers */
+ if ((mm_gdbus_modem_location_get_supported_assistance_data (ctx->skeleton) != MM_MODEM_LOCATION_ASSISTANCE_DATA_TYPE_NONE) &&
+ MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->load_assistance_data_servers &&
+ MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->load_assistance_data_servers_finish) {
+ MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->load_assistance_data_servers (
+ self,
+ (GAsyncReadyCallback)load_assistance_data_servers_ready,
+ task);
+ return;
+ }
+ /* Fall down to next step */
+ ctx->step++;
+
case INITIALIZATION_STEP_GPS_REFRESH_RATE:
/* If we have GPS capabilities, expose the GPS refresh rate */
if (ctx->capabilities & ((MM_MODEM_LOCATION_SOURCE_GPS_RAW |
@@ -1599,6 +1782,10 @@ interface_initialization_step (GTask *task)
G_CALLBACK (handle_set_supl_server),
self);
g_signal_connect (ctx->skeleton,
+ "handle-inject-assistance-data",
+ G_CALLBACK (handle_inject_assistance_data),
+ self);
+ g_signal_connect (ctx->skeleton,
"handle-set-gps-refresh-rate",
G_CALLBACK (handle_set_gps_refresh_rate),
self);
@@ -1646,6 +1833,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_supported_assistance_data (skeleton, MM_MODEM_LOCATION_ASSISTANCE_DATA_TYPE_NONE);
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,