符号链接上出现意外的ioctl行为

时间:2016-12-13 10:57:43

标签: linux symlink ioctl udev

我目前正在使用HID设备。它有两种设置模式:HID和RS232。因此,我使用此udev规则编写了一个小脚本,将其切换为RS232,无论何时将其作为HID设备插入:

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模式。

然而,当我尝试在udev规则创建的/dev/hid_device符号链接上使用我的脚本时,它在99%的时间内无效,告诉我{{1} }。更奇怪的是,它有效,但有1%的时间(可能更少)。

有没有人知道这可能来自哪里,如何修复或解决它?提前谢谢。

1 个答案:

答案 0 :(得分:0)

我发现了问题。

这取决于我的udev规则:它不够精确。

当我插入设备时,linux会在character special中创建两个/dev/设备文件:hidraw0input/event15(在我的情况下)。他们共享许多环境值,例如他们的ID_VENDOR_ID或他们的ID_USB_DRIVER。但是,它们不共享MAJOR

所以我所做的是在我的udev规则中添加ENV{MAJOR}=="correct_major",现在我的符号链接链接到正确的设备文件。

它还解释了为什么它有时会起作用:我想由于udev规则中缺少细节,有时符号链接被链接到正确的设备文件,有时不会。