I. INPUT SUBSYSTEM architecture
The input subsystem is drivers by the drive layer , inputs the subsystem core input core, event processing layer events handler composition.
An input event that is sent to the system via the input device such as mouse movement, keyboard keys press inferior via device driver->input core (handler->event function)->event handler->user space to the application by reaching the user space in the order.
An output event that is sent through the system to the input device via the user space->event Handler->input core (dev->event function)->device driver
1, the driving function layer: responsible for dealing with the underlying hardware equipment, the underlying hardware device to the user input response into the standard input events and then sent upward to the core layer of the input system
2, Input system core layer: by the driver/input/input.c and related header files, he provided the device driver layer interface, on the above provides the event processing layer into the interface.
3. The event processing layer distributes the events escalated by the hardware device to the user space and the kernel.
The structure diagram is as follows:
Waiting to upload photos
Second, write The function required by input driver
1) contains header file <linux/input.h>, which is The interface of the input subsystem and provides the necessary definition messages
2) I Nput_allocate_device ()
Assigned an input device structure, set his bit field to tell input subsystem what events he can produce or receive.
3) input_register_device (struct Input_dev *dev)
Add the dev struct to the input_dev_list Global List
by Input_attach_handler (struct Input_dev *dev, struct input_handler *handler) to find the corresponding Handler,
Input_attach_handler actually called the input_match_device (const struct INPUT_DEVICE_ID *id,struct Input_dev *dev)
Once the Input_attach_handler has found the corresponding handler, it executes the handler->connect
4) input_report_key (struct Input_dev *dev, unsigned int code, int value)
5) input_sync (struct Input_dev *dev)
Tell the receiver of the event that this is a complete message. For example, we get x,y values on touch screen, so that as an event, the Input_sync Add the report x,y is worth the back.
6) Other event type, output event handling
Other events are:
Ev_led: led light used as a keyboard
EV_SND: Buzzer used as a keyboard
He is similar to keyboard events, except that the keyboard event is Input_pass_to_device, and the output event is input_pass_to_handlers, From the system to the input device driver, if your driver is going to handle these events, you must set the corresponding bit in evbit and implement a callback function.
s truct Input_dev *button_dev;
b utton_dev->event = button_event; This is the callback function that handles the output event
Three, ordinary key implementation input driver example
/*drivers->input core->event handlerfunction:this file is button driverdate:20150101author:lei_wang*/#include & lt;linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/irq.h># Include <asm/irq.h> #include <asm/io.h> #include <mach/regs-gpio.h> #include <mach/hardware.h > #include <linux/interrupt.h> #include <linux/gpio.h> #include <linux/input.h>static struct Input_dev *button_dev;static irqreturn_t button_intr (int irq, void *dev_id) {int val;val = S3c2410_gpio_getpin (S3C2410_ GPG (0));//PRINTK (kern_info "key value is%d\n", Val); Input_report_key (Button_dev, Btn_0, Val); Input_sync (Button_dev); Return Irq_retval (irq_handled);} static int __init button_init (void) {int ret;ret = REQUEST_IRQ (Irq_eint8, Button_intr, Irq_type_edge_both, "Button0", NULL); if (ret) {PRINTK (kern_err "%s request failed\n", __func__); Return-enodev;} Button_dev = Input_allocate_device (); if (!button_dev) {PRINTK (kern_err "Button.c:nOT enough memory\n "); Free_irq (Irq_eint8, NULL); return-enomem;} Button_dev->name = "Button0"; button_dev->evbit[0] = Bit_mask (Ev_syn) | Bit_mask (Ev_key); Button_dev->keybit[bit_word (btn_0)] = Bit_mask (BTN_0); ret = Input_register_device (Button_dev); if (ret) {PRINTK (kern_err "button.c:failed to register device\n"); Input_free_device (Button_dev); Free_irq (Irq_eint8, NULL); Return-enodev;} PRINTK (kern_info "button init ok!\n"); return 0;} static void __exit button_exit (void) {Input_unregister_device (Button_dev); Input_free_device (Button_dev); FREE_IRQ ( Irq_eint8, NULL);p rintk (kern_info "button exit ok!\n");} Module_init (Button_init); Module_exit (Button_exit); Module_license ("GPL"); Module_author ("Realsil Luckywang");
Makefile as follows:
Obj-m = Button.okerneldir? =/home/lei/linux-2.6.32.2modules:$ (Make)-C $ (kerneldir) m=$ (shell pwd) MODULESCLEAN:RM-RF * . o *.MOD.C *.order *.symvers
The Include/linux/bitops.h defines the
#define BIT (NR) (1UL << (NR))
#define Bit_mask (NR) (1UL << (NR)% Bits_per_long)
#define Bit_word (NR) ((NR)/Bits_per_long)
#define BTN_0 0x100
Button_dev->evbit[0] = Bit_mask (Ev_key);
Button_dev->keybit[bit_word (btn_0)] = Bit_mask (BTN_0);
Description
1) The above 0x100 indicates that btn_0 this bit is in all the bits 0x100 (bit) bit, then
Bit_word (BTN_0) represents a bit of the keybit array (8th) in this array.
Bit_mask (BTN_0) Representative bit in the Keybit The value of the first array of this array (the bit0 of the 8th array)
2) Event type --code Code--Value
Evbit is an array of events,evbit This event array can put a lot of event types, such as key,abs , etc.
Event Key inside there are many specific code btn_0,btn_touch , etc.
Event ABS also has a lot of specific code abs_x,abs_y , etc.
Different encodings have different values
In addition http://blog.csdn.net/ylyuanlu/article/details/6704744 this blog on the following said very detailed
1) Registration of the struct Input_dev, struct handler of the input subsystem
2) How struct Input_dev and struct Input_handler match each other (similar to device and driver match)
3) Event Handling process
Iv. Examples of the corresponding application
/*20150101just a simple input test codelei_wang*/#include <stdio.h> #include <stdlib.h> #include < unistd.h> #include <fcntl.h> #include <string.h> #include <linux/input.h>int main () {int Fd;int Version;int ret;struct input_event ev;fd = open ("/dev/input/event1", o_rdonly), if (FD < 0) {printf ("Open File failed\n" ); exit (1);} IOCTL (FD, Eviocgversion, &version);p rintf ("Evdev driver version is 0x%x:%d.%d.%d\n", Version, Version>>16, ( version>>8) & 0xFF, version & 0xFF); while (1) {ret = read (FD, &ev, sizeof (struct input_event)); if (Ret & Lt 0) {printf ("read event error!\n"); exit (1);} if (Ev.type = = Ev_key) printf ("Type%d,code%d, value%d\n", Ev.type, Ev.code, ev.value);} return 0;}
the above is just a simple application test. When you press K1, the serial terminal will have a message that displays the keystrokes reported by input Dev.
In addition there are many inside the IOCTL call content is not experimental, specifically can refer to this blog http://www.cnblogs.com/leaven/archive/2011/02/12/1952793.html, Try again on each case of the IOCTL and the read call to find your own experience.
Input subsystem--architecture, drivers, applications