在 C Linux 上检查某个 USB 端口以获取设备 fd

Posted

技术标签:

【中文标题】在 C Linux 上检查某个 USB 端口以获取设备 fd【英文标题】:Check certain USB port to get device fd on C Linux 【发布时间】:2017-10-27 14:01:18 【问题描述】:

我正在编写一个程序来检查每个/dev/input/eventX 并使用 ioctl 我可以获得它的功能并检查它是什么(鼠标、键盘、触摸屏)。

现在我需要检查某个 USB 输出(端口)是否连接了设备,我打开它并执行与 /dev/input/eventX 相同的操作。 我在/sys/bus/usb/devices/ 中找到了一些符号链接,这似乎是关于 USB 端口的存储信息,但我不确定。我尝试使用 libudev 打开它,但它会查找子系统“USB”中的所有文件,但我只需要 /sys/bus/usb/devices/3-2/

我需要什么:

    检查某些 USB 端口(仅检查我在定义或通过命令行的某处硬编码的端口) 如果设备连接在上面,打开 dev 的 fd 并使用 ioctl 获取信息 如果它(例如鼠标)程序开始工作,否则它说找不到设备...

如何做就足够了,我不需要完整的代码。

只需要普通的 C 就可以使用像 libudev 这样的库

【问题讨论】:

考虑在 D-Bus 上监听连接事件。 你试过在/dev/input目录上监听inotify通风口吗? 感谢您的建议,我尝试一下... ionify 表示监听所有事件,但我只需要某些 USB,可能是错误的,需要阅读 man 【参考方案1】:

我找到了一个适合我的任务的解决方案,可能对某人也有帮助,所以我把这个例子留在这里。 我使用libudev库

我找了一些例子并稍作修改:

1) 创建枚举并添加您的子系统:

enumerate = udev_enumerate_new(udev);
udev_enumerate_add_match_subsystem(enumerate, "input");

您可以在我没有看到input 的那个文件夹中查找ls /sys/class 中的子系统,但只需尝试添加它的工作即可。

2) 使用 foreach 获取列表条目和列表:

list = udev_enumerate_get_list_entry(enumerate);

    udev_list_entry_foreach(node, list) 
    
        char *str = NULL;
        path = udev_list_entry_get_name(node);
        dev = udev_device_new_from_syspath(udev, path);
        if  (str = strstr(path, REQUESTED_USB_PORT))
        
             if (str = strstr(str, "event"))
             
                  dev_path = strdup(udev_device_get_devnode(dev));
                  udev_device_unref(dev);
                  break;
             
        
        udev_device_unref(dev);
    

所以在这里我们会收到类似这样的路径:

/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.6/1-1.6:1.0/0003:046D:C31C.0005/input/input9
/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.6/1-1.6:1.0/0003:046D:C31C.0005/input/input9/event6

为什么我给你看两条路?因为正如你所看到的,它返回的字符串看起来一样,但我们只需要一个,在哪里显示 eventX。REQUESTED_USB_PORT 它是一个带有端口的定义,你需要在我的情况下检查"1-1.6:1.0"

有很多方法可以找到你需要的端口我停在cat /proc/bus/input/devices

它显示每个设备的输出:

I: Bus=0003 Vendor=046d Product=c31c Version=0110
N: Name="Logitech USB Keyboard"
P: Phys=usb-0000:00:1a.0-1.6/input0
S: Sysfs=/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.6/1-1.6:1.0/0003:046D:C31C.0005/input/input9
U: Uniq=
H: Handlers=sysrq kbd event6 leds 
B: PROP=0
B: EV=120013
B: KEY=1000000000007 ff9f207ac14057ff febeffdfffefffff fffffffffffffffe
B: MSC=10
B: LED=1f

另一个步骤是获取/dev/input/eventX,您可以使用udev_device_get_devnode() 函数获取它,该函数返回带有路径的字符串。

所以我写了我的get_devinfo_fromusb() 和上面发布的代码,如果不是NULL,则返回字符串/dev/input/eventXNULL 我这样做:

调用另一个函数并将 device_path 作为参数传递

int get_dev_type(char *dev_event_path)

    int dev_fd;
    unsigned long eventBits = 0;

    if ((dev_fd = open(dev_event_path, O_RDONLY)) < 0)
    
        puts("Dont have access to open file %s");
        puts("Run as root");
        exit(1);
    
    ioctl(dev_fd, EVIOCGBIT(0, EV_MAX), &eventBits);

    if (((eventBits >> EV_KEY) & 1) &&
        ((eventBits >> EV_SYN) & 1) &&
        ((eventBits >> EV_REL) & 1) &&
        ((eventBits >> EV_MSC) & 1)) 
        puts("look like mouse");
        close(dev_fd);
        return (MOUSE_TYPE);
    

    if (((eventBits >> EV_KEY) & 1) &&
        ((eventBits >> EV_LED) & 1) &&
        ((eventBits >> EV_REP) & 1)) 
        puts("looks like kbd");
        close(dev_fd);
        return (KBD_TYPE);

我认为这些小例子足以弄清楚发生了什么。因此,您可以检查某些 USB 端口并获取有关该设备(鼠标或键盘)的信息,您还可以检查耳机触摸屏等。

【讨论】:

以上是关于在 C Linux 上检查某个 USB 端口以获取设备 fd的主要内容,如果未能解决你的问题,请参考以下文章

Linux如何查询哪些端口被占用

Linux如何查询哪些端口被占用

Linux如何查询哪些端口被占用

使用PowerShell从com端口获取Linux设备IP地址

Linux笔记(固定USB摄像头硬件端口,绑定前后置摄像头)

linux / libusb 获取usb设备路径