aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2019-11-27 17:30:07 +0100
committerAleksander Morgado <aleksander@aleksander.es>2019-11-27 17:30:07 +0100
commit551f0e0250e4610200d9b79a7543948424002d46 (patch)
tree4b8635c43ea9cb9d32cf02e33da7cec443b362e6
parent792f15648ca30a15097c7c90c4ebfd1cc0a13d30 (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.
-rw-r--r--src/mm-port-mbim.c108
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