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.
This commit is contained in:
Aleksander Morgado
2018-08-21 13:26:08 +00:00
committed by Dan Williams
parent 0798f32362
commit 091bf4dbd8
9 changed files with 596 additions and 14 deletions
+188
View File
@@ -1034,6 +1034,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;
@@ -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;
@@ -1464,6 +1568,55 @@ initialization_context_free (InitializationContext *ctx)
g_free (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,
@@ -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 |
@@ -1598,6 +1781,10 @@ interface_initialization_step (GTask *task)
"handle-set-supl-server",
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),
@@ -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,
+26
View File
@@ -50,6 +50,22 @@ struct _MMIfaceModemLocation {
GAsyncResult *res,
GError **error);
/* Loading of the AssistanceDataServers property */
void (* load_assistance_data_servers) (MMIfaceModemLocation *self,
GAsyncReadyCallback callback,
gpointer user_data);
gchar ** (* load_assistance_data_servers_finish) (MMIfaceModemLocation *self,
GAsyncResult *res,
GError **error);
/* Loading of the SupportedAssistanceData property */
void (* load_supported_assistance_data) (MMIfaceModemLocation *self,
GAsyncReadyCallback callback,
gpointer user_data);
MMModemLocationAssistanceDataType (* load_supported_assistance_data_finish) (MMIfaceModemLocation *self,
GAsyncResult *res,
GError **error);
/* Enable location gathering (async) */
void (* enable_location_gathering) (MMIfaceModemLocation *self,
MMModemLocationSource source,
@@ -76,6 +92,16 @@ struct _MMIfaceModemLocation {
gboolean (*set_supl_server_finish) (MMIfaceModemLocation *self,
GAsyncResult *res,
GError **error);
/* Inject assistance data (async) */
void (* inject_assistance_data) (MMIfaceModemLocation *self,
const guint8 *data,
gsize data_size,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean (*inject_assistance_data_finish) (MMIfaceModemLocation *self,
GAsyncResult *res,
GError **error);
};
GType mm_iface_modem_location_get_type (void);