Skip to content

Instantly share code, notes, and snippets.

@cheeseonamonkey
Last active November 10, 2023 00:20
Show Gist options
  • Save cheeseonamonkey/0ec66cf19cf11189283c1603a2522b76 to your computer and use it in GitHub Desktop.
Save cheeseonamonkey/0ec66cf19cf11189283c1603a2522b76 to your computer and use it in GitHub Desktop.
power_cycle_usb devices programatically (unplug, wait a short moment, then plug it back in; originally for use troubleshooting mobile tethering)
power_cycle_usb() {
# Check if no arguments are passed
if [[ $# -eq 0 ]]; then
power_cycle_usb -h;
return;
fi;
# Define local variables
local quiet=false verbose=false help=false sleep_time=0.5 wait_finish=true choice=false device
local RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' BLUE='\033[0;34m' NC='\033[0m'
# Parse command line options
while getopts "qvhs:bc" opt; do
case ${opt} in
q) quiet=true ;;
v) verbose=true ;;
h) help=true ;;
s) sleep_time=$OPTARG ;;
b) wait_finish=false ;;
c) choice=true ;;
\?) echo "Invalid option -$OPTARG" >&2 ;;
esac
done
shift $((OPTIND -1))
device=$1
# Display help message if -h option is passed
if $help; then
echo -e " Usage: power_cycle_usb ${RED}[-v]${NC} ${GREEN}[-s <seconds>]${NC} ${YELLOW}[-b]${NC} ${BLUE}[-c|device]${NC} (${RED}V${NC}erbose, ${GREEN}S${NC}leep, ${YELLOW}B${NC}ackground, ${BLUE}C${NC}hoice)
Examples:
${CYAN}power_cycle_usb ${RED}-v${NC}$GREEN -s 2$NC $BLUE 1-2:3-4$NC
${CYAN}power_cycle_usb $RED-q$NC $BLUE-c${NC}
${CYAN}power_cycle_usb $YELLOW-b$BLUE 2-1:5-6${NC}
"
return
fi
# Allow user to select a device if -c option is passed
if $choice; then
echo "Select a device (check lsusb):"
select device_option in $(lsusb | awk '{print $2 "-" $4}' | tr -d ':'); do
device=$(echo $device_option | awk -F '-' '{print $1 "-" $2}')
break
done
fi
# Check if device is specified
if [[ -z $device ]]; then
echo "Error: No device specified."
return
fi
# Check if device exists
if ! lsusb | grep -q "$device"; then
echo "Error: Device $device does not exist."
return
fi
# Display verbose output if -v option is passed
if $verbose; then
echo "Device: $device"
echo "Sleep time: $sleep_time"
echo "Wait for finish: $wait_finish"
fi
# Power cycle the USB device
{
if ! $quiet; then echo "Unplugging $device..."; fi
if echo $device | sudo tee /sys/bus/usb/drivers/usb/unbind; then
sleep $sleep_time
if ! $quiet; then echo "Pluggin in $device..."; fi
if ! echo $device | sudo tee /sys/bus/usb/drivers/usb/bind; then
echo "Error: Failed to power on $device."
return
fi
else
echo "Error: Failed to power off $device."
return
fi
} &
# Wait for the power cycle to finish if -b option is not passed
if $wait_finish; then
wait
fi
}
run_tests() {
# Define color codes
local GREEN='\033[0;32m'
local RED='\033[0;31m'
local NC='\033[0m' # No Color
# ASCII border
echo
hr '_'
echo
echo "| Running Unit Tests |"
hr '_'
echo
echo
function hr {
cols=$(tput cols)
printf '%*s\n' "${cols}" '' | tr ' ' "$1\r"
}
# Test 1: Help message
echo "Test 1: Help message"
power_cycle_usb -h && echo -e "\n${GREEN}Test 1 \npassed${NC}" || echo -e "${RED}Test 1 failed${NC}"
hr '_'
echo -n "press enter to continue...\r"
read
echo
# Test 2: Verbose output with sleep time
echo "Test 2: Verbose output with sleep time"
power_cycle_usb -v -s 1 1-2:3-4 && echo -e "\n${GREEN}Test 2 \npassed${NC}" || echo -e "${RED}Test 2 failed${NC}"
hr '_'
echo -n "press enter to continue...\r"
read
echo
# Test 3: Quiet output with device choice
echo "Test 3: Quiet output with device choice"
power_cycle_usb -q -c && echo -e "\n${GREEN}Test 3 \npassed${NC}" || echo -e "${RED}Test 3 failed${NC}"
hr '_'
echo -n "press enter to continue...\r"
read
echo
# Test 4: Background execution with device specified
echo "Test 4: Background execution with device specified"
power_cycle_usb -b 2-1:5-6 && echo -e "\n${GREEN}Test 4 \npassed${NC}" || echo -e "${RED}Test 4 failed${NC}"
hr '_'
echo -n "press enter to continue...\r"
read
echo
# Test 5: Invalid option
echo "Test 5: Invalid option"
power_cycle_usb -x && echo -e "\n${GREEN}Test 5 \npassed${NC}" || echo -e "${RED}Test 5 failed${NC}"
hr '_'
echo -n "press enter to continue...\r"
read
echo
# Test 6: No device specified
echo "Test 6: No device specified"
power_cycle_usb && echo -e "\n${GREEN}Test 6 \npassed${NC}" || echo -e "${RED}Test 6 failed${NC}"
hr '_'
echo -n "press enter to continue...\r"
read
echo
# Test 7: Non-existent device
echo "Test 7: Non-existent device"
power_cycle_usb 3-4:5-6 && echo -e "\n${GREEN}Test 7 \npassed${NC}" || echo -e "${RED}Test 7 failed${NC}"
hr '_'
echo -n "press enter to continue...\r"
read
echo
# ASCII border
echo "+----------------------------------------------------+"
echo "| Unit Tests Completed |"
echo "+----------------------------------------------------+"
echo
}
# Run the tests
run_tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment