2007年2月5日星期一

The Linux USB Input Subsystem

Software As the USB input subsystem spreads further with each kernel release, it's time to understand what it's doing for your devices.

The Linux USB input subsystem is a single, harmonized way to manage all input devices. This is a relatively new approach for Linux, with the system being partly incorporated in kernel version 2.4 and fully integrated in the 2.5 development series.

This article covers four basic areas: a description of what the input subsystem does, a short historical perspective on development, a description of how the input subsystem is implemented in the kernel and an overview of the user-space API for the input subsystem and how you can use it in your programs. The first three areas are discussed in this article. The user-space API, the final topic, will be discussed in Part II of this article.

What Is the Input Subsystem?

The input subsystem is the part of the Linux kernel that manages the various input devices (such as keyboards, mice, joysticks, tablets and a wide range of other devices) that a user uses to interact with the kernel, command line and graphical user interface. This subsystem is included in the kernel because these devices usually are accessed through special hardware interfaces (such as serial ports, PS/2 ports, Apple Desktop Bus and the Universal Serial Bus), which are protected and managed by the kernel. The kernel then exposes the user input in a consistent, device-independent way to user space through a range of defined APIs.

How We Got Here

The Linux input subsystem is primarily the work of Vojtech Pavlik, who saw the need for a flexible input system from his early work on joystick support for Linux and his later work on supporting USB. The first integration for the input subsystem replaced existing joystick and USB drivers in the 2.3 development kernel series. This support carried over to version 2.4, and input support in the 2.4 series is basically limited to joysticks and USB input devices.

The 2.5 development kernel series fully integrates the input subsystem. This tutorial is based on the full integration, which will be the input API for the 2.6 stable kernel. Although some differences exist in the user-space APIs between 2.4 and 2.5 kernels at the time of this writing, there is ongoing work to harmonize them--mainly by updating the 2.4 kernel.

Under the Hood--Understanding the Kernel Internals

The three elements of the input subsystem are the input core, drivers and event handlers. The relationship between them is shown in Figure 1. Note that while the normal path is from low-level hardware to drivers, drivers to input core, input core to handler and handler to user space, there usually is a return path as well. This return path allows for such things as setting the LEDs on a keyboard and providing motion commands to force feedback joysticks. Both directions use the same event definition, with different type identifiers.

Figure 1. The Relationship between the Elements of the Input Subsystem

The interaction between various elements is through events, which are implemented as structures (see Listing 1). The first field (time) is a simple timestamp, while the other fields are more interesting. The type field shows the generic type of event being reported, for example, a key press or button press, relative motion (like moving a mouse) or absolute motion (like moving a joystick). The code field tells which of the various buttons or axes are being manipulated, while the value field tells you what the state or motion is. For example, if the type is a key or button, code tells you which key or button it is, and value tells you if the button has been pressed or released. Similarly, if type is a relative axis, then code tells you which axis, and value tells you how much motion you have and the direction of that motion on that axis. If you move a mouse in a diagonal direction, while simultaneously moving the scroll wheel, you will get three relative events per update: one for motion in the vertical direction (Y-axis), one for motion in the horizontal direction (X-axis) and one for motion of the wheel.

Listing 1. event-dev-struct.txt

Event handlers provide the interface to user space, converting the standard event format into the format required by a particular API. Handlers usually take care of the device nodes (/dev entries) too. The most common handler is the keyboard handler, which is the ``standard input'' that most programmers (especially C programmers) are familiar with.

Drivers usually interface with low-level hardware, such as USB, PCI memory or I/O regions, or serial port I/O regions. They convert the low-level hardware version of the user input into the standard event format before sending it to the input core. The input core uses a standard kernel plugin design, with input_register_device() used to add each device and input_unregister_device() used to remove it. The argument to these calls is the input_dev structure, which is shown in Listing 1. Although this structure looks quite large, most of the entries are provided to allow a driver to specify the capabilities of the device, such as which event types and codes may be sent or received by the device.

In addition to managing drivers and handlers, the input core also exports a useful /proc filesystem interface, which can be used to see what devices and handlers are currently active. Here is a typical example from /proc/bus/input/devices showing a USB mouse:

I: Bus=0003 Vendor=046d Product=c002 Version=0120
N: Name="Logitech USB-PS/2 Mouse M-BA47"
P: Phys=usb-00:01.2-2.2/input0
H: Handlers=mouse0 event2
B: EV=7
B: KEY=f0000 0 0 0 0 0 0 0 0
B: REL=103

