input 子系统(五) 事件上报及监听

版权声明:本文为博主原创文章,任何组织或者个人可以在任何媒介上发表或转载我的文章、图片等.且转载后必须注明出处和邮箱,博客地址(https://blog.csdn.net/u011011827),本人邮箱([email protected]) https://blog.csdn.net/u011011827/article/details/87891596

上报流程


事件的生产者 是 input 设备驱动
途径 input.c(input core),到达 handler,
然后由handler 提供给消费者.


  • 驱动中的上报

    input_report_key(button_dev, KEY_POWER,1);
    input_report_key(button_dev, KEY_POWER,0);
    input_sync(button_dev);

  • 上报流程

//监听 /dev/input/eventX 之前
input_report_key
    input_event(dev, EV_KEY, code, !!value); // 检查dev 是否支持该事件
        input_handle_event(dev, type, code, value);
            if (disposition & INPUT_PASS_TO_HANDLERS){
                
                // 存储 sync及 之前的
            }
            if (disposition & INPUT_FLUSH) { // 如果 sync 到来
                // 
                input_pass_values
                    input_to_handler
                        list_for_each_entry_rcu(handle, &dev->h_list, d_node) 
                            if (handle->open) { // 一定要注意,这个是handle ,还有一个 handler ,下两行会提到 ,在 open /dev/input/eventX 事,才会将 evdev对应的handle->open ++ .默认为0
                                input_to_handler(handle, vals, count); // 执行一次 , 这一次 是 kbd 的 event
                                    handler->event // 第一次,没有下文 // 此时 handler->events 为 NULL
                            }
            }
            

//监听 /dev/input/eventX 之后 //调用了evdev_open

input_report_key
    input_event(dev, EV_KEY, code, !!value);
        input_handle_event(dev, type, code, value);
            if (disposition & INPUT_FLUSH) {
                input_pass_values
                    input_to_handler
                        list_for_each_entry_rcu(handle, &dev->h_list, d_node)  // rcu
                            if (handle->open) {
                                input_to_handler(handle, vals, count); // 执行两次
                                    handler->event // 第一次 kbd // kbd_event
                                    handler->events // 第二次  evdev evdev_events // 优先 events
                                    evdev_events
                                    	evdev_pass_values
                                    		__pass_event
                                                client->tail = (client->head - 2) & (client->bufsize - 1);                
                                                client->buffer[client->tail].time = event->time;                             
                                                client->buffer[client->tail].type = EV_SYN;                                  
                                                client->buffer[client->tail].code = SYN_DROPPED;                             
                                                client->buffer[client->tail].value = 0;                                   
                                                client->packet_head = client->tail;
                            }

            }


监听流程

  • open

evdev_open 做了什么
    evdev_attach_client
        list_add_tail_rcu(&client->node, &evdev->client_list); //rcu
    handle->open ++;

    open 了之后,建立了缓冲区.建立缓冲区 ,64 字节
    这个buffer的作用是,上层OPEN了此节点,但是没有读取此节点的数据的时候,会保存到该缓冲区
    
    在open 之前,事件就没有到 handler 中. 消亡在 input.c

  • poll

- 阻塞流程

evdev_poll
    poll_wait(file, &evdev->wait, wait);

- 唤醒流程

evdev_pass_values
    if (v->type == EV_SYN && v->code == SYN_REPORT)
        wakeup = true;
    if (wakeup) 
        wake_up_interruptible(&evdev->wait); 

  • read

evdev_read

猜你喜欢

转载自blog.csdn.net/u011011827/article/details/87891596