input input subsystem--basic knowledge 1

drivers/input/input.c:
    input_init > err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
    
static const struct file_operations input_fops = {
    .owner = THIS_MODULE,
    .open = input_open_file,
};

Q: How to read the keys?

input_open_file
    struct input_handler *handler = input_table[iminor(inode) >> 5];
    new_fops = fops_get(handler->fops)  //  =>&evdev_fops
    file->f_op = new_fops;
    err = new_fops->open(inode, file);

app: read > ... > file->f_op->read  

Who constructs the input_table array?

input_register_handler


Register input_handler:
input_register_handler
    // put into the array
    input_table[handler->minor >> 5] = handler;
    
    // put into the linked list
    list_add_tail(&handler->node, &input_handler_list);

    // For each input_dev, call input_attach_handler
    list_for_each_entry(dev, &input_dev_list, node)
        input_attach_handler(dev, handler); // Determine whether the input_dev can be supported according to the id_table of input_handler
    
    


Register input device:
input_register_device
    // Put it into the linked list
    list_add_tail(&dev->node, &input_dev_list);
    
    // For each input_handler, call input_attach_handler
    list_for_each_entry(handler, &input_handler_list, node)
        input_attach_handler(dev, handler); // According to input_handler id_table determines whether this input_dev can be supported


input_attach_handler
    id = input_match_device(handler->id_table, dev);
    
    error = handler->connect(handler, dev, id);


When registering input_dev or input_handler, it will compare the input_dev on the left and the input_handler on the right.
According to the id_table of the input_handler, judge whether the input_handler can support the input_dev.
If it can, call the connect function of input_handler to establish a "connection"

How to establish a connection?
1. Assign an input_handle structure
2. 
    input_handle.dev = input_dev; // point to the left input_dev
    input_handle.handler = input_handler; // point to the right input_handler
3. Register:
   input_handler->h_list = &input_handle;
   inpu_dev->h_list = &input_handle ;


evdev_connect
    evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL); // allocate an input_handle
    
    // set
    evdev->handle.dev = dev; // point to the left input_dev
    evdev->handle.name = evdev->name;
    evdev ->handle.handler = handler; // Input_handler pointing to the right
    evdev->handle.private = evdev;
    
    // Registration
    error = input_register_handle(&evdev->handle);
    
How to read the button?
app: read
--------------------------
   .......
           evdev_read
               // If there is no data and it is opened in non-blocking mode, it will return immediately
            if (client->head == client->tail && evdev->exist && (file->f_flags & O_NONBLOCK))
                return -EAGAIN;
            

            retval = wait_event_interruptible(evdev->wait,
                client->head != client->tail || !evdev->exist);
               

Who will wake up?
evdev_event wake_up_interruptible
    (&evdev->wait);


Who calls evdev_event?
Guess: it should be the hardware-related code, which is called by the input_dev layer.
In the interrupt service routine of the device, determine what the event is, and then call the corresponding input_handler event processing function
gpio_keys_isr
    // report event
    input_event(input, type, button-> code, !!state);
    input_sync(input);
    
input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
    struct input_handle *handle;

    list_for_each_entry(handle, &dev->h_list, d_node)
        if (handle->open)
            handle->handler->event(handle, type, code, value);


How to write a driver that conforms to the input subsystem framework?
1. Assign an input_dev structure
2. Settings
3. Registration
4. Hardware-related code, such as reporting events in the interrupt service routine
            


struct input_dev {

    void *private;

    const char *name;
    const char *phys;
    const char *uniq;
    struct input_id id;

    unsigned long evbit[NBITS(EV_MAX)]; // Indicates which types of events can be generated
    unsigned long keybit[NBITS(KEY_MAX)]; // Indicates which keys can be generated
    unsigned long relbit[NBITS(REL_MAX)]; // Indicates that they can be generated Which relative displacement events, x,y,wheel
    unsigned long absbit[NBITS(ABS_MAX)]; // Indicates which absolute displacement events can be generated, x,y
    unsigned long mscbit[NBITS(MSC_MAX)];
    unsigned long ledbit[NBITS(LED_MAX) )];
    unsigned long sndbit[NBITS(SND_MAX)];
    unsigned long ffbit[NBITS(FF_MAX)];
    unsigned long swbit[NBITS(SW_MAX)];

Test:
1. 
the hexdump / dev / EVENT1 (Open (/ dev / EVENT1), Read (),)
           second microseconds class value code
0000000 0bb2 000C 0000 0001 0026 0001 0000 0e48
0000010 0bb2 000C 0000 0000 0000 0000 0000 0e54
0.00002 million 0bb2 0000 5815 000e 0001 0026 0000 0000
0000030 0bb2 0000 581f 000e 0000 0000 0000 0000

2. If you do not start QT:
cat /dev/tty1
press: s2, s3, s4
to get ls

Or:
exec 0</dev/tty1
and then you can use the keys to enter


3. If you have started QT:
you can click to open Notepad
and then press: s2, s3, s4

 

 

Guess you like

Origin blog.csdn.net/qq_26690505/article/details/86494624