27

I have a mouse that will stop working randomly. The solution is easy, unplug and replug. Is there a way I can do this via the command line though? Doing via command line has a few advantages.

  1. Doesn't wear out the connector.
  2. Faster.
  3. Saves me the trouble of crawling under my desk.
  4. Most important: prevents me from accidentally unplugging something else.

Plus I am curious how to do this.

OS is Debian 8.

Thanks!

2

5 Answers 5

17

Save the following to usbreset.c

/* usbreset -- send a USB port reset to a USB device */

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>

#include <linux/usbdevice_fs.h>


int main(int argc, char **argv)
{
    const char *filename;
    int fd;
    int rc;

    if (argc != 2) {
        fprintf(stderr, "Usage: usbreset device-filename\n");
        return 1;
    }
    filename = argv[1];

    fd = open(filename, O_WRONLY);
    if (fd < 0) {
        perror("Error opening output file");
        return 1;
    }

    printf("Resetting USB device %s\n", filename);
    rc = ioctl(fd, USBDEVFS_RESET, 0);
    if (rc < 0) {
        perror("Error in ioctl");
        return 1;
    }
    printf("Reset successful\n");

    close(fd);
    return 0;
}

The run the following commands in terminal:

  1. Compile the program:

    cc usbreset.c -o usbreset
    
  2. Get the Bus and Device ID of the USB device you want to reset:

    lsusb -t 
    
    Bus#  4  
    -Dev#   1 Vendor 0x1d6b Product 0x0001    
    -Dev#   3 Vendor 0x046b Product 0xff10
    
  3. Make our compiled program executable:

    chmod +x usbreset
    
  4. Execute the program with sudo privilege; make necessary substitution for <Bus> and <Device> ids as found by running the lsusb command:

    sudo ./usbreset /dev/bus/usb/004/003
    
    Resetting USB device /dev/bus/usb/004/003
    
    Reset successful
    

Source of above program: http://marc.info/?l=linux-usb&m=121459435621262&w=2

5
  • 1
    Does this effectively reset the power on the device and would therefore completely reset it without having to unplug and replug it in?
    – Jarryd
    Nov 16, 2015 at 23:55
  • This worked like a charm. Aug 18, 2016 at 23:33
  • If a program has opened a serial USB device(say, /dev/ttyUSB0 symlinked from /dev/myserialdevice as specified in /etc/udev/rules.d/mystuff.rules), and the device gets hung for some reason, is it then necessary to reset it with an ioctl() as above, or is it sufficient to simply close() and open() it again? Apr 4, 2017 at 11:40
  • 1
    @Jarryd see Alan's explanation in the link above: Note however, that reset followed by re-enumeration is _not_ the same thing as power-cycle followed by reconnect and re-enumeration.
    – ckujau
    Aug 12, 2017 at 17:43
  • Getting the following error: Error in ioctl: Is a directory
    – jumelet
    Nov 24, 2022 at 18:09
6

I've created a Python script that simplifies the whole process based on answers here: https://askubuntu.com/questions/645/how-do-you-reset-a-usb-device-from-the-command-line.

Save the script below as reset_usb.py or clone this repo: https://github.com/mcarans/resetusb/.

Usage:

python reset_usb.py help : Show this help

sudo python reset_usb.py list : List all USB devices

sudo python reset_usb.py path /dev/bus/usb/XXX/YYY : Reset USB device using path /dev/bus/usb/XXX/YYY

sudo python reset_usb.py search "search terms" : Search for USB device using the search terms within the search string returned by list and reset matching device

sudo python reset_usb.py listpci : List all PCI USB devices

sudo python reset_usb.py pathpci /sys/bus/pci/drivers/.../XXXX:XX:XX.X : Reset PCI USB device using path /sys/bus/pci/drivers/.../XXXX:XX:XX.X

sudo python reset_usb.py searchpci "search terms" : Search for PCI USB device using the search terms within the search string returned by listpci and reset matching device

#!/usr/bin/env python
import os
import sys
from subprocess import Popen, PIPE
import fcntl

instructions = '''
Usage: python reset_usb.py help : Show this help
       sudo python reset_usb.py list : List all USB devices
       sudo python reset_usb.py path /dev/bus/usb/XXX/YYY : Reset USB device using path /dev/bus/usb/XXX/YYY
       sudo python reset_usb.py search "search terms" : Search for USB device using the search terms within the search string returned by list and reset matching device
       sudo python reset_usb.py listpci : List all PCI USB devices
       sudo python reset_usb.py pathpci /sys/bus/pci/drivers/.../XXXX:XX:XX.X : Reset PCI USB device using path
       sudo python reset_usb.py searchpci "search terms" : Search for PCI USB device using the search terms within the search string returned by listpci and reset matching device       
       '''


if len(sys.argv) < 2:
    print(instructions)
    sys.exit(0)

option = sys.argv[1].lower()
if 'help' in option:
    print(instructions)
    sys.exit(0)


def create_pci_list():
    pci_usb_list = list()
    try:
        lspci_out = Popen('lspci -Dvmm', shell=True, bufsize=64, stdin=PIPE, stdout=PIPE, close_fds=True).stdout.read().strip().decode('utf-8')
        pci_devices = lspci_out.split('%s%s' % (os.linesep, os.linesep))
        for pci_device in pci_devices:
            device_dict = dict()
            categories = pci_device.split(os.linesep)
            for category in categories:
                key, value = category.split('\t')
                device_dict[key[:-1]] = value.strip()
            if 'USB' not in device_dict['Class']:
                continue
            for root, dirs, files in os.walk('/sys/bus/pci/drivers/'):
                slot = device_dict['Slot']
                if slot in dirs:
                    device_dict['path'] = os.path.join(root, slot)
                    break
            pci_usb_list.append(device_dict)
    except Exception as ex:
        print('Failed to list pci devices! Error: %s' % ex)
        sys.exit(-1)
    return pci_usb_list


def create_usb_list():
    device_list = list()
    try:
        lsusb_out = Popen('lsusb -v', shell=True, bufsize=64, stdin=PIPE, stdout=PIPE, close_fds=True).stdout.read().strip().decode('utf-8')
        usb_devices = lsusb_out.split('%s%s' % (os.linesep, os.linesep))
        for device_categories in usb_devices:
            if not device_categories:
                continue
            categories = device_categories.split(os.linesep)
            device_stuff = categories[0].strip().split()
            bus = device_stuff[1]
            device = device_stuff[3][:-1]
            device_dict = {'bus': bus, 'device': device}
            device_info = ' '.join(device_stuff[6:])
            device_dict['description'] = device_info
            for category in categories:
                if not category:
                    continue
                categoryinfo = category.strip().split()
                if categoryinfo[0] == 'iManufacturer':
                    manufacturer_info = ' '.join(categoryinfo[2:])
                    device_dict['manufacturer'] = manufacturer_info
                if categoryinfo[0] == 'iProduct':
                    device_info = ' '.join(categoryinfo[2:])
                    device_dict['device'] = device_info
            path = '/dev/bus/usb/%s/%s' % (bus, device)
            device_dict['path'] = path

            device_list.append(device_dict)
    except Exception as ex:
        print('Failed to list usb devices! Error: %s' % ex)
        sys.exit(-1)
    return device_list


if 'listpci' in option:
    pci_usb_list = create_pci_list()
    for device in pci_usb_list:
        print('path=%s' % device['path'])
        print('    manufacturer=%s' % device['SVendor'])
        print('    device=%s' % device['SDevice'])
        print('    search string=%s %s' % (device['SVendor'], device['SDevice']))
    sys.exit(0)

if 'list' in option:
    usb_list = create_usb_list()
    for device in usb_list:
        print('path=%s' % device['path'])
        print('    description=%s' % device['description'])
        print('    manufacturer=%s' % device['manufacturer'])
        print('    device=%s' % device['device'])
        print('    search string=%s %s %s' % (device['description'], device['manufacturer'], device['device']))
    sys.exit(0)

if len(sys.argv) < 3:
    print(instructions)
    sys.exit(0)

option2 = sys.argv[2]

print('Resetting device: %s' % option2)


