aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2022-01-11 12:26:26 +0100
committerAleksander Morgado <aleksander@aleksander.es>2022-01-14 10:36:39 +0100
commit60f61e974042a71ff039c36a431a270eeb730ef4 (patch)
treebc43b3328e591828950c217c93868d4aee3584dc
parent1291754e60a3d904b059efc428f7013f6a241d7c (diff)
broadband-modem-qmi: setup operation context for power up/down/off
We must keep a valid QmiClient reference for as long as the operation runs, so that we can use it in all the request send operations we do, and also so that we can remove the indication id upon completing the operation. The timeout id and indication id, which are also part of a single power operation are also included in the operation context, because they don't have any other meaning out of it. The operation context is stored as task data.
-rw-r--r--src/mm-broadband-modem-qmi.c209
1 files changed, 98 insertions, 111 deletions
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index 26b4c7c2..c157a375 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -162,12 +162,8 @@ struct _MMBroadbandModemQmiPrivate {
/* For notifying when the qmi-proxy connection is dead */
guint qmi_device_removed_id;
- /* Power Indication Helper */
- guint power_event_report_indication_id;
-
/* Power Set Operating Mode Helper */
GTask *set_operating_mode_task;
- guint set_operating_timeout_id;
};
/*****************************************************************************/
@@ -1708,6 +1704,22 @@ load_signal_quality (MMIfaceModem *self,
/*****************************************************************************/
/* Powering up/down/off the modem (Modem interface) */
+typedef struct {
+ QmiDmsOperatingMode mode;
+ QmiClientDms *client;
+ guint indication_id;
+ guint timeout_id;
+} SetOperatingModeContext;
+
+static void
+set_operating_mode_context_free (SetOperatingModeContext *ctx)
+{
+ g_assert (ctx->indication_id == 0);
+ g_assert (ctx->timeout_id == 0);
+ g_clear_object (&ctx->client);
+ g_slice_free (SetOperatingModeContext, ctx);
+}
+
static gboolean
modem_power_up_down_off_finish (MMIfaceModem *self,
GAsyncResult *res,
@@ -1717,51 +1729,36 @@ modem_power_up_down_off_finish (MMIfaceModem *self,
}
static void
-modem_power_indication_deregister (MMBroadbandModemQmi *self)
+set_operating_mode_complete (MMBroadbandModemQmi *self,
+ GError *error)
{
- g_autoptr(QmiMessageDmsSetEventReportInput) input = NULL;
- QmiClient *client;
-
- g_assert (self->priv->power_event_report_indication_id != 0);
- g_signal_handler_disconnect (QMI_CLIENT_DMS (client),
- self->priv->power_event_report_indication_id);
- self->priv->power_event_report_indication_id = 0;
+ GTask *task;
+ SetOperatingModeContext *ctx;
- client = mm_shared_qmi_peek_client (MM_SHARED_QMI (self),
- QMI_SERVICE_DMS,
- MM_PORT_QMI_FLAG_DEFAULT,
- NULL);
- if (!client)
- return;
+ g_assert (self->priv->set_operating_mode_task);
+ task = g_steal_pointer (&self->priv->set_operating_mode_task);
+ ctx = g_task_get_task_data (task);
- input = qmi_message_dms_set_event_report_input_new ();
- qmi_message_dms_set_event_report_input_set_operating_mode_reporting (input, FALSE, NULL);
- mm_obj_dbg (self, "Power indication deregistration request is sent");
- qmi_client_dms_set_event_report (QMI_CLIENT_DMS (client), input, 5, NULL, NULL, NULL);
-}
+ if (ctx->timeout_id) {
+ g_source_remove (ctx->timeout_id);
+ ctx->timeout_id = 0;
+ }
-static void
-dms_set_operating_mode_complete (MMBroadbandModemQmi *self,
- GError *error)
-{
- GTask *task;
+ if (ctx->indication_id) {
+ g_autoptr(QmiMessageDmsSetEventReportInput) input = NULL;
- task = g_steal_pointer (&self->priv->set_operating_mode_task);
- g_assert (task != NULL);
+ g_signal_handler_disconnect (ctx->client, ctx->indication_id);
+ ctx->indication_id = 0;
- if (self->priv->set_operating_timeout_id) {
- g_source_remove (self->priv->set_operating_timeout_id);
- self->priv->set_operating_timeout_id = 0;
- }
- if (self->priv->power_event_report_indication_id) {
- modem_power_indication_deregister (self);
+ input = qmi_message_dms_set_event_report_input_new ();
+ qmi_message_dms_set_event_report_input_set_operating_mode_reporting (input, FALSE, NULL);
+ qmi_client_dms_set_event_report (ctx->client, input, 5, NULL, NULL, NULL);
}
- if (error) {
+ if (error)
g_task_return_error (task, error);
- } else {
+ else
g_task_return_boolean (task, TRUE);
- }
g_object_unref (task);
}
@@ -1771,7 +1768,7 @@ dms_set_operating_mode_timeout_cb (MMBroadbandModemQmi *self)
GError *error = NULL;
error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Power update operation timed out");
- dms_set_operating_mode_complete (self, error);
+ set_operating_mode_complete (self, error);
}
static void
@@ -1779,31 +1776,31 @@ power_event_report_indication_cb (QmiClientDms *client,
QmiIndicationDmsEventReportOutput *output,
MMBroadbandModemQmi *self)
{
- QmiDmsOperatingMode state;
- GTask *task;
- GError *error = NULL;
- QmiDmsOperatingMode mode;
+ QmiDmsOperatingMode state;
+ GError *error = NULL;
+ SetOperatingModeContext *ctx;
if (!qmi_indication_dms_event_report_output_get_operating_mode (output, &state, NULL)) {
error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Invalid power indication received");
- dms_set_operating_mode_complete (self, error);
+ set_operating_mode_complete (self, error);
return;
}
- task = self->priv->set_operating_mode_task;
- mode = GPOINTER_TO_UINT (g_task_get_task_data (task));
- if (mode == state) {
+ g_assert (self->priv->set_operating_mode_task);
+ ctx = g_task_get_task_data (self->priv->set_operating_mode_task);
+
+ if (ctx->mode == state) {
mm_obj_dbg (self, "Power state successfully updated: '%s'", qmi_dms_operating_mode_get_string (state));
- dms_set_operating_mode_complete (self, NULL);
+ set_operating_mode_complete (self, NULL);
return;
}
error = g_error_new (MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Requested mode (%s) and mode received (%s) did not match",
- qmi_dms_operating_mode_get_string (mode),
+ qmi_dms_operating_mode_get_string (ctx->mode),
qmi_dms_operating_mode_get_string (state));
- dms_set_operating_mode_complete (self, error);
+ set_operating_mode_complete (self, error);
}
static void
@@ -1811,19 +1808,17 @@ dms_set_operating_mode_ready (QmiClientDms *client,
GAsyncResult *res,
MMBroadbandModemQmi *self) /* full reference */
{
- GTask *task;
- QmiDmsOperatingMode mode;
- GError *error = NULL;
g_autoptr (QmiMessageDmsSetOperatingModeOutput) output = NULL;
+ GError *error = NULL;
+ SetOperatingModeContext *ctx;
- task = self->priv->set_operating_mode_task;
- if (task == NULL) {
+ if (!self->priv->set_operating_mode_task) {
/* We completed the operation already via indication */
g_object_unref (self);
return;
}
- mode = GPOINTER_TO_UINT (g_task_get_task_data (task));
+ ctx = g_task_get_task_data (self->priv->set_operating_mode_task);
output = qmi_client_dms_set_operating_mode_finish (client, res, &error);
if (!output) {
@@ -1846,7 +1841,7 @@ dms_set_operating_mode_ready (QmiClientDms *client,
* retrying. Notify this to upper layers with the special MM_CORE_ERROR_RETRY
* error.
*/
- if ((mode == QMI_DMS_OPERATING_MODE_ONLINE) &&
+ if ((ctx->mode == QMI_DMS_OPERATING_MODE_ONLINE) &&
((g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_INTERNAL) ||
g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_INVALID_TRANSITION)))) {
g_clear_error (&error);
@@ -1855,7 +1850,7 @@ dms_set_operating_mode_ready (QmiClientDms *client,
}
if (error)
- dms_set_operating_mode_complete (self, error);
+ set_operating_mode_complete (self, error);
else
mm_obj_dbg (self, "operating mode request sent, waiting for power update indication");
@@ -1865,26 +1860,15 @@ dms_set_operating_mode_ready (QmiClientDms *client,
static void
dms_set_operating_mode (MMBroadbandModemQmi *self)
{
- QmiClient *client;
- GError *error = NULL;
- GTask *task;
- QmiDmsOperatingMode mode;
g_autoptr (QmiMessageDmsSetOperatingModeInput) input = NULL;
+ SetOperatingModeContext *ctx;
- task = self->priv->set_operating_mode_task;
- mode = GPOINTER_TO_UINT (g_task_get_task_data(task));
- client = mm_shared_qmi_peek_client (MM_SHARED_QMI (self),
- QMI_SERVICE_DMS,
- MM_PORT_QMI_FLAG_DEFAULT,
- &error);
- if (!client) {
- dms_set_operating_mode_complete (self, error);
- return;
- }
+ g_assert (self->priv->set_operating_mode_task);
+ ctx = g_task_get_task_data (self->priv->set_operating_mode_task);
input = qmi_message_dms_set_operating_mode_input_new ();
- qmi_message_dms_set_operating_mode_input_set_mode (input, mode, NULL);
- qmi_client_dms_set_operating_mode (QMI_CLIENT_DMS (client),
+ qmi_message_dms_set_operating_mode_input_set_mode (input, ctx->mode, NULL);
+ qmi_client_dms_set_operating_mode (ctx->client,
input,
20,
NULL,
@@ -1892,9 +1876,9 @@ dms_set_operating_mode (MMBroadbandModemQmi *self)
g_object_ref (self));
mm_obj_dbg (self, "Starting timeout for indication receiving for 10 seconds");
- self->priv->set_operating_timeout_id = g_timeout_add_seconds (10,
- (GSourceFunc) dms_set_operating_mode_timeout_cb,
- self);
+ ctx->timeout_id = g_timeout_add_seconds (10,
+ (GSourceFunc) dms_set_operating_mode_timeout_cb,
+ self);
}
static void
@@ -1904,31 +1888,26 @@ dms_set_event_report_operating_mode_activate_ready (QmiClientDms *client,
{
g_autoptr(QmiMessageDmsSetEventReportOutput) output = NULL;
GError *error = NULL;
+ SetOperatingModeContext *ctx;
+
+ g_assert (self->priv->set_operating_mode_task);
+ ctx = g_task_get_task_data (self->priv->set_operating_mode_task);
output = qmi_client_dms_set_event_report_finish (client, res, &error);
- if (!output) {
- g_prefix_error (&error, "Power indication activation qmi operation failed");
- dms_set_operating_mode_complete (self, error);
- g_object_unref (self);
- return;
- }
- if (!qmi_message_dms_set_event_report_output_get_result (output, &error)) {
- g_prefix_error (&error, "Power indication failed: couldn't set event report");
- dms_set_operating_mode_complete (self, error);
+ if (!output || !qmi_message_dms_set_event_report_output_get_result (output, &error)) {
+ g_prefix_error (&error, "Couldn't register for power indications: ");
+ set_operating_mode_complete (self, error);
g_object_unref (self);
return;
}
- g_assert (self->priv->power_event_report_indication_id == 0);
- self->priv->power_event_report_indication_id =
- g_signal_connect (client,
- "event-report",
- G_CALLBACK (power_event_report_indication_cb),
- self);
+ g_assert (ctx->indication_id == 0);
+ ctx->indication_id = g_signal_connect (client,
+ "event-report",
+ G_CALLBACK (power_event_report_indication_cb),
+ self);
- g_assert (self->priv->set_operating_mode_task != NULL);
mm_obj_dbg (self, "Power operation is pending");
-
dms_set_operating_mode (self);
g_object_unref (self);
}
@@ -1937,24 +1916,16 @@ static void
modem_power_indication_register (MMBroadbandModemQmi *self)
{
g_autoptr(QmiMessageDmsSetEventReportInput) input = NULL;
- QmiClient *client;
- GError *error = NULL;
+ SetOperatingModeContext *ctx;
- client = mm_shared_qmi_peek_client (MM_SHARED_QMI (self),
- QMI_SERVICE_DMS,
- MM_PORT_QMI_FLAG_DEFAULT,
- &error);
-
- if (!client) {
- dms_set_operating_mode_complete (self, error);
- return;
- }
+ g_assert (self->priv->set_operating_mode_task);
+ ctx = g_task_get_task_data (self->priv->set_operating_mode_task);
input = qmi_message_dms_set_event_report_input_new ();
qmi_message_dms_set_event_report_input_set_operating_mode_reporting (input, TRUE, NULL);
mm_obj_dbg (self, "Power indication registration request is sent");
qmi_client_dms_set_event_report (
- QMI_CLIENT_DMS (client),
+ ctx->client,
input,
5,
NULL,
@@ -1968,12 +1939,13 @@ common_power_up_down_off (MMIfaceModem *_self,
GAsyncReadyCallback callback,
gpointer user_data)
{
- GTask *task;
- GError *error = NULL;
- MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self);
+ MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self);
+ GError *error = NULL;
+ GTask *task;
+ SetOperatingModeContext *ctx;
+ QmiClient *client;
task = g_task_new (self, NULL, callback, user_data);
- g_task_set_task_data (task, GUINT_TO_POINTER (mode), NULL);
if (self->priv->set_operating_mode_task) {
error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_IN_PROGRESS, "Another operation in progress");
@@ -1982,6 +1954,21 @@ common_power_up_down_off (MMIfaceModem *_self,
return;
}
+ client = mm_shared_qmi_peek_client (MM_SHARED_QMI (self),
+ QMI_SERVICE_DMS,
+ MM_PORT_QMI_FLAG_DEFAULT,
+ &error);
+ if (!client) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ ctx = g_slice_new0 (SetOperatingModeContext);
+ ctx->mode = mode;
+ ctx->client = QMI_CLIENT_DMS (g_object_ref (client));
+ g_task_set_task_data (task, ctx, (GDestroyNotify)set_operating_mode_context_free);
+
self->priv->set_operating_mode_task = task;
modem_power_indication_register (self);
}