Can I reboot a USB device within a driver's probe function?
gregkh at linuxfoundation.org
Mon Sep 14 01:26:02 EDT 2020
On Sun, Sep 13, 2020 at 06:17:49PM +0200, Thierry Seegers wrote:
Short answer to your subject line, yes, you can, we have been doing so
since the 1990's :)
> I have a USB device that when plugged into a computer shows up as a
> generic USB device with product ID "0580". The only thing you're
> expected to do is to upload firmware to it and reboot it. It then
> disappears from the system and reappears as a USB video camera with
> product ID "058a".
Very common device from the "early days" of USB.
> For example, here's a Python script
> that does just that. It uses Python usb.core and usb.util to upload a
> firmware file as control packets. When that is done, it sends a
> special control packet to reboot the device. After the device is
> rebooted, it no longer shows up (using "lsusb", for example) as the
> generic device but as a USB camera device and is taken in charge by
> the corresponding driver. Note that sending that last control packet,
> it will fail with an EPIPE error but that is expected since the
> interface we were talking to is actually gone.
> One can even have this script executed automatically through a
> ".rules" file. So far so good. My question is: can I write a driver
> that will perform the same thing?
Yes, but why? We pushed most of this logic out to userspace as it is
easier to handle there. Why do you want a kernel driver for this?
> I started exploring the idea but I'm stuck. I have written such a
> driver that performs the firmware upload and sends that special
> control packet. It does all of this within the USB probe() function
> which is called on the driver to see if it wants to handle the device.
> My problem is that, after returning from the probe() function, the
> system does not realize that the interface is actually gone and that a
> new one has appeared.
Did your problem function return an error (saying the driver is not in
control of the device), or 0, saying it is? I recommend sending an
error, that should free up the reference counting properly.
> If I do "lsusb", the same "0580" device is still
> listed and the new USB camera device isn't discovered.
Are you sure you sent the proper data to the device?
> No matter what I tried, I can't get the OS to "shake" this device
> which is gone. I've tried the following:
> - usb_driver_release_interface()
> - usb_reset_configuration()
> - interface->condition = USB_INTERFACE_UNBOUND;
> - interface->needs_binding = 1;
> - usb_put_intf();
> - usb_put_dev();
> - return -ENODEV
> - return -EBUSY
> I don't know what I'm supposed to do within (or outside) the probe
> function to signify to the OS that this interface is actually not
> existent anymore, that this driver doesn't want to deal with this
> device any further and that it (the OS) should be listening to new
> device connections.
> Note that after sending the reboot packet, you can't communicate with
> the device anymore, it would simply return EPIPE.
That's fine, but it is up to the device to reset itself. Are you sure
you are sending the correct data?
More information about the Kernelnewbies