Unplug and plug in again a USB device in the terminal

I wrote a script to show how I’d do that:

#!/bin/bash

port="1-1.1" # as shown by lsusb -t: {bus}-{port}(.{subport})

bind_usb() {
  echo "$1" >/sys/bus/usb/drivers/usb/bind
}

unbind_usb() {
  echo "$1" >/sys/bus/usb/drivers/usb/unbind
}

unbind_usb "$port"
# sleep 1 # enable delay here
bind_usb "$port"

First you need to get the bus and port number of the usb port in question. You can do that with lsusb and any device you recognize in lsusb’s output, I use a Sandisk pendrive here:

$ lsusb
Bus 001 Device 005: ID 04f2:b39a Chicony Electronics Co., Ltd 
Bus 001 Device 112: ID 8087:07dc Intel Corp. 
Bus 001 Device 019: ID 04d9:1603 Holtek Semiconductor, Inc. Keyboard
Bus 001 Device 018: ID 0424:2504 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 022: ID 0781:5567 SanDisk Corp. Cruzer Blade
Bus 001 Device 002: ID 8087:8000 Intel Corp. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
$ lsusb -t
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/3p, 480M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/8p, 480M
        |__ Port 1: Dev 22, If 0, Class=Mass Storage, Driver=usb-storage, 480M
        |__ Port 2: Dev 18, If 0, Class=Hub, Driver=hub/4p, 480M
            |__ Port 1: Dev 19, If 1, Class=Human Interface Device, Driver=usbhid, 1.5M
            |__ Port 1: Dev 19, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
        |__ Port 7: Dev 112, If 0, Class=Wireless, Driver=btusb, 12M
        |__ Port 7: Dev 112, If 1, Class=Wireless, Driver=btusb, 12M
        |__ Port 8: Dev 5, If 1, Class=Video, Driver=uvcvideo, 480M
        |__ Port 8: Dev 5, If 0, Class=Video, Driver=uvcvideo, 480M

From the output of lsusb you get the bus and device number of the device, then search this device in the output of lsusb -t to get the bus and port number (sometimes with subports). The syntax is:

1-2.3 # for Bus 1 Port 2 Subport 3 – strip leading zeroes!

Use this as port in the script. Now you just need to make it executable with chmod +x /path/to/script and run it with root permissions:

sudo /path/to/script

I didn’t need one for my pendrive, but it may be necessary for you to add a delay between unbinding and binding again, that’s what the commented out sleep 1 line is for – you can experiment with the values, e.g. sleep 0.5 for half a second.

Note that this approach shows how to disable and enable again a certain USB port, if you want a specific device to be unbound and rebound again you’ll have to use the same USB port for this to work. One could think of a way to parse lsusb’s output to dynamically get the bus and port number of a specific device every time the script is called, this would allow you to use any USB port, but I feel that would be an overkill here.

Suggestions taken from this linux.com blog article.


#!/bin/bash

port="usb1" # replace '1' with actual bus number as shown by lsusb -t: {bus}-{port}(.{subport})

bind_usb() {
  echo "$1" >/sys/bus/usb/drivers/usb/bind
}

unbind_usb() {
  echo "$1" >/sys/bus/usb/drivers/usb/unbind
}

unbind_usb "$port"
# sleep 1 # enable delay here
bind_usb "$port"

Similarly to previous answers, this will reset the hub. If you observe the usb traffic in a program such as wireshark, you'll see that the previous answers don't cause the device to be re-enumerated, but simply restart the device driver. Restarting the hub goes a little deeper in the usb tree of the kernel and forces the device to completely re-enumerate.


you can also use ioctl to send a reset to the device in question - assuming it's still responsive

   /* 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;
}

you would call like this

sudo ./usbreset /dev/bus/usb/002/004

not my code, but I don't know who to attribute to