首页 > 其他 > 详细

输入子系统 13

时间:2016-01-27 19:11:01      阅读:113      评论:0      收藏:0      [点我收藏+]

 

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:标准错误                        

 

技术分享

 

技术分享

输入子系统 13

原文:http://www.cnblogs.com/CZM-/p/5164046.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!