The I: line is the identity information--showing bus type 3 (which is USB) and the vendor, product and version information from the USB descriptors in the mouse. The N: line shows the name, which in this case is a string provided by the USB descriptors. The P: line shows the physical device information; here, it's structure information comprised of the PCI address for the USB controller, the USB tree and the input interface. The input0 part indicates this is the first logical input device for the physical device. Some devices, such as multimedia keyboards, can map part of the physical device to one logical input device and map another part to a second logical input device. The H: line shows the handler drivers associated with this device; we'll discuss this in more detail later in the article. The various B: lines show the bitfields that identify the devices' capabilities, in this case some keys for the buttons and relative axes for the ball and the scroll wheel.

Listing 2. register.c

This /proc interface is a useful way to test some simple drivers. Let's consider the example of a driver that registers on init and unregisters on removal, as shown in Listing 2. This does some preliminary initialization using init_input_dev(). It sets up the name, physical and identification descriptors, and then sets up the bit arrays to indicate that the device is capable of providing one type of event (EV_KEY indicating buttons and keys) with two possible codes (KEY_A and KEY_B, indicating the key labels). The initialization routine then registers the device with the input core. If you add this code to the kernel (using modprobe), you can see the new device has been added to /proc/bus/input/devices, as shown below:

I: Bus=0019 Vendor=0001 Product=0001 Version=0100
N: Name="Example 1 device"
P: Phys=A/Fake/Path
H: Handlers=kbd event3
B: EV=3
B: KEY=10000 40000000

If we actually want to send events from our device driver to the input core, we need to call input_event or one of the convenience wrappers, such as input_report_key or input_report_abs, provided in . An example of code that does this is shown in Listing 3. This example is basically the same setup as the previous one, except that we add a timer that calls ex2_timeout(). This new routine sends four presses of KEY_A and four presses of KEY_B. Note that 16 key press events are created in total, because a separate event is created for each press and each release. These events are passed to the input core and, in turn, to the keyboard handler, which will cause the pattern ``aaaabbbb'' or ``AAAABBBB'', depending on the Shift key selection, to be transmitted to the console or command line. The timer is then set up to run four seconds later, looping infinitely. The four-second delay is intended to give you enough time to remove the module when you have seen enough of the pattern. If you reduce the delay, make sure you have another way of accessing the system, such as an SSH connection. Also note the call to the input_sync function. This function is used to inform the event handler (in this case, the keyboard handler) that the device has transmitted an internally consistent set of data. The handler may choose to buffer events until input_sync is called.

Listing 3. aaaabbbb.c

Let's look at one final example of a driver, this time showing how relative information is provided, shown in Listing 4. This example is a driver that emulates a mouse. The initial setup configures the device to have two relative axes (REL_X and REL_Y) and one key (BTN_LEFT). As in the previous example, we use a timer to run ex3_timeout. This timer then calls input_report_rel to provide small relative motion (five unit steps--the relative movement is the third argument to the function) consisting of 30 steps right, 30 steps down, 30 steps left and 30 steps up, so the cursor is moved in a square pattern. To provide the illusion of movement, the timeout is only 20 milliseconds. Again, note the call to input_sync, which is used to ensure that input handlers only process events that make up a consistent set. This specification wasn't strictly necessary in our previous example. But, it is definitely required to convey information like relative movement to the input core, because more than one axis may be required to represent movement. If you were moving diagonally, you would do something like:

...
input_report_rel(..., REL_X, ...);
input_report_rel(..., REL_Y, ...);
input_sync(...);
...

which ensures that the mouse will move diagonally and not across, then up.

Listing 4. squares.c

Handlers--Getting to User Space

In the previous section, we saw that the device drivers basically sat between the hardware and the input core, translating hardware events, usually interrupts, into input events. To make use of those input events, we use handlers, which provide a user-space interface.

The input subsystem includes most of the handlers you'll likely need: a keyboard handler to provide a console, a mouse handler for applications like the X Window System, a joystick handler for games and also a touchscreen handler. There is also a general-purpose handler called the event handler, which basically provides input events to user space. This means you almost never need to write a handler in the kernel, because you can do the same thing with the event handler and equivalent code in user space. This API discussion is covered in the second part of this article.

Acknowledgements

I'd like to thank Greg Kroah-Hartman and Vojtech Pavlik for their assistance with this article.



