Проблемы с блокировкой чтения с использованием libudev в Linux - PullRequest
2 голосов
/ 29 апреля 2010

Мы используем следующую процедуру (в Linux, с libudev) для чтения данных с микроконтроллера PIC, настроенного как устройство HID USB. Данные отправляются только при нажатии или отпускании кнопки, подключенной к микроконтроллеру PIC.

В подпрограмме отсутствуют сообщения от контроллера PIC, и я подозреваю, что это потому, что приведенный ниже вызов 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;
}

Я уверен, что я делаю что-то не так, но я погуглил проблему и, похоже, не могу найти соответствующих ответов. Любая помощь будет принята с благодарностью - Thx.

1 Ответ

4 голосов
/ 29 апреля 2010

Причина, по которой poll продолжает указывать, что дескриптор файла доступен для чтения, заключается в том, что вы никогда не read() из него. ioctl() не считается read(). Предположительно, устройство предоставляет некоторые данные для чтения, даже если это всего лишь фиктивное значение, чтобы разбудить процесс пользовательского пространства.

...