Linux/android--input Subsystem Core

Source: Internet
Author: User
Tags goto

Before the blog has involved in Linux input subsystem, here to learn to record the input module.

The input subsystem, as the hub for managing input devices interacting with the system, will have to register their devices with the kernel through input.

Commonly used input devices are mouse, keyboard, touch screen.

A little subdivision of the entire input system, is the hardware driver layer ,input core relay layer , the event processing layer . Transfers between layers are in the form of event events, where input joins the upper and lower layers, providing the interface respectively.

Before the analysis of the Usbtouchscreen driver, which is the hardware driver, here simply record the input core transfer processing input.c.


Writing is not easy, reprint need to indicate the source: http://blog.csdn.net/jscese/article/details/42123673

Input_init:

Source code is located in/kernel/drivers/input/input.c, module initial call Port Subsys_initcall (input_init),

Initiated by Kernel by Kernel_init-->do_basic_setup ();-->do_initcalls call to, this start up logic, follow the opportunity to learn,

Here first call to the initial function:

static int __init input_init (void) {    int err;    Err = Class_register (&input_class); Registering input class, you can see the corresponding node file    if (err) {        Pr_err ("Unable to register Input_dev class\n") under/sys/class;        return err;    }    Err = Input_proc_init (); Proc FS under some initial operations, function prototype in input.c, can see/proc/bus/input    if (err)        goto fail1;    Err = Register_chrdev (input_major, "INPUT", &input_fops); Register the input character device, the master node is input_major==13, you can go to the input_fops to see the registration function, register to/dev/input    if (err) {        Pr_err ("Unable to Register char major%d ", input_major);        Goto fail2;    }    return 0; FAIL2:    input_proc_exit (); Fail1:    class_unregister (&input_class);    return err;}

This is the beginning of the initialization process.


You can look at the registration method function:

static const struct File_operations input_fops = {    . Owner = This_module,    . Open = Input_open_file,    . Llseek = No Op_llseek,};

This focus on the open file method can be analyzed later.


There are many other interfaces as well as global data in the INPUT.C, followed by the first call to the registration Input_register_device from the device driver.


