• 输入子系统 13


    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,

    };

    怎么读按键呢?

    input_open_file  

        struct input_handler *handler = input_table[iminor(inode) >> 5];  

        new_fops = fops_get(handler->fops)  

        file->f_op = new_fops;    

        err = new_fops->open(inode, file);

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

       

    input_table数组由谁构造?

    注册input_handler:

    input_register_handler 

       //放入数组

       input_table[handler->minor >> 5] = handler;  

       //放入链表  

      list_add_tail(&handler->node, &input_handler_list);  

       //对于每一个input_handler,都调用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_handler结构体

    2.   evdev->handle.dev = dev;    //指向左边的input_dev

      evdev->handle.handler = handler;  //指向右边的input_handler

    3. 注册  

    input_handler->h_list = &input_handler;  

    input_dev->h_list     = &input_handler;      

    evdev_connect

       evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL); //分配一个input_handle  

      //设置

        evdev->handle.name = evdev->name;

      

       evdev->handle.private = evdev;    

      //注册  

    error = input_register_handle(&evdev->handle);  

     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->event(handle, type, code, value);  

    怎么写符合输入子系统框架的驱动 

    1. 分配一个input_dev结构体

    2. 设置 

    3. 注册

    4. 硬件相关的代码,比如在中断服务程序里上报事件

     struct input_dev {

     void *private;

     const char *name;

     const char *phys;  

     const char *uniq;  

     struct input_id id;

     unsigned long evbit[NBITS(EV_MAX)];     //产生哪一类事件

     unsigned long keybit[NBITS(KEY_MAX)];    //表示能产生哪些按键

     unsigned long relbit[NBITS(REL_MAX)];    //表示产生哪些相对位移位移事件,x,y,滚轮

     unsigned long absbit[NBITS(ABS_MAX)];    //表示产生哪些绝对位移事件,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)];

     unsigned int keycodemax;

     unsigned int keycodesize;

     void *keycode;

     int (*setkeycode)(struct input_dev *dev, int scancode, int keycode);

     int (*getkeycode)(struct input_dev *dev, int scancode, int *keycode);

     struct ff_device *ff;

     unsigned int repeat_key;  struct timer_list timer;

     int state;

     int sync;

     int abs[ABS_MAX + 1];  int rep[REP_MAX + 1];

     unsigned long key[NBITS(KEY_MAX)];

     unsigned long led[NBITS(LED_MAX)];

     unsigned long snd[NBITS(SND_MAX)];

     unsigned long sw[NBITS(SW_MAX)];

     int absmax[ABS_MAX + 1];

     int absmin[ABS_MAX + 1];

     int absfuzz[ABS_MAX + 1];

     int absflat[ABS_MAX + 1];

     int (*open)(struct input_dev *dev);

     void (*close)(struct input_dev *dev);

     int (*flush)(struct input_dev *dev, struct file *file);

     int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);

     struct input_handle *grab;

     struct mutex mutex; /* serializes open and close operations */

     unsigned int users;

     struct class_device cdev;

     union {   /* temporarily so while we switching to struct device */

      struct device *parent;

     } dev;

     struct list_head h_list;  

    struct list_head node;

    };       

      ls -l /dev/event*  //查看事件命令   

    1. hexdump /dev/event1   (open(/dev/event1), read(), )

                 秒       微秒         类   code     value 

    0000000 4918 0000 7e8c 0005 0001 0026 0001 0000    //按下L

    0000010 4918 0000 7e98 0005 0000 0000 0000 0000    //同步事件

    0000020 4918 0000 628e 0009 0001 0026 0000 0000    //松开L

    0000030 4918 0000 6297 0009 0000 0000 0000 0000    //同步事件    

    2.如果没有启动QT:

    cat /dev/tty1

    按:S2,S3,S4, 就可以得到ls

    或者

    exec 0</dev/tty1

    把sh 0号文件由串口输入改为/dev/tty1输入

    ls -l /proc/770/fd

    查看sh程序打开哪些文件

     0:标准输入, 1:标准输出, 2:标准错误                        

  • 相关阅读:
    centos6.8 搭建nginx+uwsgi+Flask
    mysql root密码
    mysql查询最近一小时的数据
    linux-ssh远程后台执行脚本-放置后台执行问题(转)
    (转,有改动)测试网页响应时间的shell脚本[需要curl支持]
    shell将标准错误输出重定向到 其他地方
    CentOS6 Shell脚本/bin/bash^M: bad interpreter错误解决方法
    linux文件分发脚本
    Lucas定理及应用
    [SHOI2015]超能粒子炮·改
  • 原文地址:https://www.cnblogs.com/CZM-/p/5164046.html
Copyright © 2020-2023  润新知