【问题标题】:(Linux) Get /dev/input/eventX from an attached USB device with PID:VID(Linux) 使用 PID:VID 从连接的 USB 设备获取 /dev/input/eventX
【发布时间】:2011-10-07 00:29:18
【问题描述】:

所以我的守护进程会坐在那里听 udev,等待连接/断开连接事件,以便通知其他线程附加或停止读取 /dev/input/eventX 文件。

本质上,它正在侦听连接到本地系统(模拟 HID 键盘)的 USB RFID 扫描仪。

现在我已经让 /dev/input/eventX 读取代码运行了 - 但由于我线程化了它,UDEV 线程崩溃了。

从已知 USB 设备(如 VID:PID)获取正确的 /dev/input/eventX 设备的最佳方法是什么?

【问题讨论】:

    标签: c linux events input libusb


    【解决方案1】:

    您可以添加一个 udev 规则,该规则运行一个脚本来通知您的程序,或者为您提供一个指向具有可预测名称的设备的符号链接。快速搜索出现了this page,解释了如何创建规则。

    【讨论】:

    • 这正是我在相同情况下所做的 - 如果 VID:PID 正确,则使用 udevd 规则创建指向事件设备的符号链接。
    【解决方案2】:

    好吧,代码崩溃是完全由其他原因造成的(vfprintf 与 fprintf)——无论如何,从 172 版开始的 libudev 有一个漂亮的小功能,即在枚举设备时,它会自动将搜索(枚举)绑定到单个父项并且只返回它的孩子:

    udev_enumerate_add_match_parent()
    

    我已经编写了通过 VID/PID 查找 hidraw 设备的代码:

    /sys/devices/pci000xyz/000.000.XYZ/usbX/X-Y
    

    我只是在等待该 udev 版本与 Ubuntu Natty 一起简化,因为那时我将创建一个新的枚举并将我在上一个枚举中找到的 udev_device 交给它并获取它的所有子项;包括我想要的子设备:

    /sys/devices/pci000xyz/000.000.XYZ/usbX/X-Y/X-Y:A.B/input/inputX/eventY
    

    与此同时,我将按照建议进行操作并创建一个符号链接 - 干杯 Dmitri。

    【讨论】:

      【解决方案3】:

      看这个文件:/proc/bus/input/devices

      文件中的示例行:

      I: Bus=0003 Vendor=1a2c Product=0c23 Version=0110
      N: Name="USB USB Keyboard"
      P: Phys=usb-0000:00:14.0-3/input0
      S: Sysfs=/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.0/0003:1A2C:0C23.0015/input/input30
      U: Uniq=
      H: Handlers=sysrq kbd event10 
      B: PROP=0
      B: EV=120013
      B: KEY=1000000000007 ff800000000007ff febeffdff3cfffff fffffffffffffffe
      B: MSC=10
      B: LED=7 
      

      此函数从具有匹配 VID:PID 的设备中获取事件编号:

      #include <string>
      #include <iostream>
      #include <fstream>
      
      void open_device (std::string device_vid, std::string device_pid)
      {       
          try
          {
              std::ifstream file_input;
              std::size_t pos;
              std::string device_path, current_line, search_str, event_str;
              std::string device_list_file = "/proc/bus/input/devices";
              bool vid_pid_found = false;
              int fd = 0;
              bool debug = true;
      
              // 1. open device list file
              file_input.open(device_list_file.c_str());
              if (!file_input.is_open())
              {
                  std::cerr << "file_input.open >> " << std::strerror(errno) << std::endl;
                  throw -2;
              }
      
              // 2. search for first VID:PID and get event number
              search_str = "Vendor=" + device_vid + " Product=" + device_pid;
              while (getline(file_input, current_line))
              {
                  if (!vid_pid_found)
                  {
                      pos = current_line.find(search_str, 0);
                      if (pos != std::string::npos)
                      {
                          vid_pid_found = true;
                          search_str = "event";
                      }               
                  }
                  else
                  {
                      pos = current_line.find(search_str, 0);
                      if (pos != std::string::npos)
                      {
                          event_str = current_line.substr(pos);
                          // remove spaces from string
                          event_str.erase(std::remove(event_str.begin(), event_str.end(), ' '), event_str.end());
                          break;
                      }
                  }
              }
      
              // 3.  build device path
              device_path = "/dev/input/" + event_str;
              if (debug) std::cout << "device_path = " << device_path << std::endl;   
              // 4.  connect to device
              fd = open (device_path.c_str(), O_RDONLY);
              if (fd < 0)
              {
                  std::cerr << "open >> errno = " << std::strerror(errno) << std::endl;       
                  throw -3;
              }
          }
          catch (const std::exception &e)
          {
              std::cerr << "e.what() = " << e.what() << std::endl;
              throw -1;
          }
      
          return;
      }
      

      事件在插入时被枚举。ls /dev/input 在拔出 USB 设备之前和之后会显示不同的结果。

      【讨论】:

        猜你喜欢
        • 2018-04-03
        • 1970-01-01
        • 2023-03-22
        • 2015-01-30
        • 1970-01-01
        • 2020-10-02
        • 1970-01-01
        • 2020-06-26
        • 2011-03-20
        相关资源
        最近更新 更多