zoukankan      html  css  js  c++  java
  • 输入子系统框架

    drivers/input/input.c
        input_init > err = class_register(&input_class);

    static const struct file_operations input_fops = {
        .owner = THIS_MODULE,
        .open = input_open_file,
    };

    怎么读按键?
    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

    input_table数组的由来:

    input_register_handler
        //放入数组
        input_table[handler->minor >> 5] = handler;
        
        //放入链表
        list_add_tail(&handler->node, &input_handler_list);
        
        //对于每个input_dev,调用input_attach_handler
        list_for_each_entry(dev, &input_dev_list, node)
            input_attach_handler(dev, handler);//根据input_handler的id_table判断能否支持这个input_dev


    input_register_device
        //放入链表
        list_add_tail(&dev->node, &input_dev_list);
        
        //对于每一个input_handler都调用input_attach_handler
        list_for_each_entry(handler, &input_handler_list, node)
            input_attach_handler(dev, handler);//根据input_handler的id_table判断能否支持这个input_dev
            
            
    input_attach_handler        
            id = input_match_device(handler->id_table, dev);
            error = handler->connect(handler, dev, id);
            
            
    注册input_dev或者input_handler时,会两两比较左边的input_dev和右边的input_handler,
    根据input_handler的id_table判断这两个input_handler能否支持这个input_dev,
    如果能支持,则调用input_handler的connect函数建立连接

    建立连接:
    1.分配一个input_handle结构体
    2.input_handle.dev = input_dev;            //指向左边的input_dev
      input_handle.handler = input_handler; //指向右边的input_handler
    3.注册
      input_handler->h_list = &input_handle;
      input_dev->h_list     = &input_handle;
     
    evdev_connect
        evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);//分配一个input_handle
        
        //设置
        evdev->handle.dev = input_get_device(dev);//指向左边的input_dev
        evdev->handle.name = dev_name(&evdev->dev);
        evdev->handle.handler = handler;//指向右边的input_handler
        evdev->handle.private = evdev;
        
        //注册
        error = input_register_handle(&evdev->handle);
            list_add_tail_rcu(&handle->d_node, &dev->h_list);
            list_add_tail(&handle->h_node, &handler->h_list);
            
    怎么读按键:
    app:read
        ......
            evdev_read
                //无数据,并且是非阻塞方式打开,则立刻返回
                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);
                    
    谁来唤醒?
    evdev_event
        wake_up_interruptible(&evdev->wait);
        
    evdev_event被谁调用
        //硬件相关的代码,input_dev调用
        在设备的中断服务程序里面,确定事件是什么,然后调用相应的input_handler的event处理函数
        
    gpio_keys_isr
        //上报事件
        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->envent(handle, type, code, value);
               
    符合输入子系统框架的驱动程序
    1.分配一个input_dev结构体
    2.设置
    3.注册
    4。硬件相关的代码,比如在中断服务程序里上报事件

  • 相关阅读:
    POJ 1795 DNA Laboratory
    CodeForces 303B Rectangle Puzzle II
    HDU 2197 本源串
    HDU 5965 扫雷
    POJ 3099 Go Go Gorelians
    CodeForces 762D Maximum path
    CodeForces 731C Socks
    HDU 1231 最大连续子序列
    HDU 5650 so easy
    大话接口隐私与安全 转载
  • 原文地址:https://www.cnblogs.com/liulipeng/p/3322763.html
Copyright © 2011-2022 走看看