首页 > 解决方案 > 在 Linux 中无需拔出即可软重置 USB 设备

问题描述

问题: 我有 USB 设备连接到远程 linux 机器。我想使用文件描述符重置它们。

我使用通用端口名称连接到一个端口/dev/usbTTYXX。不幸的是,我很快发现这是一种不好的方法,因为它们是按顺序生成的。如果我首先插入一个 tty 设备,它将生成ttyUSB0,如果我插入第二个 tty 设备,它将生成TTYUSB1,依此类推。不幸的是,我有太多不同的ttyUSB设备和其他破坏此顺序的设备。简而言之,它只是对用户不友好,是一场噩梦。我发现最好使用/dev/serial/by-id. 这是最好的选择,因为它们看起来非常独特,即使在重新启动后也不会改变,尽管插入 USB 的顺序也会重新启动。

所以我可以像这样以更健壮的方式打开一个端口。(我什至为此有一个json)

// 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);

无论我重新连接多少,USB 设备都不会改变(与 /dev/ttyUSB0 不同)。无论如何,我发现这段代码可能会对设备执行软重置,所以我不需要重新插入它。这是源代码

如果我使用这个文件描述符/dev/bus/usb/001/010,它就可以工作。/dev/bus/usb/XXX/YYY其中 XXX 是总线号(在 Pi 上几乎总是 001),YYY 是设备号(从 lsusb 获取这两个)。同样 lsusb 似乎也经常变化。(更麻烦的是,我有类似的 USB 设备适配器使用相同的产品和供应商 ID!)

但是,如果我使用/dev/ttyUSB0或通过 id 使用/dev/serial/by-id/. 我得到的错误是Error in ioctl: Inappropriate ioctl for device..

问题:如何将 ioctrl USBDEVFS_RESET 方法与 /dev/serial/by-id/文件 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;
}

标签: c++linuxioctl

解决方案


推荐阅读