Getting information about the HID device identity

The evdev interface supports getting information associated with the device using the EVIOCGID ioctl. The argument is a pointer to a input_devinfo structure.

The input_devinfo structure is defined as:

struct input_devinfo {
        uint16_t bustype;
        uint16_t vendor;
        uint16_t product;
        uint16_t version;
};

The bustype field is always BUS_USB for USB devices, but has other values for other devices. In the 2.5.x and later series kernels, the input subsytem is used for all input devices, and this value can take a wide range of values. In the 2.4.x series kernels, the input subsystem has restricted application (for example, USB and Apple Desktop Bus).

The vendor, product and version elements are associated with the device. For a USB device, they have one-to-one correspondence with wVendor, wProduct and bcdRevision fields in the USB device descriptor.

Lets look at an example of the EVIOCGID ioctl call.

NoteAbout this example
 

This example is intentionally a code fragment, and is not complete,nor is it meant to show good programming style.

A complete form of this example (that will compile with gcc -Wall -W) is provided in the second part of this document.

Example 2. EVIOCGID example

  ioctl(fd, EVIOCGID, &device_info);

  printf("vendor 0x%04hx product 0x%04hx version 0x%04hx is on",
         device_info.vendor, device_info.product,
         device_info.version);
  switch ( device_info.bustype)
      {
      case BUS_USB :
          printf(" a Universal Serial Bus\n");
          break;
      default:
          printf(" an unknown bus type: 0x%04hx", device_info.bustype);
      }

Another useful ioctl for getting information on the device is EVIOCGNAME. It returns a char array, containing the name of the device.

Lets look at an example of the EVIOCGNAME ioctl call.

NoteAbout this example
 

This example is intentionally a code fragment, and is not complete,nor is it meant to show good programming style.

A complete form of this example (that will compile with gcc -Wall -W) is provided in the second part of this document.

Example 3. EVIOCGNAME example

  char name[256]= "Unknown";

  if(ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0) {
      perror("evdev ioctl");
  }

  printf("The device on %s says it's name is %s\n", argv[1], name);

The EVIOCGNAME ioctl returns the length of the string if it succeeds, and a negative number if it fails. For USB devices, the string is made by concatenating the strings from iManufacturer and iProduct string descriptors reported by the USB device. Note that these are both optional.

If the string is too long to fit into the argument, it will be truncated.

If it seems strange that the third argument isn't &name, remember that the name of an array is the same as a pointer to the first element. Therefore &name would be a pointer to a pointer to the first element, which is not what we want. If you really want to use a dereference, use &(name[0]).

On my system, with a joystick, running a version of this code produces:

[root@localhost evdev-example3]# ./example3 /dev/input/event0
The device on /dev/input/event0 says it's name is Microsoft SideWinder
Joystick