我们使用以下例程(在 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/