2016-12-13 4 views
0

В настоящее время я работаю с устройством HID. Он имеет два режима настройки: HID и RS232. Так что я написал небольшой скрипт для переключения его на RS232, когда он подключен как HID устройство, используя это правило Udev:Неожиданное поведение ioctl на символических ссылках

ENV{ID_VENDOR}=="Vendor", ENV{ID_VENDOR_ID}=="001d", ENV{ID_USB_DRIVER}=="usbhid",\ 
SYMLINK+="hid_device", RUN+="/path/to/HID_to_serial" 

Сценарий следующим образом:

// HID_to_serial.c 
#include <errno.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/ioctl.h> 
#include <unistd.h> 

//#define DEFAULT_DEVICE_PATH "/dev/hidraw0" 
#define DEFAULT_DEVICE_PATH  "/dev/hid_device" 

int main(int argc, char **argv) 
{ 
    int fd = open(DEFAULT_DEVICE_PATH, O_RDWR); 

    if (fd < 0) 
    { 
     perror("Unable to open device"); 
     return 1; 
    } 

    // Very specific report descriptor 
    const char buf[64] = { 0x02, 0x0b, 0x02, 0x04, 0x42, 0x40, 0x10, 0x42, 
          0x62, 0x10, 0x42, 0x42, 0x03, 0x00, 0x00, 0x00, 
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 

    int res = ioctl(fd, _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, 64), buf); 
    if (res < 0) 
     perror("ioctl"); 
    else 
     printf("Device was succesfully switched back to serial mode!\n"); 

    return 0; 
} 

Сейчас, как правило, когда Я подключаю устройство, Linux дает ему файл /dev/hidraw0. И когда я использую свой скрипт на /dev/hidraw0, он отлично работает. Дескриптор отчета, используемый в скрипте, является правильным, и все работает по назначению: устройство HID переключается обратно в режим RS232.

Однако, когда я пытаюсь использовать мой сценарий на /dev/hid_device линке, созданный по правилу udev, он не работает 99% времени, говоря мне ioctl: Invalid argument. Еще страннее то, что он работает, но 1% времени (может быть, даже реже).

Есть ли у кого-нибудь идеи, откуда это может произойти, и как его исправить или обойти? Заранее спасибо.

ответ

0

Я нашел проблему.

Оно лежит в моем правиле udev: оно недостаточно точное.

Когда я подключить устройство, линукс создает два character special файлы устройств в /dev/: hidraw0 и input/event15 (в моем случае). Они разделяют множество значений среды, например, их ID_VENDOR_ID или их ID_USB_DRIVER. Однако они не имеют одинаковых MAJOR.

Так что я сделал, добавлял ENV{MAJOR}=="correct_major" в мое правило udev, и теперь моя символическая ссылка связана с правильным файлом устройства.

Он также объясняет, почему он работал иногда: я предполагаю, что из-за отсутствия деталей в правиле udev иногда символическая ссылка была связана с правильным файлом устройства, иногда нет.

Смежные вопросы