Reset USB on Failures
Because USB connectors were not made for vibration and being reset continuously, like people usually do during robot development, there can be many errors which happen.
- Multiple ways to see the details of USB settings and errors
- A simple script to hard-reset the whole USB stack and all devices cleanly
How to Debug Broken USB
Debug with dmesg
You can check for errors by searching dmesg
and grepping for usb
, such as dmesg | grep -i USB
. If you see errors you may need to reset the usb bus and have the system find everything again. You will see groupings like the below output. If you see error
anywhere,
...
[ 950.080459] usb 1-1.4: new high-speed USB device number 8 using xhci_hcd
[ 950.387494] usb 1-1.4: New USB device found, idVendor=046d, idProduct=082c
[ 950.387501] usb 1-1.4: New USB device strings: Mfr=0, Product=2, SerialNumber=1
[ 950.387505] usb 1-1.4: Product: HD Webcam C615
[ 950.387509] usb 1-1.4: SerialNumber: 7E6298D0
[ 950.679920] input: HD Webcam C615 as /devices/pci0000:00/0000:00:15.0/usb1/1-1/1-1.4/1-1.4:1.2/input/input28
Debug with lsusb
This will output the list of currently visible (and working) USB devices. You can use this and unplug/replug to figure out which virtual serial port or other device has the specific details you need to debug it.
Bus 002 Device 002: ID 2109:0813 VIA Labs, Inc.
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 007: ID 0403:6015 Future Technology Devices International, Ltd Bridge(I2C/SPI/UART/FIFO)
Bus 001 Device 005: ID 8087:0aa7 Intel Corp.
Bus 001 Device 003: ID 093a:2510 Pixart Imaging, Inc. Optical Mouse
Bus 001 Device 008: ID 046d:082c Logitech, Inc.
Bus 001 Device 006: ID 046d:0892 Logitech, Inc. OrbiCam
Bus 001 Device 004: ID 04d9:8009 Holtek Semiconductor, Inc.
Bus 001 Device 002: ID 2109:2813 VIA Labs, Inc.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Debug with usb-devices
This is a more in-depth view of the drivers, serial numbers, etc for every device and useful for creating udev rules based on its values.
T: Bus=01 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 6 Spd=480 MxCh= 0
D: Ver= 2.00 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=046d ProdID=0892 Rev=00.19
S: Product=HD Pro Webcam C920
S: SerialNumber=91863D1F
C: #Ifs= 4 Cfg#= 1 Atr=80 MxPwr=500mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=0e(video) Sub=01 Prot=00 Driver=uvcvideo
I: If#= 1 Alt= 0 #EPs= 0 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo
I: If#= 2 Alt= 0 #EPs= 0 Cls=01(audio) Sub=01 Prot=00 Driver=snd-usb-audio
I: If#= 3 Alt= 0 #EPs= 0 Cls=01(audio) Sub=02 Prot=00 Driver=snd-usb-audio
Script to Reset the USB Stack
We recommend copying this script into reset_usb.sh
and executing it as sudo with sudo sh reset_usb.sh
on your robot if you have USB errors or have updated udev rules.
#!/bin/sh
if [ "$(id -u)" -ne 0 ]; then
echo 'This script must be run by root with `sudo sh reset_usb.sh`' >&2
exit 1
fi
echo 'Reloading UDEV rules to find any changes in naming, simlinks, etc'
udevadm control --reload-rules && udevadm trigger
sudo service udev restart
echo 'Re-binding all USB ports'
for i in /sys/bus/pci/drivers/[uoex]hci_hcd/*:*; do
echo " Resetting ${i%/*}"
echo "${i##*/}" > "${i%/*}/unbind"
sleep 3
echo "${i##*/}" > "${i%/*}/bind"
done
echo 'Waiting for 5 seconds to allow USB devices to be re-found'
sleep 5
echo 'Reset complete'
echo 'USB Devices which currently exist:'
lsusb
Once you have saved this, run sudo sh reset_usb.sh
to reload the UDEV rules and trigger this.
Make sure your devices don't power down
Many USB buses power down devices over a period of time based on their own rules. You can set a udev rule for all USB devices to no allow the USB to lower their power. This can lead to intermittent failures, especially on virtual serial ports and other "generic" devices which the computer doesn't understand.
Create a new file in /etc/udev/rules.d/99-usb-power.rules
with these contents, which will turn off the autosuspend of devices.
ACTION=="add", SUBSYSTEM=="usb", TEST=="power/control", ATTR{power/control}:="on"
ACTION=="add", SUBSYSTEM=="usb", TEST=="power/autosuspend", ATTR{power/autosuspend}:="-1"
ACTION=="add", SUBSYSTEM=="usb", TEST=="power/autosuspend_delay_ms", ATTR{power/autosuspend_delay_ms}:="-1"
If nothing else... Unplug, replug, repeat...
If this doesn't work, the actual USB device may have crashed and you will need to power it down to get it working. As many devices are remembered based on the specific port they were on, you should always try swapping to a different open USB port.
And, if all else fails, reset the computer and try again...
Updated over 4 years ago