From 091bf4dbd811a7e556613397cd0efa7b8998a2cd Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Mon, 2 Jul 2018 00:25:54 +0200 Subject: [PATCH] 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. --- cli/mmcli-modem-location.c | 162 +++++++++++++-- docs/reference/api/ModemManager-sections.txt | 1 + .../libmm-glib/libmm-glib-sections.txt | 14 ++ include/ModemManager-enums.h | 12 ++ ...eedesktop.ModemManager1.Modem.Location.xml | 34 ++++ libmm-glib/mm-modem-location.c | 153 ++++++++++++++ libmm-glib/mm-modem-location.h | 20 ++ src/mm-iface-modem-location.c | 188 ++++++++++++++++++ src/mm-iface-modem-location.h | 26 +++ 9 files changed, 596 insertions(+), 14 deletions(-) diff --git a/cli/mmcli-modem-location.c b/cli/mmcli-modem-location.c index 0568b513..997e1a84 100644 --- a/cli/mmcli-modem-location.c +++ b/cli/mmcli-modem-location.c @@ -66,6 +66,8 @@ static gboolean set_enable_signal_flag; static gboolean set_disable_signal_flag; static gboolean get_all_flag; static gchar *set_supl_server_str; +static gchar *set_supl_server_str; +static gchar *inject_assistance_data_str; static gchar *set_gps_refresh_rate_str; static GOptionEntry entries[] = { @@ -145,6 +147,10 @@ static GOptionEntry entries[] = { "Set SUPL server address", "[IP:PORT] or [URL]" }, + { "location-inject-assistance-data", 0, 0, G_OPTION_ARG_FILENAME, &inject_assistance_data_str, + "Inject assistance data in the GNSS module", + "[PATH]" + }, { "location-set-gps-refresh-rate", 0, 0, G_OPTION_ARG_STRING, &set_gps_refresh_rate_str, "Set GPS refresh rate in seconds, or 0 disable the explicit rate.", "[RATE]" @@ -226,6 +232,7 @@ mmcli_modem_location_options_enabled (void) get_gps_raw_flag + get_cdma_bs_flag) + !!set_supl_server_str + + !!inject_assistance_data_str + !!set_gps_refresh_rate_str); if (n_actions > 1) { @@ -300,27 +307,52 @@ print_location_status (void) enabled_str, mm_modem_location_signals_location (ctx->modem_location) ? "yes" : "no"); - /* If A-GPS supported, show SUPL server setup */ - if (mm_modem_location_get_capabilities (ctx->modem_location) & MM_MODEM_LOCATION_SOURCE_AGPS) { - const gchar *supl_server; - - supl_server = mm_modem_location_get_supl_server (ctx->modem_location); - g_print (" ----------------------------\n" - " A-GPS | SUPL server: '%s'\n", - supl_server ? supl_server : "unset"); - } - - /* If GPS supported, show GPS refresh rate */ + /* If GPS supported, show GPS refresh rate and supported assistance data */ if (mm_modem_location_get_capabilities (ctx->modem_location) & (MM_MODEM_LOCATION_SOURCE_GPS_RAW | MM_MODEM_LOCATION_SOURCE_GPS_NMEA)) { - guint rate; + guint rate; + MMModemLocationAssistanceDataType mask; + gchar *mask_str; rate = mm_modem_location_get_gps_refresh_rate (ctx->modem_location); g_print (" ----------------------------\n"); if (rate > 0) - g_print (" GPS | refresh rate: '%u'\n", rate); + g_print (" GPS | refresh rate: '%u'\n", rate); else - g_print (" GPS | refresh rate: disabled\n"); + g_print (" GPS | refresh rate: disabled\n"); + + /* If A-GPS supported, show SUPL server setup */ + if (mm_modem_location_get_capabilities (ctx->modem_location) & MM_MODEM_LOCATION_SOURCE_AGPS) { + const gchar *supl_server; + + supl_server = mm_modem_location_get_supl_server (ctx->modem_location); + g_print (" | A-GPS SUPL server: '%s'\n", + supl_server ? supl_server : "unset"); + } + + mask = mm_modem_location_get_supported_assistance_data (ctx->modem_location); + mask_str = mm_modem_location_assistance_data_type_build_string_from_mask (mask); + g_print (" | supported assistance data: '%s'\n", mask_str); + g_free (mask_str); + + /* If any assistance data supported, show server list */ + if (mask != MM_MODEM_LOCATION_ASSISTANCE_DATA_TYPE_NONE) { + const gchar **servers; + + servers = mm_modem_location_get_assistance_data_servers (ctx->modem_location); + if (!servers) + g_print (" | assistance data servers: 'n/a'\n"); + else { + guint server_i; + + for (server_i = 0; servers[server_i]; server_i++) { + if (server_i == 0) + g_print (" | assistance data servers: '%s'\n", servers[server_i]); + else + g_print (" | '%s'\n", servers[server_i]); + } + } + } } g_free (capabilities_str); @@ -379,6 +411,65 @@ set_supl_server_ready (MMModemLocation *modem_location, mmcli_async_operation_done (); } +static gboolean +parse_inject_assistance_data (guint8 **o_data, + gsize *o_data_size) +{ + gboolean result = FALSE; + GFile *file = NULL; + gchar *data; + gsize data_size; + GError *error = NULL; + + file = g_file_new_for_commandline_arg (inject_assistance_data_str); + + if (!g_file_load_contents (file, NULL, &data, &data_size, NULL, &error)) { + g_printerr ("error: cannot load file contents: %s\n", error->message); + goto out; + } + + if (data_size == 0) { + g_printerr ("error: file is empty\n"); + goto out; + } + + *o_data = (guint8 *)data; + *o_data_size = data_size; + result = TRUE; + +out: + if (error) + g_error_free (error); + g_object_unref (file); + return result; +} + +static void +inject_assistance_data_process_reply (gboolean result, + const GError *error) +{ + if (!result) { + g_printerr ("error: couldn't inject assistance data: '%s'\n", + error ? error->message : "unknown error"); + exit (EXIT_FAILURE); + } + + g_print ("successfully injected assistance data\n"); +} + +static void +inject_assistance_data_ready (MMModemLocation *modem_location, + GAsyncResult *result) +{ + gboolean operation_result; + GError *error = NULL; + + operation_result = mm_modem_location_inject_assistance_data_finish (modem_location, result, &error); + inject_assistance_data_process_reply (operation_result, error); + + mmcli_async_operation_done (); +} + static void set_gps_refresh_rate_process_reply (gboolean result, const GError *error) @@ -667,6 +758,27 @@ get_modem_ready (GObject *source, return; } + /* Request to inject assistance data? */ + if (inject_assistance_data_str) { + guint8 *data; + gsize data_size; + + if (!parse_inject_assistance_data (&data, &data_size)) { + g_printerr ("error: couldn't inject assistance data: invalid parameters given: '%s'\n", + inject_assistance_data_str); + exit (EXIT_FAILURE); + } + + g_debug ("Asynchronously injecting assistance data..."); + mm_modem_location_inject_assistance_data (ctx->modem_location, + data, data_size, + ctx->cancellable, + (GAsyncReadyCallback)inject_assistance_data_ready, + NULL); + g_free (data); + return; + } + /* Request to set GPS refresh rate? */ if (set_gps_refresh_rate_str) { guint rate; @@ -792,6 +904,28 @@ mmcli_modem_location_run_synchronous (GDBusConnection *connection) return; } + /* Request to inject assistance data? */ + if (inject_assistance_data_str) { + gboolean result; + guint8 *data; + gsize data_size; + + if (!parse_inject_assistance_data (&data, &data_size)) { + g_printerr ("error: couldn't inject assistance data: invalid parameters given: '%s'\n", + inject_assistance_data_str); + exit (EXIT_FAILURE); + } + + g_debug ("Synchronously setting assistance data..."); + result = mm_modem_location_inject_assistance_data_sync (ctx->modem_location, + data, data_size, + NULL, + &error); + inject_assistance_data_process_reply (result, error); + g_free (data); + return; + } + /* Request to set GPS refresh rate? */ if (set_gps_refresh_rate_str) { gboolean result; diff --git a/docs/reference/api/ModemManager-sections.txt b/docs/reference/api/ModemManager-sections.txt index 497f6e38..5ec728db 100644 --- a/docs/reference/api/ModemManager-sections.txt +++ b/docs/reference/api/ModemManager-sections.txt @@ -31,6 +31,7 @@ MMModemCdmaRegistrationState MMModemCdmaRmProtocol MMModemContactsStorage MMModemLocationSource +MMModemLocationAssistanceDataType MMModemLock MMModemMode MMModemState diff --git a/docs/reference/libmm-glib/libmm-glib-sections.txt b/docs/reference/libmm-glib/libmm-glib-sections.txt index 3cd3364d..f41f4a7e 100644 --- a/docs/reference/libmm-glib/libmm-glib-sections.txt +++ b/docs/reference/libmm-glib/libmm-glib-sections.txt @@ -423,6 +423,7 @@ mm_modem_location_get_enabled mm_modem_location_signals_location mm_modem_location_dup_supl_server mm_modem_location_get_supl_server +mm_modem_location_get_supported_assistance_data mm_modem_location_get_gps_refresh_rate mm_modem_location_setup @@ -431,6 +432,9 @@ mm_modem_location_setup_sync mm_modem_location_set_supl_server mm_modem_location_set_supl_server_finish mm_modem_location_set_supl_server_sync +mm_modem_location_inject_assistance_data +mm_modem_location_inject_assistance_data_finish +mm_modem_location_inject_assistance_data_sync mm_modem_location_set_gps_refresh_rate mm_modem_location_set_gps_refresh_rate_finish mm_modem_location_set_gps_refresh_rate_sync @@ -1363,6 +1367,7 @@ mm_modem_cdma_registration_state_get_string mm_modem_cdma_activation_state_get_string mm_modem_cdma_rm_protocol_get_string mm_modem_location_source_build_string_from_mask +mm_modem_location_assistance_data_type_build_string_from_mask mm_modem_contacts_storage_get_string mm_sms_pdu_type_get_string mm_sms_state_get_string @@ -1397,6 +1402,7 @@ mm_sms_validity_type_build_string_from_mask mm_sms_cdma_teleservice_id_build_string_from_mask mm_sms_cdma_service_category_build_string_from_mask mm_modem_location_source_get_string +mm_modem_location_assistance_data_type_get_string mm_modem_contacts_storage_build_string_from_mask mm_bearer_ip_family_build_string_from_mask mm_bearer_ip_method_build_string_from_mask @@ -1438,6 +1444,7 @@ MM_TYPE_MODEM_CDMA_REGISTRATION_STATE MM_TYPE_MODEM_CDMA_RM_PROTOCOL MM_TYPE_MODEM_CONTACTS_STORAGE MM_TYPE_MODEM_LOCATION_SOURCE +MM_TYPE_MODEM_LOCATION_ASSISTANCE_DATA_TYPE MM_TYPE_MODEM_LOCK MM_TYPE_MODEM_MODE MM_TYPE_MODEM_STATE @@ -1477,6 +1484,7 @@ mm_modem_cdma_registration_state_get_type mm_modem_cdma_rm_protocol_get_type mm_modem_contacts_storage_get_type mm_modem_location_source_get_type +mm_modem_location_assistance_data_type_get_type mm_modem_lock_get_type mm_modem_mode_get_type mm_modem_state_change_reason_get_type @@ -2152,6 +2160,10 @@ mm_gdbus_modem_location_call_setup_sync mm_gdbus_modem_location_call_set_supl_server mm_gdbus_modem_location_call_set_supl_server_finish mm_gdbus_modem_location_call_set_supl_server_sync +mm_gdbus_modem_location_call_inject_assistance_data +mm_gdbus_modem_location_call_inject_assistance_data_finish +mm_gdbus_modem_location_call_inject_assistance_data_sync +mm_gdbus_modem_location_get_supported_assistance_data mm_gdbus_modem_location_call_set_gps_refresh_rate mm_gdbus_modem_location_call_set_gps_refresh_rate_finish mm_gdbus_modem_location_call_set_gps_refresh_rate_sync @@ -2161,10 +2173,12 @@ mm_gdbus_modem_location_set_enabled mm_gdbus_modem_location_set_location mm_gdbus_modem_location_set_signals_location mm_gdbus_modem_location_set_supl_server +mm_gdbus_modem_location_set_supported_assistance_data mm_gdbus_modem_location_set_gps_refresh_rate mm_gdbus_modem_location_complete_get_location mm_gdbus_modem_location_complete_setup mm_gdbus_modem_location_complete_set_supl_server +mm_gdbus_modem_location_complete_inject_assistance_data mm_gdbus_modem_location_complete_set_gps_refresh_rate mm_gdbus_modem_location_interface_info mm_gdbus_modem_location_override_properties diff --git a/include/ModemManager-enums.h b/include/ModemManager-enums.h index 10166d24..60bbb027 100644 --- a/include/ModemManager-enums.h +++ b/include/ModemManager-enums.h @@ -910,6 +910,18 @@ typedef enum { /*< underscore_name=mm_modem_location_source >*/ MM_MODEM_LOCATION_SOURCE_AGPS = 1 << 5, } MMModemLocationSource; +/** + * MMModemLocationAssistanceDataType: + * @MM_MODEM_LOCATION_ASSISTANCE_DATA_TYPE_NONE: None. + * @MM_MODEM_LOCATION_ASSISTANCE_DATA_TYPE_XTRA: Qualcomm gpsOneXTRA. + * + * Type of assistance data that may be injected to the GNSS module. + */ +typedef enum { /*< underscore_name=mm_modem_location_assistance_data_type >*/ + MM_MODEM_LOCATION_ASSISTANCE_DATA_TYPE_NONE = 0, + MM_MODEM_LOCATION_ASSISTANCE_DATA_TYPE_XTRA = 1 << 0, +} MMModemLocationAssistanceDataType; + /** * MMModemContactsStorage: * @MM_MODEM_CONTACTS_STORAGE_UNKNOWN: Unknown location. diff --git a/introspection/org.freedesktop.ModemManager1.Modem.Location.xml b/introspection/org.freedesktop.ModemManager1.Modem.Location.xml index fa51a6e2..7c490c6a 100644 --- a/introspection/org.freedesktop.ModemManager1.Modem.Location.xml +++ b/introspection/org.freedesktop.ModemManager1.Modem.Location.xml @@ -79,6 +79,24 @@ + + + + + + + + + + + + +