Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Resetting a USB port in Debian 10

1,327 views
Skip to first unread message

Jason

unread,
May 18, 2022, 7:00:06 PM5/18/22
to
Hello,

What is the best way to power cycle or reset a USB port? I need to do this to reset a USB modem if it stops responding. The system in question is Debian 10 aarch64 on RockPi 4b+.

Thanks,
--
Jason

IL Ka

unread,
May 18, 2022, 7:50:05 PM5/18/22
to

Anssi Saari

unread,
May 19, 2022, 3:00:06 AM5/19/22
to
Jason <elec...@emypeople.net> writes:

> What is the best way to power cycle or reset a USB port? I need to do
> this to reset a USB modem if it stops responding. The system in
> question is Debian 10 aarch64 on RockPi 4b+.

As far as I know, power cycling is not usually a function of USB.

For resetting, in my case a stupid mouse that doesn't come back after
sleep, I've used resetusb from https://github.com/mcarans/resetusb/

It has a convenient search function so I can just tell it to search for
my mouse by name instead of me having to fiddle with bus and device
numbers.

There's some discussion and alternative programs at
https://askubuntu.com/questions/645/how-do-you-reset-a-usb-device-from-the-command-line

to...@tuxteam.de

unread,
May 19, 2022, 3:30:05 AM5/19/22
to
On Thu, May 19, 2022 at 09:55:54AM +0300, Anssi Saari wrote:
> Jason <elec...@emypeople.net> writes:
>
> > What is the best way to power cycle or reset a USB port? I need to do
> > this to reset a USB modem if it stops responding. The system in
> > question is Debian 10 aarch64 on RockPi 4b+.
>
> As far as I know, power cycling is not usually a function of USB.

Oh, it is. Cutting power to "misbehaving" USB gadgets is even part
of the spec, so a compliant port has to have the hardware for that.

Inconveniencing my favourite search engine (guess which one *not*)
yields a couple of hits:

https://stackoverflow.com/questions/4702216/controlling-a-usb-power-supply-on-off-with-linux
https://unix.stackexchange.com/questions/165447/turning-off-power-to-usb-port-or-turn-off-power-to-entire-usb-subsystem/321945#321945
http://blog.andrew.net.au/2009/01/17
https://superuser.com/questions/524391/how-can-i-power-cycle-a-usb-device-on-raspberry-pi

So depending on your hardware, drivers, kernel version and possibly
moon phase, you might be lucky :)

Happy poking
--
t
signature.asc

Tixy

unread,
May 19, 2022, 4:00:04 AM5/19/22
to
On Wed, 2022-05-18 at 17:22 -0500, Jason wrote:
> What is the best way to power cycle or reset a USB port?

The method I use, which I found described online is to unbind the
driver then re-bind it like...

echo "$ID" >/sys/bus/usb/drivers/usb/unbind
sleep 1
echo "$ID" >/sys/bus/usb/drivers/usb/bind

To find the device ID my bash script scans the USB serial numbers
looking for the one I'm interested in...

