Kernel Input Subsystem Analysis

Source: Internet
Author: User

Open/DRIVER/INPUT/INPUT.C This is the core of the input code.

Found it

static int __init input_init (void)


Err = Class_register (&input_class); Registers a class that will appear in the Sys/class input directory after registration.


Err = Register_chrdev (input_major, "input", &input_fops), registering an INPUT device with a main device number of 13,


Open Input_fops

static const struct File_operations Input_fops = {
. Owner = This_module,
. open = Input_open_file,

Only one to register an open function in the kernel, then read,write, and so on should be registered, should be registered in the Input_open_file,

parsing static int input_open_file (struct inode *inode, struct file *file)


struct Input_handler *handler = Input_table[iminor (inode) >> 5]; Assigns a member of the input_table array to handler, which is analyzed in detail below

if (!handler | |!) ( New_fops = Fops_get (handler->fops))) Gets the file_operations structure in handler

Old_fops = file->f_op;
File->f_op = New_fops;

Err = New_fops->open (inode, file); Open this handler->fops->open function


Q 1:input_table[iminor (inode) >> 5] This array is someone who assigns a value.

int Input_register_handler (struct Input_handler *handler)


Init_list_head (&handler->h_list);

Input_table[handler->minor >> 5] = handler; Assigns the handler to the Input_table array, and the position is divided by this device number by 32.

List_add_tail (&handler->node, &input_handler_list); Add this handler node to the Input_handler_list list

List_for_each_entry (Dev, &input_dev_list, node) iterates through the Input_dev devices in the Input_dev_list list at once, then matches the handler that are passed in, looking for input_ Is there a device in Dev_list that supports this handler?
Input_attach_handler (Dev, handler); The exact matching method will be analyzed in detail next


Question 2: Then who will call Input_register_handler, which is where handler comes from

Search to get

EVBUG.C (drivers\input): 106:return Input_register_handler (&evbug_handler);
EVDEV.C (drivers\input): 745:return Input_register_handler (&evdev_handler);
Input.c (drivers\input): 1193:int input_register_handler (struct Input_handler *handler)
Input.c (drivers\input): 1219:export_symbol (Input_register_handler);
Input.h (include\linux): 1130:int input_register_handler (struct input_handler *);
JOYDEV.C (drivers\input): 647:return Input_register_handler (&joydev_handler);
KEYBOARD.C (Drivers\char): 1367:error = Input_register_handler (&kbd_handler);
----= Input_register_handler (&kbd_handler); Matches (1 in 1 files)----
KEYBOARD.C (Drivers\char): 1367:error = Input_register_handler (&kbd_handler);
Then open the KEYBOARD.C, take it as an example, and analyze how this is registered.
static struct Input_handler Kbd_handler = {
. event = Kbd_event,
. connect = Kbd_connect,
. Disconnect = Kbd_disconnect,
. Start = Kbd_start,
. Name = "KBD",
. id_table = Kbd_ids,
int __init kbd_init (void)


Error = Input_register_handler (&kbd_handler);


Actually, it is. Kbd_handler This structure is passed to input_table;

Let's summarize:

int __init kbd_init (void)->error = Input_register_handler (&kbd_handler)

{Input_table[handler->minor >> 5] = handler;

List_add_tail (&handler->node, &input_handler_list);

List_for_each_entry (Dev, &input_dev_list, node)
Input_attach_handler (Dev, handler);


Analyze how to match the Input_attach_handler (Dev, Kbd_hander)


id = input_match_device (handler->id_table, dev); If the match returns an ID successfully

Error = Handler->connect (handler, Dev, id), then the device and Kbd_handler are connected based on the returned ID, and the Connect function is Kbd_handler->kbd_ Connect


Next detailed analysis Input_match_device


for (; Id->flags | | id->driver_info; id++) {

        if (id->flags & Input_device_id_match_bus)
            if (id->bustype! = Dev->id.bustype)

For handler->id->flags, compare the different types if the comparison succeeds
Enter the following macro comparison, otherwise enter the next ID

Match_bit (Evbit, Ev_max);
The type of event supported by the position comparison, only if all unmatched successes are successfully returned, otherwise enter the next ID
return ID;

return NULL;


If the match succeeds, it will enter the connection, analyze Kbd_connect

static int kbd_connect (struct input_handler *handler, struct input_dev *dev,const struct input_device_id *id)


struct Input_handle *handle; define a Input_hanlde pointer

handle = Kzalloc (sizeof (struct input_handle), Gfp_kernel), allocating input_handle structural body space

Handle->dev = dev; make dev in assigned handle point and handler match Input_dev
Handle->handler = handler; make handler in handle point and Input_dev match Input_handler
Handle->name = "KBD";

Error = Input_register_handle (handle); Register this newly assigned handle;

Error = Input_open_device (handle);


Continue analysis

int Input_register_handle (struct input_handle *handle)
struct Input_handler *handler = handle->handler;

List_add_tail (&handle->d_node, &handle->dev->h_list); Hang the Handle->d_node on the input_dev->h_list.
List_add_tail (&handle->h_node, &handler->h_list); Handle->h_node Mount Handler->h_list on
This allows the handle to be found through h_list in Input_handler and then handle->dev to find a matching Input_dev

You can also find Handl by H_list in Input_dev, and then find a matching input_handler by Handle->handler

So Input_handler,input
if (Handler->start)
Handler->start (handle);

return 0;
} Continue Analysis

int Input_open_device (struct input_handle *handle)
struct Input_dev *dev = handle->dev;
int err;
Handle->open++;//handle Open Count plus 1, note and evdev the difference between open

if (!dev->users++ && dev->open)
Err = Dev->open (dev);//If this input-dev does not have a process reference and defines the open
method, you call the Open method,

if (err)//retval=1 description, did not open successfully,

Summing up the role of Connect is to create a new struct input_handle based on the matching successful Input_dev and Input_handler, and then assign the dev and handler in the struct to Input_dev and input_ Handler

In this way, the Input_dev and the Input_hanlder can be connected by input_handle the structure;

static int __init input_init (void)->err = Register_chrdev (input_major, "input", &input_fops)->input_fops- > Input_open_file

{struct Input_handler *handler = Input_table[iminor (inode) >> 5];

if (!new_fops->open) {
Fops_put (New_fops);

Err = New_fops->open (inode, file), this open function is the open in Kbd_handler FoPs, which is not initialized fops in this keyboard;


For registered input devices:
Put the list
List_add_tail (&dev->node, &input_dev_list);

For each of the Input_handler, call Input_attach_handler
List_for_each_entry (handler, &input_handler_list, node)
Input_attach_handler (Dev, handler); Judging by Input_handler's id_table, can you support this input_dev?

id = input_match_device (handler->id_table, Dev);

Error = Handler->connect (handler, dev, id);

Similar to Input_handler, we analyze ourselves

Kernel Input Subsystem Analysis

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.