diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2022-01-11 12:26:26 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2022-01-14 10:36:39 +0100 |
commit | 60f61e974042a71ff039c36a431a270eeb730ef4 (patch) | |
tree | bc43b3328e591828950c217c93868d4aee3584dc | |
parent | 1291754e60a3d904b059efc428f7013f6a241d7c (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.c | 209 |
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); } |