Last active
September 30, 2020 22:09
-
-
Save jettero/15919217ff4137a40ff73ed9cc51e723 to your computer and use it in GitHub Desktop.
Every now and again my xhci_hcd goes wonky and I can't get USB devices to pop up on it. I hate rebooting for usb problems, so I came up with this.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# old http://billauer.co.il/blog/2013/02/usb-reset-ehci-uhci-linux/ | |
# old http://enc.com.au/2014/02/14/resetting-usb-devices/ | |
# | |
# http://www.linux.org/threads/resetting-the-usb-subsystem.6256/ | |
# (page was dead, used google cache) | |
# | |
# XXX This definitely worked (2016-08-21), the trouble is finding the serial | |
# number and the bind/unbind kernel interfaces | |
# | |
# echo 0000:00:14.0 | sudo tee /sys/bus/pci/drivers/xhci_hcd/unbind | |
# echo 0000:00:14.0 | sudo tee /sys/bus/pci/drivers/xhci_hcd/bind | |
# | |
# XXX This program produces the right output, but will it work in 6 months or | |
# whenver the hell I need this reset again?? | |
# | |
## dmesg notes | |
# [5809402.670110] usb 3-4: new full-speed USB device number 35 using xhci_hcd | |
# [5809407.786315] usb 3-4: device descriptor read/8, error -110 | |
# [5809412.999259] usb 3-4: device descriptor read/8, error -110 | |
# [5809413.212180] usb 3-4: new full-speed USB device number 36 using xhci_hcd | |
# [5809418.324116] usb 3-4: device descriptor read/8, error -110 | |
# [5809423.537067] usb 3-4: device descriptor read/8, error -110 | |
## serial notes | |
# the article uses lsusb, which is slow and meant for human parsing, not | |
# machine parsing. this file seems to have the serial I need though, and | |
# matches the bus number that was malfunctioning (3) | |
# | |
# echo $(< /sys/bus/usb/devices/usb3/serial) | |
# 0000:00:14.0 | |
# | |
## find notes | |
# it's not always going to be xhci_hcd (there's also uhci and ehci, etc) | |
# this usually produces exactly one match. | |
# application of s/$serial/unbind/ aught to do the trick | |
# | |
# find /sys/bus/pci/drivers -name 0000:00:14.0 | |
# /sys/bus/pci/drivers/xhci_hcd/0000:00:14.0 | |
BUSNUMBER="$1"; shift | |
function perform-the-reset() { | |
SERIAL="$1"; shift | |
DRV="$(sed -e "s,/$SERIAL\$,," <<< "$1")"; shift | |
echo "sending unbind: echo $SERIAL | sudo tee $DRV/unbind" | |
[ -z "$DRY_RUN" ] && (echo "$SERIAL" | sudo tee "$DRV/unbind") | |
[ -z "$DRY_RUN" ] && sleep 2 # doubt this is ever necessary … meh | |
echo "sending bind: echo $SERIAL | sudo tee $DRV/bind" | |
[ -z "$DRY_RUN" ] && (echo "$SERIAL" | sudo tee "$DRV/bind") | |
} | |
if [ -z "$BUSNUMBER" ]; then | |
echo | |
echo BUSNUMBER unspecified, trying to guess | |
dmesg | grep 'usb [0-9]-[0-9].*error' | tail -n 10 | sed -e 's/^/ /' | |
lasterr="$(dmesg | grep 'usb [0-9]-[0-9].*error' | tail -n 1)" | |
if [[ "$lasterr" =~ ([0-9])-([0-9]): ]]; then | |
GUESS="${BASH_REMATCH[1]}" | |
echo "guessing bus=$GUESS hit enter if this is right" | |
else | |
echo | |
fi | |
read -ep "usb bus number: " -i "$GUESS" BUSNUMBER | |
fi | |
if [ -d "/sys/bus/usb/devices/usb$BUSNUMBER" ]; then | |
echo "found the bus device in sysfs /sys/bus/usb/devices/usb$BUSNUMBER" | |
SERIAL="$(< /sys/bus/usb/devices/usb$BUSNUMBER/serial)" | |
if [ -n "$SERIAL" ]; then | |
echo "found the serial number: $SERIAL" | |
echo "trying to find the driver bind/unbind files" | |
drvsno=( $(find /sys/bus/pci/drivers -name "$SERIAL") ) | |
drvsnoc=${#drvsno[*]} | |
if [ $drvsnoc == 1 ]; then | |
echo "found this serial in exactly one driver $drvsno" | |
perform-the-reset $SERIAL $drvsno | |
elif [ $drvsnoc == 0 ]; then | |
echo "unable to find any drivers with this serial, strange" | |
echo "this tool was only ever tested on xhci_hcd … patches welcome" | |
else | |
echo "found more than one driver, please specify which you wish to try" | |
for d in "${drvsno[@]}"; do | |
echo $d | |
done | |
read -ep which: -i "${drvsno[0]}" driver | |
perform-the-reset $SERIAL $driver | |
fi | |
fi | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment