Re: USB hub clear POWER feature -> device still in 'lsusb' ?!

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 23 May 2017, Harald Welte wrote:

> Dear Linux Kernel USB hackers,
> 
> I'm facing the following overall problem / use case:
> 
> * there is an embedded device, attached to USB, with complex internal
>   software, which every so often needs to be physically power cycled in
>   order to reset all of its internal state.  In the particular case it's
>   a cellular modem, but that doesn't really matter here
> 
> * in order to perform the power cycle, I use a (custom built) USB hub
>   of which I'm sure that disabling the POWER feature of the hub port
>   actually will control the downstream VBUS supply to the device
> 
> * In absence of any sysfs control or other API exposed to userland, I'm
>   using uhubctl (https://github.com/mvp/uhubctl) to directly clear the
>   POWER feature on said downstream USB port of the hub.
> 
> * The Linux kernel USB stack (tested up to 4.11) does notice this state
>   change (I can see it doing GET_STATUS as a follow-up), but the USB
>   device still stays in the USB tree, i.e. it shows up in lsusb despite
>   being powered off.  This also means that all associated devices like
>   cdc_acm, cdc_ether etc. still remain seen by applications, despite the
>   device being gone

This may be because the hub does not set the port-connect-change status
bit when a connected port is powered off (see section 11.24.2.7.2.1 of
the USB-2.0 spec).

However, it's not easy to predict exactly what will happen -- I would
have guessed that the hub driver would not notice anything at all.  A
usbmon trace would provide better information.

> * Only when the device is turned on again via SET_FEATURE POWER, the
>   USB device logical structure is remove from the kernel USB stack, and
>   it subsequently re-enumerates.
> 
> I know that bypassin the kernel USB hub driver is probably not the
> cleanest approach, but in absence of any API/sysfs to do so (forgive me
> if I simply didn't find it), we have to resort to issuing CONTROL
> requests to the USB hub directly.

That's right.  There is no way to tell the hub driver to turn off power 
to a port.

> As a work-around, I have found that issuing something like
> 	"echo 1 > /sys/bus/usb/devices/1-4.1/remove"
> will clear the ENABLE feature on the port and at the same time the
> kernel code will call usb_remove_device() and hence it disappears from
> lsusb as well as any associated device nodes re removed.
> 
> Hoewver, in this case I have not found any designated way to re-attach
> the device.  Given that we're talking about embedded devices in
> industrial applications installed at remote locations, and about a mPCIe
> physical form factor, re-plugging the device simply won't be an option.

The way to re-attach a device after writing to its
/sys/bus/usb/.../remove file is to disconnect and reconnect the USB
cable.  Of course, that's not possible in this case.  The .../remove
file was meant to be used rather like the "Safely remove hardware"
button in Windows -- which wouldn't work in this situation either.

> I'm wondering that after decades of a production-grade Linux USB stack,
> why is there no standard method to re-enable such a port.  Once again,
> if I'm missing it, please let me know.

Linux's USB stack was designed with the idea that the driver is in full 
control of the device.  If you change the device's state without the 
driver knowing about it, naturally things will not work as intended.

> Given that power cycling was the actual requirement at hand: With ENABLE
> cleared via sysfs "remove", the POWER feature is still set and hence
> power is still applied to the downstream usb port at this point.  But
> then, as indicated above, I can use uhubctl to remove the power and
> re-enable the power, which will make the device re-enumerate.
> 
> But this weird combination between sysfs on the one hand side and
> directly issuing USB hub control requests via uhubctl on the other side
> really looks ugly.  Is this really how one is supposed to power-cycle a
> USB device?  It doesn't seam like such a completely odd requirement,
> does it?

One is not supposed to power-cycle a USB device at all.  The API 
doesn't include any provision for this; the only way to do it is by 
working around the design, as you have found.  (Not to mention the fact 
that most hubs do not support actual power switching.)

Of course, the API can always be enlarged.  So far there have not been 
any requests for this feature to be added.

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux