[Content Summary]
This paper introduces the three components of Input-subsystem, analyzes the main structures and functions, and how they relate to each other.
[Overview]
The kernel's input subsystem is a driver that unifies disparate input devices such as keyboards, mice, tracking balls, joysticks, touch screens, accelerometers, and handwriting boards. The benefits of the input subsystem:
Unified the processing function of similar input devices with different physical forms. For example, all kinds of mouse, whether it is PS/2, USB, or Bluetooth, do the same treatment;
Provides a simple event interface for distributing input reports to user applications;
The general part of the input driver is extracted, the driver is simplified, and the consistency is introduced.
[Input-subsystem frame composition]
[Input-core]
The core layer provides the programming interface of the device driver layer, and provides the programming interface for the event processing layer.
[Related documents]
Driver/input/input.c
Include/linux/input.h
[Key data Structures]
Struct Input_dev The basic data structure of the physical input device, including some information related to the equipment;structInput_dev {ConstChar*name; Constchar *phys; Constchar *uniq;structINPUT_ID ID; UnsignedLongEvbit[bits_to_longs (ev_cnt)]; UnsignedLong keybit[bits_to_longs (key_cnt)]; Unsignedlong relbit[bits_to_longs (rel_cnt)]; unsignedlong absbit[bits_to_longs (abs_cnt)]; unsignedlong mscbit[bits_to_longs (msc_cnt)]; unsignedlong ledbit[bits_to_longs (led_cnt)]; unsignedlong sndbit[bits_to_longs (snd_cnt)]; unsignedlong ffbit[bits_to_longs (ff_cnt)]; unsignedlong swbit[bits_to_longs (sw_cnt)]; ........ structDevice Dev;structList_head h_list;structList_head node; }; Name input device name;
Bitmap supported by the Evbit event;
The bitmap supported by the Kerbit key;
Dev embedded device structure body;
The h_list linked list indicates a handler that is associated with this input_dev;
The node list connects this input_dev to the global Input_dev_list list, and all Input_dev in the www.linuxidc.com kernel are connected to it;
Struct Input_handler event handling structure to define methods for handling events;structInput_handler {void*Private;void(*event) (structInput_handle *handle, unsigned inttype, unsignedintCodeintValue);int(*connect) (structInput_handler *handler, Structinput_dev *dev,Conststructinput_device_id *id);void(*disconnect) (structInput_handle *handle);void(*start) (structInput_handle *handle); Conststruct file_operations *fops; Intminor; Constchar *name; Conststruct input_device_id *id_table; Conststruct input_device_id *blacklist;structList_head h_list;structList_head node; }; The event () function is used by the input subsystem to handle events sent to the device;
Connet () used to connect handler and Input_dev;
The h_list linked list indicates a handler that is associated with this input_handler;
The node list connects this input_handler to the global Input_handler_list list, and all the input_handler in the kernel are connected to it;
Struct Input_handle is used to create the structure of the relationship between Input_dev and Input_handler;structInput_handle {void*Private; Intopen; Constchar *name; Structinput_dev *dev; Structinput_handler *handler;structList_head D_node;structList_head H_node; }; D_node the handle into the device-related list, which is placed in the list of input_dev->h_list;
H_node the handle into a input_handler-related table, which is placed in a list of input_handler->h_list representations;
[Subsystem initialization function]Staticint__init Input_init (void) {Interr; Input_init_abs_bypass (); Err= Class_register (&input_class);if(ERR) {PRINTK (kern_err "input:unable to register Input_dev class\n"); Returnerr; } err= Input_proc_init ();if(err) Gotofail1; Err= Register_chrdev (input_major, "INPUT", &input_fops);if(ERR) {PRINTK (kern_err "input:unable to register char major%d", input_major); GOTOFAIL2; } Return0; Fail2:input_proc_exit (); Fail1:class_unregister (&input_class); returnErr The initialization function will complete three jobs:
1, Class_register (&input_class) register an input class;
2, Input_proc_init () in the proc under the establishment of related interactive documents;
3, Register_chrdev (Input_major, "INPUT", &input_fops) registered as a character device.
[File_operations]StaticConststructFile_operationsinput_fops = {. owner= this_module,. open= Input_open_file,}; You're going to wonder why file_operations only implemented the Open method, OK, let's look at the source code of Input_open_fileStaticintInput_open_file (structInode*inode,structFile *file) {Structinput_handler *handler; Conststruct file_operations *old_fops, *new_fops = NULL; Interr; Lock_kernel (); /*no Load-on-demand here? * * handler= Input_table[iminor (inode) >> 5];if(!handler | |!) (New_fops = Fops_get (handler->fops))) {err=-enodev; Gotoout; }/* that ' s _really_ odd. Usually NULL->openmeans "Nothing special", * not "no device". Oh, so ... *if(!new_fops->open) {fops_put (new_fops); Err=-enodev; Gotoout; } old_fops= file->f_op; File->f_op= New_fops; Err= New_fops->open (inode, file);if(ERR) {fops_put (FILE->F_OP); file->f_op= Fops_get (old_fops); } fops_put (Old_fops); Out:unlock_kernel (); Returnerr; This open method completes two tasks:
1, redirect the File->fops to the Input_handler->fops, because Input_handler->fops defines the action method of the specific event; through file-> FoPs we can operate on different devices;
2, open the device with Input_handler->fops.
[InputDevice Drivers]
The driver layer provides read and write access to the hardware registers and the response of the underlying hardware to the user input access to the standard input event, which is then submitted to the event processing layer through the core layer.
[Related documents]
Driver/input/mouse
Drvier/input/touchscreen
Driver/input/joystick
......
[Input_dev]
The Struct Input_dev represents an input device, the main structure of the drive layer, www.linuxidc.com the work we do is to populate this structure.
[Assign an input device]
struct Input_dev*input_allocate_device (void)
[Registration and cancellation]
int Input_register_device (struct Input_dev*dev)
void Input_unregister_device (Structinput_dev *dev)
[Input_register_device Analysis]intInput_register_device (struct input_dev*dev) { Staticatomic_t input_no = atomic_init (0); structinput_handler *handler; constchar *path; interror; __set_bit (ev_syn, dev-> Evbit); /* support all event */ /* * If delay and period are pre-set by thedriver, then autorepeating * is handled by the drivEr itself and we don ' tdo it in input.c. */ init_timer (&dev->