免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: projl
打印 上一主题 下一主题

《Linux 那些事儿之我是U盘》 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2008-06-06 13:37 |只看该作者
1084 module_init(usb_stor_init);

1085 module_exit(usb_stor_exit);

其实,module_init/module_exit 只是一个宏,通常写模块的人为了彰显自己的个性,会给自
己的初始化函数和注销函数另外起个名字,比如这里module_init(usb_stor_init) 以及
module_exit(usb_stor_exit) 实际上就是告诉这个世界,真正的函数是usb_stor_init 和
usb_stor_exit. 这种伎俩在Linux 内核代码中屡见不鲜.见多了也就不必大惊小怪了,天要下雨
娘要嫁人,随她去吧.我们下面当然就从usb_stor_init 正式开始我们的探索之旅.
外面的世界很精彩

看代码之前,我曾经认真的思考过这么一个问题,我需要关注的仅仅是drivers/usb/storage/目
录下面那相关的3000 多行代码吗?就是这样几个文件就能让一个个不同的U 盘在Linux 下面工
作起来吗? 像一开始那样把这个目录比作一个小城的话,也许,城里的月光很漂亮,她能够把人的
梦照亮,能够温暖人的心房.但我们真的就能厮守在这个城里,一生一世吗?

很不幸,问题远不是这样简单.外面的世界很精彩,作为U 盘,她需要与usb core 打交道,需要与
scsi core 打交道,需要与内存管理单元打交道,还有内核中许许多多其它模块打交道.外面的世界
很大,远比我们想象的大.

什么是usb core? 她负责实现一些核心的功能,为别的设备驱动程序提供服务,比如申请内存,比
如实现一些所有的设备都会需要的公共的函数,事实上,在usb 的世界里,一个普通的设备要正常
的工作,除了要有设备本身以外,还需要有一个叫做控制器的冬冬,老外把它叫做host controller,
和这个控制器相连接在一起的有另一个咚咚,她叫root hub,hub 我们应该不会陌生,在大学里,
有的宿舍里网口有限,但是我们这一代人上大学基本上是每人一台电脑,所以网口不够,于是有人
会使用hub, 让多个人共用一个网口,这是以太网上的hub, 而usb 的世界里同样有hub, 其实原
理是一样的,任何支持usb 的电脑不会说只允许你只能一个时刻使用一个usb 设备,比如你插入
了u 盘,你同样还可以插入usb 键盘,还可以再插一个usb 鼠标,因为你会发现你的电脑里并不只
是一个usb 接口.这些口实际上就是所谓的hub 口.而现实中经常是让一个usb 控制器和一个
hub 绑定在一起,专业一点说叫集成,而这个hub 也被称作root hub,换言之,和usb 控制器绑定
在一起的hub 就是系统中最根本的hub, 其它的hub 可以连接到她这里,然后可以延伸出去,外接
别的设备,当然也可以不用别的hub, 让usb 设备直接接到root hub 上.hub 干嘛用的我们知道
了,那么usb host controller 本身是干什么用的呢?controller,控制器,顾名思义,用于控制,控
制什么,控制所有的usb 设备的通信.通常计算机的cpu 并不是直接和usb 设备打交道,而是和控
制器打交道,他要对设备做什么,他会告诉控制器,而不是直接把指令发给设备,然后控制器再去负
责处理这件事情,他会去指挥设备执行命令,而cpu 就不用管剩下的事情,他还是该干嘛干嘛去,
控制器替他去完成剩下的事情,事情办完了再通知cpu. 否则让cpu 去盯着每一个设备做每一件
事情,那是不现实的,那就好比让一个学院的院长去盯着我们每一个本科生上课,去管理我们的出
勤,只能说,不现实.所以我们就被分成了几个系,通常院长有什么指示直接跟各系领导说就可以了,
如果他要和三个系主任说事情,他即使不把三个人都召集起来开个会,也可以给三个人各打一个
电话,打完电话他就忙他自己的事情去了,比如去和他带的女硕士风花雪月.而三个系主任就会去
安排下面的人去执行具体的任务,完了之后他们就会像院长汇报.

所以,Linux 内核开发者们,专门写了一些代码,并美其名曰usb core. 时代总在发展,当年胖杨贵
妃照样迷死唐明皇,而如今人们欣赏的则是林志玲这样的魔鬼身材.同样,早期的Linux 内核,其结
构并不是如今天这般有层次感,远不像今天这般错落有致,那时候drivers/usb/ 这个目录下边放
了很多很多文件,usb core 与其他各种设备的驱动程序的代码都堆砌在这里,后来,怎奈世间万千
的变幻,总爱把有情的人分两端.于是在drivers/usb/ 目录下面出来了一个core 目录,就专门放

论坛徽章:
0
12 [报告]
发表于 2008-06-06 13:38 |只看该作者
一些核心的代码,比如初始化整个usb 系统,初始化root hub, 初始化host controller 的代码,
再后来甚至把host controller 相关的代码也单独建了一个目录,叫host 目录,这是因为usb
host controller 随着时代的发展,也开始有了好几种,不再像刚开始那样只有一种,所以呢,设计
者们把一些host controller 公共的代码仍然留在core 目录下,而一些各host controller 单独
的代码则移到host 目录下面让负责各种host controller 的人去维护,常见的host controller
有三种,分别叫做EHCI,UHCI,OHCI, 所以这样,出来了三个概念,usb core,usb host,usb
device,即原本是一家人,却被活生生的分成了两岸三地...的确,现实总是很无奈,然而,心若知道
灵犀的方向,哪怕不能够朝夕相伴?没错,usb 通信的灵魂就是usb 协议. usb 协议将是所有usb
设备和usb 主机所必须遵循的游戏规则.这种规则也很自然的体现在了代码中.于是,我们需要了
解的不仅仅是drivers/usb/storage/目录下面的冬冬,还得去了解那外面的世界,虽然,只需要
了解一点点.

未曾开始却似结束

还是回到那个初始化函数吧,usb_stor_init, 看了它的代码每一个人的心中都有一种莫名的兴奋,
因为它太短了,就那么几行,除了两个printk 语句以外,就是一个函数的调用,usb_register.

printk 不用我说,每一个有志青年都该知道,就算没见过printk 也该见过printf 吧,否则的话,你
扪心自问,你对得起谭浩强大哥吗?在谭浩强大哥的带领下我们学会了用
#include<stdio.h>->main()->printf() 来打印hello,world! 从而向全世界展示了我们懂C
语言.而stdio.h 就是一个C 库,printf 是一个函数,来自函数库,可是内核中没有标准C 库,所以
开发者们自己准备了一些函数,专门用于内核代码中,所以就出来了一个printk,printk 的"k" 就
是kernel, 内核.所以我们只要把它当作printf 的兄弟即可,如果感兴趣,可以去研究一下printk
的特点,她和printf 多少有些不同,但基本思想是一样的.所以我们就不多讲了,当然驱动程序中所
有的printk 语句对U 盘的工作都没有什么用,她无非是打出来给我们看的,或者说打印给用户看,
或者呢,打印给开发者看,特别是开发者要调试程序的时候,就会很有用.

于是我们更开心了,不用看printk 的话,那就只有一个函数调用了,usb_register. 这个函数是干
嘛的?首先这个函数正是来自usb core.凡是usb 设备驱动,都要调用这个函数来向usb core 注
册,从而让usb core知道有这么一个设备.这就像政府规定,一对夫妻结婚要到相关部门那里去登
记是一样的,我们无需知道政府是如何管理的,只需要知道去政府那里登记即可.

这样,insmod 的时候,usb_stor_init 这个函数会被调用,初始化就算完成了.于是设备就开始工
作了... 而当我们rmmod 的时候,usb_stor_exit 这个函数会被调用,我们发现,这个函数也很短,
我们能看出来,US_DEBUG 也就是打印一些咚咚,因此,这里实际上也就是调用了一个函数
usb_deregister(),她和usb_register() 是一对,完成了注销的工作,从此设备就从usb core 中
消失了.于是我们惊人的发现,编写设备驱动竟是如此的简单,驱动程序真的就这么结束了?...

这一切,不禁让人产生了一种幻觉,让人分不清故事从哪里开始,又从哪里结束,一切都太短暂了.
仿佛开始在结束的时候开始,而结束却在开始的时候就早已结束.

真的吗?

答案是否定的.孔子已经教育过我们,不光要看懂代码,更要理解代码背后的哲学.

所以我们在继续之前,先来看看这里到底有什么哲学.而这,就是伟大的Linux Kernel 2.6 中的统
一的设备模型.

论坛徽章:
0
13 [报告]
发表于 2008-06-06 13:39 |只看该作者
我们并无意去详细介绍2.6 中的设备模型,但是不懂设备模型又怎能说自己懂设备驱动呢?读代
码的人,写代码的人,都要知道,什么是设备驱动?什么又是设备?设备和驱动之间究竟是什么关系?
设备如何与计算机主机联系起来?我相信在中关村买盗版光盘的哥们儿也能回答这个问题.计算
机世界里,设备有很多种类,比如PCI 设备,比如ISA 设备,再比如SCSI 设备,再比如我们这里的
USB 设备.为设备联姻的是总线,是他把设备连入了计算机主机.但是与其说设备是嫁给了计算机
主机,倒不如说设备是嫁给了设备驱动程序.很显然,在计算机世界里,无论风里雨里,陪伴着设备
的正是驱动程序.

唯一的遗憾是,计算机中的设备和驱动程序的关系却并非如可乐和拉环的关系那样,一对一.然而
世上又有多少事情总能如人愿呢.

狂欢是一群人的孤单

Linux 设备模型中三个很重要的概念就是总线,设备,驱动.即bus,device,driver, 而实际上内核
中也定义了这么一些数据结构,他们是struct bus_type,struct device,struct device_driver,
这三个重要的数据结构都来自一个地方,include/linux/device.h. 我们知道总线有很多种,pci
总线,scsi 总线,usb 总线,所以我们会看到Linux 内核代码中出现
pci_bus_type,scsi_bus_type,usb_bus_type, 他们都是struct bus_type 类型的变量.而
struct bus_type 结构中两个非常重要的成员就是struct kset drivers 和struct kset
devices.kset 和另一个叫做kobject 正是Linux Kernel 2.6 中设备模型的基本元素,但此处我
们却不愿多讲,因为暂时不用去认识他们.我们的生命中会遇见许许多多的人和事,但更多的人和
事与我们只是擦肩而过,只是我们生命中的过客而已.在我们人生的电影中,他们也许只有一个镜
头,甚至那一个镜头后来也被剪辑掉了.这里我们只需要知道,drivers 和devices 的存在,让
struct bus_type 与两个链表联系了起来,一个是devices 的链表,一个是drivers 的链表,也就
是说,知道一条总线所对应的数据结构,就可以找到这条总线所关联的设备有哪些,又有哪些支持
这类设备的驱动程序.

而要实现这些,就要求每次出现一个设备就要向总线汇报,或者说注册,每次出现一个驱动,也要向
总线汇报,或者说注册.比如系统初始化的时候,会扫描连接了哪些设备,并为每一个设备建立起一
个struct device 的变量,每一次有一个驱动程序,就要准备一个struct device_driver 结构的
变量.把这些变量统统加入相应的链表,device 插入devices 链表,driver 插入drivers 链表. 这
样通过总线就能找到每一个设备,每一个驱动.

然而,假如计算机里只有设备却没有对应的驱动,那么设备无法工作.反过来,倘若只有驱动却没有
设备,驱动也起不了任何作用.在他们遇见彼此之前,双方都如同路埂的野草,一个飘啊飘,一个摇
啊摇,谁也不知道未来在哪里,只能在生命的风里飘摇.于是总线上的两张表里就慢慢的就挂上了
那许多孤单的灵魂.devices 开始多了,drivers 开始多了,他们像是两个来自世界,devices 们彼
此取暖,drivers 们一起狂欢,但他们有一点是相同的,都只是在等待属于自己的那个另一半.

看代码的我,一直好奇的想知道,他们是否和我们现实中一样,有些人注定是等别人,而有些人是注
定被人等的.

论坛徽章:
0
14 [报告]
发表于 2008-06-06 13:39 |只看该作者
总线,设备,和驱动(上)

struct bus_type 中为devices 和drivers 准备了两个链表,而代表device 的结构体struct
device 中又有两个成员,struct bus_type *bus 和struct device_driver *driver,同样,代表
driver 的结构体struct device_driver 同样有两个成员,struct bus_type *bus 和struct
list_head devices,struct device 和struct device_driver 的定义和struct bus_type 一样,
在include/linux/device.h 中.凭一种男人的直觉,可以知晓,struct device 中的bus 记录的是
这个设备连在哪条总线上,driver 记录的是这个设备用的是哪个驱动,反过来,struct
device_driver 中的bus 代表的也是这个驱动属于哪条总线,devices 记录的是这个驱动支持的
那些设备,没错,是devices( 复数),而不是device(单数),因为一个驱动程序可以支持一个或多个
设备,反过来一个设备则只会绑定给一个驱动程序.

于是我们想知道,关于bus,关于device,关于driver,他们是如何建立联系的呢?换言之,这三个
数据结构中的指针是如何被赋值的?绝对不可能发生的事情是,一旦为一条总线申请了一个
struct bus_type 的数据结构之后,它就知道它的devices 链表和drivers 链表会包含哪些东西,
这些咚咚一定不会是先天就有的,只能是后天填进来的.而具体到usb 系统,完成这个工作的就是
usb core.usb core 的代码会进行整个usb 系统的初始化,比如申请struct bus_type
usb_bus_type, 然后会扫描usb 总线,看线上连接了哪些usb 设备,或者说root hub 上连了哪
些usb 设备,比如说连了一个usb 键盘,那么就为它准备一个struct device, 根据它的实际情况,
为这个struct device 赋值,并插入devices 链表中来.又比如root hub 上连了一个普通的hub,
那么除了要为这个hub 本身准备一个struct device 以外,还得继续扫描看这个hub 上是否又
连了别的设备,有的话继续重复之前的事情,这样一直进行下去,直到完成整个扫描,最终就把
usb_bus_type 中的devices 链表给建立了起来.

那么drivers 链表呢?这个就不用bus 方面主动了,而该由每一个driver 本身去bus 上面登记,
或者说挂牌.具体到usb 系统,每一个usb 设备的驱动程序都会有一个struct usb_driver 结构
体,其代码如下,来自include/linux/usb.h

485 /* -------------------------------------------------------------------------- */

486

487 /**

488 * struct usb_driver - identifies USB driver to usbcore

489 * @owner: Pointer to the module owner of this driver; initialize

490 * it using THIS_MODULE.

491 * @name: The driver name should be unique among USB drivers,

492 * and should normally be the same as the module name.

493 * @probe: Called to see if the driver is willing to manage a particular

494 * interface on a device. If it is, probe returns zero and uses

495 * dev_set_drvdata() to associate driver-specific data with the

496 * interface. It may also use usb_set_interface() to specify the

497 * appropriate altsetting. If unwilling to manage the interface,

498 * return a negative errno value.

499 * @disconnect: Called when the interface is no longer accessible, usually

500 * because its device has been (or is being) disconnected or the

501 * driver module is being unloaded.

论坛徽章:
0
15 [报告]
发表于 2008-06-06 13:40 |只看该作者
502 * @ioctl: Used for drivers that want to talk to userspace through
503 * the "usbfs" filesystem. This lets devices provide ways to
504 * expose information to user space regardless of where they
505 * do (or don't) show up otherwise in the filesystem.
506 * @suspend: Called when the device is going to be suspended by the

system.
507 * @resume: Called when the device is being resumed by the system.
508 * @id_table: USB drivers use ID table to support hotplugging.
509 * Export this with MODULE_DEVICE_TABLE(usb,...). This must be set
510 * or your driver's probe function will never get called.
511 * @driver: the driver model core driver structure.
512 *
513 * USB drivers must provide a name, probe() and disconnect() methods,
514 * and an id_table. Other driver fields are optional.
515 *
516 * The id_table is used in hotplugging. It holds a set of descriptors,
517 * and specialized data may be associated with each entry. That table
518 * is used by both user and kernel mode hotplugging support.
519 *
520 * The probe() and disconnect() methods are called in a context where
521 * they can sleep, but they should avoid abusing the privilege. Most
522 * work to connect to a device should be done when the device is opened,
523 * and undone at the last close. The disconnect code needs to address
524 * concurrency issues with respect to open() and close() methods, as
525 * well as forcing all pending I/O requests to complete (by unlinking
526 * them as necessary, and blocking until the unlinks complete).
527 */
528 struct usb_driver {
529 struct module *owner;
530
531 const char *name;
532
533 int (*probe) (struct usb_interface *intf,
534 const struct usb_device_id *id);
535
536 void (*disconnect) (struct usb_interface *intf);
537
538 int (*ioctl) (struct usb_interface *intf, unsigned int code, void *buf);
539
540 int (*suspend) (struct usb_interface *intf, u32 state);
541 int (*resume) (struct usb_interface *intf);
542
543 const struct usb_device_id *id_table;
544

论坛徽章:
0
16 [报告]
发表于 2008-06-06 13:40 |只看该作者
545 struct device_driver driver;

546 };

547 #define to_usb_driver(d) container_of(d, struct usb_driver, driver)

看似很长一段,实际上也就是注释为主.而此刻我们只需注意到其中的struct device_driver
driver 这个成员,usb core 为每一个设备驱动准备了一个函数,让它把自己的这个struct
device_driver driver 插入到usb_bus_type 中的drivers 链表中去.而这个函数正是我们此
前看到的usb_register. 而与之对应的usb_deregister 所从事的正是与之相反的工作,把这个
结构体从drivers 链表中删除.可以说,usb core 的确是用心良苦,为每一个usb 设备驱动做足了
功课,正因为如此,作为一个实际的usb 设备驱动,它在初始化阶段所要做的事情就很少,很简单了,
直接调用usb_register 即可.事实上,没有人是理所当然应该为你做什么的,但usb core 这么做
了.所以每一个写usb 设备驱动的人应该铭记,usb device driver 绝不是一个人在工作,在他身
后,是usb core 所提供的默默无闻又不可或缺的支持.

总线,设备,和驱动(下)

bus 上的两张链表记录了每一个device 和driver, 那么device 和driver 这两者之间又是如何联系起来的
呢?此刻,必须抛出这样一个问题,先有device 还是driver?

很久很久以前,在那激情燃烧的岁月里,先有的是device, 每一个要用的device 在计算机启动之前就已经插
好了,插放在它应该在的位置上,然后计算机启动,然后操作系统开始初始化,总线开始扫描设备,每找到一个
设备,就为其申请一个struct device 结构,并且挂入总线中的devices 链表中来,然后每一个驱动程序开始
初始化,开始注册其struct device_driver 结构,然后它去总线的devices 链表中去寻找(遍历),去寻找每
一个还没有绑定driver 的设备,即struct device 中的struct device_driver 指针仍为空的设备,然后它会
去观察这种设备的特征,看是否是他所支持的设备,如果是,那么调用一个叫做device_bind_driver 的函数,
然后他们就结为了秦晋之好.换句话说,把struct device 中的struct device_driver driver 指向这个
driver, 而struct device_driver driver 把struct device 加入他的那张struct list_head devices 链表
中来.就这样,bus,device, 和driver, 这三者之间或者说他们中的两两之间,就给联系上了.知道其中之一,就
能找到另外两个.一荣俱荣,一损俱损.

但现在情况变了,在这红莲绽放的日子里,在这樱花伤逝的日子里,出现了一种新的名词,叫热插拔.device
可以在计算机启动以后在插入或者拔出计算机了.因此,很难再说是先有device 还是先有driver 了.因为都
有可能.device 可以在任何时刻出现,而driver 也可以在任何时刻被加载,所以,出现的情况就是,每当一个
struct device 诞生,它就会去bus 的drivers 链表中寻找自己的另一半,反之,每当一个一个struct
device_driver 诞生,它就去bus 的devices 链表中寻找它的那些设备.如果找到了合适的,那么ok,和之前
那种情况一下,调用device_bind_driver 绑定好.如果找不到,没有关系,等待吧,等到昙花再开,等到风景看
透,心中相信,这世界上总有一个人是你所等的,只是还没有遇到而已.

好,继续,事实上,完善这个三角关系,正是每一个设备驱动初始化阶段所完成的重要使命之一.让我们还是回
到代码中来,usb_register 这个函数调用是调用了,但是传递给他的参数是什么呢?

我们注意到,那句调用是这样子的,

1064 /* register the driver, return usb_register return code if error *
/
1065 retval = usb_register(&usb_storage_driver)
;


是的,传递了一个叫做usb_storage_driver 的家伙,这是什么?同一文件中,drivers/usb/storage/usb.c:

论坛徽章:
0
17 [报告]
发表于 2008-06-06 13:41 |只看该作者
232 struct usb_driver usb_storage_driver = {

233 .owner = THIS_MODULE,

234 .name = "usb-storage",

235 .probe = storage_probe,

236 .disconnect = storage_disconnect,

237 .id_table = storage_usb_ids,

238 };

可以看到这里定义了一个struct usb_driver 的结构体变量,usb_storage_driver, 关于usb_driver 我们
上节已经说过了,当时主要说的是其中的成员driver, 而眼下要讲的则是另外几个成员.首先,.owner
和.name 这两个没啥好多说的,owner 这玩艺是用来给模块计数的,每个模块都这么用,赋值总是
THIS_MODULE, 而name 就是这个模块的名字,usb core 会处理它,所以如果这个模块正常被加载了的话,
使用lsmod 命令能看到一个叫做usb-storage 的模块名.重点要讲一讲,.probe 和.disconnect 以及这个
id_table.

我是谁的他?

probe,disconnect,id_table,这三个咚咚中首先要登场亮相的是id_table, 它是干嘛用的呢?

我们说过,一个device 只能绑定一个driver, 但driver 并非只能支持一种设备,道理很简单,比如
我有两块U 盘,那么我可以一起都插入,但是我只需要加载一个模块,usb-storage, 没听说过插入
两块U 盘就得加载两次驱动程序的,除非这两块U 盘本身就得使用不同的驱动程序.也正是因为
一个模块可以被多个设备共用,才会有模块计数这么一个说法.

ok,既然一个driver 可以支持多个device,那么当发现一个device 的时候,如何知道哪个driver
才是她的Mr.Right 呢?这就是id_table 的用处,让每一个struct usb_driver 准备一张表,里边
注明该driver 支持哪些设备,这总可以了吧.如果你这个设备属于这张表里的,那么ok,绑定吧,如
果不属于这张表里的,那么不好意思,您请便.哪凉快上哪去.

来自struct usb_driver 中的id_table,

const struct usb_device_id *id_table;

实际上是一个指针,一个struct usb_device_id 结构体的指针,当然赋了值以后就是代表一个数
组名了,正如我们在定义struct usb_driver usb_storage_driver 中所赋的值那
样,.id_table=storage_usb_ids,那好,我们来看一下usb_device_id 这究竟是怎样一个结构
体.

struct usb_device_id 来自include/linux/mod_devicetable.h,

40 /
*
41 * Device table entry for "new style" table-driven USB drivers.
42 * User mode code can read these tables to choose which modules to load.
43 * Declare the table as a MODULE_DEVICE_TABLE.
44
*
45 * A probe() parameter will point to a matching entry from this table.
46 * Use the driver_info field for each match to hold information tied

论坛徽章:
0
18 [报告]
发表于 2008-06-06 13:41 |只看该作者
47 * to that match: device quirks, etc.
48
*
49 * Terminate the driver's table with an all-zeroes entry.
50 * Use the flag values to control which fields are compared.
51 *
/
52
53 /*
*
54 * struct usb_device_id - identifies USB devices for probing and hotplugging
55 * @match_flags: Bit mask controlling of the other fields are used to match
56 * against new devices. Any field except for driver_info may be used,
57 * although some only make sense in conjunction with other fields.
58 * This is usually set by a USB_DEVICE_*() macro, which sets all
59 * other fields in this structure except for driver_info.
60 * @idVendor: USB vendor ID for a device; numbers are assigned
61 * by the USB forum to its members.
62 * @idProduct: Vendor-assigned product ID.
63 * @bcdDevice_lo: Low end of range of vendor-assigned product version


numbers.
64 * This is also used to identify individual product versions, for
65 * a range consisting of a single device.
66 * @bcdDevice_hi: High end of version number range. The range of product
67 * versions is inclusive.
68 * @bDeviceClass: Class of device; numbers are assigned
69 * by the USB forum. Products may choose to implement classes,
70 * or be vendor-specific. Device classes specify behavior of all
71 * the interfaces on a devices.
72 * @bDeviceSubClass: Subclass of device; associated with bDeviceClass.
73 * @bDeviceProtocol: Protocol of device; associated with bDeviceClass.
74 * @bInterfaceClass: Class of interface; numbers are assigned

75 * by the USB forum. Products may choose to implement classes,
76 * or be vendor-specific. Interface classes specify behavior only
77 * of a given interface; other interfaces may support other classes.
78 * @bInterfaceSubClass: Subclass of interface; associated with bInterfaceClass.
79 * @bInterfaceProtocol: Protocol of interface; associated with bInterfaceClass.
80 * @driver_info: Holds information used by the driver. Usually it holds
81 * a pointer to a descriptor understood by the driver, or perhaps
82 * device flags.
83
*
84 * In most cases, drivers will create a table of device IDs by using
85 * USB_DEVICE(), or similar macros designed for that purpose.
86 * They will then export it to userspace using MODULE_DEVICE_TABLE()
,
87 * and provide it to the USB core through their usb_driver structure.
88
*
89 * See the usb_match_id() function for information about how matches are

论坛徽章:
0
19 [报告]
发表于 2008-06-06 13:42 |只看该作者
90 * performed. Briefly, you will normally use one of several macros to help
91 * construct these entries. Each entry you provide will either identify
92 * one or more specific products, or will identify a class of products
93 * which have agreed to behave the same. You should put the more specific
94 * matches towards the beginning of your table, so that driver_info can
95 * record quirks of specific products.
96 *
/
97 struct usb_device_id
{
98 /* which fields to match against? *
/
99 __u16 match_flags;


100
101 /* Used for product specific matches; range is inclusive *
/
102 __u16 idVendor;
103 __u16 idProduct;
104 __u16 bcdDevice_lo;
105 __u16 bcdDevice_hi;
106
107 /* Used for device class matches *
/
108 __u8 bDeviceClass;
109 __u8 bDeviceSubClass;
110 __u8 bDeviceProtocol;
111
112 /* Used for interface class matches *
/
113 __u8 bInterfaceClass;
114 __u8 bInterfaceSubClass;
115 __u8 bInterfaceProtocol;
116
117 /* not matched against *
/
118 kernel_ulong_t driver_info;
119 }
;


实际上这个结构体对每一个usb设备来说,就相当于是她的身份证,记录了她的一些基本信息,通常我们的身
份证上会记录我们的姓名,性别,出生年月,户口地址等等,而usb 设备她也有她需要记录的信息,以区分她和
别的usb 设备,比如Vendor-厂家,Product-产品,以及其他一些比如产品编号,产品的类别,遵循的协议,这
些都会在usb 的规范里边找到对应的冬冬.暂且先不细说.

于是我们知道,一个usb_driver 会把它的这张id 表去和每一个usb 设备的实际情况进行比较,如果该设备
的实际情况和这张表里的某一个id 相同,准确地说,只有这许多特征都吻合,才能够把一个usb device 和这
个usb driver 进行绑定,这些特征哪怕差一点也不行.就像我们每个人都是一道弧,都在不停寻找能让彼此
嵌成完整的圆的另一道弧,事实却是,每个人对Π(PI)的理解不尽相同,而圆心能否重合,或许只有痛过才知
道.差之毫厘,失之交臂.

那么usb 设备的实际情况是什么时候建立起来的?嗯,在介绍.probe 指针之前有必要先谈一谈另一个数据
结构了,她就是struct usb_device.

论坛徽章:
0
20 [报告]
发表于 2008-06-06 13:43 |只看该作者
从协议中来,到协议中去(上)

在struct usb_driver 中,.probe 和.disconnect 的原型如下:

int (*probe) (struct usb_interface *intf,const struct usb_device_id *id);

void (*disconnect) (struct usb_interface *intf);

我们来看其中的参数,struct usb_device_id 这个不用说了,刚才已经介绍过,那么struct usb_interface
从何而来?还是让我们先从struct usb_device 说起.

我们知道每一个device 对应一个struct device 结构体变量,但是device 不可能是万能的,生命是多样性
的,就像我们可以用"人"来统称全人类,但是分的细一点,又有男人和女人的区别,那么device 也一样,由于
有各种各样的设备,于是又出来了更多的词汇(数据结构),比如针对usb 设备,开发者们设计了一个叫做
struct usb_device 的结构体.她定义于include/linux/usb.h,

294 /
*
295 * struct usb_device - kernel's representation of a USB device
296
*
297 * FIXME: Write the kerneldoc!
298
*
299 * Usbcore drivers should not set usbdev->state directly. Instead use
300 * usb_set_device_state()
.
301 *
/
302 struct usb_device
{
303 int devnum; /* Address on USB bus *
/
304 char devpath [16]; /* Use in messages: /port/port/... *
/
305 enum usb_device_state state; /* configured, not attached, etc *
/
306 enum usb_device_speed speed; /* high/full/low (or error) *
/
307
308 struct usb_tt *tt; /* low/full speed dev, highspeed hub *
/
309 int ttport; /* device port on that tt hub *
/
310
311 struct semaphore serialize;
312
313 unsigned int toggle[2]; /* one bit for each endpoint ([0] = IN, [1]
=


OUT) */
314 int epmaxpacketin[16]; /* INput endpoint specific maximums */
315

int epmaxpacketout[16]; /* OUTput endpoint specific maximums

*/
316
317

struct usb_device *parent; /* our hub, unless we're the root */
318

struct usb_bus *bus; /* Bus we're part of *
/
319
320


struct device dev; /* Generic device interface *
/
321
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP