从上节的上节我们已经知道,usb_generic_driver在自己的生命线里,以一己之力将设备的各个接口送给了linux的设备模型,让usb总线的match函数,也就是usb_device_match,在自己的那条驱动链表里为它们寻找一个合适的接口驱动程序。现在让咱们轻声的问一句,这些接口驱动都从哪里来?

这就要说到每个玩儿linux的人都会知道的那几个著名的命令insmod,modprobe,rmmod。你insmod或modprobe驱动的时候,经过一个曲折的过程,会调用到你驱动里的那个xxx_init函数,进而去调用usb_register()将你的驱动提交给设备模型,添加到usb总线的驱动链表里。你rmmod驱动时候,同样经过一个曲折的过程之后,调用到你驱动里的那个xxx_cleanup函数,进而调用usb_deregister()将你的驱动从usb总线的驱动链表里删除掉。现在就看看include/linux/usb.h里定义的usb_register函数

#define usb_register(driver) \usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)

看到这个函数,让人不得不感叹一下,现在什么都要讲究包装,内核里也免不了这个俗,注册个驱动也要包装个两层,不过这个包装不是为了出名,而是方便大伙儿的。
本来在两年以前是没这么多道道儿的,也没有usb_register_driver这么一个函数,只有个usb_register(),它直接就把啥事儿都做了。而且那个时候struct usb_driver结构里还有一个有名的owner字段,每个在那个岁月里写过usb驱动的人都会认得它,并且都会毫无犹豫的将它设置为THIS_MODULE。但是经过岁月的洗礼,在早先贴出来的struct usb_driver结构内容里,你发现owner已经无影无踪了。要搞清楚这个历史变迁的来龙去脉,你得知道这个owner和THIS_MODULE都代表了什么。
从那个时代走过来的人,都应该知道owner是一个struct module *类型的结构体指针,现在告诉你的是每个struct module结构体在内核里都代表了一个内核模块,就像十七大里的每个代表都代表了一批人,至于代表了什么人,选他们的人才知道,同样,每个struct module结构体代表了什么模块,对它进行初始化的模块才知道。当然,初始化这个结构不是写驱动的人该做的事,是在刚才略过的那个从insmod或modprobe到你驱动的xxx_init函数的曲折过程中做的事。insmod命令执行后,会调用kernel/module.c里的一个系统调用sys_init_module,它会调用load_module函数,将用户空间传入的整个内核模块文件创建成一个内核模块,并返回一个struct module结构体,从此,内核中便以这个结构体代表这个内核模块。
再看看THIS_MODULE宏是什么意思,它在include/linux/export.h里的定义是

#define THIS_MODULE (&__this_module)

是一个struct module变量,代表当前模块,与那个著名的current有几分相似,可以通过THIS_MODULE宏来引用模块的struct module结构,比如使用THIS_MODULE->state可以获得当前模块的状态。现在你应该明白为啥在那个岁月里,你需要毫不犹豫毫不迟疑的将struct usb_driver结构里的owner设置为THIS_MODULE了吧,这个owner指针指向的就是你的模块自己。那现在owner咋就说没就没了那?这个说来可就话长了,咱就长话短说吧。不知道那个时候你有没有忘记过初始化owner,反正是很多人都会忘记,大家都把注意力集中到probe、disconnect等等需要动脑子的角色上面了,这个不需要动脑子,只需要花个几秒钟指定一下的owner反倒常常被忽视。于是在2006年的春节前夕,在咱们都无心工作无心学习等着过春节的时候,Greg坚守一线,去掉了owner,于是千千万万个写usb驱动的人再也不用去时刻谨记初始化owner了。咱们是不用设置owner了,可core里不能不设置,struct usb_driver结构里不是没有owner了么,可它里面嵌的那个struct device_driver结构里还有啊,设置了它就可以了。于是Greg同时又增加了usb_register_driver()这么一层,usb_register()可以通过将参数指定为THIS_MODULE去调用它,所有的事情都挪到它里面去做。反正usb_register()也是宏定义,并不会增加调用的开销。现在是时机看看usb_register_driver函数了

drivers/usb/core/driver.c

int usb_register_driver(struct usb_driver *new_driver, struct module *owner,const char *mod_name)
{int retval = 0;if (usb_disabled())return -ENODEV;new_driver->drvwrap.for_devices = 0;new_driver->drvwrap.driver.name = new_driver->name;new_driver->drvwrap.driver.bus = &usb_bus_type;new_driver->drvwrap.driver.probe = usb_probe_interface;new_driver->drvwrap.driver.remove = usb_unbind_interface;new_driver->drvwrap.driver.owner = owner;new_driver->drvwrap.driver.mod_name = mod_name;spin_lock_init(&new_driver->dynids.lock);INIT_LIST_HEAD(&new_driver->dynids.list);retval = driver_register(&new_driver->drvwrap.driver);if (retval)goto out;retval = usb_create_newid_files(new_driver);if (retval)goto out_newid;pr_info("%s: registered new interface driver %s\n",usbcore_name, new_driver->name);out:return retval;out_newid:driver_unregister(&new_driver->drvwrap.driver);printk(KERN_ERR "%s: error %d registering interface ""    driver %s\n",usbcore_name, retval, new_driver->name);goto out;
}

这函数和前面见过的usb_register_device_driver长的很相,你如果是从那里一路看过来的话,不用俺说什么,你都会明明白白它的意思。不过,本着与人为善的态度,俺还是要简单提一点,for_devices在9行设置成了0,有了这行,match里的那个is_usb_device_driver把门儿的才不会把它当成设备驱动放过去。然后就是在19行将你的驱动提交给设备模型,从而添加到usb总线的驱动链表里,从此之后,接口和接口驱动就可以通过usb总线的match函数传情达意眉来眼去。当然,usb的世界里要想对上眼,都得严格的满足对方的条件。

Linux那些事儿 之 戏说USB(34)接口的驱动相关推荐

  1. Linux那些事儿 之 戏说USB(12)接口是设备的接口(一)

    前面的前面已经说了,接口是设备的接口.设备可以有多个接口,每个接口代表一个功能,每个接口对应着一个驱动.Linux设备模型的device落实在USB子系统,成了两个结构,一个是struct usb_d ...

  2. Linux那些事儿 之 戏说USB(13)接口是设备的接口(二)

    前面struct usb_interface里表示接口设置的struct usb_host_interface就被有意无意的飘过了,咱们在这里看看它的真面目,同样在include/linux/usb. ...

  3. Linux那些事儿 之 戏说USB(25)设备的生命线(八)

    回到struct usb_hcd,继续努力的往下看. 7行,又见kref,usb主机控制器的引用计数.struct usb_hcd也有自己专用的引用计数函数,看drivers/usb/core/hcd ...

  4. Linux那些事儿 之 戏说USB(18)设备的生命线(一)

    首先当然是你将usb设备连接在hub的某个端口上,hub检测到有设备连接了进来,它会为设备分配一个struct usb_device结构的对象并初始化,并调用设备模型提供的接口将设备添加到usb总线的 ...

  5. Linux那些事儿 之 戏说USB(19)设备

    转载地址:http://blog.csdn.net/fudan_abc/article/details/1807800 第一眼看到struct usb_device这个结构,我仿佛置身于衡山路的酒吧里 ...

  6. 【转】Linux那些事儿 之 戏说USB(19)设备

    第一眼看到struct usb_device这个结构,我仿佛置身于衡山路的酒吧里,盯着舞池里扭动的符号,眼神迷离. 交大里苟了几年,毕业了又是住在学校附近的徐虹北路上,沿着虹桥路走过去,到徐家汇不过1 ...

  7. Linux那些事儿 之 戏说USB(大结局)还是那个match

    从上次在几米的向左走向右走遇到usb总线的那个match函数usb_device_match()开始到现在,遇到了设备,遇到了设备驱动,遇到了接口,也遇到了接口驱动,期间还多次遇到usb_device ...

  8. Linux那些事儿 之 戏说USB(32)驱动的生命线(四)

    设备自从有了Address,拿到了各种描述符,就在那儿看usb_generic_driver忙活了,不过还算没白忙,设备总算是幸福的进入Configured了. Address有点像你合几代人之力辛辛 ...

  9. Linux那些事儿 之 戏说USB(20)设备的生命线(三)

    函数usb_control_msg调用了usb_internal_control_msg之后就去一边儿睡大觉了,脏活儿累活儿,全部留给usb_internal_control_msg去做了. driv ...

最新文章

  1. 栈与队列2——两个栈组成队列
  2. PTA 基础编程题目集 7-11 分段计算居民水费 C语言
  3. VTK:图表之MutableDirectedGraphToDirectedGraph
  4. linux 部署项目
  5. 使用“using” 的 “Cursor”
  6. python-自定义模块-文件的操作
  7. 不戴眼镜听不清?Google用视觉信号分离语音 | 附论文
  8. Python基本数据类型之set
  9. Django-admin源码流程
  10. Google Code Jam
  11. Navicat数据库查询时字体
  12. 准确生成电信、联通、移动IP地址段
  13. 用html创建数独,数独做不出来怎么办
  14. mac node repl_如何使用Node.js REPL
  15. 命令 修复损坏的 Ubuntu 系统 ,不用重装
  16. 数据结构课程设计(部分选题)
  17. 建个网站需要多少钱?你真的知道吗?
  18. rust放置木箱转向_rust笔记五 - cyper的个人空间 - OSCHINA - 中文开源技术交流社区...
  19. uniapp使用Painter画板
  20. Hot scene AGAIN!

热门文章

  1. 为什么静态方法无法直接调用非静态成员变量和方法
  2. 设计模式中的六大基本原则
  3. go get 无法下载问题解决方案及下载 aliyun-oss-go-sdk incompatible.info
  4. [摘录]代码优化规则
  5. 2016.4.2 动态规划练习--讲课整理
  6. Android OpenGL ES(十一)绘制一个20面体 .
  7. Effective STL 为包含指针的关联容器指定比较类型
  8. 《OpenCV3编程入门》学习笔记10 角点检测(三)亚像素级角点检测
  9. TensorFlow基本计算单元:代码示例
  10. 二元关系在计算机中的应用(数据库为主),数据库技术复习题答案 选择题