The Linux USB Input Subsystem, Part I

The Linux USB Input Subsystem, Part I

(2008-06-20 14:19:13)
  

 

The Linux USB input subsystem is a single, harmonized way tomanage all input devices. This is a relatively new approach forLinux, with the system being partly incorporated in kernel version2.4 and fully integrated in the 2.5 development series.

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

What Is the Input Subsystem?

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

How We Got Here

The Linux input subsystem is primarily the work of VojtechPavlik, who saw the need for a flexible input system from his earlywork on joystick support for Linux and his later work on supportingUSB. The first integration for the input subsystem replacedexisting joystick and USB drivers in the 2.3 development kernelseries. This support carried over to version 2.4, and input supportin the 2.4 series is basically limited to joysticks and USB inputdevices.

The 2.5 development kernel series fully integrates the inputsubsystem. This tutorial is based on the full integration, whichwill be the input API for the 2.6 stable kernel. Although somedifferences exist in the user-space APIs between 2.4 and 2.5kernels at the time of this writing, there is ongoing work toharmonize them—mainly by updating the 2.4 kernel.

Under the Hood—Understanding the Kernel Internals

The three elements of the input subsystem are the inputcore, drivers and event handlers. Therelationship between them is shown in Figure 1. Note that while thenormal path is from low-level hardware to drivers, drivers to inputcore, input core to handler and handler to user space, thereusually is a return path as well. This return path allows for suchthings as setting the LEDs on a keyboard and providing motioncommands to force feedback joysticks. Both directions use the sameevent definition, with different type identifiers.

The <wbr>Linux <wbr>USB <wbr>Input <wbr>Subsystem, <wbr>Part <wbr>I

Figure 1. The Relationship between the Elements of the InputSubsystem

The interaction between various elements is throughevents, which are implemented as structures (see Listing1). The first field (time) is a simple timestamp, while the otherfields are more interesting. The type field shows the generic typeof event being reported, for example, a key press or button press,relative motion (like moving a mouse) or absolute motion (likemoving a joystick). The code field tells which of the variousbuttons or axes are being manipulated, while the value field tellsyou what the state or motion is. For example, if the type is a keyor button, code tells you which key or button it is, and valuetells you if the button has been pressed or released. Similarly, iftype is a relative axis, then code tells you which axis, and valuetells you how much motion you have and the direction of that motionon that axis. If you move a mouse in a diagonal direction, whilesimultaneously moving the scroll wheel, you will get three relativeevents per update: one for motion in the verticaldirection (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, convertingthe standard event format into the format required by a particularAPI. 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 convertthe low-level hardware version of the user input into the standardevent format before sending it to the input core. The input coreuses a standard kernel plugin design, with input_register_device()used to add each device and input_unregister_device() used toremove it. The argument to these calls is the input_dev structure,which is shown in Listing 1. Although this structure looks quitelarge, most of the entries are provided to allow a driver tospecify the capabilities of the device, such as which event typesand codes may be sent or received by the device.

In addition to managing drivers and handlers, the input corealso exports a useful /proc filesystem interface, which can be usedto see what devices and handlers are currently active. Here is atypical example from /proc/bus/input/devices showing a USBmouse:

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—showingbus type 3 (which is USB) and the vendor, product and versioninformation from the USB descriptors in the mouse. TheN: line shows the name, which in this case is astring provided by the USB descriptors. The P: lineshows the physical device information; here, it's structureinformation comprised of the PCI address for the USB controller,the USB tree and the input interface. The input0 part indicatesthis is the first logical input device for the physical device.Some devices, such as multimedia keyboards, can map part of thephysical device to one logical input device and map another part toa second logical input device. The H: line showsthe handler drivers associated with this device; we'll discuss thisin 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 theball and the scroll wheel.

Listing 2. register.c

This /proc interface is a useful way to test some simpledrivers. Let's consider the example of a driver that registers oninit and unregisters on removal, as shown in Listing 2. This doessome preliminary initialization using init_input_dev(). It sets upthe name, physical and identification descriptors, and then sets upthe bit arrays to indicate that the device is capable of providingone type of event (EV_KEY indicating buttons and keys) with twopossible codes (KEY_A and KEY_B, indicating the key labels). Theinitialization routine then registers the device with the inputcore. 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 theinput core, we need to call input_event or one of the conveniencewrappers, such as input_report_key or input_report_abs, provided in<linux/input.h>. An example of codethat does this is shown in Listing 3. This example is basically thesame setup as the previous one, except that we add a timer thatcalls ex2_timeout(). This new routine sends four presses of KEY_Aand four presses of KEY_B. Note that 16 key press events arecreated in total, because a separate event is created for eachpress and each release. These events are passed to the input coreand, in turn, to the keyboard handler, which will cause the pattern“aaaabbbb” or “AAAABBBB”, depending on the Shift key selection, tobe transmitted to the console or command line. The timer is thenset up to run four seconds later, looping infinitely. Thefour-second delay is intended to give you enough time to remove themodule when you have seen enough of the pattern. If you reduce thedelay, make sure you have another way of accessing the system, suchas an SSH connection. Also note the call to the input_syncfunction. This function is used to inform the event handler (inthis case, the keyboard handler) that the device has transmitted aninternally consistent set of data. The handler may choose to bufferevents until input_sync is called.

Listing 3. aaaabbbb.c

Let's look at one final example of a driver, this time showinghow relative information is provided, shown in Listing 4. Thisexample is a driver that emulates a mouse. The initial setupconfigures 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 timerto run ex3_timeout. This timer then calls input_report_relto provide small relative motion (five unit steps—the relativemovement is the third argument to the function) consisting of 30steps right, 30 steps down, 30 steps left and 30 steps up, so thecursor is moved in a square pattern. To provide the illusion ofmovement, the timeout is only 20 milliseconds. Again, note the callto input_sync, which is used to ensure that input handlers onlyprocess events that make up a consistent set. This specificationwasn't strictly necessary in our previous example. But, it isdefinitely required to convey information like relative movement tothe input core, because more than one axis may be required torepresent movement. If you were moving diagonally, you would dosomething like:

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

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

Listing 4. squares.c

Handlers—Getting to User Space

In the previous section, we saw that the device driversbasically sat between the hardware and the input core, translatinghardware events, usually interrupts, into input events. To make useof those input events, we use handlers, which provide a user-spaceinterface.

The input subsystem includes most of the handlers you'll likelyneed: a keyboard handler to provide a console, amouse handler for applications like the X Window System, a joystickhandler for games and also a touchscreen handler. There is also ageneral-purpose handler called the event handler, which basicallyprovides input events to user space. This means you almost neverneed to write a handler in the kernel, because you can do the samething with the event handler and equivalent code in user space.This API discussion is covered in the second part of thisarticle.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值