PART II

http://www.linuxjournal.com/article/6429


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.

Listing 1. Sample EVIOCGVERSION Function

Finding Information about the Device's Identity

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 . 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.

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.

Listing 6. Finding a Unique Identifier

Determining the Device Capabilities and Features

For some applications, it might be enough to know the device identity, because this would allow you to handle any special cases depending on what device is being used. However, it doesn't scale well; consider a case where you want to enable scroll wheel handling only if the device has a scroll wheel. You really don't want to have to list the vendor and product information for every mouse with a scroll wheel in your code.

To avoid this problem, the event interface allows you to determine which features and capabilities are available for a particular device. The types of features supported by the event interface are:

  • EV_KEY: absolute binary results, such as keys and buttons.

  • EV_REL: relative results, such as the axes on a mouse.

  • EV_ABS: absolute integer results, such as the axes on a joystick or for a tablet.

  • EV_MSC: miscellaneous uses that didn't fit anywhere else.

  • EV_LED: LEDs and similar indications.

  • EV_SND: sound output, such as buzzers.

  • EV_REP: enables autorepeat of keys in the input core.

  • EV_FF: sends force-feedback effects to a device.

  • EV_FF_STATUS: device reporting of force-feedback effects back to the host.

  • EV_PWR: power management events.

These are only the types of features; a wide range of individual features can be found within each type. For example, the EV_REL feature type distinguishes between X, Y and Z axes and horizontal and vertical wheels. Similarly, the EV_KEY feature type includes literally hundreds of different keys and buttons.

The capabilities or features of each device can be determined through the event interface, using the EVIOCGBIT ioctl. This function allows you to determine the types of features supported by any particular device, for example, whether it has keys, buttons or neither. It further allows you to determine the specific features that are supported, for example, which keys or buttons are present.

The EVIOCGBIT ioctl takes four arguments. If we consider it as ioctl(fd, EVIOCGBIT(ev_type, max_bytes), bitfield), then the fd argument is an open file descriptor; ev_type is the type of features to return (with 0 as a special case, indicating the list of all feature types supported should be returned, rather than the list of particular features for that type); max_bytes shows the upper limit on how many bytes should be returned; and bitfield is a pointer to the memory area where the result should be copied. The return value is the number of bytes actually copied on success or a negative error code on failure.

Let's look at a couple of examples of the EVIOCGBIT ioctl call. The first example, Listing 7, shows how to determine the types of features present. It determines how much memory is required for the bit array using evtype_bitmask, based on the EV_MAX definition in . The ioctl is then submitted, and the event layer fills in the bit array. We then test each bit in the array and show where the bit was set, which indicates the device does have at least one of this type of feature. All devices support the EV_SYN feature type in 2.5; the input core sets this bit.

Listing 7. Determining Features with EVIOCGBIT

When run, with a keyboard as the target, the example in Listing 7 produces:

Supported event types:
Event type 0x00 (Synchronization Events)
Event type 0x01 (Keys or Buttons)
Event type 0x11 (LEDs)
Event type 0x14 (Repeat)

With a mouse as the target, the example produces:

Supported event types:
Event type 0x00 (Synchronization Events)
Event type 0x01 (Keys or Buttons)
Event type 0x02 (Relative Axes)


Retrieving Input from (and to) the Device

Having determined what capabilities a particular device has, you know what types of events it will produce and what types of events you can send.

Retrieving events from a device requires a standard character device ``read'' function. Each time you read from the event device (e.g., /dev/input/event0), you will get a whole number of events, each consisting of a struct input_event.

Listing 8. Checking for Busy Spots

The example shown in Listing 8 does a busy loop on the open file descriptor, trying to read any events. It filters out any events that don't correspond to keys and then prints out the various fields in the input_event structure. Running this while typing on my keyboard produced:

Event: time 1033621164.003838, type 1, code 37, value 1
Event: time 1033621164.027829, type 1, code 38, value 0
Event: time 1033621164.139813, type 1, code 38, value 1
Event: time 1033621164.147807, type 1, code 37, value 0
Event: time 1033621164.259790, type 1, code 38, value 0
Event: time 1033621164.283772, type 1, code 36, value 1
Event: time 1033621164.419761, type 1, code 36, value 0
Event: time 1033621164.691710, type 1, code 14, value 1
Event: time 1033621164.795691, type 1, code 14, value 0

You get one event per key press and another per key release.

