Soft Reset USB Device Without Unplugging in Linux

Viewed 1038

Problem: I have USB devices connected to a remote linux machine. I would like to reset them using file descriptors.

I connect to a port using generic port names in /dev/usbTTYXX. Unfortunately, I quickly found out this was a bad approach as these are generated in order. If I plugged in a tty device first it will generate ttyUSB0 and if I plugin a second tty device it will generate TTYUSB1 and so on. Unfortunately I have too many different ttyUSB devices and others that break this order. In short its just not user friendly and is a nightmare. I found that it is better to open a port using specific simlink file descriptors in /dev/serial/by-id. This is best preferred since they seem very unique and do not change even after restart, reboot despite order of USB plugged in.

So I can open a port in a more robust way like so. (I even have a json for this)

// old
int serial_port = open("/dev/ttyUSB1", O_RDWR | O_NOCTTY);
// new
int serial_port = open("/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AC00MET6-if00-port0", O_RDWR | O_NOCTTY);

No matter how much I reconnect, the USB device will not change (unlike /dev/ttyUSB0). Anyways I found this code that potentially performs a soft-reset to a device so I do not need to replug it in. Here is the source:

If I use this file descriptor /dev/bus/usb/001/010 it works. /dev/bus/usb/XXX/YYY where XXX is the bus number (nearly always 001 on the Pi) and YYY is the device number (get both of these from lsusb). Again lsusb also seems to change quite often. (Even more troublesome, I have similar device adapters for the USB which use the same Product and Vendor ID!)

However it will not work if I use /dev/ttyUSB0 or by id with /dev/serial/by-id/. The error I get is Error in ioctl: Inappropriate ioctl for device..

Question: How can I use the ioctrl USBDEVFS_RESET method with the /dev/serial/by-id/ file simlinks?

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