Application analysis of Linux input subsystem

Source: Internet
Author: User
Tags mutex volatile

Input device (such as key, keyboard, touch screen, mouse, etc.) is a typical character device, its general working mechanism is the bottom in the key, touch and other actions to generate an interrupt (or drive through Timer timing query), and then the CPU through the SPI, I2 C or external memory bus reading key values, coordinates and other data, In 1 buffers, the character device driver manages the buffer, while the drive's read () interface allows the user to read data such as key values, coordinates, and so on.

Obviously, in these jobs, only interrupts, read values are device-dependent, and the input event's buffer management and character device-driven file_operations interface are common to the input device. Based on this, the kernel designs the input subsystem, which handles the public work by the core layer. The hardware-driven layer handles interrupts, read-value correlation (read-out values are reported in interrupts).

Input subsystem layered Design, a total of three layers: hardware drive layer, subsystem core layer, event processing layer.

The driver layer is completed by the driver programmer, mainly processing interrupts (escalation event-read value).

The core layer of the subsystem is the link between the other two layers, which provides the interface of the driving layer, and the interface of the event processing layer upward.

The event processing layer is responsible for dealing with the user program and reporting the events from the hardware drivers to the user program.

The device driver does not create a file node, it is only responsible for the acquisition of data through the INPUT.C function input_event () up one layer , and each event driver will be their respective interest in the event information extracted, through the file node, provided to the user. in this process, the core of the input subsystem is responsible for the interaction of the two layers, and manages and maintains a linked list of their respective information.

The event escalated in the driver, input subsystem has been specified, in linux/input.h.the supported event types (event types) have ev_cnt(Ev_syn synchronization events, Ev_key key events, ev_rel relative coordinate events, ev_abs absolute coordinate events, ev_msc scattered events, EV_SW switch events, ev_led LED events, Ev_snd,ev_rep repeat events, ev_ff,ev_ PWR,EV_FF_STATUS,EV_MAX,EV_CNE) (the latter items are used for service event types, not actual events), denoted by "type" in the code. Each event type has a number of attributes (or options, or encodings), with code indicating that the value for each property is the data to be escalated (read value above).The event-Property-property value (Type-code-value) uniquely characterizes an escalation event, and the "Type-code" input subsystem has a complete set of rules that support the event through "bitmask" in the code. For a simple example, the touch device supports an absolute coordinate event Ev_abs,ev_abs has abs_cnt code, where abs_x represents the x-coordinate and abs_y represents the y-coordinate.
Input_dev structure with event-dependent arrays,As follows:
unsigned long evbit[bits_to_longs (ev_cnt)];
unsigned long keybit[bits_to_longs (key_cnt)];
unsigned long relbit[bits_to_longs (rel_cnt)];
unsigned long absbit[bits_to_longs (abs_cnt)];
unsigned long mscbit[bits_to_longs (msc_cnt)];
unsigned long ledbit[bits_to_longs (led_cnt)];
unsigned long sndbit[bits_to_longs (snd_cnt)];
unsigned long ffbit[bits_to_longs (ff_cnt)];
unsigned long swbit[bits_to_longs (sw_cnt)];
all input events, the kernel is a unified data structure to describe, this data structure is input_event.
struct Input_event {
struct Timeval time;
__U16 type;
__U16 Code;
__S32 value;
};
----------------------------------------------------------------------------------------------------
The events supported by the device are set in the Driver module load function and are generally set as:
Button_dev->evbit[0] = Bit_mask (Ev_key); Direct bit assignment (poor compatibility)
static inline void __set_bit (int nr, volatile unsigned long *addr); function settings, non-atomic
static inline void Set_bit (int nr, volatile unsigned long *addr); function set, Atom, asm/bitops/atomic.h
The interrupt escalation event is input_event (), and 3 variant functions are used to report the Ev_key, Ev_rel, ev_abs events respectively.
void Input_event (struct input_dev *dev, unsigned int type, unsigned int code, int value);
static inline void Input_report_key (struct input_dev *dev, unsigned int code, int value);
static inline void Input_report_rel (struct input_dev *dev, unsigned int code, int value);
static inline void Input_report_abs (struct input_dev *dev, unsigned int code, int value);
Input_sync () is used for event synchronization, informing the event receiver that a full report has been issued.
static inline void Input_sync (struct Input_dev *dev)
{
Input_event (Dev, Ev_syn, syn_report, 0);
}
In Song Baohua's "Linux device driver Development details", the input subsystem is introduced to increase the drive work.
>> tells the input subsystem device what can be reported in the module load function. (Set_bit ())
>> registers the input device in the module load function. (int input_register_device (struct input_dev *dev);)
>> the status of what happened and the corresponding key/coordinate is reported by Input_report_xxx () when the key is pressed/lifted, the touch screen is touched/lifted/moved, the mouse is moved/clicked/lifted.
>> unregisters the input device in the module unload function. (void Input_unregister_device (struct input_dev *dev);)
---------------------------------------------------------------------------------------------------
The event processing layer deals with the user program and the input subsystem core, which is a two-tier bridge. The general kernel has several event handlers, like Evdev,mousedev,joydev.The Evdev event handler can handle everything.
Evdev user-side structure:

1.structevdev_client {2.structinput_event Buffer[evdev_buffer_size]; 3.//This is an array of input_event data structures, Input_event represents an event, a basic member: type, encoding (code), values (value)4.intHead//index against the buffer array5.intTail//for the index of the buffer array, when head is equal to tail, no event is indicated6. spinlock_t Buffer_lock;/*protects access to buffer, head and tail*/  7.structFasync_struct *fasync;//Asynchronous Notification functions8.structEvdev *evdev;//Evdev Equipment9.structList_head node;//evdev_client linked list itemsTen. };


This structure calls Evdev's Open method when the process opens the EVENT0 device, creates the structure in open, and initializes it. This structure is released when the device file is closed. Copied to the user space when read.
How does the user-space application access the device, and the device file?

1.structEvdev {2.intexist; 3.intOpen//Open Flag4.intMinor//Secondary Device number5.structInput_handle handle;//The associated Input_handle6. wait_queue_head_t wait;//wait for the queue, the process will sleep on it when the process reads the device and no events are generated7.structEvdev_client *grab;//forced binding of the evdev_client structure, after which the structure is analyzed again8.structList_head client_list;//evdev_client linked list, which shows that a evdev device can handle multiple evdev_client and can have multiple processes accessing Evdev devices9. spinlock_t Client_lock;/*protects Client_list*/  Ten.structmutex mutex;  One.structDevice Dev;//device structure, which indicates that this is an equipment structure A. };


Evdev structure is generated when pairing succeeds, generated by handler->connect, corresponding device file is/dev/input/event (n), such as touch screen driver event0, this device is the device that user space wants to access, It can be understood that it is a virtual device, because there is no corresponding hardware, but through the Handle->dev can find the INPUT_DEV structure, and it corresponds to the touch screen, the device file is/dev/input/input0. This device structure is generated and saved in Evdev_table, and the index value is minor.The device file is associated with a device number.
In Evdev_connect (), there is a device file initialization process:
...
Dev_set_name (&evdev->dev, "event%d", minor);
...
Evdev->dev.devt = MKDEV (input_major, evdev_minor_base + MINOR);
Evdev->dev.class = &input_class;
Evdev->dev.parent = &dev->dev;
Evdev->dev.release = Evdev_free;
Device_initialize (&evdev->dev);
...
You can also view the device files via/proc/bus/input/devices, and test the PC virtual machine as follows:
Cat/proc/bus/input/devices
i:bus=0019 vendor=0000 product=0001 version=0000
n:name= "Power button"
p:phys=lnxpwrbn/button/input0
s:sysfs=/devices/lnxsystm:00/lnxpwrbn:00/input/input0
u:uniq=
h:handlers=kbd event0
b:prop=0
b:ev=3
b:key=100000 0 0 0
... ..
i:bus=0011 vendor=0002 product=0005 version=0000
n:name= "Imps/2 Generic Wheel Mouse"
p:phys=isa0060/serio1/input0
S:SYSFS=/DEVICES/PLATFORM/I8042/SERIO1/INPUT/INPUT3
u:uniq=
h:handlers=mouse1 Event3
b:prop=0
b:ev=7
b:key=70000 0 0 0 0 0 0 0 0
b:rel=103
By comparing the VID, PID to find the corresponding USB mouse device, and then find the corresponding mouse1, Event3
Actually can also not write application, directly throughcat/dev/input/mouse1 | hexdumpTo get the mouse data.
An online example is as follows:

1./*2.20150101 3.    Just a simple input test code 4.    Lei_wang 5. */  6. 7. #include <stdio.h>8. #include <stdlib.h>9. #include <unistd.h>Ten. #include <fcntl.h> One. #include <string.h> A. #include <linux/input.h> -.  -.intMain () the. {   -.intFD;  -.intversion;  -.intret;  +.structinput_event ev;  -.  +. FD = open ("/dev/input/event1", o_rdonly);  A.if(FD <0) {   at. printf"Open File failed\n");  -. Exit1);  -. }   -.  -. IOCTL (FD, Eviocgversion, &version);  -. printf"Evdev driver version is 0x%x:%d.%d.%d\n",   in. Version, version>> -, (version>>8) &0xFF, Version &0xFF);  -.  to. while(1) {   +. ret = Read (FD, &ev,sizeof(structinput_event));  -.if(Ret <0) {   the. printf"Read Event error!\n");  *. Exit1);  $. }  Panax Notoginseng.  -.if(Ev.type = =Ev_key) the. printf"type%d,code%d, value%d\n", Ev.type, Ev.code, Ev.value);  +. }   A.  the.return 0;  +. }

Reference:

    1. Http://www.linuxidc.com/Linux/2011-09/43187.htm Input Subsystem Analysis
    2. HTTP://BLOG.CSDN.NET/ZHANGXIZHICN/ARTICLE/DETAILS/6642062 Linux Input Subsystem analysis
    3. Layered design idea driven by http://blog.csdn.net/21cnbao/article/details/5615493 Linux device
    4. Linux device driver detailed Song Baohua
    5. http://blog.csdn.net/luckywang1103/article/details/42324229 input Subsystem-architecture, drivers, applications
    6. http://www.cnblogs.com/leaven/archive/2011/02/12/1952793.html Linux input Subsystem IO control field

Application analysis of Linux input subsystem

Related Article

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.