All of lore.kernel.org
 help / color / mirror / Atom feed
* Can I reboot a USB device within a driver's probe function?
@ 2020-09-13 16:17 Thierry Seegers
  2020-09-14  5:26 ` Greg KH
  0 siblings, 1 reply; 5+ messages in thread
From: Thierry Seegers @ 2020-09-13 16:17 UTC (permalink / raw)
  To: kernelnewbies

Hi,

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".

For example, here's a Python script
(https://github.com/longjie/ps4eye/blob/master/script/ps4eye_init.py)
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?

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. If I do "lsusb", the same "0580" device is still
listed and the new USB camera device isn't discovered.

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.

Thanks for your help

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Can I reboot a USB device within a driver's probe function?
  2020-09-13 16:17 Can I reboot a USB device within a driver's probe function? Thierry Seegers
@ 2020-09-14  5:26 ` Greg KH
  2020-09-14  8:03   ` Thierry Seegers
  0 siblings, 1 reply; 5+ messages in thread
From: Greg KH @ 2020-09-14  5:26 UTC (permalink / raw)
  To: Thierry Seegers; +Cc: kernelnewbies

On Sun, Sep 13, 2020 at 06:17:49PM +0200, Thierry Seegers wrote:
> Hi,

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
> (https://github.com/longjie/ps4eye/blob/master/script/ps4eye_init.py)
> 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?

good luck!

greg k-h

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Can I reboot a USB device within a driver's probe function?
  2020-09-14  5:26 ` Greg KH
@ 2020-09-14  8:03   ` Thierry Seegers
  2020-09-14  8:17     ` Greg KH
  0 siblings, 1 reply; 5+ messages in thread
From: Thierry Seegers @ 2020-09-14  8:03 UTC (permalink / raw)
  To: Greg KH; +Cc: kernelnewbies

Hi, thanks for the reply.

> > 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?

Here's my (perhaps incorrect thought) as to why doing this in a driver would
be desirable. In the case of the Python script executed through a .rules file,
the script can't know which device this is in response to. It is only launched
because "some" device with product ID "0580" has been connected. Then,
it just searches the system for "a" device with product ID "0580" and talks to
*the first one it finds*. In the case where two devices would be plugged in to
the computer at roughly the same time, I think this mechanism would break
because there's a chance both scripts would attempt to talk to the same
device and fail to update it. You end up with a device in a bad state and a
second "0580" device that wouldn't even be spoken to ever.

Contrast with a driver where if two devices are connected at the same time, two
separate instances of the driver code would be executed for each
specific device.
There would be no chance of both probe() functions talking to the same device
because the probe() function would be invoked for a specific device.

> 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.

I'll keep hacking at it but I agree with you that regardless of
anything else, the
probe() function ought to return an error code.

> Are you sure you sent the proper data to the device?

I'm sure in so far as I straight copy pasted the code from a
user-executed program
that did the exact same thing successfully.

Thanks for your help!

Regards

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Can I reboot a USB device within a driver's probe function?
  2020-09-14  8:03   ` Thierry Seegers
@ 2020-09-14  8:17     ` Greg KH
  2020-09-14  9:10       ` Thierry Seegers
  0 siblings, 1 reply; 5+ messages in thread
From: Greg KH @ 2020-09-14  8:17 UTC (permalink / raw)
  To: Thierry Seegers; +Cc: kernelnewbies

On Mon, Sep 14, 2020 at 10:03:49AM +0200, Thierry Seegers wrote:
> Hi, thanks for the reply.
> 
> > > 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?
> 
> Here's my (perhaps incorrect thought) as to why doing this in a driver would
> be desirable. In the case of the Python script executed through a .rules file,
> the script can't know which device this is in response to.

Then you need to fix your script, as it can be determined from the
environment variables that are passed to it by udev.  Otherwise udev and
scripts that trigger off of device discovery would not work very well :)

> Contrast with a driver where if two devices are connected at the same time, two
> separate instances of the driver code would be executed for each
> specific device.

Same for userspace scripts.

good luck!

greg k-h

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Can I reboot a USB device within a driver's probe function?
  2020-09-14  8:17     ` Greg KH
@ 2020-09-14  9:10       ` Thierry Seegers
  0 siblings, 0 replies; 5+ messages in thread
From: Thierry Seegers @ 2020-09-14  9:10 UTC (permalink / raw)
  To: Greg KH; +Cc: kernelnewbies

> Then you need to fix your script, as it can be determined from the
> environment variables that are passed to it by udev.  Otherwise udev and
> scripts that trigger off of device discovery would not work very well :)

Aaaah! That's the puzzle piece I was missing! Yes, it makes sense now
and, oh lookie here the information I get as environment variables when
the script is invoked:

DEVNAME=/dev/bus/usb/002/002
DEVPATH=/devices/pci0000:00/0000:00:0c.0/usb2/2-1

I think I can work with that. :)

Thanks!

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-09-14  9:12 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-13 16:17 Can I reboot a USB device within a driver's probe function? Thierry Seegers
2020-09-14  5:26 ` Greg KH
2020-09-14  8:03   ` Thierry Seegers
2020-09-14  8:17     ` Greg KH
2020-09-14  9:10       ` Thierry Seegers

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.