This read interface has all the normal characteristics of a character device, meaning you don't need to use a busy loop. You can simply wait until your program needs some input from the device and then perform the read call. In addition, if you are interested in the input from a number of devices, you can use the poll and select functions to wait on a number of open devices at the same time.

Sending information to the device is a process similar to receiving it, except you use the standard write function instead of read. It is important to remember that the data used in the write call has to be a struct input_event.

A simple example of writing data is shown in Listing 9. This example turns the Caps Lock LED on, waits 200 milliseconds and then turns the Caps Lock LED off. It then turns the Num Lock LED on, waits 200 milliseconds, and then turns the Num Lock LED off. The cycle then repeats (in an infinite busy loop), so you see alternate flashing of the two keyboard LEDs.

Listing 9. Sample Data Write Function

By now it should be fairly clear that you receive events only when something changes--a key is pressed or released, the mouse is moved and so on. For some applications, you need to be able to determine what the global state of the device is. For example, a program that manages keyboards may need to determine which LEDs are currently lit and which keys are currently depressed on the keyboard, even though some of the keys may have been depressed before the application started.

The EVIOCGKEY ioctl is used to determine the global key and button state for a device. An example is shown in Listing 10. This ioctl is similar to the EVIOCGBIT(...,EV_KEY,...) function in some ways; instead of setting a bit in the bit array for each key or button that the device can send, EVIOCGKEY sets a bit in the bit array for each key or button that is depressed.

Listing 10. Determining a Device's Global Key and Button State

The EVIOCGLED and EVIOCGSND functions are analogous to EVIOCGKEY, except that they return which LEDs are currently lit and sounds that are currently turned on, respectively. An example of how you would use EVIOCGLED is shown in Listing 11. Again, each bit is interpreted in the same way as the bits in the bit array are filled in by EVIOCGBIT.

Listing 11. Using EVIOCGLED

You can determine the repeat rate settings for a keyboard using the EVIOCGREP ioctl. An example is shown in Listing 12, with two elements to the array. The first element specifies the delay before the keyboard starts repeating, and the second element specifies the delay between subsequent repeats. So if you hold down a key, you'll get one character straight away, a second character rep[0] milliseconds later, a third character rep[1] milliseconds after the second character and another character every rep[1] milliseconds thereafter, until you release the key.

Listing 12. Checking the Repeat Rate Settings

You also can set the key repeat rate using EVIOCSREP. This uses the same two-element array that you'd use to get the settings, as shown in Listing 13; it sets the initial delay to 2.5 seconds and the repeat rate to 1 per second.

Listing 13. Setting the Repeat Rates

Some input drivers support variable mappings between the keys held down (which are interpreted by the keyboard scan and reported as scancodes) and the events sent to the input layer. You can determine what key is associated with each scancode using the EVIOCGKEYCODE ioctl. An example is shown in Listing 14, which loops over the first 100 scancodes. The value of the scancode (input to the function) is the first element in the integer array, and the resulting input event key number (keycode) is the second element in the array. You can also modify the mapping, using the EVIOCSKEYCODE ioctl. An example is shown in Listing 15; this ioctl maps my M key to always produce a letter N. Be aware that keycode ioctl functions may not work on every keyboard--that USB keyboard is an example of a driver that does not support variable mappings.

Listing 14. Looping over Scancodes

Listing 15. Mapping Keys

The EVIOCGABS function also provides state information. Instead of filling in a bit array that represents the global state of boolean values, however, it provides a struct input_absinfo (see Listing 16) for one absolute axis. If you want the global state for a device, you have to call the function for each axis present on the device. An example is shown in Listing 17. The elements in the array are signed 32-bit quantities, and you can safely treat them as equivalent to int32_t. The first element shows the current value of the axis, the second and third elements show the current limits of the axis, the fourth element shows the size of the ``flat'' section (if any) of the response and the last element shows the size of the error that may be present.

Listing 16. input_absinfo for an Absolute Axis

Listing 17. Checking Globabl State by Axis

Force Feedback

Three additional ioctl functions may be used for controlling force-feedback devices: EVIOCSFF, EVIOCRMFF and EVIOCGEFFECT. These functions currently send a force-feedback effect, remove a force-feedback effect and determine how many simultaneous effects can be used, respectively. Because the force-feedback support is still emerging and substantial work remains to be done, it is a little premature to fully document the API. The web sites listed in the Resources section of this article may have updated information by the time you read this.

没有评论: