diff options
author | Aleksander Morgado <aleksandermj@chromium.org> | 2024-04-05 10:19:11 +0000 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2024-04-23 07:25:12 +0000 |
commit | 6980f2ff6a92425d723726b52d6e5bd4d58a73b5 (patch) | |
tree | 4b6d5d74daf907eeec977d6d3cde0137b93ab85a /src/mm-port-mbim.c | |
parent | 0d11ff85664ea6bc941adf62a36dd1ab4e326a59 (diff) |
port-mbim: preload supported services and allow querying
Diffstat (limited to 'src/mm-port-mbim.c')
-rw-r--r-- | src/mm-port-mbim.c | 212 |
1 files changed, 119 insertions, 93 deletions
diff --git a/src/mm-port-mbim.c b/src/mm-port-mbim.c index bfa8e8cf..d14d61c4 100644 --- a/src/mm-port-mbim.c +++ b/src/mm-port-mbim.c @@ -47,8 +47,11 @@ struct _MMPortMbimPrivate { gulong timeout_monitoring_id; gulong removed_monitoring_id; + /* supported services info */ + MbimDeviceServiceElement **device_services; + guint32 device_services_count; + #if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED - gboolean qmi_supported; QmiDevice *qmi_device; GList *qmi_clients; #endif @@ -469,6 +472,43 @@ setup_monitoring (MMPortMbim *self, /*****************************************************************************/ gboolean +mm_port_mbim_supports_service (MMPortMbim *self, + MbimService service) +{ + return mm_port_mbim_supports_command (self, service, 0); +} + +gboolean +mm_port_mbim_supports_command (MMPortMbim *self, + MbimService service, + guint cid) +{ + guint i; + + for (i = 0; i < self->priv->device_services_count; i++) { + if (mbim_uuid_to_service (&self->priv->device_services[i]->device_service_id) == service) { + guint j; + + /* If not asking for a specific CID, we're asking for overall service + * support */ + if (cid == 0) + return TRUE; + + for (j = 0; j < self->priv->device_services[i]->cids_count; j++) { + if (self->priv->device_services[i]->cids[j] == cid) + return TRUE; + } + /* service found but not matching cid */ + return FALSE; + } + } + /* service not found */ + return FALSE; +} + +/*****************************************************************************/ + +gboolean mm_port_mbim_open_finish (MMPortMbim *self, GAsyncResult *res, GError **error) @@ -476,6 +516,21 @@ mm_port_mbim_open_finish (MMPortMbim *self, return g_task_propagate_boolean (G_TASK (res), error); } +static void +open_complete (GTask *task, GError *error) +{ + MMPortMbim *self; + + self = g_task_get_source_object (task); + self->priv->in_progress = FALSE; + if (error) { + g_clear_object (&self->priv->mbim_device); + g_task_return_error (task, error); + } else + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + #if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED static void @@ -483,25 +538,21 @@ qmi_device_open_ready (QmiDevice *dev, GAsyncResult *res, GTask *task) { - GError *error = NULL; - MMPortMbim *self; + g_autoptr(GError) error = NULL; + MMPortMbim *self; self = g_task_get_source_object (task); if (!qmi_device_open_finish (dev, res, &error)) { mm_obj_dbg (self, "error: couldn't open QmiDevice: %s", error->message); - g_error_free (error); g_clear_object (&self->priv->qmi_device); /* Ignore error and complete */ mm_obj_msg (self, "MBIM device is not QMI capable"); - self->priv->qmi_supported = FALSE; } else { mm_obj_msg (self, "MBIM device is QMI capable"); } - self->priv->in_progress = FALSE; - g_task_return_boolean (task, TRUE); - g_object_unref (task); + open_complete (task, NULL); } static void @@ -509,21 +560,17 @@ qmi_device_new_ready (GObject *unused, GAsyncResult *res, GTask *task) { - GError *error = NULL; - MMPortMbim *self; + g_autoptr(GError) error = NULL; + MMPortMbim *self; self = g_task_get_source_object (task); self->priv->qmi_device = qmi_device_new_finish (res, &error); if (!self->priv->qmi_device) { mm_obj_dbg (self, "error: couldn't create QmiDevice: %s", error->message); - g_error_free (error); /* Ignore error and complete */ mm_obj_msg (self, "MBIM device is not QMI capable"); - self->priv->qmi_supported = FALSE; - self->priv->in_progress = FALSE; - g_task_return_boolean (task, TRUE); - g_object_unref (task); + open_complete (task, NULL); return; } @@ -541,57 +588,23 @@ qmi_device_new_ready (GObject *unused, } static void -mbim_query_device_services_ready (MbimDevice *device, - GAsyncResult *res, - GTask *task) +check_qmi_support (GTask *task) { - MMPortMbim *self; - MbimMessage *response; - GError *error = NULL; - MbimDeviceServiceElement **device_services; - guint32 device_services_count; - GFile *file; + MMPortMbim *self; + GFile *file; self = g_task_get_source_object (task); + file = G_FILE (g_task_get_task_data (task)); - response = mbim_device_command_finish (device, res, &error); - if (response && - mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error) && - mbim_message_device_services_response_parse ( - response, - &device_services_count, - NULL, /* max_dss_sessions */ - &device_services, - &error)) { - guint32 i; - - /* Look for the QMI service */ - for (i = 0; i < device_services_count; i++) { - if (mbim_uuid_to_service (&device_services[i]->device_service_id) == MBIM_SERVICE_QMI) - break; - } - /* If we were able to successfully list device services and none of them - * is the QMI service, we'll skip trying to check QMI support. */ - if (i == device_services_count) - self->priv->qmi_supported = FALSE; - mbim_device_service_element_array_free (device_services); - } else { - /* Ignore error */ - mm_obj_dbg (self, "Couldn't query device services, will attempt QMI open anyway: %s", error->message); - g_error_free (error); + if (!file) { + mm_obj_msg (self, "Skipping QMI support check in MBIM device"); + open_complete (task, NULL); + return; } - if (response) - mbim_message_unref (response); - - /* File path of the device */ - file = G_FILE (g_task_get_task_data (task)); - - if (!file || !self->priv->qmi_supported) { + if (!mm_port_mbim_supports_service (self, MBIM_SERVICE_QMI)) { mm_obj_msg (self, "MBIM device is not QMI capable"); - self->priv->in_progress = FALSE; - g_task_return_boolean (task, TRUE); - g_object_unref (task); + open_complete (task, NULL); return; } @@ -603,11 +616,47 @@ mbim_query_device_services_ready (MbimDevice *device, task); } +#endif + +static void +mbim_query_device_services_ready (MbimDevice *device, + GAsyncResult *res, + GTask *task) +{ + g_autoptr(MbimMessage) response = NULL; + g_autoptr(GError) error = NULL; + MMPortMbim *self; + + self = g_task_get_source_object (task); + + /* reset any before reloading */ + self->priv->device_services_count = 0; + g_clear_pointer (&self->priv->device_services, (GDestroyNotify)mbim_device_service_element_array_free); + + response = mbim_device_command_finish (device, res, &error); + if (!response || + !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error) || + !mbim_message_device_services_response_parse ( + response, + &self->priv->device_services_count, + NULL, /* max_dss_sessions */ + &self->priv->device_services, + &error)) { + mm_obj_warn (self, "couldn't query device services: %s", error->message); + } + +#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED + check_qmi_support (task); +#else + open_complete (task, NULL); +#endif +} + static void mbim_query_device_services (GTask *task) { - MbimMessage *message; - MMPortMbim *self; + g_autoptr(MbimMessage) message = NULL; + MMPortMbim *self; self = g_task_get_source_object (task); @@ -618,11 +667,8 @@ mbim_query_device_services (GTask *task) NULL, (GAsyncReadyCallback)mbim_query_device_services_ready, task); - mbim_message_unref (message); } -#endif - static void mbim_device_open_ready (MbimDevice *mbim_device, GAsyncResult *res, @@ -634,26 +680,14 @@ mbim_device_open_ready (MbimDevice *mbim_device, self = g_task_get_source_object (task); if (!mbim_device_open_full_finish (mbim_device, res, &error)) { - g_clear_object (&self->priv->mbim_device); - self->priv->in_progress = FALSE; - g_task_return_error (task, error); - g_object_unref (task); + open_complete (task, error); return; } mm_obj_dbg (self, "MBIM device is now open"); setup_monitoring (self, mbim_device); -#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED - if (self->priv->qmi_supported) { - mbim_query_device_services (task); - return; - } -#endif - - self->priv->in_progress = FALSE; - g_task_return_boolean (task, TRUE); - g_object_unref (task); + mbim_query_device_services (task); } static void @@ -667,9 +701,7 @@ mbim_device_new_ready (GObject *unused, self = g_task_get_source_object (task); self->priv->mbim_device = mbim_device_new_finish (res, &error); if (!self->priv->mbim_device) { - self->priv->in_progress = FALSE; - g_task_return_error (task, error); - g_object_unref (task); + open_complete (task, error); return; } @@ -691,9 +723,9 @@ mm_port_mbim_open (MMPortMbim *self, GAsyncReadyCallback callback, gpointer user_data) { - GFile *file; - gchar *fullpath; - GTask *task; + g_autoptr(GFile) file = NULL; + g_autofree gchar *fullpath = NULL; + GTask *task; g_return_if_fail (MM_IS_PORT_MBIM (self)); @@ -728,9 +760,6 @@ mm_port_mbim_open (MMPortMbim *self, cancellable, (GAsyncReadyCallback)mbim_device_new_ready, task); - - g_free (fullpath); - g_object_unref (file); } /*****************************************************************************/ @@ -919,12 +948,6 @@ static void mm_port_mbim_init (MMPortMbim *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_PORT_MBIM, MMPortMbimPrivate); - -#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED - /* By default, always assume that QMI is supported, we'll later check if - * that's true or not. */ - self->priv->qmi_supported = TRUE; -#endif } static void @@ -932,6 +955,9 @@ dispose (GObject *object) { MMPortMbim *self = MM_PORT_MBIM (object); + self->priv->device_services_count = 0; + g_clear_pointer (&self->priv->device_services, (GDestroyNotify)mbim_device_service_element_array_free); + #if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED g_list_free_full (self->priv->qmi_clients, g_object_unref); self->priv->qmi_clients = NULL; |