diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2019-11-27 17:30:07 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2019-11-27 17:30:07 +0100 |
commit | 551f0e0250e4610200d9b79a7543948424002d46 (patch) | |
tree | 4b8635c43ea9cb9d32cf02e33da7cec443b362e6 /src | |
parent | 792f15648ca30a15097c7c90c4ebfd1cc0a13d30 (diff) |
port-mbim: before attempting to use QMI over MBIM, check device services
If we blindly try to use QMI over MBIM on devices that don't support
it, the logic works ok but it's very slow, given that the QMI device
open operation has several internal retries, and all those end up
timing out.
Avoid that lost time by checking the list of services supported by the
MBIM modem, and if the QMI over MBIM service is not listed, we'll
avoid trying to open the QMI device right away.
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-port-mbim.c | 108 |
1 files changed, 95 insertions, 13 deletions
diff --git a/src/mm-port-mbim.c b/src/mm-port-mbim.c index 51f6fb7a..143f8299 100644 --- a/src/mm-port-mbim.c +++ b/src/mm-port-mbim.c @@ -34,6 +34,7 @@ struct _MMPortMbimPrivate { gboolean in_progress; MbimDevice *mbim_device; #if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED + gboolean qmi_supported; QmiDevice *qmi_device; GList *qmi_clients; #endif @@ -183,6 +184,7 @@ qmi_device_open_ready (QmiDevice *dev, /* Ignore error and complete */ mm_info ("[%s] MBIM device is not QMI capable", mm_port_get_device (MM_PORT (self))); + self->priv->qmi_supported = FALSE; } else { mm_info ("[%s] MBIM device is QMI capable", mm_port_get_device (MM_PORT (self))); @@ -212,6 +214,7 @@ qmi_device_new_ready (GObject *unused, /* Ignore error and complete */ mm_info ("[%s] MBIM device is not QMI capable", mm_port_get_device (MM_PORT (self))); + self->priv->qmi_supported = FALSE; self->priv->in_progress = FALSE; g_task_return_boolean (task, TRUE); g_object_unref (task); @@ -232,6 +235,89 @@ qmi_device_new_ready (GObject *unused, task); } +static void +mbim_query_device_services_ready (MbimDevice *device, + GAsyncResult *res, + GTask *task) +{ + MMPortMbim *self; + MbimMessage *response; + GError *error = NULL; + MbimDeviceServiceElement **device_services; + guint32 device_services_count; + GFile *file; + + self = g_task_get_source_object (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_dbg ("Couldn't query device services, will attempt QMI open anyway: %s", error->message); + g_error_free (error); + } + + 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) { + mm_info ("[%s] MBIM device is not QMI capable", + mm_port_get_device (MM_PORT (self))); + self->priv->in_progress = FALSE; + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + } + + /* Attempt to create and open the QMI device */ + mm_dbg ("[%s] checking if QMI over MBIM is supported", + mm_port_get_device (MM_PORT (self))); + qmi_device_new (file, + g_task_get_cancellable (task), + (GAsyncReadyCallback) qmi_device_new_ready, + task); +} + +static void +mbim_query_device_services (GTask *task) +{ + MbimMessage *message; + MMPortMbim *self; + + self = g_task_get_source_object (task); + + message = mbim_message_device_services_query_new (NULL); + mbim_device_command (self->priv->mbim_device, + message, + 10, + NULL, + (GAsyncReadyCallback)mbim_query_device_services_ready, + task); + mbim_message_unref (message); +} + #endif static void @@ -256,25 +342,15 @@ mbim_device_open_ready (MbimDevice *mbim_device, mm_port_get_device (MM_PORT (self))); #if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED - { - GFile *file; - - if ((file = G_FILE (g_task_get_task_data (task)))) { - mm_dbg ("[%s] checking if QMI over MBIM is supported", - mm_port_get_device (MM_PORT (self))); - qmi_device_new (file, - g_task_get_cancellable (task), - (GAsyncReadyCallback) qmi_device_new_ready, - task); - return; - } + 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); - } static void @@ -481,6 +557,12 @@ 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 |