diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2020-02-20 16:11:42 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2020-03-03 17:23:07 +0000 |
commit | b9e6f30ba835f5019db55d98631f6571fdc575ef (patch) | |
tree | 39156eda97dfe2ecd6fbc4c01013d8a871bab14b /src/kerneldevice/mm-kernel-device-udev.c | |
parent | 6eabfd27bf3c4c53d7779722b46e7261d22c1d92 (diff) |
kerneldevice,udev: don't assume interface is the direct parent object
E.g. it may be one more layer up:
looking at device '/devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.4/1-8.4:1.1/ttyUSB1/tty/ttyUSB1':
KERNEL=="ttyUSB1"
SUBSYSTEM=="tty"
DRIVER==""
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.4/1-8.4:1.1/ttyUSB1':
KERNELS=="ttyUSB1"
SUBSYSTEMS=="usb-serial"
DRIVERS=="option1"
ATTRS{port_number}=="0"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.4/1-8.4:1.1':
KERNELS=="1-8.4:1.1"
SUBSYSTEMS=="usb"
DRIVERS=="option"
ATTRS{bNumEndpoints}=="02"
ATTRS{supports_autosuspend}=="1"
ATTRS{bInterfaceNumber}=="01"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bInterfaceSubClass}=="06"
ATTRS{bInterfaceProtocol}=="13"
ATTRS{interface}=="Huawei Mobile Connect - Application"
ATTRS{bInterfaceClass}=="ff"
ATTRS{authorized}=="1"
Diffstat (limited to 'src/kerneldevice/mm-kernel-device-udev.c')
-rw-r--r-- | src/kerneldevice/mm-kernel-device-udev.c | 62 |
1 files changed, 46 insertions, 16 deletions
diff --git a/src/kerneldevice/mm-kernel-device-udev.c b/src/kerneldevice/mm-kernel-device-udev.c index 3dc3eeb7..620d1441 100644 --- a/src/kerneldevice/mm-kernel-device-udev.c +++ b/src/kerneldevice/mm-kernel-device-udev.c @@ -39,7 +39,7 @@ static GParamSpec *properties[PROP_LAST]; struct _MMKernelDeviceUdevPrivate { GUdevDevice *device; - GUdevDevice *parent; + GUdevDevice *interface; GUdevDevice *physdev; guint16 vendor; guint16 product; @@ -263,12 +263,42 @@ ensure_physdev (MMKernelDeviceUdev *self) /*****************************************************************************/ static void -ensure_parent (MMKernelDeviceUdev *self) +ensure_interface (MMKernelDeviceUdev *self) { - if (self->priv->parent) + GUdevDevice *new_parent; + GUdevDevice *parent; + + if (self->priv->interface) return; - if (self->priv->device) - self->priv->parent = g_udev_device_get_parent (self->priv->device); + + if (!self->priv->device) + return; + + ensure_physdev (self); + + parent = g_udev_device_get_parent (self->priv->device); + while (1) { + /* Abort if no parent found */ + if (!parent) + break; + + /* Look for the first parent that is a USB interface (i.e. has + * bInterfaceClass) */ + if (g_udev_device_has_sysfs_attr (parent, "bInterfaceClass")) { + self->priv->interface = parent; + break; + } + + /* If unknown physdev, just stop right away */ + if (!self->priv->physdev || parent == self->priv->physdev) { + g_object_unref (parent); + break; + } + + new_parent = g_udev_device_get_parent (parent); + g_object_unref (parent); + parent = new_parent; + } } /*****************************************************************************/ @@ -494,8 +524,8 @@ kernel_device_get_interface_class (MMKernelDevice *_self) g_return_val_if_fail (MM_IS_KERNEL_DEVICE_UDEV (_self), -1); self = MM_KERNEL_DEVICE_UDEV (_self); - ensure_parent (self); - return (self->priv->parent ? g_udev_device_get_sysfs_attr_as_int (self->priv->parent, "bInterfaceClass") : -1); + ensure_interface (self); + return (self->priv->interface ? g_udev_device_get_sysfs_attr_as_int (self->priv->interface, "bInterfaceClass") : -1); } static gint @@ -506,8 +536,8 @@ kernel_device_get_interface_subclass (MMKernelDevice *_self) g_return_val_if_fail (MM_IS_KERNEL_DEVICE_UDEV (_self), -1); self = MM_KERNEL_DEVICE_UDEV (_self); - ensure_parent (self); - return (self->priv->parent ? g_udev_device_get_sysfs_attr_as_int (self->priv->parent, "bInterfaceSubClass") : -1); + ensure_interface (self); + return (self->priv->interface ? g_udev_device_get_sysfs_attr_as_int (self->priv->interface, "bInterfaceSubClass") : -1); } static gint @@ -518,8 +548,8 @@ kernel_device_get_interface_protocol (MMKernelDevice *_self) g_return_val_if_fail (MM_IS_KERNEL_DEVICE_UDEV (_self), -1); self = MM_KERNEL_DEVICE_UDEV (_self); - ensure_parent (self); - return (self->priv->parent ? g_udev_device_get_sysfs_attr_as_int (self->priv->parent, "bInterfaceProtocol") : -1); + ensure_interface (self); + return (self->priv->interface ? g_udev_device_get_sysfs_attr_as_int (self->priv->interface, "bInterfaceProtocol") : -1); } static const gchar * @@ -530,8 +560,8 @@ kernel_device_get_interface_sysfs_path (MMKernelDevice *_self) g_return_val_if_fail (MM_IS_KERNEL_DEVICE_UDEV (_self), NULL); self = MM_KERNEL_DEVICE_UDEV (_self); - ensure_parent (self); - return (self->priv->parent ? g_udev_device_get_sysfs_path (self->priv->parent) : NULL); + ensure_interface (self); + return (self->priv->interface ? g_udev_device_get_sysfs_path (self->priv->interface) : NULL); } static const gchar * @@ -542,8 +572,8 @@ kernel_device_get_interface_description (MMKernelDevice *_self) g_return_val_if_fail (MM_IS_KERNEL_DEVICE_UDEV (_self), NULL); self = MM_KERNEL_DEVICE_UDEV (_self); - ensure_parent (self); - return (self->priv->parent ? g_udev_device_get_sysfs_attr (self->priv->parent, "interface") : NULL); + ensure_interface (self); + return (self->priv->interface ? g_udev_device_get_sysfs_attr (self->priv->interface, "interface") : NULL); } static gboolean @@ -906,7 +936,7 @@ dispose (GObject *object) MMKernelDeviceUdev *self = MM_KERNEL_DEVICE_UDEV (object); g_clear_object (&self->priv->physdev); - g_clear_object (&self->priv->parent); + g_clear_object (&self->priv->interface); g_clear_object (&self->priv->device); g_clear_object (&self->priv->properties); |