Input_register_device:
/** * input_register_device-register device with input core * @dev: Device to being registered * * This function registers Device with input core. The device must is * allocated with input_allocate_device () and all it's capabilities * set up before registering. * If function fails the device must is freed with Input_free_device (). * Once Device has been successfully registered it can is unregistered * with Input_unregister_device (); Input_free_device () should not is * called in this case.          */int input_register_device (struct Input_dev *dev) {static atomic_t input_no = Atomic_init (0);    This atomic variable, representing a total of registered input devices, each registered a plus 1, because it is a static variable, so each call will not be zeroed out of the struct Input_handler *handler;    const char *path;    int error;  __set_bit (Ev_syn, dev->evbit); En_syn This is the type of event that the device supports, so set/* * IF delay and period are pre-set by the driver, then autorepeating * is Handl     Ed by the driver itself and we don ' t do it in input.c. *///This core timer is a init_timer set for repeating keystrokes (&dev->timer);        if (!dev->rep[rep_delay] &&!dev->rep[rep_period]) {Dev->timer.data = (long) dev;        Dev->timer.function = Input_repeat_key;        Dev->rep[rep_delay] = 250;        Dev->rep[rep_period] = 33;    If there is no correlation value defined for the duplicate key, use the kernel default} if (!dev->getkeycode) Dev->getkeycode = Input_default_getkeycode;        if (!dev->setkeycode) Dev->setkeycode = Input_default_setkeycode; The default function set above is provided by input core dev_set_name (&dev->dev, "input%ld", (unsigned long) Atomic_inc_return (&INP        UT_NO)-1);        Set the name of the device in the Input_dev, which will appear in/class/input error = Device_add (&dev->dev);    Add device to the Linux device model to the IF (error) return error;    Path = Kobject_get_path (&dev->dev.kobj, Gfp_kernel);    PRINTK (kern_info "input:%s as%s\n", Dev->name? Dev->name: "Unspecified device", Path Path: "N/a");        Kfree (path); This gets the path name and prints out the error = Mutex_lock_interrUptible (&input_mutex);        if (Error) {Device_del (&dev->dev);    return error;        } list_add_tail (&dev->node, &input_dev_list); Connect the newly assigned input device to the Input_dev_list list list_for_each_entry (handler, &input_handler_list, node) Input_attach_han        Dler (Dev, handler); Traversing the Input_handler_list list, pairing Input_dev and Input_handler//input_attach_handler This function is the key to pairing, the following will be analyzed in detail Input_wakeup_pro        Cfs_readers ();    In connection with proc file system, Mutex_unlock (&input_mutex) is not considered for the time being;   return 0; }


You can see that there are some initial settings, added to the INPUT.C global Input_dev list, and the following line matches the corresponding handler when you need to traverse the handler linked list:

Static List_head (input_dev_list); static List_head (input_handler_list);

You can see the use of a List_for_each_entry,Just started to see not understand, this is a macro definition, the prototype is in/kernel/include/linux/list.h:

/** * List_for_each_entry    -    iterate over list of given type * @pos: the type * To use as    a loop cursor. * @hea D: The    head for your list. * @member: The name of the    list_struct within the struct. */#define List_for_each_entry (POS, head, member)                    for (pos = list_entry (head)->next, typeof (*pos), member);             &pos->member! = (head);     \    //is a for loop, and the exit condition is naturally traversed to find the same         pos = List_entry (Pos->member.next, typeof (*pos), member))


Input_attach_handler (Dev, handler) matches this handler to register Dev:

static int Input_attach_handler (struct Input_dev *dev, struct Input_handler *handler) {    const struct INPUT_DEVICE_ID *id;    int error;    id = input_match_device (handler, Dev); Returns the matching ID, type is struct input_device_id    if (!id)        Return-enodev;    Error = Handler->connect (handler, dev, id); <span><span class= "comment" >//pairing successfully calls Handler's Connect function, which is defined in the event handler, primarily generates a INPUT_HANDLE structure, and initializes the Also generates an event handler-related device structure </span></span>    if (Error && Error! =-enodev)        Pr_err ("Failed to attach Handler%s to device%s, error:%d\n ",               Handler->name, Kobject_name (&dev->dev.kobj), error);    return error;}


You can see the structure of the matching ID:

struct INPUT_DEVICE_ID {kernel_ulong_t flags;__u16 bustype;__u16 vendor;__u16 product;__u16 version;kernel_ulong_t Evbit[input_device_id_ev_max/bits_per_long + 1];kernel_ulong_t Keybit[input_device_id_key_max/bits_per_long + 1]; kernel_ulong_t Relbit[input_device_id_rel_max/bits_per_long + 1];kernel_ulong_t Absbit[INPUT_DEVICE_ID_ABS_MAX/ Bits_per_long + 1];kernel_ulong_t Mscbit[input_device_id_msc_max/bits_per_long + 1];kernel_ulong_t ledbit[INPUT_ Device_id_led_max/bits_per_long + 1];kernel_ulong_t Sndbit[input_device_id_snd_max/bits_per_long + 1];kernel_ulong_ T Ffbit[input_device_id_ff_max/bits_per_long + 1];kernel_ulong_t Swbit[input_device_id_sw_max/bits_per_long + 1]; Kernel_ulong_t Driver_info;};


There are two function Input_match_device and the following connect need to know:


Input_match_device:

static const struct INPUT_DEVICE_ID *input_match_device (struct input_handler *handler, struct I    Nput_dev *dev) {const struct input_device_id *id;    int i; for (id = handler->id_table; Id->flags | | id->driver_info; id++) {if (Id->flags & Input_device_id_        Match_bus)//Match Bus ID if (id->bustype! = Dev->id.bustype) Continue;                if (Id->flags & Input_device_id_match_vendor)//Match manufacturer ID if (Id->vendor! = Dev->id.vendor)        Continue                if (Id->flags & input_device_id_match_product)//Match Product ID if (id->product! = dev->id.product)        Continue                if (Id->flags & input_device_id_match_version)//Match version if (id->version! = dev->id.version)        Continue  Match_bit (Evbit, Ev_max);        Matches the ID of the evbit and Input_dev in the evbit of the individual bits, if the mismatch is continue, the next device in the array match_bit (Keybit, Key_max); Match_bit (relbit, Rel_max);        Match_bit (Absbit, Abs_max);        Match_bit (Mscbit, Msc_max);        Match_bit (Ledbit, Led_max);        Match_bit (Sndbit, Snd_max);        Match_bit (Ffbit, Ff_max);        Match_bit (Swbit, Sw_max);    if (!handler->match | | handler->match (handler, dev)) return ID; } return NULL;

Match_bit Prototypes:

#define MATCH_BIT (BIT, max) for (i = 0; i < bits_to_longs (max); i++) if ((Id->bit[i] & dev->bit[i])! = Id-> ; bit[i]) break; if (i! = bits_to_longs (max)) continue;

You can see the purpose of so many steps in addition to the initial and add Input_dev to the list, just to match the corresponding handler in input_handler_list ,

The match is ultimately required to be compared to the ID in handler and Input_dev, where the ID type in Input_dev is input_id :

struct INPUT_ID {__u16 bustype;__u16 vendor;__u16 product;__u16 version;};

This matches the ID variable of the input_device_id in the Input_handler structure above to confirm the handler!

At the very beginning, it was mentioned that the whole input system is divided into three levels, and now the input core layer does the following:

When the hardware-driven layer calls Input_register_device, the kernel registers the driver and matches the applicable event processing layer (Input_handler) according to the relevant ID of the hardware.

The Connect function of the corresponding Input_handler is called after the match.


Input_handler:

The Input_dev variable represents the hardware device, the previous linux/android--input subsystem input_event transmission is introduced

The Input_handler variable represents the event handler

Also defined in Input.h:

/** * struct input_handler-implements One of interfaces for input devices * @private: driver-specific data * @event: Eve NT handler. This method was being called by input core with *interrupts disabled and Dev->event_lock Spinlock held and so *it may no T sleep * @filter: similar to @event; Separates normal event handlers from * "Filters". * @match: Called after comparing device's ID with handler ' s id_table *to perform fine-grained matching between device and Handler * @connect: Called when attaching a handler to an input device * @disconnect: Disconnects a handler from input dev Ice * @start: Starts handler for given handle. This function was called by *input Core right after connect () method and also when a process *that "grabbed" a device Relea SES it * @fops: File Operations This driver implements * @minor: Beginning of range of the minors for devices this driver * can provide * @name: Name of the handler, to is shown in/proc/bus/input/handlers * @id_table: Pointer to a table of input_device_ids this driver can *handle * @h_list: List of input handles associated with the handler * @node: for placing the Driver onto input_handler_list * * Input handlers attach to input devices and create input handles. There * is likely several handlers attached to any given input device at the * same time. All of them would get their copy of input event generated by * the device. * * The very same structure is used to implement input filters.  Input Core * Allows filters to run first and won't pass event to regular handlers * if all of the filters indicate that The event should is filtered (by * returning%true from their filter () method). * * Note that the input core serializes calls to connect () and disconnect () * methods.  */struct Input_handler {void *private;void (*event) (struct input_handle *handle, unsigned int type, unsigned int code, int Value), BOOL (*filter) (struct input_handle *handle, unsigned int type, unsigned int code, int value); bool (*match) (struct Input_handler *handler, struct input_dev *dev); int (*connect) (struct Input_handler *handler, struct input_dev *dev, const struct INPUT_DEVICE _id *id);  //above is called the function pointer Void (*disconnect) (struct input_handle *handle); void (*start) (struct input_handle *handle); const struct file_operations *fops;int minor;const char *name;const struct input_device_id *id_table; This is what is said above will be compared with Input_dev in the input_id of the ID item of the struct list_headh_list;struct List_headnode;};

The detailed meaning of this structure, annotated there.

This structure only needs to be understood for the time being:

Registering Input_dev, which matches the Input_handler on the event-handling data list, calls its *connect function pointer to connect,

Input_dev and Input_handler to bind, the subsequent operation of the event handler processing will walk this input_handler *event!

The last call to the event phase in the previous Input_event pass.


Here is a simple record here, the next chapter describes the processing mechanism of Input_handler ~




Linux/android--input Subsystem Core

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.