linux - 在 Linux 上使用 libudev 阻止读取的问题

标签 linux hid udev

我们使用以下例程(在 Linux 上,使用 libudev)从配置为 USB HID 设备的 PIC 微 Controller 读取数据。仅当按下或释放连接到 PIC 单片机的按钮时才会发送数据。

例程缺少来自 PIC Controller 的消息,我怀疑这是因为下面对 poll 的调用没有按其应有的方式运行。

在读取第一条消息之前,对 poll 的调用将可靠地阻塞 1 秒。一旦读取到第一条消息,对 poll 的调用就会立即返回,而不是像应有的那样阻塞 1 秒(1000 毫秒)。

我通过在每次读取后关闭并重新打开设备来解决这个问题。这使得轮询行为正确,但我认为关闭并重新打开设备可能是丢失消息的原因。

bool PicIo::Receive (unsigned char* picData, const size_t picDataSize) {

    static hiddev_report_info     hidReportInfo;
    static hiddev_usage_ref_multi hidUsageRef;

    if (-1 == PicDeviceDescriptor()) {
        return false;
    }

    // Determine whether or not there is data available to be read
    pollfd pollFd;

    pollFd.fd = PicDeviceDescriptor();
    pollFd.events = POLLIN;

    int dataPending = poll (&pollFd, 1, 1000);

    if (dataPending <= 0) {
        return false;
    }  


    // Initialize the HID Report structure for an input report
    hidReportInfo.report_type = HID_REPORT_TYPE_INPUT;
    hidReportInfo.report_id   = 0;
    hidReportInfo.num_fields  = 64;

    if (-1 == ioctl(PicDeviceDescriptor(), HIDIOCGREPORT, &hidReportInfo)) {
        return false;
    }

    // Initizlize the HID Usage Reference for an Input report
    hidUsageRef.uref.report_type = HID_REPORT_TYPE_INPUT;
    hidUsageRef.uref.report_id   = 0;
    hidUsageRef.uref.field_index = 0;
    hidUsageRef.uref.usage_index = 0;
    hidUsageRef.num_values       = 64;

    if (-1 == ioctl(PicDeviceDescriptor(), HIDIOCGUSAGES, &hidUsageRef)) {
        return false;
    }

    // Transfer bytes from the usage report into the return value.
    for (size_t idx=0; (idx < 64) && (idx < picDataSize); ++idx) {
        picData[idx] = hidUsageRef.values[idx];
    }

    return true;
}

函数 PicDeviceDescriptor() 会检查设备以确保它存在。以下是 PicDeviceDescriptor 函数的相关详细信息,显示了如何开始打开设备。

int PicIo::PicDeviceDescriptor(int command) {

    struct stat     statInfo;
    static int      picDeviceDescriptor = -1;
    string          picDevicePath       = "/dev/usb/hiddev0";

    if ((-1 != picDeviceDescriptor) && (CLOSE == command)) {
        close (picDeviceDescriptor);
        picDeviceDescriptor = -1;
    } else if ((-1 != picDeviceDescriptor) && (-1 == fstat(picDeviceDescriptor, &statInfo))) {
        // Handle the case where the PIC device had previously been detected, and
        // is now disconnected.
        close (picDeviceDescriptor);
        picDeviceDescriptor = -1;
    } else if ((-1 == picDeviceDescriptor) && (m_picDevice.IsConnected())) {
        // Create the PIC device descriptor if the PIC device is present (i.e. its 
        // device node is present) and if the descriptor does not already exist
        picDeviceDescriptor = open (picDevicePath.c_str(), O_RDONLY);
    }

    return picDeviceDescriptor;
}

我确信我做错了什么,但我用 Google 搜索了这个问题,但似乎找不到任何相关答案。任何帮助将非常感激 - 谢谢。

最佳答案

poll 持续指示文件描述符可读的原因是您从未read() 从中读取。 ioctl() 不算作 read()。据推测,设备会提供一些数据可供读取 - 即使它只是唤醒用户空间进程的虚拟值。

关于linux - 在 Linux 上使用 libudev 阻止读取的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2734143/

相关文章:

linux - 允许特定供应商拇指驱动器的 udev 规则是什么?

linux - udev - += 和 := 之间的区别

mount - 如何在使用 UDEV 挂载设备后运行 shell 脚本

linux - 阻止构建管道的 Teamcity 构建代理

Linux 脚本 while 循环 "-a"

java - 创建名称为 '/' 的目录

ubuntu - SDL2 看不到操纵杆,但操作系统可以

c - 如何在客户端应用程序中使用 "control endpoint"(默认端点)?

linux - 如何grep一个文件并输出一行的匹配部分以及周围的一些单词?

macos - 如何从 Mac OSX 弹出 USB HID 设备以在 Ubuntu VM 中使用?