diff options
-rw-r--r-- | src/mm-broadband-modem-qmi.c | 164 |
1 files changed, 157 insertions, 7 deletions
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c index 85e33f88..aea6cbf1 100644 --- a/src/mm-broadband-modem-qmi.c +++ b/src/mm-broadband-modem-qmi.c @@ -9662,6 +9662,113 @@ signal_load_values (MMIfaceModemSignal *self, } /*****************************************************************************/ +/* Reset data interfaces during initialization */ + +typedef struct { + GList *ports; + MMPort *data; + MMPortQmi *qmi; +} ResetPortsContext; + +static void +reset_ports_context_free (ResetPortsContext *ctx) +{ + g_assert (!ctx->data); + g_assert (!ctx->qmi); + g_list_free_full (ctx->ports, g_object_unref); + g_slice_free (ResetPortsContext, ctx); +} + +static gboolean +reset_ports_finish (MMBroadbandModemQmi *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void reset_next_port (GTask *task); + +static void +port_qmi_reset_ready (MMPortQmi *qmi, + GAsyncResult *res, + GTask *task) +{ + MMBroadbandModemQmi *self; + ResetPortsContext *ctx; + g_autoptr(GError) error = NULL; + + self = g_task_get_source_object (task); + ctx = g_task_get_task_data (task); + + if (!mm_port_qmi_reset_finish (qmi, res, &error)) + mm_obj_warn (self, "couldn't reset QMI port '%s' with data interface '%s': %s", + mm_port_get_device (MM_PORT (ctx->qmi)), + mm_port_get_device (ctx->data), + error->message); + + g_clear_object (&ctx->data); + g_clear_object (&ctx->qmi); + reset_next_port (task); +} + +static void +reset_next_port (GTask *task) +{ + MMBroadbandModemQmi *self; + ResetPortsContext *ctx; + + self = g_task_get_source_object (task); + ctx = g_task_get_task_data (task); + + if (!ctx->ports) { + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + } + + /* steal full data port reference from list head */ + ctx->data = ctx->ports->data; + ctx->ports = g_list_delete_link (ctx->ports, ctx->ports); + + ctx->qmi = mm_broadband_modem_qmi_get_port_qmi_for_data (self, ctx->data, NULL, NULL); + if (!ctx->qmi) { + mm_obj_dbg (self, "no QMI port associated to data port '%s': ignoring data interface reset", + mm_port_get_device (ctx->data)); + g_clear_object (&ctx->data); + reset_next_port (task); + return; + } + + mm_obj_dbg (self, "running QMI port '%s' reset with data interface '%s'", + mm_port_get_device (MM_PORT (ctx->qmi)), mm_port_get_device (ctx->data)); + + mm_port_qmi_reset (ctx->qmi, + ctx->data, + (GAsyncReadyCallback) port_qmi_reset_ready, + task); +} + +static void +reset_ports (MMBroadbandModemQmi *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + ResetPortsContext *ctx; + + task = g_task_new (self, NULL, callback, user_data); + ctx = g_slice_new0 (ResetPortsContext); + g_task_set_task_data (task, ctx, (GDestroyNotify)reset_ports_context_free); + + ctx->ports = mm_base_modem_find_ports (MM_BASE_MODEM (self), + MM_PORT_SUBSYS_UNKNOWN, + MM_PORT_TYPE_NET); + + reset_next_port (task); +} + +/*****************************************************************************/ /* First enabling step */ static gboolean @@ -9961,7 +10068,7 @@ allocate_next_client (GTask *task) if (ctx->service_index == G_N_ELEMENTS (qmi_services)) { GError *error = NULL; - /* Done we are, track device removal and launch parent's callback */ + /* Done we are, track device removal and launch next step */ if (!track_qmi_device_removed (self, ctx->qmi, &error)) { g_task_return_error (task, error); g_object_unref (task); @@ -10029,6 +10136,54 @@ qmi_port_open_ready (MMPortQmi *qmi, } static void +initialization_open_port (GTask *task) +{ + InitializationStartedContext *ctx; + + ctx = g_task_get_task_data (task); + + mm_port_qmi_open (ctx->qmi, + TRUE, + NULL, + (GAsyncReadyCallback)qmi_port_open_ready, + task); +} + +static void +reset_ports_ready (MMBroadbandModemQmi *self, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + + if (!reset_ports_finish (self, res, &error)) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + initialization_open_port (task); +} + +static void +initialization_reset_ports (GTask *task) +{ + MMBroadbandModemQmi *self; + + self = g_task_get_source_object (task); + + /* reseting the data interfaces is really only needed if the device + * hasn't been hotplugged */ + if (mm_base_modem_get_hotplugged (MM_BASE_MODEM (self))) { + mm_obj_dbg (self, "not running data interface reset procedure: device is hotplugged"); + initialization_open_port (task); + return; + } + + reset_ports (self, (GAsyncReadyCallback)reset_ports_ready, task); +} + +static void initialization_started (MMBroadbandModem *self, GAsyncReadyCallback callback, gpointer user_data) @@ -10066,12 +10221,7 @@ initialization_started (MMBroadbandModem *self, return; } - /* Now open our QMI port */ - mm_port_qmi_open (ctx->qmi, - TRUE, - NULL, - (GAsyncReadyCallback)qmi_port_open_ready, - task); + initialization_reset_ports (task); } /*****************************************************************************/ |