从第一节我们已经知道,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函数。

usb_register函数封装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/module.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函数了。

/**
* usb_register_driver - register a USB interface driver
* @new_driver: USB operations for the interface driver
* @owner: module owner of this driver.
* @mod_name: module name string
*
* Registers a USB interface driver with the USB core. The list of
* unattached interfaces will be rescanned whenever a new driver is
* added, allowing the new driver to attach to any recognized interfaces.
* Returns a negative error code on failure and 0 on success.
*
* NOTE: if you want your driver to use the USB major number, you must call
* usb_register_dev() to enable that functionality. This function no longer
* takes care of that.
*/
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 = (char *) 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) {
pr_info("%s: registered new interface driver %s\n",
usbcore_name, new_driver->name);
usbfs_update_special();
usb_create_newid_file(new_driver);
} else {
printk(KERN_ERR "%s: error %d registering interface "
" driver %s\n",
usbcore_name, retval, new_driver->name);
} return retval;
}

这函数和前面见过的usb_register_device_driver长的很相,你如果是从那里一路看过来的话,你都会明明白白它的意思。现在还是要简单提一点,new_driver->drvwrap.for_devices = 0行设置成了0, match里的那个is_usb_device_driver把门儿的才不会把它当成设备驱动放过去。然后就是在driver_register行将你的驱动提交给设备模型,从而添加到usb总线的驱动链表里,从此之后,接口和接口驱动就可以通过usb总线的match函数匹配。

usb驱动开发24之接口驱动的更多相关文章

  1. usb驱动开发7之接口描述符

    前面struct usb_interface里表示接口设置的struct usb_host_interface被有意的飘过了,咱们在这节主要讲讲这个结构体,同样在include/linux/usb.h ...

  2. android系统平台显示驱动开发简要:LCD驱动调试篇『四』

    平台信息: 内核:linux3.4.39系统:android4.4 平台:S5P4418(cortex a9) 作者:瘋耔(欢迎转载,请注明作者) 欢迎指正错误,共同学习.共同进步!! 关注博主新浪博 ...

  3. Linux驱动开发之字符设备驱动模型之file_operations

    90%的驱动模型都是按照下图开发的 下面来说下设备描述结构是什么东西 打开Linux-2.6.32.2的Source Insight 工程,搜索cdev 比如一个应用程序需要调用read和write这 ...

  4. Linux驱动开发2——字符设备驱动

    1.申请设备号 #include <linux/fs.h> int register_chrdev_region(dev_t first, unsigned int count, char ...

  5. Linux 下wifi 驱动开发(三)—— SDIO接口WiFi驱动浅析

    SDIO-Wifi模块是基于SDIO接口的符合wifi无线网络标准的嵌入式模块,内置无线网络协议IEEE802.11协议栈以及TCP/IP协议栈.可以实现用户主平台数据通过SDIO口到无线网络之间的转 ...

  6. HarmonyOS USB DDK助你轻松实现USB驱动开发

    HDF(Hardware Driver Foundation)驱动框架是HarmonyOS硬件生态开放的基础,为开发者提供了驱动加载.驱动服务管理和驱动消息机制等驱动能力,让开发者能精准且高效地开发驱 ...

  7. usb驱动开发10之usb_device_match

    在第五节我们说过会专门分析函数usb_device_match,以体现模型的重要性.同时,我们还是要守信用的. 再贴一遍代码,看代码就要不厌其烦. static int usb_device_matc ...

  8. Android深度探索HAL与驱动开发 第二章 搭建Android开发环境

    通常以应用移植和系统移植的为Andorid系统移植的主要部分.同时为了适应不同平台硬件设备,对源代码进行相应的修改.除了要移植相适应的CPU架构,最重要是移植Linux驱动. 但是由于一些特别的原因, ...

  9. Android深度探索HAL和驱动开发(卷1) 第一章 Android系统移植和驱动开发

    由于Android是基于Linux内核的,因此,Android和其他Linux系统的核心部分差异非常小.然而不同版本的Android使用的Linux内核的版本有细微的差异,所以不同Android驱动可 ...

随机推荐

  1. Java-使用二叉树实现快速排序-遁地龙卷风

    (-1)写在前面 在一次面试中被问及快速排序,回来后又看了一次以前做过的案例,说来惭愧,时至今日还需要读好长时间,才能明白自己代码的意思,主要是缺少注释和图解,深有感慨,决定好好记录一下. 之所以使用 ...

  2. XML序列化和反序列化

    上篇总结了下JSON的序列化和反序列化,博园中大牛给了很多牛叉的评论,学习了不少. 不过在上篇中忘了把json序列化和反序列化的另外一种方式写上去了,这里做个简单的补充: Json篇:http://w ...

  3. 《C#微信开发系列(1)-启用开发者模式》

    1.0启用开发者模式 ①填写服务器配置 启用开发模式需要先成为开发者,而且编辑模式和开发模式只能选择一个(进入微信公众平台=>开发=>基本配置)就可以看到以下的界面: 点击修改配置,会出现 ...

  4. web移动端fixed布局和input等表单的爱恨情仇 - 终极BUG,完美解决

    [问题]移动端开发,ios下当fixed属性和输入框input(这里不限于input,只要可以调用移动端输入法的都包括,如:textarea.HTML5中contenteditable等),同时存在的 ...

  5. iframe高度自适应

    前两天在网上看到了一道面试题,问iframe高度自适应的问题.发现自己之前几乎没有关注过iframe的问题,所以在这里记录一下. 原题目是: 页面A的域名是:http://www.taobao.com ...

  6. [threeJs][新浪股票api][css3]3D新浪财经数据-最近A股涨的也太疯了......

    使用threeJS搭配新浪股票财经API 在线: http://wangxinsheng.herokuapp.com/stock 截图: A股涨幅榜[一片红10%] 检索[单击添加到自选内,自选使用l ...

  7. Python开发【第三篇】:Python基本之文件操作

    Python基本之文本操作 一.初识文本的基本操作 在python中打开文件有两种方式,即:open(...) 和  file(...) ,本质上前者在内部会调用后者来进行文件操作,推荐使用 open ...

  8. MySQL相关

    1.进入安装目录 cd E:\ZYXDocument\Software\mariadb-10.0.20-win32\bin 2.安装mysql服务将E:\ZYXDocument\Software\ma ...

  9. 好像越来越觉得 SharePoint “难用”了

    一开始,我觉得 SharePoint 很神秘,不知道它到底是用来做什么的. 后来,我觉得 SharePoint 很强大,能做很多事情. 再后来,我觉得,SharePoint 没有他们宣传的那-么强大, ...

  10. iOS多线程之5.GCD的基本使用

      上一篇文章我对GCD的几个基本概念做了介绍,但是大家看完了可能觉得对理解GCD并没有什么卵用.其实会用GCD其实很简单,只要记住两条就可以了. 1. 主队列里的任务必须在异步函数中执行.   主队 ...