The input subsystem consists of the driver layer, input subsystem core, and event processing layer. An input event, such as moving the mouse or pressing the keyboard, arrives at the application of the user control in the order of driver> inputcore> event handler> userspace.
Driver layer: converts the underlying hardware input into a unified event form and wants to input the core (input core) for reporting.
Input subsystem core: linking up and down. Provide the input device registration and operation interfaces for the driver layer, for example, input_register_device; Notify the event processing layer to process the event; generate corresponding device information under/proc
Event Processing Layer: Mainly used to interact with user spaces. (In Linux, all the devices in the user space are processed in the original file. Because fops interfaces are provided in common drivers and corresponding device files are generated under/dev, these operations are completed by the event processing layer in the input subsystem)
Device description:
Input_dev Structure
The core work of implementing a device driver is to report input events (events, which are described by the input_event structure) such as buttons and touch screens to the system, and there is no need to care about file operation interfaces. The driver reports the event to the user space through inputcore and eventhandler.
Register the input device function:
Int input_register_device (struct input_dev * Dev)
Function for logging out of the input device:
Void input_unregister_device (struct input_dev * Dev)
Driver implementation-initialization (event support ):
Set_bit () tells the input subsystem which events and buttons are supported. For example:
Set_bit (ev_key, button_dev.evbit) (where button_dev is struct
Input_dev type)
Struct input_dev has two members:
Evbit:
Event type (including
Ev_rst, ev_rel, ev_msc, ev_key, ev_abs, ev_rep, etc)
Keybit:
Key type (when the event type is ev_key, including
Btn_left, btn_0, btn_1, btn_middle, etc)
Driver implementation -- Report events:
The functions used to report ev_key, ev_rel, and ev_abs events are void
Input_report_key (struct
Input_dev * Dev, unsigned int code, int value)
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)
Driver implementation-end of report:
Input_sync () synchronization is used to tell the input core subsystem that the report has ended.
Example: In the driver of a touch screen device, the entire report process of one click is as follows:
Input_reprot_abs (input_dev, abs_x, x); // X coordinate
Input_reprot_abs (input_dev, abs_y, Y); // y coordinate
Input_reprot_abs (input_dev, abs_pressure, 1 );
Input_sync (input_dev); // synchronization ends
Instance analysis (Key interrupt program ):
// Key initialization
Static int _ init button_init (void)
{// Application interrupted
If (request_irq (button_irq, button_interrupt, 0, "button", null ))
Return-ebusy;
Set_bit (ev_key, button_dev.evbit); // supports ev_key events.
Set_bit (btn_0, button_dev.keybit); // supports two device keys.
Set_bit (btn_1, button_dev.keybit );//
Input_register_device (& button_dev); // register the input device
}
/* Report events during key interruption */
Static void button_interrupt (int irq, void * dummy, struct pt_regs * FP)
{
Input_report_key (& button_dev, btn_0, INB (button_port0); // read the value of the Register button_port0
Input_report_key (& button_dev, btn_1, INB (button_port1 ));
Input_sync (& button_dev );
}
Conclusion: The input subsystem is still a character device driver, but the amount of code is much reduced. The input subsystem only needs to complete two tasks: initialization and Event Reporting (this is achieved through interruptions in Linux ). You may use sourceinsignt to input input_init to search for the implementation of the input subsystem.