Linux input subsystem programming, analysis and templates

Source: Internet
Author: User
Tags documentation

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:

    1. 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

    2. 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:

    1. 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.

    2. 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

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: info-contact@alibabacloud.com 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.