Input devices have commonality: Interrupt drive + character Io, based on layered thinking, the Linux kernel extracts the public parts of these devices, provides interfaces based on Cdev, designs input subsystems, and all devices built using the input subsystem use the main device number 13. The input subsystem also supports the automatic creation of device files, which are created under "/dev/input/" by blocking IO Read and write methods. As shown in. The input subsystem in the kernel is divided into the device driver layer, input core layer, event processing layer. Because each input device escalated events differently, in order for the application layer to be able to identify escalated events well, the kernel also encapsulates a standard interface for the application layer to describe an event, which is in "/include/upai/linux/input".
The device driver layer is the specific hardware-related implementation, is also the main part of the driver development,
The input core layer mainly provides some APIs for device driver layer invocation, and the data escalated by these API device drivers can be passed to the event processing layer.
The event processing layer is responsible for creating the device files and passing escalated events to the user space.
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/1022162/201702/1022162-20170222224016851-52601100. PNG "style=" margin:0px;padding:0px;border:0px; "alt=" 1022162-20170222224016851-52601100.png "/>
Use of input
The
Input object describes an input device, including the events it may escalate, which are described using bitmaps, and the corresponding tools provided by the kernel help us build an input object that you can refer to in the kernel documentation "documentation/input/ Input-programming.txt ", there is a detailed description of the use of the input subsystem.
Input Device Object 121 struct input_dev {122 const char *name;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)];135 Unsigned long sndbit[bits_to_longs (snd_cnt)];136 unsigned long ffbit[Bits_to_longs (FF_CNT)];137 unsigned long swbit [Bits_to_longs (SW_CNT)];155 162 unsigned long key[bits_to_longs (key_cnt)];163 unsigned long led[bits_to_longs (led_cnt)];164 unsigned long snd[bits_to_longs (snd_cnt)];165 unsigned long sw[bits_to_longs (sw_cnt)];166 172 struct Input_handle __rcu *grab;179 180 struct device dev;181 182 struct list_head h_list;183 struct list_head node;190 };
struct INPUT_DEV
--122--> This name is not a device name, the device name of the input subsystem is specified in the subsystem source code, not this.
--129--> device supported input event bitmap, Ev_key,ev_rel, etc
--130--> for keystroke events, the input sub-event bitmap supported by the device
--132--> for relative coordinate events, the device supports relative coordinate sub-event bitmaps
--133--> for absolute coordinate events, the device supports absolute coordinate sub-event bitmaps
--134--> supported sub-event bitmap for hybrid devices
--180--> says this is a device.
--182-->h_list is a linked list used to link related handle.
--183-->node linked lists used to link other Input_dev
Allocation/Release
drivers/input/input.c//creates an input object struct Input_dev *input_allocate_device (void);//releases an input object void Input_free_ Device (struct Input_dev *dev);
Initialization
Initializing an input object is the main work of writing a drive using the input subsystem, which specifies common input events for some common input devices in the header file "Include/uapi/linux/input.h". These macros and arrays are the tools that we initialize the input object to. These macros are used in both event resolution and driver event registration in the user space and can be seen as a communication protocol for both driver and user space, so it is important to understand the meaning. In the input subsystem, the occurrence of each event is described using the event (type), child event (code), and value (value) level three, for example, key event, key F1 child event, key F1 the value of the child event trigger is high Level 1. Note that events and sub-events and values are mutually reinforcing, and only the event Ev_key is registered to register the child event Btn_0, and only this is meaningful.
The following is the Type field of the event object for the application layer, which is the kernel convention
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/1022162/201702/ 1022162-20170222223927132-2029841847.png "style=" margin:0px;padding:0px;border:0px; "alt=" 1022162-20170222223927132-2029841847.png "/>
These are the types of key sub-events, and you can see the definition of the PC key value
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/1022162/201702/ 1022162-20170222223931007-1806760144.png "style=" margin:0px;padding:0px;border:0px; "alt=" 1022162-20170222223931007-1806760144.png "/>
In addition to describing commonly used events, the kernel also provides tools to properly populate these events in the bitmap that describes the events in the input object.
First//This method is ideal for registering multiple events simultaneously button_dev->evbit[0] = Bit_mask (Ev_key) | Bit_mask (Ev_rel); Button_dev->keybit[bit_word (btn_mouse)] = Bit_mask (btn_left) | Bit_mask (btn_right) | Bit_mask (Btn_middle);
The second//is usually used to register only one event set_bit (ev_key,button_dev.evbit); Set_bit (btn_0,button_dev.keybit);
Registration/Logout
An input object is initialized, and then it needs to be registered to the kernel
Registers the input object to the kernel int input_register_device (struct input_dev *dev);//Unregisters an input object from the kernel void Input_unregister_device (struct Input_dev *dev);
Drive Layer Reporting Events
At the right time (because the input is ultimately an interrupt representation, so usually in the drive interrupt handler) The driver can escalate the registered event and can escalate multiple events at the same time, the following is the API provided by the kernel
Escalate the specified event + child event + value void input_event (struct input_dev *dev,unsigned int type,unsigned int code,int value);//escalation key value void Input_ Report_key (struct input_dev *dev,unsigned int code,int value);//escalation absolute coordinate void input_report_abs (struct Input_dev *dev, unsigned int code,int value);//Report synchronization event void Input_report_rel (struct input_dev *dev,unsigned int code,int value);// Synchronize all escalated void Input_sync (struct input_dev *dev);
There are 2 points to be aware of when reporting an event:
The report function will not be really reported, just ready to report, Sync will really just report the incident really reported to the input core
Input core will make the decision to escalate the event processing layer, so for the key event, must first Report 1 0 (or vice versa), not only report 1 or 0, so that the core will be considered an event was mistakenly triggered several times and only reported once, although we really pressed several times.
Application Layer Parsing
The event processing layer will eventually organize the events of the report to be organized into a struct input_value[] in the form of the application layer, when the application layer obtains the escalated event from the corresponding device file, it should be noted that:
The number of received array elements will be more than the underlying empty element, similar to writing of_device_id[] when the last empty element, this application layer should be noted when parsing.
The event processing layer does not cache the received events, and if a new event arrives, it will be overwritten even if the old event is not read, so the application needs to be read in a timely manner.
As mentioned earlier, the macros in "Include/uapi/linux/input.h" are communication protocols that are shared between the application layer and the driver layer, so the application layer only needs "include <linux/" when parsing the received struct Input_value object. Input.h> "To use the macros in them.
/* * The event structure itself */struct input_event {struct timeval time; __U16 type; __U16 Code; __s32 value;};
Input analysis
As mentioned above, the input subsystem uses a three-tier structure to implement the transfer of the drive event to the application layer. Specifically, each of these three levels is composed of a structure chain list, in the device drive layer, the core structure is input_dev; at the input core layer, it is input_handle; At the event processing level, it is input_handler. The kernel combines the three by linking lists and pointers, finally realizing many-to-many mappings between Input_dev and Input_handler, which can be described in a simple form.
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/1022162/201702/ 1022162-20170222223951288-2060693637.png "style=" margin:0px;padding:0px;border:0px; "alt=" 1022162-20170222223951288-2060693637.png "/>
Template
The following template first uses the input subsystem to escalate key events and then reads them at the application layer.
Input key Device driver
/{
[Email protected] {
compatible = "Xj4412,key";
Interrupt-parent = <&gpx1>;
Interrupts = <2 2>;
};
};
static struct input_dev *button_dev;static int button_irq;static int Irqflags;static irqreturn_t button_interrupt (Int irq, void *dummy) { input_report_key (button_dev, btn_0, 0); input_report_key (Button_dev, btn_0, 1); input_sync (Button_dev); return irq_ HANDLED;} static int button_init (void) {&NBSP;&NBSP;&NBSP;&NBSP;REQUEST_IRQ (button_irq, button_ interrupt,irqflags, "button", null)) ; button_ Dev = input_allocate_device (); button_dev->name = "button"; button_dev->evbit[0] = bit_mask (Ev_key); button_ Dev->keybit[bit_word (BTN_0)] = bit_mask (BTN_0); Input_register_device (Button_dev); return 0;} Static int button_exit (void) { input_free_device (Button_dev); &NBSP;&NBSP;FREE_IRQ (Button_irq, button_interrupt); return 0; }static int key_probe (Struct platform_device *pdev) { struct resource *irq_res; irq_res = platform_get_resource (pdev, ioresource_irq, 0); if (irq_res) { button_irq = irq_res->start; irqflags = irq_res->flags & irqf_trigger_mask; }else{ return -EINVAL; } return button_init ();} Static int key_remove (Struct platform_devIce *dev) { return button_exit ();} struct of_device_id of_tbl[] = { {.compatible = "xj4412, Key ",}, {},}; Module_device_table (OF,&NBSP;OF_TBL);struct platform_driver key_drv = { .probe = key_probe, .remove = key_remove, .driver.name = "Keydrv", .driver.of_match_table = of_tbl,}; Module_platform_driver_register (KEY_DRV); Module_license ("GPL");
The application layer gets the key value
#include <linux/input.h>struct input_event { struct timeval time; unsigned short type; unsigned short code; int value;}; Int main (int argc, char * const argv[]) {&NBSP;&NBSP;&NBSP;&NBSP;INT&NBSP;FD = 0; struct input_event event[3] = {0}; //3!!! , the driver uploads 2 events, and the third one is for empty elements int ret = 0; fd = open (argv[1],o_rdonly); while (1) { Ret = read (fd,&event,sizeof (event)); printf ("RET: %d,val0:%d,val1:%d,val12:%d\n ", Ret,event[0].value,event[1].value,event[2].value); //2!!! , and the last one is empty &NBSP;&NBsp; sleep (1); } return 0;}
Linux input subsystem programming, analysis and templates