base-modem: quicker find matching cdc-wdm QMI or MBIM ports

This commit is contained in:
Aleksander Morgado
2014-06-22 17:54:33 +02:00
parent b520503686
commit 08ecc14722

View File

@@ -638,117 +638,40 @@ mm_base_modem_peek_port_qmi_for_data (MMBaseModem *self,
MMPort *data, MMPort *data,
GError **error) GError **error)
{ {
MMPortQmi *found; GList *cdc_wdm_qmi_ports, *l;
GUdevClient *client; const gchar *net_port_parent_path;
GUdevDevice *data_device;
GUdevDevice *data_device_parent;
GList *l;
if (mm_port_get_subsys (data) != MM_PORT_SUBSYS_NET) { g_warn_if_fail (mm_port_get_subsys (data) == MM_PORT_SUBSYS_NET);
g_set_error (error, net_port_parent_path = mm_port_get_parent_path (data);
MM_CORE_ERROR, if (!net_port_parent_path) {
MM_CORE_ERROR_UNSUPPORTED,
"Cannot look for QMI port associated to a non-net data port");
return NULL;
}
/* don't listen for uevents */
client = g_udev_client_new (NULL);
/* Get udev device for the data port */
data_device = (g_udev_client_query_by_subsystem_and_name (
client,
"net",
mm_port_get_device (data)));
if (!data_device) {
g_set_error (error, g_set_error (error,
MM_CORE_ERROR, MM_CORE_ERROR,
MM_CORE_ERROR_FAILED, MM_CORE_ERROR_FAILED,
"Couldn't find udev device for port 'net/%s'", "No parent path for 'net/%s'",
mm_port_get_device (data)); mm_port_get_device (data));
g_object_unref (client);
return NULL; return NULL;
} }
/* Get parent of the data device */ /* Find the CDC-WDM port on the same USB interface as the given net port */
data_device_parent = g_udev_device_get_parent (data_device); cdc_wdm_qmi_ports = mm_base_modem_find_ports (MM_BASE_MODEM (self),
if (!data_device_parent) { MM_PORT_SUBSYS_USB,
g_set_error (error, MM_PORT_TYPE_QMI,
MM_CORE_ERROR, NULL);
MM_CORE_ERROR_FAILED, for (l = cdc_wdm_qmi_ports; l; l = g_list_next (l)) {
"Couldn't get udev device parent for port 'net/%s'", const gchar *wdm_port_parent_path;
mm_port_get_device (data));
g_object_unref (data_device); g_assert (MM_IS_PORT_QMI (l->data));
g_object_unref (client); wdm_port_parent_path = mm_port_get_parent_path (MM_PORT (l->data));
return NULL; if (wdm_port_parent_path && g_str_equal (wdm_port_parent_path, net_port_parent_path))
return MM_PORT_QMI (l->data);
} }
/* Now walk the list of QMI ports looking for a match */ g_set_error (error,
found = NULL; MM_CORE_ERROR,
for (l = self->priv->qmi; l && !found; l = g_list_next (l)) { MM_CORE_ERROR_NOT_FOUND,
GUdevDevice *qmi_device; "Couldn't find associated QMI port for 'net/%s'",
GUdevDevice *qmi_device_parent; mm_port_get_device (data));
return NULL;
/* Get udev device for the QMI port */
qmi_device = (g_udev_client_query_by_subsystem_and_name (
client,
"usb",
mm_port_get_device (MM_PORT (l->data))));
if (!qmi_device) {
qmi_device = (g_udev_client_query_by_subsystem_and_name (
client,
"usbmisc",
mm_port_get_device (MM_PORT (l->data))));
if (!qmi_device) {
mm_warn ("Couldn't get udev device for QMI port '%s'",
mm_port_get_device (MM_PORT (l->data)));
continue;
}
}
/* Get parent of the QMI device */
qmi_device_parent = g_udev_device_get_parent (qmi_device);
g_object_unref (qmi_device);
if (!qmi_device_parent) {
mm_warn ("Couldn't get udev device parent for QMI port '%s'",
mm_port_get_device (MM_PORT (l->data)));
continue;
}
if (g_str_equal (g_udev_device_get_sysfs_path (data_device_parent),
g_udev_device_get_sysfs_path (qmi_device_parent)))
found = MM_PORT_QMI (l->data);
g_object_unref (qmi_device_parent);
}
g_object_unref (data_device_parent);
g_object_unref (data_device);
g_object_unref (client);
if (!found) {
/* For the case where we have only 1 data port and 1 QMI port and they
* don't match with the previous rules (e.g. in some Huawei modems),
* just return the found one */
if (g_list_length (self->priv->data) == 1 &&
g_list_length (self->priv->qmi) == 1 &&
self->priv->data->data == data) {
mm_info ("Assuming QMI port '%s' is associated to net/%s",
mm_port_get_device (MM_PORT (self->priv->qmi->data)),
mm_port_get_device (data));
found = MM_PORT_QMI (self->priv->qmi->data);
} else {
g_set_error (error,
MM_CORE_ERROR,
MM_CORE_ERROR_NOT_FOUND,
"Couldn't find associated QMI port for 'net/%s'",
mm_port_get_device (data));
return NULL;
}
}
return found;
} }
#endif /* WITH_QMI */ #endif /* WITH_QMI */
@@ -789,117 +712,40 @@ mm_base_modem_peek_port_mbim_for_data (MMBaseModem *self,
MMPort *data, MMPort *data,
GError **error) GError **error)
{ {
MMPortMbim *found; GList *cdc_wdm_mbim_ports, *l;
GUdevClient *client; const gchar *net_port_parent_path;
GUdevDevice *data_device;
GUdevDevice *data_device_parent;
GList *l;
if (mm_port_get_subsys (data) != MM_PORT_SUBSYS_NET) { g_warn_if_fail (mm_port_get_subsys (data) == MM_PORT_SUBSYS_NET);
g_set_error (error, net_port_parent_path = mm_port_get_parent_path (data);
MM_CORE_ERROR, if (!net_port_parent_path) {
MM_CORE_ERROR_UNSUPPORTED,
"Cannot look for MBIM port associated to a non-net data port");
return NULL;
}
/* don't listen for uevents */
client = g_udev_client_new (NULL);
/* Get udev device for the data port */
data_device = (g_udev_client_query_by_subsystem_and_name (
client,
"net",
mm_port_get_device (data)));
if (!data_device) {
g_set_error (error, g_set_error (error,
MM_CORE_ERROR, MM_CORE_ERROR,
MM_CORE_ERROR_FAILED, MM_CORE_ERROR_FAILED,
"Couldn't find udev device for port 'net/%s'", "No parent path for 'net/%s'",
mm_port_get_device (data)); mm_port_get_device (data));
g_object_unref (client);
return NULL; return NULL;
} }
/* Get parent of the data device */ /* Find the CDC-WDM port on the same USB interface as the given net port */
data_device_parent = g_udev_device_get_parent (data_device); cdc_wdm_mbim_ports = mm_base_modem_find_ports (MM_BASE_MODEM (self),
if (!data_device_parent) { MM_PORT_SUBSYS_USB,
g_set_error (error, MM_PORT_TYPE_MBIM,
MM_CORE_ERROR, NULL);
MM_CORE_ERROR_FAILED, for (l = cdc_wdm_mbim_ports; l; l = g_list_next (l)) {
"Couldn't get udev device parent for port 'net/%s'", const gchar *wdm_port_parent_path;
mm_port_get_device (data));
g_object_unref (data_device); g_assert (MM_IS_PORT_MBIM (l->data));
g_object_unref (client); wdm_port_parent_path = mm_port_get_parent_path (MM_PORT (l->data));
return NULL; if (wdm_port_parent_path && g_str_equal (wdm_port_parent_path, net_port_parent_path))
return MM_PORT_MBIM (l->data);
} }
/* Now walk the list of MBIM ports looking for a match */ g_set_error (error,
found = NULL; MM_CORE_ERROR,
for (l = self->priv->mbim; l && !found; l = g_list_next (l)) { MM_CORE_ERROR_NOT_FOUND,
GUdevDevice *mbim_device; "Couldn't find associated MBIM port for 'net/%s'",
GUdevDevice *mbim_device_parent; mm_port_get_device (data));
return NULL;
/* Get udev device for the MBIM port */
mbim_device = (g_udev_client_query_by_subsystem_and_name (
client,
"usb",
mm_port_get_device (MM_PORT (l->data))));
if (!mbim_device) {
mbim_device = (g_udev_client_query_by_subsystem_and_name (
client,
"usbmisc",
mm_port_get_device (MM_PORT (l->data))));
if (!mbim_device) {
mm_warn ("Couldn't get udev device for MBIM port '%s'",
mm_port_get_device (MM_PORT (l->data)));
continue;
}
}
/* Get parent of the MBIM device */
mbim_device_parent = g_udev_device_get_parent (mbim_device);
g_object_unref (mbim_device);
if (!mbim_device_parent) {
mm_warn ("Couldn't get udev device parent for MBIM port '%s'",
mm_port_get_device (MM_PORT (l->data)));
continue;
}
if (g_str_equal (g_udev_device_get_sysfs_path (data_device_parent),
g_udev_device_get_sysfs_path (mbim_device_parent)))
found = MM_PORT_MBIM (l->data);
g_object_unref (mbim_device_parent);
}
g_object_unref (data_device_parent);
g_object_unref (data_device);
g_object_unref (client);
if (!found) {
/* For the case where we have only 1 data port and 1 MBIM port and they
* don't match with the previous rules (e.g. in some Huawei modems),
* just return the found one */
if (g_list_length (self->priv->data) == 1 &&
g_list_length (self->priv->mbim) == 1 &&
self->priv->data->data == data) {
mm_info ("Assuming MBIM port '%s' is associated to net/%s",
mm_port_get_device (MM_PORT (self->priv->mbim->data)),
mm_port_get_device (data));
found = MM_PORT_MBIM (self->priv->mbim->data);
} else {
g_set_error (error,
MM_CORE_ERROR,
MM_CORE_ERROR_NOT_FOUND,
"Couldn't find associated MBIM port for 'net/%s'",
mm_port_get_device (data));
return NULL;
}
}
return found;
} }
#endif /* WITH_MBIM */ #endif /* WITH_MBIM */