diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2018-06-23 21:53:30 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2018-07-10 22:42:49 +0200 |
commit | 83aac9d99cef883ba985f1711d7ceae1e6f6d2ee (patch) | |
tree | bb303d5380b3c2d602685f11fa3a592a837346d0 | |
parent | 5f5b8314be28c59dccd81bbb8e354743aa7c2f07 (diff) | |
download | libqmi-83aac9d99cef883ba985f1711d7ceae1e6f6d2ee.tar.gz |
qmicli,loc: implement basic support
This patch is based on a previous version written by:
Thomas Weißschuh <thomas@weissschuh.net>
-rw-r--r-- | src/qmicli/Makefile.am | 1 | ||||
-rw-r--r-- | src/qmicli/qmicli-loc.c | 771 | ||||
-rw-r--r-- | src/qmicli/qmicli.c | 11 | ||||
-rw-r--r-- | src/qmicli/qmicli.h | 7 |
4 files changed, 790 insertions, 0 deletions
diff --git a/src/qmicli/Makefile.am b/src/qmicli/Makefile.am index eb63fa79..8a4fefa8 100644 --- a/src/qmicli/Makefile.am +++ b/src/qmicli/Makefile.am @@ -44,6 +44,7 @@ qmicli_SOURCES = \ qmicli-wms.c \ qmicli-wda.c \ qmicli-voice.c \ + qmicli-loc.c \ qmicli-charsets.c \ qmicli-charsets.h diff --git a/src/qmicli/qmicli-loc.c b/src/qmicli/qmicli-loc.c new file mode 100644 index 00000000..a39e4c71 --- /dev/null +++ b/src/qmicli/qmicli-loc.c @@ -0,0 +1,771 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * qmicli -- Command line interface to control QMI devices + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Copyright (C) 2018 Thomas Weißschuh <thomas@weissschuh.net> + * Copyright (C) 2018 Aleksander Morgado <aleksander@aleksander.es> + */ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <locale.h> +#include <string.h> + +#include <glib.h> +#include <gio/gio.h> + +#include <libqmi-glib.h> + +#include "qmicli.h" +#include "qmicli-helpers.h" + +/* Context */ + +typedef enum { + MONITORING_STEP_FIRST, + MONITORING_STEP_REGISTER_EVENTS, + MONITORING_STEP_SETUP_TIMEOUT, + MONITORING_STEP_ONGOING, +} MonitoringStep; + +typedef struct { + QmiDevice *device; + QmiClientLoc *client; + GCancellable *cancellable; + guint timeout_id; + MonitoringStep monitoring_step; + guint position_report_indication_id; + guint nmea_indication_id; + guint satellite_info_indication_id; +} Context; +static Context *ctx; + +/* Options */ +static gint session_id; +static gboolean start_flag; +static gboolean stop_flag; +static gboolean get_position_flag; +static gboolean get_satellite_info_flag; +static gint timeout; +static gboolean follow_position_flag; +static gboolean follow_satellite_info_flag; +static gboolean follow_nmea_flag; + +#define DEFAULT_LOC_TIMEOUT_SECS 30 + +static GOptionEntry entries[] = { + { + "loc-session-id", 0, 0, G_OPTION_ARG_INT, &session_id, + "Session ID for the LOC session", + "[ID]", + }, + { + "loc-start", 0, 0, G_OPTION_ARG_NONE, &start_flag, + "Start location gathering", + NULL, + }, + { + "loc-stop", 0, 0, G_OPTION_ARG_NONE, &stop_flag, + "Stop location gathering", + NULL, + }, + { + "loc-get-position", 0, 0, G_OPTION_ARG_NONE, &get_position_flag, + "Get position reported by the location module", + NULL, + }, + { + "loc-get-satellite-info", 0, 0, G_OPTION_ARG_NONE, &get_satellite_info_flag, + "Show satellite report", + NULL, + }, + { + "loc-timeout", 0, 0, G_OPTION_ARG_INT, &timeout, + "Maximum time to wait for information in `--loc-get-position' and `--loc-get-satellite-info' (default 30s)", + "[SECS]", + }, + { + "loc-follow-position", 0, 0, G_OPTION_ARG_NONE, &follow_position_flag, + "Follow all position updates reported by the location module indefinitely", + NULL, + }, + { + "loc-follow-satellite-info", 0, 0, G_OPTION_ARG_NONE, &follow_satellite_info_flag, + "Follow all satellite info updates reported by the location module indefinitely", + NULL, + }, + { + "loc-follow-nmea", 0, 0, G_OPTION_ARG_NONE, &follow_nmea_flag, + "Follow all NMEA trace updates reported by the location module indefinitely", + NULL, + }, + { NULL } +}; + +GOptionGroup * +qmicli_loc_get_option_group (void) +{ + GOptionGroup *group; + + group = g_option_group_new ("loc", + "LOC options", + "Show location options", NULL, NULL); + g_option_group_add_entries (group, entries); + + return group; +} + +gboolean +qmicli_loc_options_enabled (void) +{ + static guint n_actions = 0; + static gboolean checked = FALSE; + + if (checked) + return !!n_actions; + + /* Let's define the following actions:: + * - Start location engine + * - Stop location engine + * - Show current position (oneshot). + * - Show current satellite info (oneshot). + * - Follow updates indefinitely, including either position, satellite info or NMEA traces. + */ + n_actions = (start_flag + + stop_flag + + get_position_flag + + get_satellite_info_flag + + !!(follow_position_flag + follow_satellite_info_flag + follow_nmea_flag)); + + if (n_actions > 1) { + g_printerr ("error: too many LOC actions requested\n"); + exit (EXIT_FAILURE); + } + + if (session_id < 0 || session_id > G_MAXUINT8) { + g_printerr ("error: invalid session ID: %d [0,%u]\n", session_id, G_MAXUINT8); + exit (EXIT_FAILURE); + } + + if (timeout < 0) { + g_printerr ("error: invalid timeout: %d", timeout); + exit (EXIT_FAILURE); + } + + if (timeout > 0 && !(get_position_flag || get_satellite_info_flag)) { + g_printerr ("error: `--loc-timeout' is only applicable with `--loc-get-position' or `--loc-get-satellite-info'\n"); + exit (EXIT_FAILURE); + } + + checked = TRUE; + return !!n_actions; +} + +static void +context_free (Context *context) +{ + if (!context) + return; + + if (context->timeout_id) + g_source_remove (context->timeout_id); + + if (context->position_report_indication_id) + g_signal_handler_disconnect (context->client, context->position_report_indication_id); + + if (context->satellite_info_indication_id) + g_signal_handler_disconnect (context->client, context->satellite_info_indication_id); + + if (context->nmea_indication_id) + g_signal_handler_disconnect (context->client, context->nmea_indication_id); + + g_clear_object (&context->cancellable); + g_clear_object (&context->client); + g_clear_object (&context->device); + g_slice_free (Context, context); +} + +static void +operation_shutdown (gboolean operation_status) +{ + context_free (ctx); + qmicli_async_operation_done (operation_status, FALSE); +} + +static void monitoring_step_run (void); + +static gboolean +monitoring_timed_out (void) +{ + ctx->timeout_id = 0; + g_printerr ("error: operation failed: timeout\n"); + operation_shutdown (FALSE); + return G_SOURCE_REMOVE; +} + +static void +monitoring_cancelled (GCancellable *cancellable) +{ + /* For GET operations, this is a failure */ + if (get_position_flag || get_satellite_info_flag) { + g_printerr ("error: operation failed: cancelled\n"); + operation_shutdown (FALSE); + return; + } + + /* For FOLLOW operations, silently exit */ + if (follow_position_flag || follow_satellite_info_flag || follow_nmea_flag) { + operation_shutdown (TRUE); + return; + } + + g_assert_not_reached (); +} + +static void +nmea_received (QmiClientLoc *client, + QmiIndicationLocNmeaOutput *output) +{ + const gchar *nmea = NULL; + + qmi_indication_loc_nmea_output_get_nmea_string (output, &nmea, NULL); + if (nmea) + g_print ("[nmea] %s\n", nmea); +} + +static void +satellite_info_received (QmiClientLoc *client, + QmiIndicationLocGnssSatelliteInfoOutput *output) +{ + GArray *satellite_infos = NULL; + guint i; + + qmi_indication_loc_gnss_satellite_info_output_get_satellite_info (output, &satellite_infos, NULL); + + g_print ("[satellite info] %d satellites detected:\n", satellite_infos ? satellite_infos->len : 0); + for (i = 0; i < satellite_infos->len; i++) { + QmiIndicationLocGnssSatelliteInfoOutputSatelliteInfoElement *element; + + element = &g_array_index (satellite_infos, QmiIndicationLocGnssSatelliteInfoOutputSatelliteInfoElement, i); + g_print (" [satellite #%u]\n", i); + g_print (" system: %s\n", (element->valid_information & QMI_LOC_SATELLITE_VALID_INFORMATION_SYSTEM) ? qmi_loc_system_get_string (element->system) : "n/a"); + if (element->valid_information & QMI_LOC_SATELLITE_VALID_INFORMATION_GNSS_SATELLITE_ID) + g_print (" satellite id: %u\n", element->gnss_satellite_id); + else + g_print (" satellite id: n/a\n"); + g_print (" health status: %s\n", (element->valid_information & QMI_LOC_SATELLITE_VALID_INFORMATION_HEALTH_STATUS) ? qmi_loc_health_status_get_string (element->health_status) : "n/a"); + g_print (" satellite status: %s\n", (element->valid_information & QMI_LOC_SATELLITE_VALID_INFORMATION_PROCESS_STATUS) ? qmi_loc_satellite_status_get_string (element->satellite_status) : "n/a"); + g_print (" navigation data: %s\n", (element->valid_information & QMI_LOC_SATELLITE_VALID_INFORMATION_SATELLITE_INFO_MASK) ? qmi_loc_navigation_data_get_string (element->navigation_data) : "n/a"); + + if (element->valid_information & QMI_LOC_SATELLITE_VALID_INFORMATION_ELEVATION) + g_print (" elevation: %f\n", element->elevation_degrees); + else + g_print (" elevation: n/a\n"); + + if (element->valid_information & QMI_LOC_SATELLITE_VALID_INFORMATION_AZIMUTH) + g_print (" azimuth: %f\n", element->azimuth_degrees); + else + g_print (" azimuth: n/a\n"); + + if (element->valid_information & QMI_LOC_SATELLITE_VALID_INFORMATION_SIGNAL_TO_NOISE_RATIO) + g_print (" SNR: %f\n", element->signal_to_noise_ratio_bhz); + else + g_print (" SNR: n/a\n"); + } + + /* Terminate GET request */ + if (get_satellite_info_flag) + operation_shutdown (TRUE); +} + +static void +position_report_received (QmiClientLoc *client, + QmiIndicationLocPositionReportOutput *output) +{ + QmiLocSessionStatus status; + + qmi_indication_loc_position_report_output_get_session_status (output, &status, NULL); + g_print ("[position report] status: %s\n", qmi_loc_session_status_get_string (status)); + + if (status == QMI_LOC_SESSION_STATUS_SUCCESS || status == QMI_LOC_SESSION_STATUS_IN_PROGRESS) { + gdouble auxd; + gfloat auxf; + guint8 aux8; + guint32 aux32; + guint64 aux64; + QmiLocReliability reliability; + QmiLocTechnologyUsed technology; + QmiLocTimeSource time_source; + QmiLocSensorDataUsage sensor_data_usage; + QmiIndicationLocPositionReportOutputDilutionOfPrecision dop; + QmiIndicationLocPositionReportOutputGpsTime gps_time; + gchar *auxs; + gboolean auxb; + GArray *array; + + if (qmi_indication_loc_position_report_output_get_latitude (output, &auxd, NULL)) + g_print (" latitude: %lf degrees\n", auxd); + else + g_print (" latitude: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_longitude (output, &auxd, NULL)) + g_print (" longitude: %lf degrees\n", auxd); + else + g_print (" longitude: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_horizontal_uncertainty_circular (output, &auxf, NULL)) + g_print (" circular horizontal position uncertainty: %f meters\n", auxf); + else + g_print (" circular horizontal position uncertainty: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_horizontal_uncertainty_elliptical_minor (output, &auxf, NULL)) + g_print (" horizontal elliptical uncertainty (semi-minor axis): %f meters\n", auxf); + else + g_print (" horizontal elliptical uncertainty (semi-minor axis): n/a\n"); + + if (qmi_indication_loc_position_report_output_get_horizontal_uncertainty_elliptical_major (output, &auxf, NULL)) + g_print (" horizontal elliptical uncertainty (semi-major axis): %f meters\n", auxf); + else + g_print (" horizontal elliptical uncertainty (semi-major axis): n/a\n"); + + if (qmi_indication_loc_position_report_output_get_horizontal_uncertainty_elliptical_azimuth (output, &auxf, NULL)) + g_print (" horizontal elliptical uncertainty azimuth: %f meters\n", auxf); + else + g_print (" horizontal elliptical uncertainty azimuth: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_horizontal_confidence (output, &aux8, NULL)) + g_print (" horizontal confidence: %u%%\n", aux8); + else + g_print (" horizontal confidence: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_horizontal_reliability (output, &reliability, NULL)) + g_print (" horizontal reliability: %s\n", qmi_loc_reliability_get_string (reliability)); + else + g_print (" horizontal reliability: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_horizontal_speed (output, &auxf, NULL)) + g_print (" horizontal speed: %f m/s\n", auxf); + else + g_print (" horizontal speed: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_speed_uncertainty (output, &auxf, NULL)) + g_print (" speed uncertainty: %f m/s\n", auxf); + else + g_print (" speed uncertainty: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_altitude_from_ellipsoid (output, &auxf, NULL)) + g_print (" altitude w.r.t. ellipsoid: %f meters\n", auxf); + else + g_print (" altitude w.r.t. ellipsoid: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_altitude_from_sealevel (output, &auxf, NULL)) + g_print (" altitude w.r.t. mean sea level: %f meters\n", auxf); + else + g_print (" altitude w.r.t. mean sea level: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_vertical_uncertainty (output, &auxf, NULL)) + g_print (" vertical uncertainty: %f meters\n", auxf); + else + g_print (" vertical uncertainty: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_vertical_confidence (output, &aux8, NULL)) + g_print (" vertical confidence: %u%%\n", aux8); + else + g_print (" vertical confidence: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_vertical_reliability (output, &reliability, NULL)) + g_print (" vertical reliability: %s\n", qmi_loc_reliability_get_string (reliability)); + else + g_print (" vertical reliability: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_vertical_speed (output, &auxf, NULL)) + g_print (" vertical speed: %f m/s\n", auxf); + else + g_print (" vertical speed: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_heading (output, &auxf, NULL)) + g_print (" heading: %f degrees\n", auxf); + else + g_print (" heading: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_heading_uncertainty (output, &auxf, NULL)) + g_print (" heading uncertainty: %f meters\n", auxf); + else + g_print (" heading uncertainty: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_magnetic_deviation (output, &auxf, NULL)) + g_print (" magnetic deviation: %f degrees\n", auxf); + else + g_print (" magnetic deviation: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_technology_used (output, &technology, NULL)) { + auxs = qmi_loc_technology_used_build_string_from_mask (technology); + g_print (" technology: %s\n", auxs); + g_free (auxs); + } else + g_print (" technology: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_dilution_of_precision (output, &dop, NULL)) { + g_print (" position DOP: %f\n", dop.position_dilution_of_precision); + g_print (" horizontal DOP: %f\n", dop.horizontal_dilution_of_precision); + g_print (" vertical DOP: %f\n", dop.vertical_dilution_of_precision); + } else { + g_print (" position DOP: n/a\n"); + g_print (" horizontal DOP: n/a\n"); + g_print (" vertical DOP: n/a\n"); + } + + if (qmi_indication_loc_position_report_output_get_utc_timestamp (output, &aux64, NULL)) + g_print (" UTC timestamp: %" G_GUINT64_FORMAT " ms\n", aux64); + else + g_print (" UTC timestamp: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_leap_seconds (output, &aux8, NULL)) + g_print (" Leap seconds: %u\n", aux8); + else + g_print (" Leap seconds: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_gps_time (output, &gps_time, NULL)) + g_print (" GPS time: %u weeks and %ums\n", gps_time.gps_weeks, gps_time.gps_time_of_week_milliseconds); + else + g_print (" GPS time: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_time_uncertainty (output, &auxf, NULL)) + g_print (" time uncertainty: %f ms\n", auxf); + else + g_print (" time uncertainty: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_time_source (output, &time_source, NULL)) + g_print (" time source: %s\n", qmi_loc_reliability_get_string (time_source)); + else + g_print (" time source: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_sensor_data_usage (output, &sensor_data_usage, NULL)) + g_print (" sensor data usage: %s\n", qmi_loc_reliability_get_string (sensor_data_usage)); + else + g_print (" sensor data usage: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_session_fix_count (output, &aux32, NULL)) + g_print (" Fix count: %u\n", aux32); + else + g_print (" Fix count: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_satellites_used (output, &array, NULL)) { + guint i; + + g_print (" Satellites used: "); + for (i = 0; i < array->len; i++) { + guint16 sv_id; + + /* + * - For GPS: 1 to 32 + * - For SBAS: 33 to 64 + * - For GLONASS: 65 to 96 + * - For QZSS: 193 to 197 + * - For BDS: 201 to 237 + */ + sv_id = g_array_index (array, guint16, i); + g_print ("%u%s", sv_id, i == array->len - 1 ? "" : ","); + } + g_print ("\n"); + } else + g_print (" Satellites used: n/a\n"); + + if (qmi_indication_loc_position_report_output_get_altitude_assumed (output, &auxb, NULL)) + g_print (" Altitude assumed: %s\n", auxb ? "yes" : "no"); + else + g_print (" Altitude assumed: n/a\n"); + + /* Terminate GET request */ + if (get_position_flag) + operation_shutdown (TRUE); + + return; + } + + /* Otherwise, treat as error */ + g_printerr ("[position report] error: %s\n", qmi_loc_session_status_get_string (status)); + if (get_position_flag) + operation_shutdown (FALSE); +} + +static void +monitoring_step_ongoing (void) +{ + if (get_position_flag || follow_position_flag) + ctx->position_report_indication_id = g_signal_connect (ctx->client, + "position-report", + G_CALLBACK (position_report_received), + NULL); + + if (get_satellite_info_flag || follow_satellite_info_flag) + ctx->satellite_info_indication_id = g_signal_connect (ctx->client, + "gnss-satellite-info", + G_CALLBACK (satellite_info_received), + NULL); + + if (follow_nmea_flag) + ctx->nmea_indication_id = g_signal_connect (ctx->client, + "nmea", + G_CALLBACK (nmea_received), + NULL); + + g_assert (ctx->position_report_indication_id || + ctx->satellite_info_indication_id || + ctx->nmea_indication_id); +} + +static void +monitoring_step_setup_timeout (void) +{ + /* User can use Ctrl+C to cancel the monitoring at any time */ + g_cancellable_connect (ctx->cancellable, + G_CALLBACK (monitoring_cancelled), + NULL, + NULL); + + /* For non-follow requests, we also setup a timeout */ + if (get_position_flag || get_satellite_info_flag) + ctx->timeout_id = g_timeout_add_seconds (timeout > 0 ? timeout : DEFAULT_LOC_TIMEOUT_SECS, + (GSourceFunc) monitoring_timed_out, + NULL); + + /* Go on */ + ctx->monitoring_step++; + monitoring_step_run (); +} + +static void +register_events_ready (QmiClientLoc *client, + GAsyncResult *res) +{ + QmiMessageLocRegisterEventsOutput *output; + GError *error = NULL; + + output = qmi_client_loc_register_events_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + operation_shutdown (FALSE); + return; + } + + if (!qmi_message_loc_register_events_output_get_result (output, &error)) { + g_printerr ("error: could not register location tracking events: %s\n", error->message); + qmi_message_loc_register_events_output_unref (output); + g_error_free (error); + operation_shutdown (FALSE); + return; + } + + g_debug ("Registered location tracking events..."); + + /* Go on */ + ctx->monitoring_step++; + monitoring_step_run (); + + qmi_message_loc_register_events_output_unref (output); +} + +static void +monitoring_step_register_events (void) +{ + QmiMessageLocRegisterEventsInput *re_input; + QmiLocEventRegistrationFlag indication_mask = 0; + + /* Configure events to enable */ + + if (get_position_flag || follow_position_flag) { + indication_mask |= QMI_LOC_EVENT_REGISTRATION_FLAG_POSITION_REPORT; + ctx->position_report_indication_id = g_signal_connect (ctx->client, + "position-report", + G_CALLBACK (position_report_received), + NULL); + } + + if (get_satellite_info_flag || follow_satellite_info_flag) { + indication_mask |= QMI_LOC_EVENT_REGISTRATION_FLAG_GNSS_SATELLITE_INFO; + ctx->satellite_info_indication_id = g_signal_connect (ctx->client, + "gnss-satellite-info", + G_CALLBACK (satellite_info_received), + NULL); + } + + if (follow_nmea_flag) { + indication_mask |= QMI_LOC_EVENT_REGISTRATION_FLAG_NMEA; + ctx->nmea_indication_id = g_signal_connect (ctx->client, + "nmea", + G_CALLBACK (nmea_received), + NULL); + } + + g_assert (indication_mask); + + re_input = qmi_message_loc_register_events_input_new (); + qmi_message_loc_register_events_input_set_event_registration_mask ( + re_input, indication_mask, NULL); + qmi_client_loc_register_events (ctx->client, + re_input, + 10, + ctx->cancellable, + (GAsyncReadyCallback) register_events_ready, + NULL); + qmi_message_loc_register_events_input_unref (re_input); +} + +static void +monitoring_step_run (void) +{ + switch (ctx->monitoring_step) { + case MONITORING_STEP_FIRST: + ctx->monitoring_step++; + /* fall through */ + + case MONITORING_STEP_REGISTER_EVENTS: + monitoring_step_register_events (); + return; + + case MONITORING_STEP_SETUP_TIMEOUT: + monitoring_step_setup_timeout (); + return; + + case MONITORING_STEP_ONGOING: + monitoring_step_ongoing (); + return; + + default: + g_assert_not_reached(); + } +} + +static void +stop_ready (QmiClientLoc *client, + GAsyncResult *res) +{ + QmiMessageLocStopOutput *output; + GError *error = NULL; + + output = qmi_client_loc_stop_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + operation_shutdown (FALSE); + return; + } + + if (!qmi_message_loc_stop_output_get_result (output, &error)) { + g_printerr ("error: could not stop location tracking: %s\n", error->message); + qmi_message_loc_stop_output_unref (output); + g_error_free (error); + operation_shutdown (FALSE); + return; + } + + g_print ("[%s] Successfully stopped location tracking (session id %u)\n", + qmi_device_get_path_display (ctx->device), session_id); + + qmi_message_loc_stop_output_unref (output); + operation_shutdown (TRUE); +} + +static void +start_ready (QmiClientLoc *client, + GAsyncResult *res) +{ + QmiMessageLocStartOutput *output; + GError *error = NULL; + + output = qmi_client_loc_start_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + operation_shutdown (FALSE); + return; + } + + if (!qmi_message_loc_start_output_get_result (output, &error)) { + g_printerr ("error: could not start location tracking: %s\n", error->message); + qmi_message_loc_start_output_unref (output); + g_error_free (error); + operation_shutdown (FALSE); + return; + } + + g_print ("[%s] Successfully started location tracking (session id %u)\n", + qmi_device_get_path_display (ctx->device), session_id); + + qmi_message_loc_start_output_unref (output); + operation_shutdown (TRUE); +} + +void +qmicli_loc_run (QmiDevice *device, + QmiClientLoc *client, + GCancellable *cancellable) +{ + /* Initialize context */ + ctx = g_slice_new0 (Context); + ctx->device = g_object_ref (device); + ctx->client = g_object_ref (client); + if (cancellable) + ctx->cancellable = g_object_ref (cancellable); + + /* Request to start location gathering? */ + if (start_flag) { + QmiMessageLocStartInput *input; + + input = qmi_message_loc_start_input_new (); + qmi_message_loc_start_input_set_session_id (input, (guint8) session_id, NULL); + qmi_message_loc_start_input_set_intermediate_report_state (input, QMI_LOC_INTERMEDIATE_REPORT_STATE_ENABLE, NULL); + qmi_message_loc_start_input_set_minimum_interval_between_position_reports (input, 1000, NULL); + qmi_message_loc_start_input_set_fix_recurrence_type (input, QMI_LOC_FIX_RECURRENCE_TYPE_REQUEST_PERIODIC_FIXES, NULL); + qmi_client_loc_start (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback) start_ready, + NULL); + qmi_message_loc_start_input_unref (input); + return; + } + + /* Request to stop location gathering? */ + if (stop_flag) { + QmiMessageLocStopInput *input; + + input = qmi_message_loc_stop_input_new (); + qmi_message_loc_stop_input_set_session_id (input, (guint8) session_id, NULL); + qmi_client_loc_stop (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback) stop_ready, + NULL); + qmi_message_loc_stop_input_unref (input); + return; + } + + /* All the remaining actions require monitoring */ + if (get_position_flag || get_satellite_info_flag || follow_position_flag || follow_satellite_info_flag || follow_nmea_flag) { + ctx->monitoring_step = MONITORING_STEP_FIRST; + monitoring_step_run (); + return; + } + + g_warn_if_reached (); +} diff --git a/src/qmicli/qmicli.c b/src/qmicli/qmicli.c index fecae8d0..6993c9c9 100644 --- a/src/qmicli/qmicli.c +++ b/src/qmicli/qmicli.c @@ -372,6 +372,9 @@ allocate_client_ready (QmiDevice *dev, case QMI_SERVICE_VOICE: qmicli_voice_run (dev, QMI_CLIENT_VOICE (client), cancellable); return; + case QMI_SERVICE_LOC: + qmicli_loc_run (dev, QMI_CLIENT_LOC (client), cancellable); + return; default: g_assert_not_reached (); } @@ -731,6 +734,12 @@ parse_actions (void) actions_enabled++; } + /* LOC options? */ + if (qmicli_loc_options_enabled ()) { + service = QMI_SERVICE_LOC; + actions_enabled++; + } + /* Cannot mix actions from different services */ if (actions_enabled > 1) { g_printerr ("error: cannot execute multiple actions of different services\n"); @@ -774,6 +783,8 @@ int main (int argc, char **argv) qmicli_wda_get_option_group ()); g_option_context_add_group (context, qmicli_voice_get_option_group ()); + g_option_context_add_group (context, + qmicli_loc_get_option_group ()); g_option_context_add_main_entries (context, main_entries, NULL); if (!g_option_context_parse (context, &argc, &argv, &error)) { g_printerr ("error: %s\n", diff --git a/src/qmicli/qmicli.h b/src/qmicli/qmicli.h index 7db79058..df47de3b 100644 --- a/src/qmicli/qmicli.h +++ b/src/qmicli/qmicli.h @@ -90,4 +90,11 @@ void qmicli_voice_run (QmiDevice *device, QmiClientVoice *client, GCancellable *cancellable); +/* Location group */ +GOptionGroup *qmicli_loc_get_option_group (void); +gboolean qmicli_loc_options_enabled (void); +void qmicli_loc_run (QmiDevice *device, + QmiClientLoc *client, + GCancellable *cancellable); + #endif /* __QMICLI_H__ */ |