How can I disable a specific USB device using the musb_hdrc Linux driver?

Firstly, I am new to the Linux USB stack and I am trying to understand it a little more in order to achieve the following result: I need to reconnect / disconnect a specific USB device, because sometimes, hard not often, this device no longer responds. and the only solution is to physically disconnect / reconnect the USB cable from the device.

My board (AM33x Sitara) has two usb controllers with musb-hdrc drivers:

# pwd /sys/bus/platform/drivers/musb-hdrc

# ls -lrth
total 0
--w-------    1 root     root        4.0K Jul 11 10:11 uevent
--w-------    1 root     root        4.0K Jul 11 10:13 unbind
lrwxrwxrwx    1 root     root           0 Jul 11 10:13 musb-hdrc.1.auto -> ../../../../devices/ocp.2/47400000.usb/47401c00.usb/musb-hdrc.1.auto
lrwxrwxrwx    1 root     root           0 Jul 11 10:13 musb-hdrc.0.auto -> ../../../../devices/ocp.2/47400000.usb/47401400.usb/musb-hdrc.0.auto
lrwxrwxrwx    1 root     root           0 Jul 11 10:13 module -> ../../../../module/musb_hdrc
--w-------    1 root     root        4.0K Jul 11 10:13 bind

      

From dmesg, I can see that my device is using the musb-hdrc driver:

usb 2-1.4: new full-speed USB device number 17 using musb-hdrc

      

But looking at the node device, I cannot find this driver:

    # ls -lrth /sys/bus/usb/devices/2-1.4:1.0/
    total 0
    -rw-r--r--    1 root     root        4.0K Jul 11 12:03 uevent
    -r--r--r--    1 root     root        4.0K Jul 11 12:05 supports_autosuspend
    lrwxrwxrwx    1 root     root           0 Jul 11 12:05 subsystem -> ../../../../../../../../../bus/usb
    drwxr-xr-x    2 root     root           0 Jul 11 12:05 power
...
...
    -r--r--r--    1 root     root        4.0K Jul 11 12:05 bAlternateSetting
    lrwxrwxrwx    1 root     root           0 Jul 11 12:07 driver -> ../../../../../../../../../bus/usb/drivers/usbfs

      

According to https://www.kernel.org/doc/Documentation/usb/power-management.txt it is possible to suspend USB devices by doing: echo "auto" > /sys/bus/usb/devices/2-1.4/power/control

and echo 0 > /sys/bus/usb/devices/2-1.4/power/autosuspend_delay_ms

and also detaching the driver usingecho "2-1.4:1.0" > /sys/bus/usb/devices/2-1.4:1.0/driver/unbind

In dmesg I can see that the device is disconnected, but for some reason the device is automatically linked right after that.

However, when I do the same procedure using the musb-hdrc driver on the musb-hdrc.1.auto and musb-hdrc.0.auto devices, it works well, except that all my USB devices are disabled / enabled .. And I would like to tell you more about the device interface with 2-1.4: 1.0 usb interface.

The idea is to use the musb-hdrc driver to decouple the USB device interface 2-1.4: 1.0, but it says there is no such device ...

I am a little confused about this because I see the device is inside the device tree musb-hdrc.1.auto:

# ls -lrth /sys/devices/ocp.2/47400000.usb/47401c00.usb/musb-hdrc.1.auto/usb2/2-1/2-1.4/
total 0
-rw-r--r--    1 root     root        4.0K Jul 11 12:03 uevent
-r--r--r--    1 root     root        4.0K Jul 11 12:03 speed
...
...
drwxr-xr-x    6 root     root           0 Jul 11 12:03 2-1.4:1.0
...

      

Why does the unbind command say the device doesn't exist? Maybe there is a way to specify which path within the device tree points to the driver that I want to override for that particular device interface. 2-1.4: 1.0?

Thank you for your help.

+3


source to share


1 answer


Hm, intriguing question :-)

First of all, keep in mind that there is a difference between a (logical) device and a device driver. When a hardware device is physically connected, Linux creates a (logical) device instance and then tries to bind the device to the appropriate device driver instance.

Therefore, binding and unbinding is one process, and detaching (or removing) a LUN is a different process. The two are different and I'm not sure what would solve your problem.

Sometimes when you need to reset the buggy driver, you can get away with the unbind / bind loop. However, if the hardware is a nut, it might not work.

Detaching and relinking is pretty straightforward. You need to first find the driver your device is bound to and then use interfaces unbind

and bind

. Let me show you this with my USB headset.

# dmesg
[ 2073.908792] usb 2-1.2: new full-speed USB device number 8 using ehci-pci

# lsusb -t
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/3p, 480M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/6p, 480M
        |__ Port 2: Dev 10, If 0, Class=Audio, Driver=snd-usb-audio, 12M
        |__ Port 2: Dev 10, If 1, Class=Audio, Driver=snd-usb-audio, 12M
        |__ Port 2: Dev 10, If 2, Class=Audio, Driver=snd-usb-audio, 12M
        |__ Port 2: Dev 10, If 3, Class=Human Interface Device, Driver=usbhid, 12M

      

So, my USB headset usb 2-1.2

. He says he uses the ehci-pci driver, but the device will bind to the hub instead. You can find it:

# find /sys/bus/usb -name "2-1.2"
/sys/bus/usb/devices/2-1.2
/sys/bus/usb/drivers/usb/2-1.2

      

See above, driver name usb

. Or you can just follow the driver link:

# cd /sys/bus/usb/devices/2-1.2/driver
# ls -la
lrwxrwxrwx  1 root root    0 Jul 12 12:03 2-1.2 -> ../../../../devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2
--w-------  1 root root 4096 Jul 12 11:57 bind
--w-------  1 root root 4096 Jul 12 11:57 unbind

      

Now we can loop through:

# echo 2-1.2 > unbind 
# echo 2-1.2 > bind 

      



So far, we've talked about binding device driver <-> device

. Now, making the disconnect and then reconnecting the device seems to be more difficult. You can remove it:

# echo 1 > /sys/bus/usb/devices/2-1.2/remove

      

But I couldn't find how to insert it again!

After some research I came across the USBDEVFS_RESET ioctl , but there is a warning to avoid it. In any case, other people found it helpful. The post mentions an authorized interface as a way to reconfigure a device via an auth loop:

# echo 0 > /sys/bus/usb/devices/2-1.2/authorized
# echo 1 > /sys/bus/usb/devices/2-1.2/authorized

      

UPDATE

Connecting a mobile phone to the USB port, I see that neither decoupling nor de-auth can turn off VBUS. remove

of course it does, but then you cannot insert it back.

Given that USB is not working in my particular case, changing power/control

from on

to auto

appears to disable VBUS.

# echo auto > /sys/bus/usb/devices/2-1.2/power/control

      

Perhaps you can play with the power interface?

If that doesn't work for you, the alternative is to go to the musk driver and hack your way by adding your own kludge. This trick is also not unusual.

+1


source







All Articles