Read lock problems using libudev on Linux

We use the following procedure (on Linux, with libudev) to read data from a PIC microcontroller configured as a USB HID device. Data is sent only when you press or release a button connected to the PIC microcontroller.

There are no messages from the PIK controller in the procedure, and I suspect this is because the poll call below is not behaving as it should.

The poll call will block securely for 1 second if the first message is read. Once the first message is read, the poll call returns immediately, rather than blocking for 1 second (1000 milliseconds) as it should.

I worked around this issue by closing and reopening the device after every read. This makes polling correct, but I think that closing and reopening the device might be causing the lost messages.

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

      

The PicDeviceDescriptor () function performs validation on the device to make sure it is present. The following are the relevant details for the PicDeviceDescriptor function showing how the device will start to open.

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

      

I'm sure I am doing something wrong, but I have a problem with Google and cannot find any suitable answers. Any help would be much appreciated - thanks.

+2


a source to share


1 answer


The reason it poll

keeps indicating that the file descriptor is readable is because you never go read()

from it. ioctl()

does not count read()

. Presumably the device allows some data to be read - even if it's only a bogus value to wake up a user-space process.



+4


a source







All Articles