Technorati Tags: Kernel input subsystem Inputs
In Linux, input devices (such as keystrokes, keyboards, touch screens, mice, etc.) are typical character devices, the general working mechanism, is the bottom of the key, touch, trigger an interrupt, or drive through the Timer timing query, through the two ways to notify CPU,CPU and then through the SPI, I²c or i/ O interface reads the key value, coordinates and other data, puts in the buffer, the character device driver manages the buffer, provides the read interface upwards for the application to use.
In the above workflow, only the terminal, read the value is the root of the specific hardware device-related, and input event buffer management and character device-driven interface functions are common, so it is necessary to unify these different input devices, refining the general part.
The overall framework of the input subsystem for Linux is as follows:
This paper introduces the core data structure body, introduces a simple example, and then introduces the basic function function.
Core Data Structure body
Input subsystem has three layers, the core of the structure has four, respectively, input event input_event, input device Input_dev, core processing Input_handle, event processing Input_handler, divided into different levels of input, In these structures, Input_handle is at the heart of the situation. As shown in the following:
The entire input subsystem has two global linked lists, one is the input_dev_list linked list, which has the current system, all the underlying input devices, one is the input_handler_list linked list, inside the current system, all the event handler functions.
Input device
struct Input_dev {
.....
The ID of the struct input_id id;//and input_handler, including bus type, manufacturer, product type, version
Unsigned long evbit[bits_to_longs (ev_cnt)]; //Device supported event types, such as key event Ev_key
Unsigned long keybit[bits_to_longs (key_cnt)]; ///device supported sub-event types, such as key values
Int (*event) (struct Input_dev *dev, unsigned int type, unsigned int code, int value);
unsigned long key[bits_to_longs (key_cnt)];//reaction device Current key state
struct Input_handle *grab;//currently occupies the input_handle of the device
struct List_head h_list;//The linked header is used to link the input_handle associated with this device
struct List_head node; Used to link this device to the Input_dev_list
}
Event handlers
struct input_handler{
.....
int minor; Indicates the device's secondary device number
/*event for handling Events */
void (*event) (struct input_handle *handle, unsigned int type, unsigned int code, int value);
/*connect used to establish handler and device contact */
Int (*connect) (struct Input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
Some processing functions of const struct File_operations *fops;//handler
The const struct INPUT_DEVICE_ID *id_table;//is used to match device, which is the input device supported by the event processor
const struct INPUT_DEVICE_ID *blacklist;//matches the blacklist, this is the input device that the event handler should ignore
struct List_head h_list;//This list is used to link the input_handle structure that he supports, and a input_handler structure is generated after Input_dev and Input_handle are paired.
struct List_head node; Link to input_handler_list, which links all event handlers registered to the kernel
}
Connecting the structure body
Each input_handle structure represents a successful pairing of Input_dev and Input_handler.
struct Input_handle {
void *private; Each paired event handler assigns a corresponding device structure, such as the EVDEV structure of the Evdev event handler, noting that this structure is different from the Input_dev of the device driver layer, which is saved here when the handle is initialized.
int open; Open flag, each input_handle open before operation, this is generally through the event handler's Open method indirectly set
const char *name;
struct Input_dev *dev; The associated INPUT_DEV structure
struct Input_handler *handler; The associated Input_handler structure
struct List_head d_node; The Input_handle is connected to the H_list linked list on the Input_dev via the D_node.
struct List_head h_node; Input_handle is connected to the Input_handler h_list linked list via H_node.
};
The relationship between data structures
struct INPUT_DEV The basic data structure of the physical input device, including some information about the device
struct Input_handler event handling struct, defining how events are handled logically
struct Input_handle A struct used to create a relationship between Input_dev and Input_handler
Input_dev are linked together through a global input_dev_list. This is done when the device is registered.
Input_handler are linked together through a global input_handler_list. This is done when the event handler is registered (the event handler typically comes with a kernel that does not require us to write)
Input_hande does not have a global list, and it registers itself on the h_list of Input_dev and Input_handler respectively. Through Input_dev and Input_handler can find Input_handle in the device registration and event processor, registration will be paired work, after pairing will be implemented link. Input_dev and Input_handler can also be found through Input_handle.
So why would a input_device and Input_handler have h_list instead of a handle? Because a device may correspond to multiple handler, and a handler cannot handle only one device, such as a mouse, it can correspond to even handler or mouse handler, Therefore, when registering with handler in the system, it is possible to generate two instances, one is Evdev, the other is Mousedev, and there is only one handle in any instance. The way in which events are passed is determined by which instance the user program opens. It is easy to understand in the latter case that an event driver cannot serve one or even one device, and there may be multiple devices in the system that can use such handler, such as the event handler to match all the devices. In the input subsystem, there are 8 event drivers, each of which can have a maximum of 32 devices, so the total number of dev instances can be up to 256.
Input Driver Example
Here is an example of a simple drive to introduce
#include <asm/irq.h>
#include <asm/io.h>
static struct Input_dev *button_dev; /* input Device structure body */
static irqreturn_t button_interrupt (int irq, void *dummy)/* Interrupt handler function */
{
Input_report_key (Button_dev, Btn_0, INB (button_port) & 1); / * Report generated key events to input subsystem * /
Input_sync (Button_dev); / * Notifies the recipient that a report has been sent * /
return irq_handled;
}
static int __init button_init (void)/* Load function */
{
int error;
if (Request_irq (BUTTON_IRQ, button_interrupt, 0, "button", NULL))/ * Request Interrupt, bind interrupt handler * /
{
PRINTK (kern_err "Button.c:can ' t allocate IRQ%d\n", BUTTON_IRQ);
Return-ebusy;
}
Button_dev = input_allocate_device (); / * Assign a device structure * /
The Input_allocate_device () function allocates a space in memory for the input device structure and initializes its primary members.
if (!button_dev)
{
PRINTK (kern_err "Button.c:not enough memory\n");
Error =-enomem;
Goto ERR_FREE_IRQ;
}
Button_dev->evbit[0] = Bit_mask (Ev_key); / * Set Key information * /
Button_dev->keybit[bit_word (btn_0)] = Bit_mask (BTN_0);
Each is used to set the event generated by the device and the reported key values. There are two members in Struct Iput_dev, one is evbit. One is keybit. Separate with
//Indicates device The supported actions and key values.
Error = Input_register_device (button_dev); / * Register an input device * /
if (Error)
{
PRINTK (kern_err "button.c:failed to register device\n");
Goto Err_free_dev;
}
return 0;
Err_free_dev:
Input_free_device (Button_dev);
ERR_FREE_IRQ:
FREE_IRQ (BUTTON_IRQ, button_interrupt);
return error;
}
static void __exit button_exit (void)/* Unload function */
{
Input_unregister_device (Button_dev); /* Logout key device */
FREE_IRQ (BUTTON_IRQ, button_interrupt); /* Release the interrupt line occupied by the key */
}
Module_init (Button_init);
Module_exit (Button_exit);
This demo code, in Button_init (), first registers the interrupt handler function, and then calls the Input_allocate_device () function to assign a input_dev struct, and calls Input_register_ Device function to register it. In the interrupt processing function, the demo will report the received key information to the input subsystem, and the input subsystem provides key input information to the user state program.
In this simple drive, it involves a few questions.
1. How the input device passes events to the core layer
2. How the core layer finds event handlers for corresponding events
3. How the underlying input device driver is connected to the event processing layer
Basic function functions
The following is a brief introduction to the overall flow of input, starting with the use process, where only the main code flow is noted.
1. Assigning an input device
From the note, release an input device that is not yet registered, use Input_free_device, release a registered device, and use Input_unregister_device.
Since there are no input parameters, it is possible to guess that some of the configuration of this assigned Input_dev is the default configuration.
In this, the more important there are two linked list h_list and node, after allocation, we need to add their own configuration information on the basis of the default configuration.
2. Register an input device
From the comment, you know that the incoming parameter must be a return value of Input_allocate_device.
This function will set the basic event type supported by Input_dev, note that one device can support one or more event types. The input subsystem needs to appear in the Sysfs file system, so the device name of input in SYSFS is set here.
The underlying input device Input_dev is then added to the global device chain list input_dev_list, and for each handler function in the global list input_handler_list, a call
Input_attach_handler ().
Each time the Input_dev is registered, it iterates through the event-handling list input_handler_list, looking for an event handler corresponding to the input device.
Each time the Input_hanlder is registered, it traverses the device list input_dev_list, looking for the input device corresponding to the event handler.
The above two operations are almost symmetrical, and the mechanism works with the device and device driver in platform to find the type.
The specific code is as follows:
Platform mechanism of the search, is based on the device name and device driver name to match, here is no exception, the matching process, by comparing the ID members of Input_dev and Input_handler, specifically for the ID member of the bus type, device manufacturer, device number, The device version is consistent to determine if the match is successful.
3. Input device Find event handler
Normally, a match is made using the id_table in the event handler and the input device Input_dev.id member. Id_table points to the list of devices supported by the event handler.
After the match is successful, call Handler->connect and connect handler and Input_dev together.
4. Report input events to the input core layer
The core function in this is input_handle_event (Dev,type,code,value), which is a large switch, the first level of event type type, level two switch for event code, here only the analysis of key-related:
The value of disposition is as follows, which indicates how the input event is handled.
#define INPUT_IGNORE_EVENT 0//Indicates ignore event, do not process it
#define INPUT_PASS_TO_HANDLERS 1//indicates handing over events to handler processing
#define INPUT_PASS_TO_DEVICE 2//indicates handing over events to Input_dev processing
#define Input_pass_to_all (Input_pass_to_handlers | Input_pass_to_device)
If the event is passed to the device itself, it invokes the event function of the device driver itself to handle the events.
If the event is passed to the upper event handler, call Input_pass_event to pass the event, and the input device will be called the event () function of the handler to handle the input event.
Note: The event will only be received if the handle is turned on.
5. Input subsystem inputs Event processing layer
The input event processing layer is registered into the system when the system is initialized.
The core data structure of the event processing layer of the input subsystem is Input_handler, and the event handlers for all input subsystems are hung in input_handler_list. In
6. Enter Event processing layer Registration
The system defines 8 input event processing layers, which are connected by handler->h_list, and also stored in global input_table arrays (their indexes in the array are the values of the device number to the right 5 bits) and the global Input_handler_ List of lists.
As with the input device registration, the input event processing registration needs to look for the corresponding input device. The code is as follows:
In Input_attach_handler, error = Handler->connect (handler, Dev, id) is finally called;
The Evdev_connect function, which initializes input handle here, and registers to the system.
In this case, the handle will be hung on the h_list linked list of the corresponding input device. The handle is also attached to the hlist linked list of the corresponding handler, so handle can be viewed as an information set of handler and input device In this structure, a matching successful handler and input device is assembled. In this way, handler and input dev match together.
7. Event layer handles events from the core layer
In this case, the event function, the Evdev_event, is invoked. Whenever input dev reports an event, it is handed over to the handler event function that matches it, and in this case it is processed by iterating through the list to invoke Evdev_pass_event.
The operation here is to save the event upload data to Client->buffer. Client->head is the current data location, here is a ring buffer,
Writing data is written from Client->head. While reading data is read from Client->tail.
After writing, you can read the data from the buffer by initiating a sigio signal to the upper layer to notify the event that it has occurred.
7. Enter the file access interface for the event handler function
Input device in the upper layer performance of the main device number is input_major device file, read and write to him through the VFS, and finally passed to the Evdev_fops file operation structure.
1: static ssize_t evdev_read (structchar __user *buffer,
2: size_t count, loff_t *ppos)
3: {
4: struct evdev_client *client = file->private_data;
5: struct evdev *evdev = client->evdev;
6: structevent;
7: int retval;
8:
9: if (Count < Input_event_size ())
Ten: return -einval;
One :
: if (client->head = = Client->tail && evdev->exist & &
: (File->f_flags & O_nonblock))
: return -eagain;
:
: retval = wait_event_interruptible (evdev->wait,
: client->head! = Client->tail | |!evdev->exist);
: if (retval)
: return retval;
:
: if (!evdev->exist)
: return -enodev;
At :
: while (retval + input_event_size () <= count &&
: evdev_fetch_next_event (client, &event)) {
£ º
: if (input_event_to_user (buffer + retval, &event))
: return -efault;
£ º
: retval + = Input_event_size ();
: }
:
: return retval;
: }
First, it determines if the buffer size is sufficient. In the case of reading data, there may be no data readable in the current buffer. Here, sleep, wait for the cache.
There is data in the area. If you are sleeping, the. Condition is met. is not going to sleep state and returned directly. Then the buffer size is raised according to read ().
The data in the client is written to the cache in the user space.
Reference documents:
http://blog.csdn.net/lbmygf/article/details/7360084
Http://blog.chinaunix.net/uid-27717694-id-3758334.html
Linux Input Subsystem