diff options
-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); } |