pushd /sys/bus/usb/drivers/usb >/dev/null
for f in **/serial
do
if [ "$(cat $f)" = MY_SERIAL_NUMBER ]; then
ID=${f%%/*}
fi
done
popd >/dev/null

if [ "$ID" = "" ]; then
echo "Can't find device"
exit 1
fi

There's no doubt better ways of doing the above, but it works for me.
(Looking at it now I'd get rid of the pushd/popd by using an extra
string splice operation and that use of ** probably needs something
doing to it to cope with spaces in paths)

--
Tixy

Greg Wooledge

unread,
May 19, 2022, 7:10:05 AM5/19/22
to
On Thu, May 19, 2022 at 08:54:52AM +0100, Tixy wrote:
> To find the device ID my bash script scans the USB serial numbers
> looking for the one I'm interested in...
>
> pushd /sys/bus/usb/drivers/usb >/dev/null
> for f in **/serial
> do
> if [ "$(cat $f)" = MY_SERIAL_NUMBER ]; then
> ID=${f%%/*}
> fi
> done
> popd >/dev/null
>
> if [ "$ID" = "" ]; then
> echo "Can't find device"
> exit 1
> fi
>
> There's no doubt better ways of doing the above, but it works for me.
> (Looking at it now I'd get rid of the pushd/popd by using an extra
> string splice operation and that use of ** probably needs something
> doing to it to cope with spaces in paths)

1) For ** to work, you need to do "shopt -s globstar" somewhere before it.

Other issues:

2) You didn't check the success of your pushd. If it fails, you could
theoretically run the rest of the script from the wrong directory.

3) "$f" should be quoted, in "$(cat "$f")". Or, if you'd like to avoid
forking a cat(1) for every USB serial device, you could do something
like:

for f in **/serial
do
read -r serial < "$f"
if [ "$serial" = MY_SERIAL_NUMBER ]; then
id=${f%%/*}
fi
done

4) There's no reason to keep reading if you've already found the desired
id, so you could add a "break" right after the id=${...} part.

Tixy

unread,
May 19, 2022, 1:30:06 PM5/19/22
to
On Thu, 2022-05-19 at 07:00 -0400, Greg Wooledge wrote:
> On Thu, May 19, 2022 at 08:54:52AM +0100, Tixy wrote:
> > To find the device ID my bash script scans the USB serial numbers
> > looking for the one I'm interested in...
> >
> >    pushd /sys/bus/usb/drivers/usb >/dev/null
> >    for f in **/serial
> >    do
> >     if [ "$(cat $f)" = MY_SERIAL_NUMBER ]; then
> >     ID=${f%%/*}
> >     fi
> >    done
> >    popd >/dev/null
> >    
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >    if [ "$ID" = "" ]; then
> >     echo "Can't find device"
> >     exit 1
> >    fi
> >    
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> > There's no doubt better ways of doing the above, but it works for me.
> > (Looking at it now I'd get rid of the pushd/popd by using an extra
> > string splice operation and that use of ** probably needs something
> > doing to it to cope with spaces in paths)
>
> 1) For ** to work, you need to do "shopt -s globstar" somewhere before it.

I didn't know that, it works for me without setting that option.

$ shopt | grep globstar
globstar off
$ echo /sys/bus/usb/drivers/usb/**/serial
/sys/bus/usb/drivers/usb/usb1/serial
/sys/bus/usb/drivers/usb/usb2/serial
/sys/bus/usb/drivers/usb/usb3/serial
/sys/bus/usb/drivers/usb/usb4/serial

$ shopt -s globstar
$ shopt | grep globstar
globstar on
$ echo /sys/bus/usb/drivers/usb/**/serial
/sys/bus/usb/drivers/usb/usb1/serial
/sys/bus/usb/drivers/usb/usb2/serial
/sys/bus/usb/drivers/usb/usb3/serial
/sys/bus/usb/drivers/usb/usb4/serial

--
Tixy

Greg Wooledge

unread,
May 19, 2022, 1:40:05 PM5/19/22
to
On Thu, May 19, 2022 at 06:24:21PM +0100, Tixy wrote:
> On Thu, 2022-05-19 at 07:00 -0400, Greg Wooledge wrote:
> > 1) For ** to work, you need to do "shopt -s globstar" somewhere before it.
>
> I didn't know that, it works for me without setting that option.
>
> $ shopt | grep globstar
> globstar off
> $ echo /sys/bus/usb/drivers/usb/**/serial
> /sys/bus/usb/drivers/usb/usb1/serial
> /sys/bus/usb/drivers/usb/usb2/serial
> /sys/bus/usb/drivers/usb/usb3/serial
> /sys/bus/usb/drivers/usb/usb4/serial

You're getting the exact same results you'd get from
/sys/bus/usb/drivers/usb/*/serial

unicorn:~$ bash
unicorn:~$ mkdir -p /tmp/x/y/z/foo.txt
unicorn:~$ echo /tmp/**/*.txt
/tmp/dumps/greg_log.txt
unicorn:~$ shopt -s globstar
unicorn:~$ echo /tmp/**/*.txt
/tmp/dumps/greg_log.txt /tmp/x/y/z/foo.txt

With globstar on, ** and * become different.

Tixy

unread,
May 19, 2022, 1:50:05 PM5/19/22
to
On Thu, 2022-05-19 at 13:38 -0400, Greg Wooledge wrote:
> On Thu, May 19, 2022 at 06:24:21PM +0100, Tixy wrote:
> > On Thu, 2022-05-19 at 07:00 -0400, Greg Wooledge wrote:
> > > 1) For ** to work, you need to do "shopt -s globstar" somewhere before it.
> >
> > I didn't know that, it works for me without setting that option.
> >
> > $ shopt | grep globstar
> > globstar off
> > $ echo /sys/bus/usb/drivers/usb/**/serial
> > /sys/bus/usb/drivers/usb/usb1/serial
> > /sys/bus/usb/drivers/usb/usb2/serial
> > /sys/bus/usb/drivers/usb/usb3/serial
> > /sys/bus/usb/drivers/usb/usb4/serial
>
> You're getting the exact same results you'd get from
> /sys/bus/usb/drivers/usb/*/serial

Indeed, I am. So for my script I don't need ** as there is only a
single unknown directory in the path I'm interested in.

--
Tixy

Jason

unread,
May 20, 2022, 6:50:05 PM5/20/22
to
On Thu, May 19, 2022 at 09:25:23AM +0200, to...@tuxteam.de wrote:
> On Thu, May 19, 2022 at 09:55:54AM +0300, Anssi Saari wrote:
> > Jason <elec...@emypeople.net> writes:
> >
> > > What is the best way to power cycle or reset a USB port?

Turns out the easiest answer was within reach all the time: In Debian 10, 'usbreset' is included in the standard usbutils package. One glitch is that because it does not allow the user to specify the reset time (to my knowledge), my modem gets the next higher device number (ttyACM1 instead of ttyACM0). Calling usbreset a 2nd time brings it back to /dev/ttyACM0.

If usbreset turns out not to solve my problem(s), I will pursue the other excellent leads that were provided. Thank you for all the helpful responses.


--
Jason

to...@tuxteam.de

unread,
May 21, 2022, 12:50:05 AM5/21/22
to
On Fri, May 20, 2022 at 05:25:54PM -0500, Jason wrote:
> On Thu, May 19, 2022 at 09:25:23AM +0200, to...@tuxteam.de wrote:
> > On Thu, May 19, 2022 at 09:55:54AM +0300, Anssi Saari wrote:
> > > Jason <elec...@emypeople.net> writes:
> > >
> > > > What is the best way to power cycle or reset a USB port?
>
> Turns out the easiest answer was within reach all the time: In Debian 10, 'usbreset' is included in the standard usbutils package [...]

Gee. I had it all the time waiting there in /usr/bin. Thanks
for discovering it for me :-)

For the curious, here [1] is the source (for buster). The core
seems to be sending an ioctl to the relevant /dev/bus/usb/...
file.

Cheers
--
t
signature.asc
0 new messages