# echo -n "0000:39:00.0" | tee /sys/bus/pci/drivers/xhci_hcd/unbind;echo -n "0000:39:00.0" | tee /sys/bus/pci/drivers/xhci_hcd/bind
def reset_pci_usb_device(dev_path):
    folder, slot = os.path.split(dev_path)
    try:
        fp = open(os.path.join(folder, 'unbind'), 'wt')
        fp.write(slot)
        fp.close()
        fp = open(os.path.join(folder, 'bind'), 'wt')
        fp.write(slot)
        fp.close()
        print('Successfully reset %s' % dev_path)
        sys.exit(0)
    except Exception as ex:
        print('Failed to reset device! Error: %s' % ex)
        sys.exit(-1)


if 'pathpci' in option:
    reset_pci_usb_device(option2)


if 'searchpci' in option:
    pci_usb_list = create_pci_list()
    for device in pci_usb_list:
        text = '%s %s' % (device['SVendor'], device['SDevice'])
        if option2 in text:
            reset_pci_usb_device(device['path'])
    print('Failed to find device!')
    sys.exit(-1)


def reset_usb_device(dev_path):
    USBDEVFS_RESET = 21780
    try:
        f = open(dev_path, 'w', os.O_WRONLY)
        fcntl.ioctl(f, USBDEVFS_RESET, 0)
        print('Successfully reset %s' % dev_path)
        sys.exit(0)
    except Exception as ex:
        print('Failed to reset device! Error: %s' % ex)
        sys.exit(-1)


if 'path' in option:
    reset_usb_device(option2)


if 'search' in option:
    usb_list = create_usb_list()
    for device in usb_list:
        text = '%s %s %s' % (device['description'], device['manufacturer'], device['device'])
        if option2 in text:
            reset_usb_device(device['path'])
    print('Failed to find device!')
    sys.exit(-1)
0

You can always reset the USB stack via software, and also put USB devices into sleep (power saving) mode, but this does not affect the +5V port power, which is always on.

Depending on your USB hub, you may or may not be able to actually turn off (cycle) the power to a physical USB port.

Only "smart" USB hubs allow per-port power cycling. Here is a small project that allows you to control these.

0

I've also written a python script in order to reset USB devices, inspired from various authors on stackoverflow and stackexchange.

I've tried various methods (disconnect/reconnect/bind/unbind/reset signal). Best so far are bind/unbind as it forces a cold restart of the device (but no power cycle).

I came up with a solution to reset USB devices, ports and controllers in a python script, which supports all of the above methods. You can find the script at my Github page

Usage:

usb_reset.py -d 8086:1001 --reset-hub

The script uses among others the following solution to reset USB hubs/controllers:

Unbindind a USB port / controller works best via:

echo "myhub" > "/sys/bus/usb/drivers/usb/unbind"
echo "myhub" > "/sys/bus/usb/drivers/usb/bind"

Where myhub is found in /sys/bus/usb/devices/*

Or litteral controllers:

echo "mycontroller" > "/sys/bus/pci/drivers/unbind"
echo "mycontroller" > "/sys/bus/pci/drivers/bind"

Where mycontroller is found in /sys/bus/pci/drivers/[uoex]hci_hcd/*:*

0

For a USB storage device, it was much simpler. Just figured it out and leaving this here, in case someone else ends up in this thread, too, and finds it useful:

  1. Find out bus, port and device:

    $ sudo dmesg --ctime | grep usb-storage
    [Mon Feb 27 10:27:05 2023] usb-storage 3-1:1.0: USB Mass Storage device detected
    [Mon Feb 27 10:27:05 2023] scsi host4: usb-storage 3-1:1.0
    [Mon Feb 27 10:27:05 2023] usbcore: registered new interface driver usb-storage
    

    In this example, we would be looking for 3-1:1.0. Obviously, you will see more than one entry if you have (or had) more than one USB storage device connected. The timestamp should help you figure out which device you're looking for. Otherwise, lsusb -t could also be helpful.

  2. Unbind and bind again:

    $ usb=3-1:1.0
    $ printf %s\\n "$usb" | sudo tee /sys/bus/usb/drivers/usb-storage/unbind
    3-1:1.0
    $ printf %s\\n "$usb" | sudo tee /sys/bus/usb/drivers/usb-storage/bind
    3-1:1.0
    

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .