This chapter describes the driver development of the Linux input subsystem. The Linux input subsystem not only supports mouse, keyboard, and other conventional input devices, but also supports buzzer, touch screen and other devices. This chapter analyzes the Linux input subsystem in detail.
Input subsystem implementation method:
Underlying driver layer (input_dev) ----- <associate by struct input_handle> ----- input event processing layer class interface (input_handler) ----- <input core layer input. c> ----- Application Layer
17.1 introduction to the input subsystem
The input subsystem is also called the input subsystem. Its construction is flexible. You only need to call some simple functions to present the functions of an input device to the application. This section describes how to write the input subsystem driver from an instance.
17.1.1 simple instance
This section describes a simple input device driver instance. The input device has only one key, and the key is connected to an interrupt line. When the key is pressed, an interrupt occurs. The kernel detects the interrupt and processes it. The code for this instance is as follows:
01 # include <asm/irq. h>
02 # include <asm/io. h>
03 static struct input_dev * button_dev;/* enter the device struct */
04 static irqreturn_t button_interrupt (int irq, void * dummy)/* interrupt processing function */
05 {
06 input_report_key (button_dev, btn_0, INB (button_port) & 1 );
/* Report a button event to the input subsystem */
07 input_sync (button_dev);/* notify the recipient that a report has been sent */
08 return IRQ_HANDLED;
09}
10 static int _ init button_init (void)/* load function */
11 {
12 int error;
13 if (request_irq (BUTTON_IRQ, button_interrupt, 0, "button", NULL)/* applying for the interrupt processing function */
14 {
15/* If the application fails, the error message is printed */
16 printk (KERN_ERR "button. c: Can't allocate irq % d \ n", button _
Irq );
17 return-EBUSY;
18}
19 button_dev = input_allocate_device ();/* assign a device struct */
20 if (! Button_dev)/* determine whether the allocation is successful */
21 {
22 printk (KERN_ERR "button. c: Not enough memory \ n ");
23 error =-ENOMEM;
24 goto err_free_irq;
25}
26 button_dev-> evbit [0] = BIT_MASK (EV_KEY);/* set key information */
27 button_dev-> keybit [BIT_WORD (BTN_0)] = BIT_MASK (BTN_0 );
28 error = input_register_device (button_dev);/* register an input device */
29 if (error)
30 {
31 printk (KERN_ERR "button. c: Failed to register device \ n ");
32 goto err_free_dev;
33}
34 return 0;
35 err_free_dev:/* handle errors below */
36 input_free_device (button_dev );
37 err_free_irq:
38 free_irq (BUTTON_IRQ, button_interrupt );
39 return error;
40}
41 static void _ exit button_exit (void)/* uninstall function */
42 {
43 input_unregister_device (button_dev);/* cancel the key device */
44 free_irq (BUTTON_IRQ, button_interrupt);/* release the broken line occupied by the buttons */
45}
46 module_init (button_init );
47 module_exit (button_exit );
The program code of this instance is relatively simple. An interrupt handler is registered in the initialization function button_init (), and an input_allocate_device () function is called to allocate an input_dev struct and input_register_device () is called () the function registers it. In the interrupt processing function button_interrupt (), the instance reports the received key information to the input subsystem. The input subsystem provides the user State program with the key input information.
This example uses the interrupt mode. In addition to the Code related to the interrupt, the instance contains some functions provided by the input subsystem, and some important functions are analyzed.
The input_allocate_device () function of Row 3 allocates a space for the input device struct in the memory and initializes its main members. To gain a deeper understanding of the input subsystem, developers should have a little understanding of its Code. The Code of this function is as follows:
- Struct input_dev * input_allocate_device (void)
- {
- Struct input_dev * dev;
- Dev = kzarloc (sizeof (struct input_dev), GFP_KERNEL );
/* Allocate an input_dev struct and initialize it to 0 */
- If (dev ){
- Dev->Dev. type = & input_dev_type;/* initialize the device type */
- Dev->Dev. class = & input_class;/* set to input device class */
- Device_initialize (& dev->Dev);/* initialize the device structure */
- Mutex_init (& dev->Mutex);/* initialize mutex lock */
- Spin_lock_init (& dev->Event_lock);/* initialize the event spin lock */
- INIT_LIST_HEAD (& dev->H_list);/* initialize the linked list */
- INIT_LIST_HEAD (& dev->Node);/* initialize the linked list */
- _ Module_get (THIS_MODULE);/* Add 1 module reference Technology */
- }
- Return dev;
- }
This function returns a pointer to the input_dev type, which is an input device struct that contains some information about the input device, such as the key code supported by the device, the device name, and events supported by the device. When using this struct in this chapter, we will introduce it in detail. Focus on the functions in the instance.