Using the Input Subsystem, Part II

No matter how many buttons an input device has or how many kinds of events it can generate, you can now work with it from user space.

In last month's article, we saw how the
Linux input subsystem worked inside the kernel, ending with a quick
mention of the event handlers. Each handler essentially provides a
different user-space API, converting input events into the
particular format that makes up that API.

One of the key aspects of the input subsystem integration
into Linux is the availability of the event interface. This
basically exposes the raw events to userspace through a collection
of character device nodes—one character device node per logical
input device. The event interface is a really powerful technique,
because it allows the manipulation of the events in userspace
without information loss. For example, legacy mouse interfaces
support only two relative axes and up to five buttons. These are
normally mapped to the two real axes and three real buttons, with
the fourth and fifth buttons logically being mapped to the scroll
wheel up and scroll wheel down events.

However, this mapping becomes a problem when trying to use a
mouse with a scroll wheel and more than three buttons, because any
additional buttons can be mapped only to an existing button. The
legacy APIs also impede use of advanced input devices, such as
space balls and other devices' with many axes. By contrast, the
event API provides full access to the devices capabilities, and it
even includes a per-device description of those capabilities and
other device characteristics.

This month's article focuses on the various ioctl
capabilities of the event interface, in addition to the normal read
and write calls.

Finding the Version of the Event
Interface

The event interface supports determining the version of the
event device code, using the EVIOCGVERSION ioctl function. The
argument is an int (32 bits) and is meant to be interpreted as a
major version (two high bytes), a minor version (third byte) and a
patch level (low byte). The same value is returned from each event
device on a machine.

An example of the EVIOCGVERSION is shown in Listing 1. The
first argument to the ioctl function is an open file descriptor for
the event device node (for example, /dev/input/event0). Notice that
you have to pass a pointer to the integer variable, not the
variable itself, as the third argument to the ioctl call.

The event interface supports retrieving information
associated with the underlying device using the EVIOCGID ioctl. The
argument is a pointer to an input_id structure; the input_id
structure is defined as shown in Listing 2. The __u16 data type is
a Linux-specific, unsigned 16-bit integer. You can safely cast it
to a standard uint16_t in your code.

The bus type is the only field that contains accurate data.
You should probably consider it to be an opaque, enumerated type,
and compare it with the various BUS_x type definitions provided in
<linux/input.h>. The vendor, product and version fields are
bus type-specific information relating to the identity of the
device. Modern devices (typically using PCI or USB) do have
information that can be used, but legacy devices (such as serial
mice, PS/2 keyboards and game ports on ISA sound cards) do not.
These numbers therefore are not meaningful for some values of bus
type.

An example of the EVIOCGID ioctl is shown in Listing 3. This
example calls the ioctl and then prints out the results. The case
logic shows all current bus types. Here is an example of running
that code: vendor 045e product 001d version 0111 is on a
Universal Serial Bus.

In addition to the type of bus and the vendor, product and
version information, some devices can provide strings that make up
meaningful names. This can be obtained from the event interface
using the EVIOCGNAME ioctl. This ioctl provides a string and
returns the length of the string (or a negative error value). If
the string is too long to fit into the argument, it will be
truncated. An example is provided in Listing 4. If it seems strange
that the argument is not &name, remember 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]).

The device on /dev/input/event0 says its name
is Logitech USB-PS/2 Optical Mouse

Not all devices contain meaningful names, however, so kernel
input drivers try to provide something meaningful. For example, USB
devices without manufacturer or product strings concatenate the
vendor and product ID information.

Although device identity and name information is often
useful, it may not be sufficient information to tell which device
you have. For example, if you have two joysticks that are the same,
you may need to identify them based on which port they use. This is
usually known as topology information, and you can get this from
the event interface using the EVIOCGPHYS ioctl. Like EVIOCGNAME,
this provides a string and returns the length of the string (or a
negative error number). An example is shown in Listing 5; running
that example will produce something like:

The device on /dev/input/event0 says its path
is usb-00:01.2-2.1/input0

To understand what this string is showing, you need to break
it down into parts. The usb part means this is a physical topology
from the USB system. The 00:01.2 is the PCI bus information for the
USB host controller (in this case, bus 0, slot 1, function 2). The
2.1 shows the path from the root hub to the device. In this case,
the upstream hub is plugged in to the second port on the root hub,
and that device is plugged in to the first port on the upstream
hub. input0 means this is the first event device on the device.
Most devices have only one, but multimedia keyboards may present
the normal keyboard on one interface and the multimedia function
keys on a second interface. This topology example is shown in
Figure 1.

Figure 1. Keyboard Topology

This setup doesn't help if you swap the cables on two
identical devices. The only thing that can help in this case is if
the device has some form of unique identifier, such as a serial
number. You can get this information using the EVIOCGUNIQ ioctl. An
example is shown in Listing 6. Most devices don't have such an
identifier, and you will get an empty string from this
ioctl.

Comment viewing options

I am making a full source code basic tutorial for copy pasting should be done in a few days I'll post the link. It will also include handling a joystick.
A forward note in the 2.6 version of kernel you need root permissions to open event# files. So you need to run under sudo or make a dev rule.

To Solusrex: I have the same issue. I see at
that the kernel should call /sbin/hotplug which calls device-specific scripts to handle the add or remove event. I'm going to try to instrument the associated script to somehow send a message to my app to notify it. You might try the same.
E Franz

WHY would you not include the entire code fragment in each example? WHY are you obfuscating some parameter types? Example: you describe getting the unique identifier of a device using the EVIOCGUNIQ ioctl. But you reference a magical variable called 'uniq' the type of which you do not define anywhere. Exactly how is hiding this information supposed to be useful? Who edited this? Why are you trying to make my life more difficult? WTF?!?!

The author clearly does not understand the beauty of copy and paste. Each listing of code just will never compile because the variables are not defined. People have to pull their hair to figure it out.

In one of my project, I need to retrieve events from keyboard in Linux environment. For doing that in my code firstly I opened /dev/input/event0 file and it was successfully opened. However, when I was trying to read something from that file. The read() function stuck and my program can't execute any further steps. Does anybody know why this kind of problem that I encounter and how can I solve this problem. Here is my code:

P.S: In order to execute program you need to be super user and then need to execute code. Otherwise, program will can give "File can not open" error.

Geek Guides

Pick up any e-commerce web or mobile app today, and you’ll be holding a mashup of interconnected applications and services from a variety of different providers. For instance, when you connect to Amazon’s e-commerce app, cookies, tags and pixels that are monitored by solutions like Exact Target, BazaarVoice, Bing, Shopzilla, Liveramp and Google Tag Manager track every action you take. You’re presented with special offers and coupons based on your viewing and buying patterns. If you find something you want for your birthday, a third party manages your wish list, which you can share through multiple social- media outlets or email to a friend. When you select something to buy, you find yourself presented with similar items as kind suggestions. And when you finally check out, you’re offered the ability to pay with promo codes, gifts cards, PayPal or a variety of credit cards.