Home > Enterprise >  Python "[Errno 21] Is a directory" when trying access USB device [/dev/bus/usb/001/001] on
Python "[Errno 21] Is a directory" when trying access USB device [/dev/bus/usb/001/001] on

Time:09-05

I have a device that is running a custom Linux distro that has two USB devices set up on bus 001.

ln -s functions/rndis.usb0 configs/c.1
ln -s functions/mass_storage.0 configs/c.1

These show up under lsusb:

Bus 001 Device 002: ID 1eab:1a10
Bus 001 Device 001: ID 1d6b:0002

The issue is that the device sometimes gets stuck in USB Default mode - my understanding is that it is not being enumerated by Linux for some reason. I want to try and fix this by sending a reset command to the device - however - that is when I run into Error 21:

import os
import sys
import fcntl

USB_RESET = 21780

fd = os.open("/dev/bus/usb/001/001", os.O_WRONLY)
try:
        fcntl.ioctl(fd, USB_RESET, 0)
except Exception as e:
        print("Error: " str(e))
        sys.exit(1)
finally:
        os.close(fd)

The strange thing is that this works on /dev/bus/usb/001/002 When I send the command to 002 I get the output in dmesg:

usb 1-1: reset full-speed USB device number 2 using ci_hdrc

the 'file' command suggests that they are the same type of file:

001: character special
002: character special

CodePudding user response:

By digging around a little bit, I determined that the ioctl number 21780 that you are sending to the kernel is known as USBDEVFS_RESET in the kernel. (If you already knew that, it would have been really good info to include in your question.)

Using elixir.bootlin.com, I was able to track down the code that runs in the Linux kernel when you send that ioctl and look for cases that cause it to return the "is directory" error. In the usb_reset_device function in hub.c, I found this code:

    if (!udev->parent) {
        /* this requires hcd-specific logic; see ohci_restart() */
        dev_dbg(&udev->dev, "%s for root hub!\n", __func__);
        return -EISDIR;
    }

What that code shows us if that if you attempt to reset a USB device that is actually the USB root hub (because it has no parent), that is not supported. I think you are attempting to reset the USB root hub instead of the actual device that is having trouble, and Linux is telling you that it does not know how to do that.

Note that if your USB device is in the Default state as defined by the USB specification then it has not yet been assigned an address and it is just using address 0. So we wouldn't expect either of the two devices in your lsusb output to correspond to that device, because they have addresses 1 and 2.

I think maybe what you are looking for is a way to talk to whatever hub your device is connected to and tell it to reset the appropriate port. I don't think you can really talk to the device if Linux is so confused about it that it got stuck in the default state.

  • Related