shared-qmi: unlock location engine at modem start

On SDM845 (OP6T) modem always starts with engine lock 'all'.
It doesn't allow to read assistance server settings at the beginning.
QMI call 'Get Predicted Orbits Data Source' (0x0036) fails with general
failure. As a result it's not possible to inject assistance data using
'mmcli -m any --location-inject-assistance-data=<file>'.

Commit 90843b7a0d ("shared-qmi: Lock and unlock GPS engine when
starting and stopping") unlocks engine on GNSS start, that allows
geolocation to work on SDM845, but it locks engine back on GNSS stop.
As a result after GNSS stop it's not possible to inject XTRA data again.

On EG25-G engine lock settings is stored in NV storage and is preserved after
modem restart. By default engine lock is 'none'. But currently on GNSS
stop this value is changed to 'all', that blocks location engine.
If previous ModemManager version is installed after
stopping geolocation and locking the engine, geolocation will not
work, since the engine is still locked and modem restart will not help.

This commit unlocks engine on modem start so all following operations
with an engine succeed. Engine isn't locked back.

Tested on SDM845 (OP6T) and Quectel EG25-G.

Fixes: 90843b7a0d ("shared-qmi: Lock and unlock GPS engine when starting and stopping")

Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
This commit is contained in:
Andrey Skvortsov
2025-10-20 15:30:54 -05:00
committed by Dan Williams
parent f2318ecc7b
commit 9c4aeeb33a
+98 -103
View File
@@ -5107,16 +5107,16 @@ pds_gps_service_state_stop_ready (QmiClientPds *client,
}
static void
loc_lock_engine_ready (QmiClientLoc *client,
GAsyncResult *res,
GTask *task)
loc_stop_ready (QmiClientLoc *client,
GAsyncResult *res,
GTask *task)
{
MMSharedQmi *self;
Private *priv;
QmiMessageLocSetEngineLockOutput *output;
QmiMessageLocStopOutput *output;
GError *error = NULL;
output = qmi_client_loc_set_engine_lock_finish (client, res, &error);
output = qmi_client_loc_stop_finish (client, res, &error);
if (!output) {
g_prefix_error (&error, "QMI operation failed: ");
g_task_return_error (task, error);
@@ -5124,17 +5124,17 @@ loc_lock_engine_ready (QmiClientLoc *client,
return;
}
if (!qmi_message_loc_set_engine_lock_output_get_result (output, &error)
if (!qmi_message_loc_stop_output_get_result (output, &error)
&& !g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_NO_PERMISSION)) {
g_prefix_error (&error, "Couldn't lock GPS engine: ");
g_prefix_error (&error, "Couldn't stop GPS engine: ");
g_task_return_error (task, error);
g_object_unref (task);
qmi_message_loc_set_engine_lock_output_unref (output);
qmi_message_loc_stop_output_unref (output);
return;
}
g_clear_error (&error);
qmi_message_loc_set_engine_lock_output_unref (output);
qmi_message_loc_stop_output_unref (output);
self = g_task_get_source_object (task);
priv = get_private (self);
@@ -5151,45 +5151,6 @@ loc_lock_engine_ready (QmiClientLoc *client,
g_object_unref (task);
}
static void
loc_stop_ready (QmiClientLoc *client,
GAsyncResult *res,
GTask *task)
{
QmiMessageLocStopOutput *output;
QmiMessageLocSetEngineLockInput *input;
GError *error = NULL;
output = qmi_client_loc_stop_finish (client, res, &error);
if (!output) {
g_prefix_error (&error, "QMI operation failed: ");
g_task_return_error (task, error);
g_object_unref (task);
return;
}
if (!qmi_message_loc_stop_output_get_result (output, &error)) {
g_prefix_error (&error, "Couldn't stop GPS engine: ");
g_task_return_error (task, error);
g_object_unref (task);
qmi_message_loc_stop_output_unref (output);
return;
}
qmi_message_loc_stop_output_unref (output);
input = qmi_message_loc_set_engine_lock_input_new ();
qmi_message_loc_set_engine_lock_input_set_lock_type (input, QMI_LOC_LOCK_TYPE_ALL, NULL);
qmi_client_loc_set_engine_lock (QMI_CLIENT_LOC (client),
input,
10,
NULL,
(GAsyncReadyCallback) loc_lock_engine_ready,
task);
qmi_message_loc_set_engine_lock_input_unref (input);
}
static void
stop_gps_engine (MMSharedQmi *self,
GAsyncReadyCallback callback,
@@ -5741,48 +5702,6 @@ loc_start_ready (QmiClientLoc *client,
qmi_message_loc_register_events_input_unref (input);
}
static void
loc_unlock_engine_ready (QmiClientLoc *client,
GAsyncResult *res,
GTask *task)
{
QmiMessageLocStartInput *input;
QmiMessageLocSetEngineLockOutput *output;
GError *error = NULL;
output = qmi_client_loc_set_engine_lock_finish (client, res, &error);
if (!output) {
g_prefix_error (&error, "QMI operation failed: ");
g_task_return_error (task, error);
g_object_unref (task);
return;
}
if (!qmi_message_loc_set_engine_lock_output_get_result (output, &error)
&& !g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_NO_PERMISSION)) {
g_prefix_error (&error, "Couldn't unlock GPS engine: ");
g_task_return_error (task, error);
g_object_unref (task);
qmi_message_loc_set_engine_lock_output_unref (output);
return;
}
g_clear_error (&error);
qmi_message_loc_set_engine_lock_output_unref (output);
input = qmi_message_loc_start_input_new ();
qmi_message_loc_start_input_set_session_id (input, DEFAULT_LOC_SESSION_ID, NULL);
qmi_message_loc_start_input_set_intermediate_report_state (input, QMI_LOC_INTERMEDIATE_REPORT_STATE_DISABLE, 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 (QMI_CLIENT_LOC (client),
input,
10,
NULL,
(GAsyncReadyCallback) loc_start_ready,
task);
qmi_message_loc_start_input_unref (input);
}
static void
start_gps_engine (MMSharedQmi *self,
@@ -5821,17 +5740,20 @@ start_gps_engine (MMSharedQmi *self,
MM_PORT_QMI_FLAG_DEFAULT,
NULL);
if (client) {
QmiMessageLocSetEngineLockInput *input;
QmiMessageLocStartInput *input;
input = qmi_message_loc_set_engine_lock_input_new ();
qmi_message_loc_set_engine_lock_input_set_lock_type (input, QMI_LOC_LOCK_TYPE_MT, NULL);
qmi_client_loc_set_engine_lock (QMI_CLIENT_LOC (client),
input,
10,
NULL,
(GAsyncReadyCallback) loc_unlock_engine_ready,
task);
qmi_message_loc_set_engine_lock_input_unref (input);
input = qmi_message_loc_start_input_new ();
qmi_message_loc_start_input_set_session_id (input, DEFAULT_LOC_SESSION_ID, NULL);
qmi_message_loc_start_input_set_intermediate_report_state (input, QMI_LOC_INTERMEDIATE_REPORT_STATE_DISABLE, 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 (QMI_CLIENT_LOC (client),
input,
10,
NULL,
(GAsyncReadyCallback) loc_start_ready,
task);
qmi_message_loc_start_input_unref (input);
return;
}
@@ -6621,6 +6543,81 @@ parent_load_capabilities_ready (MMIfaceModemLocation *self,
g_object_unref (task);
}
static void
location_load_capabilities (MMIfaceModemLocation *self,
GTask *task)
{
Private *priv;
priv = get_private (MM_SHARED_QMI (self));
priv->iface_modem_location_parent->load_capabilities (self,
(GAsyncReadyCallback)parent_load_capabilities_ready,
task);
}
static void
loc_unlock_location_engine_ready (QmiClientLoc *client,
GAsyncResult *res,
GTask *task)
{
MMIfaceModemLocation *self;
QmiMessageLocSetEngineLockOutput *output;
GError *error = NULL;
output = qmi_client_loc_set_engine_lock_finish (client, res, &error);
if (!output) {
mm_obj_warn (client, "QMI operation failed: %s", error->message);
g_error_free (error);
}
if (!qmi_message_loc_set_engine_lock_output_get_result (output, &error)
&& !g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_NO_PERMISSION)) {
mm_obj_warn (client, "Couldn't unlock GPS engine: %s", error->message);
g_error_free (error);
}
qmi_message_loc_set_engine_lock_output_unref (output);
self = g_task_get_source_object (task);
location_load_capabilities (self, task);
}
static void
unlock_location_engine (MMIfaceModemLocation *self,
GTask *task)
{
QmiClient *client;
QmiMessageLocSetEngineLockInput *input;
/* Prefer PDS, no need to unlock engine */
if (mm_shared_qmi_peek_client (MM_SHARED_QMI (self),
QMI_SERVICE_PDS,
MM_PORT_QMI_FLAG_DEFAULT,
NULL))
goto out;
/* Otherwise LOC */
client = mm_shared_qmi_peek_client (MM_SHARED_QMI (self),
QMI_SERVICE_LOC,
MM_PORT_QMI_FLAG_DEFAULT,
NULL);
if (!client)
goto out;
input = qmi_message_loc_set_engine_lock_input_new ();
qmi_message_loc_set_engine_lock_input_set_lock_type (input, QMI_LOC_LOCK_TYPE_MT, NULL);
qmi_client_loc_set_engine_lock (QMI_CLIENT_LOC (client),
input,
10,
NULL,
(GAsyncReadyCallback) loc_unlock_location_engine_ready,
task);
qmi_message_loc_set_engine_lock_input_unref (input);
return;
out:
location_load_capabilities (self, task);
}
void
mm_shared_qmi_location_load_capabilities (MMIfaceModemLocation *self,
GAsyncReadyCallback callback,
@@ -6636,9 +6633,7 @@ mm_shared_qmi_location_load_capabilities (MMIfaceModemLocation *self,
g_assert (priv->iface_modem_location_parent->load_capabilities);
g_assert (priv->iface_modem_location_parent->load_capabilities_finish);
priv->iface_modem_location_parent->load_capabilities (self,
(GAsyncReadyCallback)parent_load_capabilities_ready,
task);
unlock_location_engine (self, task);
}
/*****************************************************************************/