Article Directory
1 Introduction to the input subsystem
The input subsystem is the subsystem that manages the input. Like the pinctrl and gpio subsystems, it is a framework created by the Linux kernel for a certain type of device. The input subsystem processes input transactions. Any input device driver can register to the kernel through the interface provided by the input input subsystem, and interact with the user space using the functions provided by the subsystem. Input devices generally include keyboards, mice, touch screens, etc., which appear as input devices in the kernel.
The input subsystem has a hierarchical structure, divided into three layers in total: hardware driver layer, subsystem core layer, and event processing layer.
(1) The hardware driver layer is responsible for operating specific hardware devices. The code of this layer is for specific drivers and needs to be written by the author of the driver.
(2) The core layer of the subsystem is the link and bridge between the other two layers, providing the interface of the driver layer downwards and the interface of the event processing layer upwards.
(3) The event processing layer is responsible for dealing with the user program, and reporting events from the hardware driver layer to the user program.
The basic unit of communication between the various layers is the event. The actions of any input device can be abstracted into an event, such as pressing the keyboard, pressing the touch screen, and moving the mouse. Events have three attributes: type, code, and value. All events supported by the input subsystem are defined in input.h, including all supported types and codes supported by the type. The direction of event transmission is hardware driver layer -> subsystem core -> event processing layer -> user space.
2 Input driver writing process
First, let's take a look at what functions are implemented in the input core layer. The input core layer file is input.c, the path: drivers/input/input.c, and some of the contents are as follows:
1767 struct class input_class = {
1768 .name = "input",
1769 .devnode = input_devnode,
1770 };
......
2414 static int __init input_init(void)
2415 {
2416 int err;
2417
2418 err = class_register(&input_class);
2419 if (err) {
2420 pr_err("unable to register input_dev class\n");
2421 return err;
2422 }
2423
2424 err = input_proc_init();
2425 if (err)
2426 goto fail1;
2427
2428 err = register_chrdev_region(MKDEV(INPUT_MAJOR, 0),
2429 INPUT_MAX_CHAR_DEVICES, "input");
2430 if (err) {
2431 pr_err("unable to register char major %d", INPUT_MAJOR);
2432 goto fail2;
2433 }
2434
2435 return 0;
2436
2437 fail2: input_proc_exit();
2438 fail1: class_unregister(&input_class);
2439 return err;
2440 }
On line 2418, an input class is registered. After the system starts, a subdirectory of the input class will be generated in the /sys/class directory, as shown in Figure 2.1:
On lines 2428 and 2489, a character device is registered, so the input subsystem is essentially a character device driver. The major device number is INPUT_MAJOR, and INPUT_MAJOR is defined in the include/uapi/linux/major.h file, which is defined as follows:
#define INPUT_MAJOR 13
so the input sub The major device number of all devices in the system is 13, and there is no need to register character devices when using the input subsystem to process input devices. We only need to register an input_device with the system.
1. Input_dev structure
input_dev structure is the basic device structure of input devices. Each input driver must be allocated and initialized such a structure. The structure is defined in the include/linux/input.h file and is defined as follows:
121 struct input_dev {
122 const char *name;
123 const char *phys;
124 const char *uniq;
125 struct input_id id;
126
127 unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];
128
129 unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; /* 事件类型的位图 */
130 unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; /* 按键值的位图 */
131 unsigned long relbit[BITS_TO_LONGS(REL_CNT)]; /* 相对坐标的位图 */
132 unsigned long absbit[BITS_TO_LONGS(ABS_CNT)]; /* 绝对坐标的位图 */
133 unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)]; /* 杂项事件的位图 */
134 unsigned long ledbit[BITS_TO_LONGS(LED_CNT)]; /*LED 相关的位图 */
135 unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];/* sound 有关的位图 */
136 unsigned long ffbit[BITS_TO_LONGS(FF_CNT)]; /* 压力反馈的位图 */
137 unsigned long swbit[BITS_TO_LONGS(SW_CNT)]; /*开关状态的位图 */
......
189 bool devres_managed;
190 };
In line 129, evbit represents the input event type. The optional event types are defined in the include/uapi/linux/input.h file. The event types are as follows:
#define EV_SYN 0x00 /* 同步事件 */
#define EV_KEY 0x01 /* 按键事件 */
#define EV_REL 0x02 /* 相对坐标事件 */
#define EV_ABS 0x03 /* 绝对坐标事件 */
#define EV_MSC 0x04 /* 杂项(其他)事件 */
#define EV_SW 0x05 /* 开关事件 */
#define EV_LED 0x11 /* LED */
#define EV_SND 0x12 /* sound(声音) */
#define EV_REP 0x14 /* 重复事件 */
#define EV_FF 0x15 /* 压力事件 */
#define EV_PWR 0x16 /* 电源事件 */
#define EV_FF_STATUS 0x17 /* 压力状态事件 */
Choose different event types according to the different devices used. In the experiments in this chapter, we will use key devices, so we need to select the EV_KEY event type.
Look at the evbit, keybit and other member variables in lines 129 to 137 in the input_dev structure, which are the values of the corresponding different event types. For example, the keybit member corresponding to the key event. The keybit is the bitmap used by the key event. The Linux kernel defines many key values. These key values are defined in the include/uapi/linux/input.h file. The key values are as follows:
215 #define KEY_RESERVED 0
216 #define KEY_ESC 1
217 #define KEY_1 2
218 #define KEY_2 3
219 #define KEY_3 4
220 #define KEY_4 5
221 #define KEY_5 6
222 #define KEY_6 7
223 #define KEY_7 8
224 #define KEY_8 9
225 #define KEY_9 10
226 #define KEY_0 11
......
794 #define BTN_TRIGGER_HAPPY39 0x2e6
795 #define BTN_TRIGGER_HAPPY40 0x2e7
When we write the input device driver, we need to create an input_dev structure variable first, but we don't need to create it manually. The input subsystem provides the following two functions to create and unregister the input_dev structure variable.
struct input_dev *input_allocate_device(void) //申请input_dev结构体
void input_free_device(struct input_dev *dev) //注销input_dev结构体
input_allocate_device函数不需要参数,直接返回申请到的input_dev结构体。
input_free_device函数用来释放掉前面申请到的input_dev结构体。
After applying for the input_dev structure, you need to initialize and specify the event type and event value according to your own device. For example, the event type of a key device is evbit and the event value is keybit.
After the input_dev structure is initialized, use the input_register_device function to register the input_dev device with the Linux kernel. The function prototype is as follows:
int input_register_device(struct input_dev *dev)
dev: input_dev to be registered.
Return value: 0, input_dev registration succeeded; negative value, input_dev registration failed.
Similarly, when unregistering the input driver, you need to use the input_unregister_device function to unregister the previously registered input_dev. The input_unregister_device function prototype is as follows:
void input_unregister_device(struct input_dev *dev)
To summarize the above content, the input_dev registration process is divided into the following steps:
① First use the input_allocate_device function to apply for an input_dev.
② Initialize the event type and event value of input_dev.
③ The input_register_device() function is a function provided by the input core. This function registers the input_dev structure into the input subsystem core.
④ If the input_register_device() function fails to register, you must call the input_free_device() function to release the allocated space. If the function is successfully registered, the input_unregister_device() function should be called in the uninstall function to unregister the input device structure.
The input_dev registration process example code is as follows:
1 struct input_dev *inputdev; /* input 结构体变量 */
2
3 /* 驱动入口函数 */
4 static int __init xxx_init(void)
5 {
6 ......
7 inputdev = input_allocate_device(); /* 申请 input_dev */
8 inputdev->name = "test_inputdev"; /* 设置 input_dev 名字 */
9
10 /*********第一种设置事件和事件值的方法***********/
11 __set_bit(EV_KEY, inputdev->evbit); /* 设置产生按键事件 */
12 __set_bit(EV_REP, inputdev->repbit); /* 重复事件 */
13 __set_bit(KEY_0, inputdev->keybit); /*设置产生哪些按键值 */
14 /************************************************/
15
16 /*********第二种设置事件和事件值的方法***********/
17 keyinputdev.inputdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
18 keyinputdev.inputdev->keybit[BIT_WORD(KEY_0)] |= BIT_MASK(KEY_0);
19 /************************************************/
20
21 /*********第三种设置事件和事件值的方法***********/
22 keyinputdev.inputdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
23 input_set_capability(keyinputdev.inputdev, EV_KEY, KEY_0);
24 /************************************************/
25
26 /* 注册 input_dev */
27 input_register_device(inputdev);
28 ......
29 return 0;
30 }
31
32 /* 驱动出口函数 */
33 static void __exit xxx_exit(void)
34 {
35 input_unregister_device(inputdev); /* 注销 input_dev */
36 input_free_device(inputdev); /* 删除 input_dev */
37 }
Lines 10~23 are all initializing input device events and key values. Three methods are used to set events and key values.
2. The input event is reported
. After the input_dev structure is applied and registered in the input device driver, the input subsystem cannot be used normally because the input device inputs some information, but the Linux kernel still does not know what the input information means and what it means Function, so we need to drive to obtain specific input values, or input events, and then report the input events to the Linux kernel. For example, for a button device, we need to report the button value to the Linux kernel after the button is generated, and the Linux kernel will execute the corresponding function after obtaining the specific button value. Different events report different functions. Let's take a look at the commonly used API functions.
input_event function: used to report the specified event and the corresponding value. The function prototype is as follows:
void input_event(struct input_dev *dev,
unsigned int type,
unsigned int code,
int value)
The meanings of function parameters and return values are as follows:
dev: input_dev to be reported.
type: The type of event reported, such as EV_KEY.
code: Event code, which is the key value we registered, such as KEY_0, KEY_1, etc.
value: event value, for example, 1 means the key is pressed, 0 means the key is released.
Return value: None.
The input_event function can be used to report all event types and event values.
input_report_key function: report key events. The specific function content is as follows:
static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)
{
input_event(dev, EV_KEY, code, !!value);
}
It can be seen that the essence of the input_report_key function is the input_event function. Of course, there is no problem with which function is used. It is more appropriate to use the corresponding function for different devices.
There are also some reporting functions corresponding to other events:
void input_report_rel(struct input_dev *dev, unsigned int code, int value)
void input_report_abs(struct input_dev *dev, unsigned int code, int value)
void input_report_ff_status(struct input_dev *dev, unsigned int code, int value)
void input_report_switch(struct input_dev *dev, unsigned int code, int value)
void input_mt_sync(struct input_dev *dev)
input_sync function: used to tell the Linux kernel input subsystem to report the end. The input_sync function essentially reports a synchronization event. The function prototype is as follows:
void input_sync(struct input_dev *dev)
Several functions are listed. Take the key device as an example, let’s see how to use it:
1 /* 用于按键消抖的定时器服务函数 */
2 void timer_function(unsigned long arg)
3 {
4 unsigned char value;
5
6 value = gpio_get_value(keydesc->gpio); /* 读取 IO 值 */
7 if(value == 0){
/* 按下按键 */
8 /* 上报按键值 */
9 input_report_key(inputdev, KEY_0, 1); /* 最后一个参数 1,按下 */
10 input_sync(inputdev); /* 同步事件 */
11 } else {
/* 按键松开 */
12 input_report_key(inputdev, KEY_0, 0); /* 最后一个参数 0,松开 */
13 input_sync(inputdev); /* 同步事件 */
14 }
15 }
Get the value of the key, and then determine whether the key is pressed, and report the value of the key through the input_report_key function, and the input_sync function indicates the end of the report.
3 input_event structure
The Linux kernel uses the input_event structure to represent all input events. The input_envent structure is defined in the include/uapi/linux/input.h file. The structure content is as follows:
24 struct input_event {
25 struct timeval time;
26 __u16 type;
27 __u16 code;
28 __s32 value;
29 };
Let's take a look at each member variable in the input_event structure in turn:
time: time, which is the time when this event occurs, is the timeval structure type, and the timeval structure is defined as follows:
1 typedef long __kernel_long_t;
2 typedef __kernel_long_t __kernel_time_t;
3 typedef __kernel_long_t __kernel_suseconds_t;
4
5 struct timeval {
6 __kernel_time_t tv_sec; /* 秒 */
7 __kernel_suseconds_t tv_usec; /* 微秒 */
8 };
The two member variables tv_sec and tv_usec are of long type, which is 32 bits. This must be remembered, and we will use it when we analyze the event report data later.
type: Event type, such as EV_KEY, indicating that this event is a key event, and this member variable is 16 bits.
code: Event code. For example, in the EV_KEY event, code represents the specific key code, such as KEY_0, KEY_1, and so on. This member variable is 16 bits.
value: value. For example, in the EV_KEY event, value is the key value, indicating whether the key has been pressed, if it is 1, it means the key is pressed, if it is 0, it means the key is not pressed or the key is released.
The input_envent structure is very important, because all input devices are finally presented to the user according to the input_event structure, and user applications can obtain specific input events or related values, such as key values, through input_event.