summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2014-02-06 19:07:53 +0100
committerAleksander Morgado <aleksander@aleksander.es>2014-09-05 12:11:18 +0200
commitfd7d0a08f73cb0f8e7166dd34bc713ec0089f62f (patch)
treed6ba59b8b068f89d3707b79c7ee6f60dc2038682
parent75f35cdb9edd0a9822b8af62cd3c36e8de95c655 (diff)
broadband-modem-qmi: implement A-GPS enabling/disabling
-rw-r--r--src/mm-broadband-modem-qmi.c371
1 files changed, 310 insertions, 61 deletions
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index 716dbd4f..d0d672a7 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -7970,6 +7970,12 @@ typedef struct {
MMBroadbandModemQmi *self;
QmiClientPds *client;
GSimpleAsyncResult *result;
+ MMModemLocationSource source;
+ /* Default tracking session (for A-GPS disabling) */
+ QmiPdsOperatingMode session_operation;
+ guint8 data_timeout;
+ guint32 interval;
+ guint32 accuracy_threshold;
} DisableLocationGatheringContext;
static void
@@ -8023,16 +8029,112 @@ gps_service_state_stop_ready (QmiClientPds *client,
qmi_message_pds_set_gps_service_state_output_unref (output);
- mm_dbg ("Removing location event report indication handling");
g_assert (ctx->self->priv->location_event_report_indication_id != 0);
g_signal_handler_disconnect (client, ctx->self->priv->location_event_report_indication_id);
ctx->self->priv->location_event_report_indication_id = 0;
+ mm_dbg ("GPS stopped");
+ ctx->self->priv->enabled_sources &= ~ctx->source;
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ disable_location_gathering_context_complete_and_free (ctx);
+}
+
+static void
+set_default_tracking_session_stop_ready (QmiClientPds *client,
+ GAsyncResult *res,
+ DisableLocationGatheringContext *ctx)
+{
+ QmiMessagePdsSetDefaultTrackingSessionOutput *output = NULL;
+ GError *error = NULL;
+
+ output = qmi_client_pds_set_default_tracking_session_finish (client, res, &error);
+ if (!output) {
+ g_prefix_error (&error, "QMI operation failed: ");
+ g_simple_async_result_take_error (ctx->result, error);
+ disable_location_gathering_context_complete_and_free (ctx);
+ return;
+ }
+
+ if (!qmi_message_pds_set_default_tracking_session_output_get_result (output, &error)) {
+ g_prefix_error (&error, "Couldn't set default tracking session: ");
+ g_simple_async_result_take_error (ctx->result, error);
+ disable_location_gathering_context_complete_and_free (ctx);
+ qmi_message_pds_set_default_tracking_session_output_unref (output);
+ return;
+ }
+
+ qmi_message_pds_set_default_tracking_session_output_unref (output);
+
+ /* Done */
+ mm_dbg ("A-GPS disabled");
+ ctx->self->priv->enabled_sources &= ~ctx->source;
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
disable_location_gathering_context_complete_and_free (ctx);
}
static void
+get_default_tracking_session_stop_ready (QmiClientPds *client,
+ GAsyncResult *res,
+ DisableLocationGatheringContext *ctx)
+{
+ QmiMessagePdsSetDefaultTrackingSessionInput *input;
+ QmiMessagePdsGetDefaultTrackingSessionOutput *output = NULL;
+ GError *error = NULL;
+
+ output = qmi_client_pds_get_default_tracking_session_finish (client, res, &error);
+ if (!output) {
+ g_prefix_error (&error, "QMI operation failed: ");
+ g_simple_async_result_take_error (ctx->result, error);
+ disable_location_gathering_context_complete_and_free (ctx);
+ return;
+ }
+
+ if (!qmi_message_pds_get_default_tracking_session_output_get_result (output, &error)) {
+ g_prefix_error (&error, "Couldn't get default tracking session: ");
+ g_simple_async_result_take_error (ctx->result, error);
+ disable_location_gathering_context_complete_and_free (ctx);
+ qmi_message_pds_get_default_tracking_session_output_unref (output);
+ return;
+ }
+
+ qmi_message_pds_get_default_tracking_session_output_get_info (
+ output,
+ &ctx->session_operation,
+ &ctx->data_timeout,
+ &ctx->interval,
+ &ctx->accuracy_threshold,
+ NULL);
+
+ qmi_message_pds_get_default_tracking_session_output_unref (output);
+
+ if (ctx->session_operation == QMI_PDS_OPERATING_MODE_STANDALONE) {
+ /* Done */
+ mm_dbg ("A-GPS already disabled");
+ ctx->self->priv->enabled_sources &= ~ctx->source;
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ disable_location_gathering_context_complete_and_free (ctx);
+ return;
+ }
+
+ input = qmi_message_pds_set_default_tracking_session_input_new ();
+ qmi_message_pds_set_default_tracking_session_input_set_info (
+ input,
+ QMI_PDS_OPERATING_MODE_STANDALONE,
+ ctx->data_timeout,
+ ctx->interval,
+ ctx->accuracy_threshold,
+ NULL);
+ qmi_client_pds_set_default_tracking_session (
+ ctx->client,
+ input,
+ 10,
+ NULL, /* cancellable */
+ (GAsyncReadyCallback)set_default_tracking_session_stop_ready,
+ ctx);
+ qmi_message_pds_set_default_tracking_session_input_unref (input);
+}
+
+static void
disable_location_gathering (MMIfaceModemLocation *self,
MMModemLocationSource source,
GAsyncReadyCallback callback,
@@ -8040,7 +8142,6 @@ disable_location_gathering (MMIfaceModemLocation *self,
{
DisableLocationGatheringContext *ctx;
QmiClient *client = NULL;
- gboolean stop_gps = FALSE;
GSimpleAsyncResult *result;
result = g_simple_async_result_new (G_OBJECT (self),
@@ -8051,53 +8152,74 @@ disable_location_gathering (MMIfaceModemLocation *self,
/* Nothing to be done to disable 3GPP or CDMA locations */
if (source == MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI ||
source == MM_MODEM_LOCATION_SOURCE_CDMA_BS) {
+ /* Just mark it as disabled */
+ MM_BROADBAND_MODEM_QMI (self)->priv->enabled_sources &= ~source;
g_simple_async_result_set_op_res_gboolean (result, TRUE);
g_simple_async_result_complete_in_idle (result);
g_object_unref (result);
return;
}
+ /* Setup context and client */
if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self),
QMI_SERVICE_PDS, &client,
callback, user_data)) {
g_object_unref (result);
return;
}
-
ctx = g_slice_new0 (DisableLocationGatheringContext);
ctx->self = g_object_ref (self);
ctx->client = g_object_ref (client);
ctx->result = result;
+ ctx->source = source;
- /* Only stop GPS engine if no GPS-related sources enabled */
- if (source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA |
- MM_MODEM_LOCATION_SOURCE_GPS_RAW)) {
- ctx->self->priv->enabled_sources &= ~source;
-
- if (!(ctx->self->priv->enabled_sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA |
- MM_MODEM_LOCATION_SOURCE_GPS_RAW)))
- stop_gps = TRUE;
- }
-
- if (stop_gps) {
- QmiMessagePdsSetGpsServiceStateInput *input;
-
- input = qmi_message_pds_set_gps_service_state_input_new ();
- qmi_message_pds_set_gps_service_state_input_set_state (input, FALSE, NULL);
- qmi_client_pds_set_gps_service_state (
+ /* Disable A-GPS? */
+ if (source == MM_MODEM_LOCATION_SOURCE_AGPS) {
+ qmi_client_pds_get_default_tracking_session (
ctx->client,
- input,
+ NULL,
10,
NULL, /* cancellable */
- (GAsyncReadyCallback)gps_service_state_stop_ready,
+ (GAsyncReadyCallback)get_default_tracking_session_stop_ready,
ctx);
- qmi_message_pds_set_gps_service_state_input_unref (input);
return;
}
- /* If still some GPS needed, just return */
- g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
- disable_location_gathering_context_complete_and_free (ctx);
+ /* Only stop GPS engine if no GPS-related sources enabled */
+ if (source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | MM_MODEM_LOCATION_SOURCE_GPS_RAW)) {
+ MMModemLocationSource tmp;
+
+ /* If no more GPS sources enabled, stop GPS */
+ tmp = ctx->self->priv->enabled_sources;
+ tmp &= ~source;
+ if (!(tmp & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | MM_MODEM_LOCATION_SOURCE_GPS_RAW))) {
+ QmiMessagePdsSetGpsServiceStateInput *input;
+
+ input = qmi_message_pds_set_gps_service_state_input_new ();
+ qmi_message_pds_set_gps_service_state_input_set_state (input, FALSE, NULL);
+ qmi_client_pds_set_gps_service_state (
+ ctx->client,
+ input,
+ 10,
+ NULL, /* cancellable */
+ (GAsyncReadyCallback)gps_service_state_stop_ready,
+ ctx);
+ qmi_message_pds_set_gps_service_state_input_unref (input);
+ return;
+ }
+
+ /* Otherwise, we have more GPS sources enabled, we shouldn't stop GPS, just
+ * return */
+ ctx->self->priv->enabled_sources &= ~source;
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ disable_location_gathering_context_complete_and_free (ctx);
+ return;
+ }
+
+ /* The QMI implementation has a fixed set of capabilities supported. Arriving
+ * here means we tried to disable one which wasn't set as supported, which should
+ * not happen */
+ g_assert_not_reached ();
}
/*****************************************************************************/
@@ -8133,6 +8255,11 @@ typedef struct {
QmiClientPds *client;
GSimpleAsyncResult *result;
MMModemLocationSource source;
+ /* Default tracking session (for A-GPS enabling) */
+ QmiPdsOperatingMode session_operation;
+ guint8 data_timeout;
+ guint32 interval;
+ guint32 accuracy_threshold;
} EnableLocationGatheringContext;
static void
@@ -8188,6 +8315,9 @@ ser_location_ready (QmiClientPds *client,
G_CALLBACK (location_event_report_indication_cb),
ctx->self);
+ /* Done */
+ mm_dbg ("GPS started");
+ ctx->self->priv->enabled_sources |= ctx->source;
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
enable_location_gathering_context_complete_and_free (ctx);
}
@@ -8283,12 +8413,107 @@ gps_service_state_start_ready (QmiClientPds *client,
}
static void
+set_default_tracking_session_start_ready (QmiClientPds *client,
+ GAsyncResult *res,
+ EnableLocationGatheringContext *ctx)
+{
+ QmiMessagePdsSetDefaultTrackingSessionOutput *output = NULL;
+ GError *error = NULL;
+
+ output = qmi_client_pds_set_default_tracking_session_finish (client, res, &error);
+ if (!output) {
+ g_prefix_error (&error, "QMI operation failed: ");
+ g_simple_async_result_take_error (ctx->result, error);
+ enable_location_gathering_context_complete_and_free (ctx);
+ return;
+ }
+
+ if (!qmi_message_pds_set_default_tracking_session_output_get_result (output, &error)) {
+ g_prefix_error (&error, "Couldn't set default tracking session: ");
+ g_simple_async_result_take_error (ctx->result, error);
+ enable_location_gathering_context_complete_and_free (ctx);
+ qmi_message_pds_set_default_tracking_session_output_unref (output);
+ return;
+ }
+
+ qmi_message_pds_set_default_tracking_session_output_unref (output);
+
+ /* Done */
+ mm_dbg ("A-GPS enabled");
+ ctx->self->priv->enabled_sources |= ctx->source;
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ enable_location_gathering_context_complete_and_free (ctx);
+}
+
+static void
+get_default_tracking_session_start_ready (QmiClientPds *client,
+ GAsyncResult *res,
+ EnableLocationGatheringContext *ctx)
+{
+ QmiMessagePdsSetDefaultTrackingSessionInput *input;
+ QmiMessagePdsGetDefaultTrackingSessionOutput *output = NULL;
+ GError *error = NULL;
+
+ output = qmi_client_pds_get_default_tracking_session_finish (client, res, &error);
+ if (!output) {
+ g_prefix_error (&error, "QMI operation failed: ");
+ g_simple_async_result_take_error (ctx->result, error);
+ enable_location_gathering_context_complete_and_free (ctx);
+ return;
+ }
+
+ if (!qmi_message_pds_get_default_tracking_session_output_get_result (output, &error)) {
+ g_prefix_error (&error, "Couldn't get default tracking session: ");
+ g_simple_async_result_take_error (ctx->result, error);
+ enable_location_gathering_context_complete_and_free (ctx);
+ qmi_message_pds_get_default_tracking_session_output_unref (output);
+ return;
+ }
+
+ qmi_message_pds_get_default_tracking_session_output_get_info (
+ output,
+ &ctx->session_operation,
+ &ctx->data_timeout,
+ &ctx->interval,
+ &ctx->accuracy_threshold,
+ NULL);
+
+ qmi_message_pds_get_default_tracking_session_output_unref (output);
+
+ if (ctx->session_operation == QMI_PDS_OPERATING_MODE_MS_ASSISTED) {
+ /* Done */
+ mm_dbg ("A-GPS already enabled");
+ ctx->self->priv->enabled_sources |= ctx->source;
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ enable_location_gathering_context_complete_and_free (ctx);
+ return;
+ }
+
+ input = qmi_message_pds_set_default_tracking_session_input_new ();
+ qmi_message_pds_set_default_tracking_session_input_set_info (
+ input,
+ QMI_PDS_OPERATING_MODE_MS_ASSISTED,
+ ctx->data_timeout,
+ ctx->interval,
+ ctx->accuracy_threshold,
+ NULL);
+ qmi_client_pds_set_default_tracking_session (
+ ctx->client,
+ input,
+ 10,
+ NULL, /* cancellable */
+ (GAsyncReadyCallback)set_default_tracking_session_start_ready,
+ ctx);
+ qmi_message_pds_set_default_tracking_session_input_unref (input);
+}
+
+static void
parent_enable_location_gathering_ready (MMIfaceModemLocation *self,
GAsyncResult *res,
EnableLocationGatheringContext *ctx)
{
- gboolean start_gps = FALSE;
GError *error = NULL;
+ QmiClient *client;
if (!iface_modem_location_parent->enable_location_gathering_finish (self, res, &error)) {
g_simple_async_result_take_error (ctx->result, error);
@@ -8296,58 +8521,81 @@ parent_enable_location_gathering_ready (MMIfaceModemLocation *self,
return;
}
- /* Now our own enabling */
+ /* Nothing else needed in the QMI side for LAC/CI */
+ if (ctx->source == MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI) {
+ ctx->self->priv->enabled_sources |= ctx->source;
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ enable_location_gathering_context_complete_and_free (ctx);
+ return;
+ }
/* CDMA modems need to re-run registration checks when enabling the CDMA BS
* location source, so that we get up to date BS location information.
* Note that we don't care for when the registration checks get finished.
*/
if (ctx->source == MM_MODEM_LOCATION_SOURCE_CDMA_BS &&
- mm_iface_modem_is_cdma (MM_IFACE_MODEM (self))) {
+ mm_iface_modem_is_cdma (MM_IFACE_MODEM (ctx->self))) {
/* Reload registration to get LAC/CI */
- mm_iface_modem_cdma_run_registration_checks (MM_IFACE_MODEM_CDMA (self), NULL, NULL);
+ mm_iface_modem_cdma_run_registration_checks (MM_IFACE_MODEM_CDMA (ctx->self), NULL, NULL);
+ /* Just mark it as enabled */
+ ctx->self->priv->enabled_sources |= ctx->source;
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ enable_location_gathering_context_complete_and_free (ctx);
+ return;
+ }
+
+ /* Setup context and client */
+ client = peek_qmi_client (ctx->self, QMI_SERVICE_PDS, &error);
+ if (!client) {
+ g_simple_async_result_take_error (ctx->result, error);
+ enable_location_gathering_context_complete_and_free (ctx);
+ return;
+ }
+ ctx->client = g_object_ref (client);
+
+ /* Enabling A-GPS? */
+ if (ctx->source == MM_MODEM_LOCATION_SOURCE_AGPS) {
+ qmi_client_pds_get_default_tracking_session (
+ ctx->client,
+ NULL,
+ 10,
+ NULL, /* cancellable */
+ (GAsyncReadyCallback)get_default_tracking_session_start_ready,
+ ctx);
+ return;
}
/* NMEA and RAW are both enabled in the same way */
- if (ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA |
- MM_MODEM_LOCATION_SOURCE_GPS_RAW)) {
+ if (ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | MM_MODEM_LOCATION_SOURCE_GPS_RAW)) {
/* Only start GPS engine if not done already */
if (!(ctx->self->priv->enabled_sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA |
- MM_MODEM_LOCATION_SOURCE_GPS_RAW)))
- start_gps = TRUE;
- ctx->self->priv->enabled_sources |= ctx->source;
- }
+ MM_MODEM_LOCATION_SOURCE_GPS_RAW))) {
+ QmiMessagePdsSetGpsServiceStateInput *input;
- if (start_gps) {
- QmiMessagePdsSetGpsServiceStateInput *input;
- QmiClient *client;
-
- client = peek_qmi_client (ctx->self, QMI_SERVICE_PDS, &error);
- if (!client) {
- g_simple_async_result_take_error (ctx->result, error);
- enable_location_gathering_context_complete_and_free (ctx);
+ input = qmi_message_pds_set_gps_service_state_input_new ();
+ qmi_message_pds_set_gps_service_state_input_set_state (input, TRUE, NULL);
+ qmi_client_pds_set_gps_service_state (
+ ctx->client,
+ input,
+ 10,
+ NULL, /* cancellable */
+ (GAsyncReadyCallback)gps_service_state_start_ready,
+ ctx);
+ qmi_message_pds_set_gps_service_state_input_unref (input);
return;
}
- /* Keep a ref around */
- ctx->client = g_object_ref (client);
-
- input = qmi_message_pds_set_gps_service_state_input_new ();
- qmi_message_pds_set_gps_service_state_input_set_state (input, TRUE, NULL);
- qmi_client_pds_set_gps_service_state (
- ctx->client,
- input,
- 10,
- NULL, /* cancellable */
- (GAsyncReadyCallback)gps_service_state_start_ready,
- ctx);
- qmi_message_pds_set_gps_service_state_input_unref (input);
+ /* GPS already started, we're done */
+ ctx->self->priv->enabled_sources |= ctx->source;
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ enable_location_gathering_context_complete_and_free (ctx);
return;
}
- /* For any other location (e.g. 3GPP), or if GPS already running just return */
- g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
- enable_location_gathering_context_complete_and_free (ctx);
+ /* The QMI implementation has a fixed set of capabilities supported. Arriving
+ * here means we tried to enable one which wasn't set as supported, which should
+ * not happen */
+ g_assert_not_reached ();
}
static void
@@ -8364,12 +8612,13 @@ enable_location_gathering (MMIfaceModemLocation *self,
callback,
user_data,
enable_location_gathering);
+ /* Store source to enable, there will be only one! */
ctx->source = source;
/* Chain up parent's gathering enable */
iface_modem_location_parent->enable_location_gathering (
- self,
- source,
+ MM_IFACE_MODEM_LOCATION (ctx->self),
+ ctx->source,
(GAsyncReadyCallback)parent_enable_location_gathering_ready,
ctx);
}