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.
This commit is contained in:
@@ -162,12 +162,8 @@ struct _MMBroadbandModemQmiPrivate {
|
|||||||
/* For notifying when the qmi-proxy connection is dead */
|
/* For notifying when the qmi-proxy connection is dead */
|
||||||
guint qmi_device_removed_id;
|
guint qmi_device_removed_id;
|
||||||
|
|
||||||
/* Power Indication Helper */
|
|
||||||
guint power_event_report_indication_id;
|
|
||||||
|
|
||||||
/* Power Set Operating Mode Helper */
|
/* Power Set Operating Mode Helper */
|
||||||
GTask *set_operating_mode_task;
|
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) */
|
/* 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
|
static gboolean
|
||||||
modem_power_up_down_off_finish (MMIfaceModem *self,
|
modem_power_up_down_off_finish (MMIfaceModem *self,
|
||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
@@ -1717,51 +1729,36 @@ modem_power_up_down_off_finish (MMIfaceModem *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
modem_power_indication_deregister (MMBroadbandModemQmi *self)
|
set_operating_mode_complete (MMBroadbandModemQmi *self,
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
client = mm_shared_qmi_peek_client (MM_SHARED_QMI (self),
|
|
||||||
QMI_SERVICE_DMS,
|
|
||||||
MM_PORT_QMI_FLAG_DEFAULT,
|
|
||||||
NULL);
|
|
||||||
if (!client)
|
|
||||||
return;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
dms_set_operating_mode_complete (MMBroadbandModemQmi *self,
|
|
||||||
GError *error)
|
GError *error)
|
||||||
{
|
{
|
||||||
GTask *task;
|
GTask *task;
|
||||||
|
SetOperatingModeContext *ctx;
|
||||||
|
|
||||||
|
g_assert (self->priv->set_operating_mode_task);
|
||||||
task = g_steal_pointer (&self->priv->set_operating_mode_task);
|
task = g_steal_pointer (&self->priv->set_operating_mode_task);
|
||||||
g_assert (task != NULL);
|
ctx = g_task_get_task_data (task);
|
||||||
|
|
||||||
if (self->priv->set_operating_timeout_id) {
|
if (ctx->timeout_id) {
|
||||||
g_source_remove (self->priv->set_operating_timeout_id);
|
g_source_remove (ctx->timeout_id);
|
||||||
self->priv->set_operating_timeout_id = 0;
|
ctx->timeout_id = 0;
|
||||||
}
|
|
||||||
if (self->priv->power_event_report_indication_id) {
|
|
||||||
modem_power_indication_deregister (self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (ctx->indication_id) {
|
||||||
|
g_autoptr(QmiMessageDmsSetEventReportInput) input = NULL;
|
||||||
|
|
||||||
|
g_signal_handler_disconnect (ctx->client, ctx->indication_id);
|
||||||
|
ctx->indication_id = 0;
|
||||||
|
|
||||||
|
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)
|
||||||
g_task_return_error (task, error);
|
g_task_return_error (task, error);
|
||||||
} else {
|
else
|
||||||
g_task_return_boolean (task, TRUE);
|
g_task_return_boolean (task, TRUE);
|
||||||
}
|
|
||||||
g_object_unref (task);
|
g_object_unref (task);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1771,7 +1768,7 @@ dms_set_operating_mode_timeout_cb (MMBroadbandModemQmi *self)
|
|||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Power update operation timed out");
|
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
|
static void
|
||||||
@@ -1780,30 +1777,30 @@ power_event_report_indication_cb (QmiClientDms *client,
|
|||||||
MMBroadbandModemQmi *self)
|
MMBroadbandModemQmi *self)
|
||||||
{
|
{
|
||||||
QmiDmsOperatingMode state;
|
QmiDmsOperatingMode state;
|
||||||
GTask *task;
|
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
QmiDmsOperatingMode mode;
|
SetOperatingModeContext *ctx;
|
||||||
|
|
||||||
if (!qmi_indication_dms_event_report_output_get_operating_mode (output, &state, NULL)) {
|
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");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
task = self->priv->set_operating_mode_task;
|
g_assert (self->priv->set_operating_mode_task);
|
||||||
mode = GPOINTER_TO_UINT (g_task_get_task_data (task));
|
ctx = g_task_get_task_data (self->priv->set_operating_mode_task);
|
||||||
if (mode == state) {
|
|
||||||
|
if (ctx->mode == state) {
|
||||||
mm_obj_dbg (self, "Power state successfully updated: '%s'", qmi_dms_operating_mode_get_string (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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = g_error_new (MM_CORE_ERROR,
|
error = g_error_new (MM_CORE_ERROR,
|
||||||
MM_CORE_ERROR_FAILED,
|
MM_CORE_ERROR_FAILED,
|
||||||
"Requested mode (%s) and mode received (%s) did not match",
|
"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));
|
qmi_dms_operating_mode_get_string (state));
|
||||||
dms_set_operating_mode_complete (self, error);
|
set_operating_mode_complete (self, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1811,19 +1808,17 @@ dms_set_operating_mode_ready (QmiClientDms *client,
|
|||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
MMBroadbandModemQmi *self) /* full reference */
|
MMBroadbandModemQmi *self) /* full reference */
|
||||||
{
|
{
|
||||||
GTask *task;
|
|
||||||
QmiDmsOperatingMode mode;
|
|
||||||
GError *error = NULL;
|
|
||||||
g_autoptr (QmiMessageDmsSetOperatingModeOutput) output = NULL;
|
g_autoptr (QmiMessageDmsSetOperatingModeOutput) output = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
SetOperatingModeContext *ctx;
|
||||||
|
|
||||||
task = self->priv->set_operating_mode_task;
|
if (!self->priv->set_operating_mode_task) {
|
||||||
if (task == NULL) {
|
|
||||||
/* We completed the operation already via indication */
|
/* We completed the operation already via indication */
|
||||||
g_object_unref (self);
|
g_object_unref (self);
|
||||||
return;
|
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);
|
output = qmi_client_dms_set_operating_mode_finish (client, res, &error);
|
||||||
if (!output) {
|
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
|
* retrying. Notify this to upper layers with the special MM_CORE_ERROR_RETRY
|
||||||
* error.
|
* 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_INTERNAL) ||
|
||||||
g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_INVALID_TRANSITION)))) {
|
g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_INVALID_TRANSITION)))) {
|
||||||
g_clear_error (&error);
|
g_clear_error (&error);
|
||||||
@@ -1855,7 +1850,7 @@ dms_set_operating_mode_ready (QmiClientDms *client,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
dms_set_operating_mode_complete (self, error);
|
set_operating_mode_complete (self, error);
|
||||||
else
|
else
|
||||||
mm_obj_dbg (self, "operating mode request sent, waiting for power update indication");
|
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
|
static void
|
||||||
dms_set_operating_mode (MMBroadbandModemQmi *self)
|
dms_set_operating_mode (MMBroadbandModemQmi *self)
|
||||||
{
|
{
|
||||||
QmiClient *client;
|
|
||||||
GError *error = NULL;
|
|
||||||
GTask *task;
|
|
||||||
QmiDmsOperatingMode mode;
|
|
||||||
g_autoptr (QmiMessageDmsSetOperatingModeInput) input = NULL;
|
g_autoptr (QmiMessageDmsSetOperatingModeInput) input = NULL;
|
||||||
|
SetOperatingModeContext *ctx;
|
||||||
|
|
||||||
task = self->priv->set_operating_mode_task;
|
g_assert (self->priv->set_operating_mode_task);
|
||||||
mode = GPOINTER_TO_UINT (g_task_get_task_data(task));
|
ctx = g_task_get_task_data (self->priv->set_operating_mode_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
input = qmi_message_dms_set_operating_mode_input_new ();
|
input = qmi_message_dms_set_operating_mode_input_new ();
|
||||||
qmi_message_dms_set_operating_mode_input_set_mode (input, mode, NULL);
|
qmi_message_dms_set_operating_mode_input_set_mode (input, ctx->mode, NULL);
|
||||||
qmi_client_dms_set_operating_mode (QMI_CLIENT_DMS (client),
|
qmi_client_dms_set_operating_mode (ctx->client,
|
||||||
input,
|
input,
|
||||||
20,
|
20,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -1892,7 +1876,7 @@ dms_set_operating_mode (MMBroadbandModemQmi *self)
|
|||||||
g_object_ref (self));
|
g_object_ref (self));
|
||||||
|
|
||||||
mm_obj_dbg (self, "Starting timeout for indication receiving for 10 seconds");
|
mm_obj_dbg (self, "Starting timeout for indication receiving for 10 seconds");
|
||||||
self->priv->set_operating_timeout_id = g_timeout_add_seconds (10,
|
ctx->timeout_id = g_timeout_add_seconds (10,
|
||||||
(GSourceFunc) dms_set_operating_mode_timeout_cb,
|
(GSourceFunc) dms_set_operating_mode_timeout_cb,
|
||||||
self);
|
self);
|
||||||
}
|
}
|
||||||
@@ -1904,31 +1888,26 @@ dms_set_event_report_operating_mode_activate_ready (QmiClientDms *client,
|
|||||||
{
|
{
|
||||||
g_autoptr(QmiMessageDmsSetEventReportOutput) output = NULL;
|
g_autoptr(QmiMessageDmsSetEventReportOutput) output = NULL;
|
||||||
GError *error = 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);
|
output = qmi_client_dms_set_event_report_finish (client, res, &error);
|
||||||
if (!output) {
|
if (!output || !qmi_message_dms_set_event_report_output_get_result (output, &error)) {
|
||||||
g_prefix_error (&error, "Power indication activation qmi operation failed");
|
g_prefix_error (&error, "Couldn't register for power indications: ");
|
||||||
dms_set_operating_mode_complete (self, error);
|
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);
|
|
||||||
g_object_unref (self);
|
g_object_unref (self);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_assert (self->priv->power_event_report_indication_id == 0);
|
g_assert (ctx->indication_id == 0);
|
||||||
self->priv->power_event_report_indication_id =
|
ctx->indication_id = g_signal_connect (client,
|
||||||
g_signal_connect (client,
|
|
||||||
"event-report",
|
"event-report",
|
||||||
G_CALLBACK (power_event_report_indication_cb),
|
G_CALLBACK (power_event_report_indication_cb),
|
||||||
self);
|
self);
|
||||||
|
|
||||||
g_assert (self->priv->set_operating_mode_task != NULL);
|
|
||||||
mm_obj_dbg (self, "Power operation is pending");
|
mm_obj_dbg (self, "Power operation is pending");
|
||||||
|
|
||||||
dms_set_operating_mode (self);
|
dms_set_operating_mode (self);
|
||||||
g_object_unref (self);
|
g_object_unref (self);
|
||||||
}
|
}
|
||||||
@@ -1937,24 +1916,16 @@ static void
|
|||||||
modem_power_indication_register (MMBroadbandModemQmi *self)
|
modem_power_indication_register (MMBroadbandModemQmi *self)
|
||||||
{
|
{
|
||||||
g_autoptr(QmiMessageDmsSetEventReportInput) input = NULL;
|
g_autoptr(QmiMessageDmsSetEventReportInput) input = NULL;
|
||||||
QmiClient *client;
|
SetOperatingModeContext *ctx;
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
client = mm_shared_qmi_peek_client (MM_SHARED_QMI (self),
|
g_assert (self->priv->set_operating_mode_task);
|
||||||
QMI_SERVICE_DMS,
|
ctx = g_task_get_task_data (self->priv->set_operating_mode_task);
|
||||||
MM_PORT_QMI_FLAG_DEFAULT,
|
|
||||||
&error);
|
|
||||||
|
|
||||||
if (!client) {
|
|
||||||
dms_set_operating_mode_complete (self, error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
input = qmi_message_dms_set_event_report_input_new ();
|
input = qmi_message_dms_set_event_report_input_new ();
|
||||||
qmi_message_dms_set_event_report_input_set_operating_mode_reporting (input, TRUE, NULL);
|
qmi_message_dms_set_event_report_input_set_operating_mode_reporting (input, TRUE, NULL);
|
||||||
mm_obj_dbg (self, "Power indication registration request is sent");
|
mm_obj_dbg (self, "Power indication registration request is sent");
|
||||||
qmi_client_dms_set_event_report (
|
qmi_client_dms_set_event_report (
|
||||||
QMI_CLIENT_DMS (client),
|
ctx->client,
|
||||||
input,
|
input,
|
||||||
5,
|
5,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -1968,12 +1939,13 @@ common_power_up_down_off (MMIfaceModem *_self,
|
|||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data)
|
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);
|
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) {
|
if (self->priv->set_operating_mode_task) {
|
||||||
error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_IN_PROGRESS, "Another operation in progress");
|
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;
|
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;
|
self->priv->set_operating_mode_task = task;
|
||||||
modem_power_indication_register (self);
|
modem_power_indication_register (self);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user