输入子系统总结

输入子系统学习的总结

从input.c 里面的input_init函数看起
{
注册了一类设备(输入类设备)
class_register(&input_class)

申请设备号
register_chrdev(INPUT_MAJOR, "input", &input_fops);
}

问题:为什么没有在类下注册具体的设备?
因为这时候不知道会有什么具体的设备,所以猜想是在具体设备
被发现的时候才注册具体的设备

查看 input_fops,它是一个file_operations结构体,里面只有成员
.open = input_open_file,再次进去查看input_open_file(inode,file)
{
  struct input_handler *handler = input_table[iminor(inode) >> 5];
  根据你的inode结构体成员算出次设备号,以此为下标取出input_table
  成员赋值。

  new_fops = fops_get(handler->fops)
  file->f_op = new_fops;
  最终将file里面的fops指向了handler里面的fops

  new_fops->open(inode, file);
  然后调用open函数
}

————————————————————————————————————————————————————————————————
从驱动程序的角度看看函数是怎么运行的。
在 buttons_init ()函数中有
{
buttons_dev=input_allocate_device()
{
这个函数做的是为开辟一个input_dev结构体并返回 ,
其中有dev->cdev.class = &input_class;标明自己属于
自己是输入类设备。
初始化了链表结构h_list 和node
}

  input_register_device(buttons_dev);
  注册设备,向谁注册呢?应该是向输入子系统注册。

  {   
      函数里面有list_add_tail(&dev->node, &input_dev_list);
      这个宏是向input_dev_list链表里面添加一个节点,也就是表明了
      自己这个设备可以被发现了。

      class_device_add(&dev->cdev);
      这里就对应了上面的在类下注册具体的设备

       list_for_each_entry(handler, &input_handler_list, node)
          input_attach_handler(dev, handler);
       这个宏做的应该是便利input_handler_list里面的成员,看看有没有
       dev和handler匹配的项。
  }

}

问题:input_handler_list是什么,谁初始化的?
handler是什么?
为什么要做匹配?
匹配的到底是在做什么?

——————————————————————————————————————————————————————————————————
硬件设备要进行输入输出的话必须对应匹配的软件驱动,既然硬件都是
自己input_register_device()向上注册的,那么软件驱动肯定也是这样的。
查看Evdev.c Joydev.c Mousedev.c里面的函数就能发现,都调用了
input_register_handler(struct input_handler *handler)
{
INIT_LIST_HEAD(&handler->h_list)
初始化了一个链表h_list,和上面的那个h_list不是同一个。

input_table[handler->minor >> 5] = handler
按照次设备号构造input_table成员。

list_add_tail(&handler->node, &input_handler_list)
往input_handler_list链表中添加一个节点

list_for_each_entry(dev, &input_dev_list, node)
input_attach_handler(dev, handler);
}

——————————————————————————————————————————————————————————————————
现在在回看上面的问题:
input_handler_list是一个链表,由各种驱动往里面添加成员,
成员结构为list_head,其实是handler大结构体里面的成员。
说白了就是把input_register_handler函数的参数handler串起来。

handler 是一个input_handler结构,里面含有file_operations成员
这样就能把通用的框架转为具体的驱动实现了。

list_for_each_entry()其实是一个宏,进去看看就是for循环
{
input_attach_handler(dev,handler)
{
input_match_device(handler->id_table, dev)
查看handler的id_table和dev是不是匹配,是的话调用
下面的函数

     handler->connect(handler, dev, id)
   }
 }

问题:input_match_device()是怎么判断匹配的?
connect()里面做了什么?

id_table是struct input_device_id结构,判断里面的成员
和dev结构里面的id里面的成员,一致的话返回id值

connect()函数的调用实际上对应了每个不同handler里面的fops
下的connect函数。

{
    evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);
    开辟空间存放evdev结构

    。。。。。
    然后各种初始化,其实就是让dev知道谁是它的handler,
    让handler知道谁是它的dev

    evdev_table[minor] = evdev;
    把evdev结构放进数组里面

    devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor)
    创建设备节点


    class_device_create(&input_class, &dev->cdev, devt,
               dev->cdev.dev, evdev->name);
    创建好类下的设备

    input_register_handle(&evdev->handle)
    让输入子系统知道存在这么一个handler
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值