2016-12-13 2 views
0

Je travaille actuellement avec un périphérique HID. Il a deux modes de configuration: HID, et RS232. J'ai donc écrit un petit script pour le passer à RS232, chaque fois qu'il est branché comme un périphérique HID, en utilisant cette règle udev:Comportement ioctl inattendu sur les liens symboliques

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

Le script est la suivante:

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

Maintenant, le plus souvent, quand Je branche l'appareil, Linux lui donne le fichier /dev/hidraw0. Et quand j'utilise mon script sur /dev/hidraw0, cela fonctionne parfaitement. Le descripteur de rapport utilisé dans le script est correct et tout fonctionne comme prévu: le périphérique HID repasse en mode RS232.

Cependant, lorsque je tente d'utiliser mon script sur le /dev/hid_device symlink créé par la règle udev, il ne fonctionne pas 99% du temps, en me disant ioctl: Invalid argument. La chose la plus étrange est que cela fonctionne, mais 1% du temps (peut-être même moins souvent).

Est-ce que quelqu'un a une idée où cela pourrait provenir, et comment le réparer, ou travailler autour d'elle? Merci d'avance.

Répondre

0

Je trouve le problème.

Il se trouve dans ma règle udev: il ne suffit pas précis.

Lorsque je branche l'appareil, Linux crée deux fichiers de périphériques character special dans /dev/: hidraw0 et input/event15 (dans mon cas). Ils partagent beaucoup de valeurs d'environnement, comme par exemple leur ID_VENDOR_ID, ou leur ID_USB_DRIVER. Cependant, ils ne partagent pas le même MAJOR.

Donc ce que je ne faisais ajouter ENV{MAJOR}=="correct_major" dans ma règle udev, et maintenant mon lien symbolique est lié au fichier du périphérique.

Il explique également pourquoi il a travaillé parfois: Je suppose qu'en raison du manque de détails dans la règle udev, parfois le lien symbolique a été lié au fichier correct de l'appareil, parfois pas.