Skip to content

Read common descriptors from sysfs, when available #458

Open

Description

@ronny-rentner

Running Debian Linux 11 with Python 3.10 and libusb1. I am trying to connect to an LG UltraFine monitor via USB-C.

It works via lsusb (running as my user):

$ lsusb -D /dev/bus/usb/003/010
Device: ID 043e:9a39 LG Electronics USA, Inc. LG Monitor Controls
Couldn't open device, some information will be missing
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass          239 Miscellaneous Device
  bDeviceSubClass         2 
  bDeviceProtocol         1 Interface Association
  bMaxPacketSize0        64
  idVendor           0x043e LG Electronics USA, Inc.
  idProduct          0x9a39 
  bcdDevice            4.11
  iManufacturer           1 LG Electronics Inc.
  iProduct                3 LG Monitor Controls
  iSerial                 4 107NTYTAD986
  bNumConfigurations      1

but not via pyusb:

$ python -c 'import usb.core; d = usb.core.find(idVendor=0x043e, idProduct=0x9a39); print(d)'
DEVICE ID 043e:9a39 on Bus 003 Address 010 =================
 bLength                :   0x12 (18 bytes)
 bDescriptorType        :    0x1 Device
 bcdUSB                 :  0x200 USB 2.0
 bDeviceClass           :   0xef Miscellaneous
 bDeviceSubClass        :    0x2
 bDeviceProtocol        :    0x1
 bMaxPacketSize0        :   0x40 (64 bytes)
 idVendor               : 0x043e
 idProduct              : 0x9a39
 bcdDevice              :  0x411 Device 4.11
 iManufacturer          :    0x1 Error Accessing String
 iProduct               :    0x3 Error Accessing String
 iSerialNumber          :    0x4 Error Accessing String
 bNumConfigurations     :    0x1
$ ls -lah /dev/bus/usb/003/010
crw-rw-r-- 1 root root 189, 265 Sep 28 07:48 /dev/bus/usb/003/010

The device file is world readable.

The strange thing is that pyusb and also lsusb try to open the device with write permissions. I wonder why those are necessary to list something.

I can also do

$ cat /sys/bus/usb/devices/3-6.3/manufacturer
LG Electronics Inc.

or

$ cat /sys/bus/usb/devices/3-6.3/product 
LG Monitor Controls
$ ll /sys/bus/usb/devices/3-6.3/product 
-r--r--r-- 1 root root 4096 Sep 28 07:48 /sys/bus/usb/devices/3-6.3/product

I would expect pyusb to be able to show the vendor and manufacturer similar to lsusb without having write permissions (which are not necessary).

Activity

  1. jonasmalacofilho commented on Oct 2, 2022

    @jonasmalacofilho
    Member

    Write permissions are required because:

    • fetching a descriptor like iManufacturer requires submitting a control transfer to the device;
    • and that, in turn, require suitable permissions, as specified by the corresponding kernel driver (in this case, usbfs).1

    Regarding why lsusb seems to you to show a bit more information, that is because lsusb can try to use a few different ways to show you the manufacturer and similar infos: one of those is indeed just fetching the corresponding descriptor from the device, but it can also read that info from udev, or fallback to the USB IDs table. But PyUSB shouldn't be compared to lsusb; rather, it's something that can be used as building block to build something like lsusb (and, IIRC, the usbutils source code includes a PyUSB-based implementation).

    Footnotes

    1. Intuition about what should be a "read" or "write" operation can be tricky: it's necessary to consider how the USB protocol works, and how the kernel driver will decide to handle it, both for correctness and security. ↩

  2. ronny-rentner commented on Oct 4, 2022

    @ronny-rentner
    Author

    Well, as it seems, when you do cat /sys/bus/usb/devices/3-6.3/manufacturer you can also just read the information without write permissions from the kernel, without using usbfs and without using udev. Or who populates /sys/bus/usb?

  3. jonasmalacofilho commented on Oct 4, 2022

    @jonasmalacofilho
    Member

    Please send a patch/PR that implements this special case.

    Or who populates /sys/bus/usb?

    The Linux kernel, specifically the USB core. But I haven't checked whether they might be missing sometimes, you need to check that and handle any cases where they are present in the device, but somehow not in sysfs.

  4. ronny-rentner commented on Oct 5, 2022

    @ronny-rentner
    Author

    Well, if you're open to accepting a patch to fix this, I'd be willing to work on it. Can we reopen the ticket for this? It might take a bit as I am also busy with other stuff.

  5. ronny-rentner commented on Oct 5, 2022

    @ronny-rentner
    Author

    PS: I would probably not replace any existing logic but just whenever there is "Error Accessing String" do an extra step and try to find the string through /sys/bus/usb
    Sounds pretty straight forward to me.

  6. changed the title [-]Wrong permission error, "Error Accessing String"[/-] [+]Read common descriptors from sysfs, when available[/+] on Oct 6, 2022
  7. jonasmalacofilho commented on Oct 6, 2022

    @jonasmalacofilho
    Member

    Can we reopen the ticket for this?

    Done, but I also renamed for accuracy.

    PS: I would probably not replace any existing logic but just whenever there is "Error Accessing String" do an extra step and try to find the string through /sys/bus/usb
    Sounds pretty straight forward to me.

    Actually, it should probably go in the Device.manufacturer and similar properties, not in Device.__str__ (which may then be reworked to use the new feature).

    PyUSB is not a lsusb clone: sure, this feature will improve Device.__str__, but it's also necessary (and, arguably, more important) to make the data available for callers using PyUSB for something more than print(dev).

    And the preference order should probably be: locally cached value > (on Linux:) sysfs value > GET_DESCRIPTOR transfer.

  8. ronny-rentner commented on Oct 9, 2022

    @ronny-rentner
    Author

    Thanks for the direction, will do it like this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions