broadband-modem-qmi: implement A-GPS enabling/disabling

This commit is contained in:
Aleksander Morgado
2014-02-06 19:07:53 +01:00
parent 75f35cdb9e
commit fd7d0a08f7

View File

@@ -7970,6 +7970,12 @@ typedef struct {
MMBroadbandModemQmi *self; MMBroadbandModemQmi *self;
QmiClientPds *client; QmiClientPds *client;
GSimpleAsyncResult *result; GSimpleAsyncResult *result;
MMModemLocationSource source;
/* Default tracking session (for A-GPS disabling) */
QmiPdsOperatingMode session_operation;
guint8 data_timeout;
guint32 interval;
guint32 accuracy_threshold;
} DisableLocationGatheringContext; } DisableLocationGatheringContext;
static void static void
@@ -8023,15 +8029,111 @@ gps_service_state_stop_ready (QmiClientPds *client,
qmi_message_pds_set_gps_service_state_output_unref (output); 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_assert (ctx->self->priv->location_event_report_indication_id != 0);
g_signal_handler_disconnect (client, ctx->self->priv->location_event_report_indication_id); g_signal_handler_disconnect (client, ctx->self->priv->location_event_report_indication_id);
ctx->self->priv->location_event_report_indication_id = 0; 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); g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
disable_location_gathering_context_complete_and_free (ctx); 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 static void
disable_location_gathering (MMIfaceModemLocation *self, disable_location_gathering (MMIfaceModemLocation *self,
MMModemLocationSource source, MMModemLocationSource source,
@@ -8040,7 +8142,6 @@ disable_location_gathering (MMIfaceModemLocation *self,
{ {
DisableLocationGatheringContext *ctx; DisableLocationGatheringContext *ctx;
QmiClient *client = NULL; QmiClient *client = NULL;
gboolean stop_gps = FALSE;
GSimpleAsyncResult *result; GSimpleAsyncResult *result;
result = g_simple_async_result_new (G_OBJECT (self), 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 */ /* Nothing to be done to disable 3GPP or CDMA locations */
if (source == MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI || if (source == MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI ||
source == MM_MODEM_LOCATION_SOURCE_CDMA_BS) { 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_set_op_res_gboolean (result, TRUE);
g_simple_async_result_complete_in_idle (result); g_simple_async_result_complete_in_idle (result);
g_object_unref (result); g_object_unref (result);
return; return;
} }
/* Setup context and client */
if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self), if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self),
QMI_SERVICE_PDS, &client, QMI_SERVICE_PDS, &client,
callback, user_data)) { callback, user_data)) {
g_object_unref (result); g_object_unref (result);
return; return;
} }
ctx = g_slice_new0 (DisableLocationGatheringContext); ctx = g_slice_new0 (DisableLocationGatheringContext);
ctx->self = g_object_ref (self); ctx->self = g_object_ref (self);
ctx->client = g_object_ref (client); ctx->client = g_object_ref (client);
ctx->result = result; ctx->result = result;
ctx->source = source;
/* Only stop GPS engine if no GPS-related sources enabled */ /* Disable A-GPS? */
if (source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | if (source == MM_MODEM_LOCATION_SOURCE_AGPS) {
MM_MODEM_LOCATION_SOURCE_GPS_RAW)) { qmi_client_pds_get_default_tracking_session (
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 (
ctx->client, ctx->client,
input, NULL,
10, 10,
NULL, /* cancellable */ NULL, /* cancellable */
(GAsyncReadyCallback)gps_service_state_stop_ready, (GAsyncReadyCallback)get_default_tracking_session_stop_ready,
ctx); ctx);
qmi_message_pds_set_gps_service_state_input_unref (input);
return; return;
} }
/* If still some GPS needed, just return */ /* Only stop GPS engine if no GPS-related sources enabled */
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); if (source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | MM_MODEM_LOCATION_SOURCE_GPS_RAW)) {
disable_location_gathering_context_complete_and_free (ctx); 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; QmiClientPds *client;
GSimpleAsyncResult *result; GSimpleAsyncResult *result;
MMModemLocationSource source; MMModemLocationSource source;
/* Default tracking session (for A-GPS enabling) */
QmiPdsOperatingMode session_operation;
guint8 data_timeout;
guint32 interval;
guint32 accuracy_threshold;
} EnableLocationGatheringContext; } EnableLocationGatheringContext;
static void static void
@@ -8188,6 +8315,9 @@ ser_location_ready (QmiClientPds *client,
G_CALLBACK (location_event_report_indication_cb), G_CALLBACK (location_event_report_indication_cb),
ctx->self); 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); g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
enable_location_gathering_context_complete_and_free (ctx); enable_location_gathering_context_complete_and_free (ctx);
} }
@@ -8282,13 +8412,108 @@ gps_service_state_start_ready (QmiClientPds *client,
qmi_message_pds_set_auto_tracking_state_input_unref (input); qmi_message_pds_set_auto_tracking_state_input_unref (input);
} }
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 static void
parent_enable_location_gathering_ready (MMIfaceModemLocation *self, parent_enable_location_gathering_ready (MMIfaceModemLocation *self,
GAsyncResult *res, GAsyncResult *res,
EnableLocationGatheringContext *ctx) EnableLocationGatheringContext *ctx)
{ {
gboolean start_gps = FALSE;
GError *error = NULL; GError *error = NULL;
QmiClient *client;
if (!iface_modem_location_parent->enable_location_gathering_finish (self, res, &error)) { if (!iface_modem_location_parent->enable_location_gathering_finish (self, res, &error)) {
g_simple_async_result_take_error (ctx->result, error); g_simple_async_result_take_error (ctx->result, error);
@@ -8296,58 +8521,81 @@ parent_enable_location_gathering_ready (MMIfaceModemLocation *self,
return; 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 /* 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. * 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. * Note that we don't care for when the registration checks get finished.
*/ */
if (ctx->source == MM_MODEM_LOCATION_SOURCE_CDMA_BS && 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 */ /* 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 */
/* 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)) {
/* 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; 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);
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);
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);
return; return;
} }
/* For any other location (e.g. 3GPP), or if GPS already running just return */ /* Setup context and client */
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); client = peek_qmi_client (ctx->self, QMI_SERVICE_PDS, &error);
enable_location_gathering_context_complete_and_free (ctx); 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)) {
/* 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))) {
QmiMessagePdsSetGpsServiceStateInput *input;
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;
}
/* 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;
}
/* 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 static void
@@ -8364,12 +8612,13 @@ enable_location_gathering (MMIfaceModemLocation *self,
callback, callback,
user_data, user_data,
enable_location_gathering); enable_location_gathering);
/* Store source to enable, there will be only one! */
ctx->source = source; ctx->source = source;
/* Chain up parent's gathering enable */ /* Chain up parent's gathering enable */
iface_modem_location_parent->enable_location_gathering ( iface_modem_location_parent->enable_location_gathering (
self, MM_IFACE_MODEM_LOCATION (ctx->self),
source, ctx->source,
(GAsyncReadyCallback)parent_enable_location_gathering_ready, (GAsyncReadyCallback)parent_enable_location_gathering_ready,
ctx); ctx);
} }