Using the Input Subsystem, Part II
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.
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.
Listing 2. iput_id Structure Definitions
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.
Listing 3. Sample EVIOCGID ioctl
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]).
Listing 4. Example Trunctated String
Here is an example of running that event code:
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
Listing 5. Using EVIOCGPHYS for Topology Information
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.
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.
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Sponsored by AMD
If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.
Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.
Sponsored by ActiveState
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?
| Speed Up Your Web Site with Varnish | Jun 19, 2013 |
| Non-Linux FOSS: libnotify, OS X Style | Jun 18, 2013 |
| Containers—Not Virtual Machines—Are the Future Cloud | Jun 17, 2013 |
| Lock-Free Multi-Producer Multi-Consumer Queue on Ring Buffer | Jun 12, 2013 |
| Weechat, Irssi's Little Brother | Jun 11, 2013 |
| One Tail Just Isn't Enough | Jun 07, 2013 |
- Speed Up Your Web Site with Varnish
- Containers—Not Virtual Machines—Are the Future Cloud
- Linux Systems Administrator
- Non-Linux FOSS: libnotify, OS X Style
- Lock-Free Multi-Producer Multi-Consumer Queue on Ring Buffer
- Senior Perl Developer
- Technical Support Rep
- UX Designer
- Web & UI Developer (JavaScript & j Query)
- RSS Feeds
- Reply to comment | Linux Journal
3 hours 51 min ago - Yeah, user namespaces are
5 hours 8 min ago - Cari Uang
8 hours 39 min ago - user namespaces
11 hours 33 min ago - yea
11 hours 58 min ago - One advantage with VMs
14 hours 27 min ago - about info
15 hours 34 sec ago - info
15 hours 1 min ago - info
15 hours 2 min ago - info
15 hours 4 min ago





Comments
Full example source.
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.
Best Way to Detect Hotplug from App
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
Seriously, how hard is it to give useful code examples?
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?!?!
What is the best way to
What is the best way to detect from an app that a USB input device was plugged/unplugged beside polling it using open() function?
Hello, you can write a small
Hello,
you can write a small app that is called from a udev rule.
(You have to add a small rule for this)
Inside of the app you can broadcast a small message on a local socket.
Every app that listens on this socket, receive this notification.
bye
Uwe
Retrieve Scan Infor
Hi all...
I need to retrieve all data (position x,y) from the driver when i try to draw something on the pad tablet....
can anyone tell me how to get the ABS when i got event scan ??
bad code
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.
HELP: Retrieving Input from a Device
Hi All,
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.
#define FILE_PATH "/dev/input/event0" int main() { printf("Starting KeyEvent Module\n"); //int file, version; size_t file; const char *str = FILE_PATH; printf("File Path: %s\n", str); if((file = open(str, O_RDWR)) < 0) { printf("ERROR:File can not open\n"); exit(0); } struct input_event event[64]; size_t reader; reader = read(file, &event, sizeof(struct input_event) * 64); printf("DO NOT COME HERE...\n"); close(file); return 0; }change this : reader =
change this :
reader = read(file, &event, sizeof(struct input_event) * 64);
to
reader = read(file, event, sizeof(struct input_event) * 64);
You need one more flag
change this:
if((file = open(str, O_RDWR)) < 0)
to
if((file = open(str, O_RDWR|O_NDELAY)) < 0)
and check manual by 'man 2 open'
nice to see, but how many users have figured how to get a joysti
I for one can figure out how /etc/devfsd.conf needs to be edited to setup /dev/joysticks, or /dev/js* with nothing under /dev/input being created either.
linux/Doc*/devices says digital joysticks are char-15,128 while the help doc under makeconfig states char 13:0+ - /dev/input/jsX
neither of this help me much.
If there was documentation somewhere in the world about how to setup joysticks we could hopefully have more people using this code :)