2

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

该例程缺少来自 PIC 控制器的消息,我怀疑这是因为下面的 poll 调用没有正常运行。

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

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

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;
}

我确定我做错了什么,但我已经用谷歌搜索了这个问题,似乎找不到任何相关的答案。任何帮助将不胜感激——谢谢。

4

1 回答 1

4

poll继续表明文件描述符是可读的原因是您永远不会read()从中读取。 ioctl()不算作read()。据推测,该设备可以读取一些数据 - 即使它只是唤醒用户空间进程的虚拟值。

于 2010-04-29T02:56:37.990 回答