代码之家  ›  专栏  ›  技术社区  ›  Nick S Arnold

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

  •  1
  • Nick S Arnold  · 技术社区  · 7 年前

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

    现在,我需要检查某些USB输出(端口),如果设备连接在它上面,我打开它,然后用同样的方法操作 /开发/输入/事件X . 我发现了一些符号链接 /sys/bus/usb/devices/ 这似乎是关于USB端口的存储信息,但我不确定。我试着用 libudev 但它在子系统“USB”中查找所有文件,但我只需要例如 /sys/bus/usb/devices/3-2/

    我需要:

    1. 检查某些USB端口(仅限于我在define中硬编码的端口,或通过命令行传递的端口)
    2. 如果设备连接在其上,则打开dev的fd并使用ioctl获取信息
    3. 如果它(例如鼠标)的程序开始工作,否则它会说该设备未找到。。。

    这将是足够的描述如何做到这一点,我不需要完整的代码。

    只需要普通C就可以使用libudev之类的库

    1 回复  |  直到 7 年前
        1
  •  3
  •   Nick S Arnold    7 年前

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

    我找到了一些例子,并对其进行了一些修改:

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

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

    您可以在中查找子系统 ls /sys/class input 但只要试着添加一个its工作。

    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() 使用代码i post,返回字符串 /开发/输入/事件X NULL 如果没有 无效的 我会这样做:

    调用另一个函数并将device\u 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端口,并获得有关该设备(鼠标或键盘)的信息,你还可以检查耳机触摸屏等。