Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1080465
  • 博文数量: 646
  • 博客积分: 288
  • 博客等级: 二等列兵
  • 技术积分: 5375
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-08 14:33
个人简介

为了技术,我不会停下学习的脚步,我相信我还能走二十年。

文章分类

全部博文(646)

文章存档

2014年(8)

2013年(134)

2012年(504)

分类:

2012-06-30 22:20:10

1、


上图是 input输入子系统框架,输入子系统由输入子系统核心层( Input Core ),驱动层和事件处理层(EventHandler)三部份组成。一个输入事件,如鼠标移动,键盘按键按下,joystick的移动等等通过 input driver -> Input core ->Event handler -> userspace 到达用户空间传给应用程序。

2、先来说下Input Core输入子系统核心层。在Linux中,输入子系统作为一个模块存在,向上,为用户层提供接口函数,向下,为驱动层程序提供统一的接口函数。主要在Input.c (linux2.6.28\drivers\input)文件中:

点击(此处)折叠或打开

  1. subsys_initcall(input_init);
  2. module_exit(input_exit);

  3. static int __init input_init(void)
  4. {
  5. int err;

  6. err = class_register(&input_class);//注册一个名为input的类

其中有:

点击(此处)折叠或打开

  1. struct class input_class = {
  2. .name = "input",
  3. };
  4. if (err) {
  5. printk(KERN_ERR "input: unable to register input_dev class\n");
  6. return err;
  7. }

  8. err = input_proc_init();
  9. if (err)
  10. goto fail1;

err = register_chrdev(INPUT_MAJOR, "input", &input_fops);注册了主设备号为INPUT_MAJOR的字符设备,操作函数集是:input_fops,如下所示:

点击(此处)折叠或打开

  1. static const struct file_operations input_fops = {
  2. .owner = THIS_MODULE,
  3. .open = input_open_file,
  4. };
  5. if (err) {
  6. printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
  7. goto fail2;
  8. }

  9. return 0;


  10.  fail2: input_proc_exit();
  11.  fail1: class_unregister(&input_class);
  12. return err;
  13. }
  14. static void __exit input_exit(void) //做和input_init函数做相反的工作
  15. {
  16. input_proc_exit();
  17. unregister_chrdev(INPUT_MAJOR, "input");
  18. class_unregister(&input_class);
  19. }

2.1、接着看下input_open_file函数,源码如下:

点击(此处)折叠或打开

  1. static int input_open_file(struct inode *inode, struct file *file)
  2. {
  3. struct input_handler *handler;
  4. const struct file_operations *old_fops, *new_fops = NULL;
  5. int err;

  6. lock_kernel();
  7. /* No load-on-demand here? */
  8. handler = input_table[iminor(inode) >> 5];

其中iminor(inode)为打开文件所对应的次设备号。input_table是一个struct input_handler全局数组,只有8个元素,其定义为:
static struct input_handler *input_table[8];

首 先将设备结点的次设备号右移5位做为索引值到input_table中取对应项,从这里也可以看到,一个handler代表 32(1<<5)个设备结点,也就是一个handler最多可以处理32个设备结点。因为在input_table中取值是以次备号右移5位 为索引的,即第5位相同的次备号对应的是同一个索引。在input_register_handler()函数中 input_table[handler->minor >> 5] = handler,其将handler赋给了input_table数组,所使用的规则也是右移5位。

其中input_handler结构体如下所示:

点击(此处)折叠或打开

  1. /**
  2.  * struct input_handler - implements one of interfaces for input devices
  3.  * @private: driver-specific data
  4.  * @event: event handler. This method is being called by input core with
  5.  * interrupts disabled and dev->event_lock spinlock held and so
  6.  * it may not sleep
  7.  * @connect: called when attaching a handler to an input device
  8.  * @disconnect: disconnects a handler from input device
  9.  * @start: starts handler for given handle. This function is called by
  10.  * input core right after connect() method and also when a process
  11.  * that "grabbed" a device releases it
  12.  * @fops: file operations this driver implements
  13.  * @minor: beginning of range of 32 minors for devices this driver
  14.  * can provide
  15.  * @name: name of the handler, to be shown in /proc/bus/input/handlers
  16.  * @id_table: pointer to a table of input_device_ids this driver can
  17.  * handle
  18.  * @blacklist: pointer to a table of input_device_ids this driver should
  19.  * ignore even if they match @id_table
  20.  * @h_list: list of input handles associated with the handler
  21.  * @node: for placing the driver onto input_handler_list
  22.  *
  23.  * Input handlers attach to input devices and create input handles. There
  24.  * are likely several handlers attached to any given input device at the
  25.  * same time. All of them will get their copy of input event generated by
  26.  * the device.
  27.  *
  28.  * Note that input core serializes calls to connect() and disconnect()
  29.  * methods.
  30.  */
  31. struct input_handler {


  32. void *private;


  33. void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
  34. int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
  35. void (*disconnect)(struct input_handle *handle);
  36. void (*start)(struct input_handle *handle);


  37. const struct file_operations *fops;
  38. int minor;
  39. const char *name;


  40. const struct input_device_id *id_table;
  41. const struct input_device_id *blacklist;


  42. struct list_head h_list;
  43. struct list_head node;
  44. };
  45.  

  46. if (!handler || !(new_fops = fops_get(handler->fops))) {
  47.  //检查handler是否存在
  48. err = -ENODEV;
  49. goto out;
  50. }


  51. /*
  52. * That's _really_ odd. Usually NULL ->open means "nothing special",
  53. * not "no device". Oh, well...
  54. */
  55. if (!new_fops->open) { //判断new_fops->open是否存在
  56. fops_put(new_fops);
  57. err = -ENODEV;
  58. goto out;
  59. }
  60. old_fops = file->f_op;
  61. file->f_op = new_fops;


  62. err = new_fops->open(inode, file); //使用新的open函数重新打开设备


  63. if (err) {
  64. fops_put(file->f_op);
  65. file->f_op = fops_get(old_fops);
  66. }
  67. fops_put(old_fops);
  68. out:
  69. unlock_kernel();
  70. return err;
  71. }

阅读(423) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~