Scsi - Index of

Scsi - Index of Scsi - Index of

07.06.2013 Views

131 container_of(intf->dev.parent, struct usb_device, dev) 23 嗬,贴这么长一段,怎么又是注释为主啊?知足吧,Linux 代码中注释实在是太少了,等你真的需要认真看某 一 个模块的时候你就会嫌注释少了.这个结构体是一个贯穿整个U 盘驱动程序的,所以虽然我们不用去深入了 解,但是需要记住,整个U 盘驱动程序在后面任何一处提到的struct usb_interface 都是同一个变量,这个 变量是在usb core 总线扫描的时候就申请好了的.我们只需贯彻鲁迅先生的拿来主义即可,直接用就是了. 比如前面说过的storage_probe(struct usb_interface *intf,const struct usb_device_id *id),storage_disconnect(struct usb_interface *intf)这两个函数中的那个参数intf. 而这里130 行这个宏-interface_to_usbdev,也会用得着的,顾名思义,就是从一个struct usb_interface 转换成一个struct usb_device,我们说过了,有些函数需要的参数就是struct usb_device,而不是 usb_interface,所以这种转换是经常会用到的,而这个宏,usb core 的设计者们也为我们准备好了,除了感 激,我们还能说什么呢? 从协议中来,到协议中去(下) 如果你是急性子,那这时候你一定很想开始看storage_probe 函数了,因为整个U 盘的工作就是 从这里开始的.不过,莎士比亚说过,磨刀不误砍柴功.不妨继续花点时间,至少把四大关键词中最 后一个给弄明白了, 前面我们已经了解了device,configuration,interface,还剩最后一个endpoint.USB通信的最 基本的形式就是通过endpoint,道上的兄弟管这个叫做端点,一个接口有一个或多个端点,而作 为像U 盘这样的存储设备吧,它至少有一个控制端点,两个bulk 端点.这些端点都是干嘛的?说来 话长,真是一言难尽哪. usb 协议里规定了,usb 设备有四种通信方式,分别是控制传输,中断传输,批量传输,等时传输.其 中,等时传输显然是用于音频和视频一类的设备,这类设备期望能够有个比较稳定的数据流,比如 你在网上QQ 视频聊天,肯定希望每分钟传输的图像/声音速率是比较稳定的,不能说这一分钟对 方看到你在向她向你深情表白,可是下一分钟却看见画面停滞在那里,只能看到你那傻样一动不 动,你说这不浪费感情嘛.所以,每一个有良知的男人都应该知道,usb-storage 里边肯定不会用 到等时传输.因为我们只管copy 一个文件,管它第一秒和第二秒的传输有什么区别,只要几十秒 内传完了就ok. 相比之下,等时传输是四种传输中最麻烦的,所以,U 盘里边用不着,那您就偷着乐去吧.不过我要 说,中断传输也用不着,对于U 盘来说,的确用不着,虽然说usb mass storage 的协议里边有一 个叫做CBI 的传输协议,CBI 就是Control/Bulk/Interrupt,即控制/批量/中断,这三种传输都会 用到,但这种传输协议并不适用于U 盘,U 盘使用的是一个叫做Bulk-Only 的传输协议.使用这种 协议的设备只有两种传输方式,一种是批量传输,另一种是控制传输,控制传输是任何一种usb 设 备都必须支持的,它专门用于传输一些控制信息.比如我想查询一下关于这个interface 的一些信 息,那么就用控制传输,而bulk 传输,它就是U 盘的主要工作了,读写数据,这种情况就得用bulk 传输.具体的传输我们后面再讲. 好了,知道了传输方式,就可以来认识endpoint 了.和endpoint 齐名的有一个叫做管道,或者有 文化的人管这个叫pipe.endpoint 就是通信的发送或者接收点,你要发送数据,那你只要把数据 发送到正确的端点那里就可以了.之所以U盘有两个bulk 端点,是因为端点也是有方向的,一个叫 做Bulk in,一个叫做Bulk out,从usb 主机到设备称为out,从设备到主机称为in.而管道,实际 上只是为了让我们能够找到端点,就相当于我们日常说的邮编地址,比如一个国家,为了通信,我们

必须给各个地方取名,完了给各条大大小小的路取名,比如你要揭发你们那里的官员腐败,你要去 24 上访,你从某偏僻的小县城出发,要到北京来上访,那你的这个端点(endpoint)就是北京,而你得 知道你来北京的路线,那这个从你们县城到北京的路线就算一条管道.有人好奇的问了,管道应该 有两端吧,一个端点是北京,那另一个端点呢?答案是,这条管道有些特殊,就比如上访,我们只需要 知道一端是北京,而另一端是哪里无所谓,因为不管你在哪里你都得到北京来上访.没听说过你在 山西你可以上访,你要在宁夏还不能上访了,没这事对吧. 严格来说,管道的另一端应该是usb 主机,即前面说的那个host,usb 协议里边也是这么说的,协 议里边说pipes 代表着一种能力,怎样一种能力呢,在主机和设备上的端点之间移动数据,听上去 挺玄的.因为事实上,usb 里边所有的数据传输都是有主机发起的.一切都是以主机为核心,各种设 备紧紧围绕在主机周围.所以呢,usb core 里边很多函数就是,为了让usb host 能够正确的完成 数据传输或者说传输调度,就得告诉host 这么一个pipe,换言之,它得知道自己这次调度的数据 是传送给谁或者从谁那里传输过来.不过有人又要问了,比如说我要从U 盘里读一个文件,那我告 诉usb host 某个端点能有用吗?那个文件又不是存放在一个端点里边,它不该是存放在U盘里边 吗?这个就只能在后面的代码里去知道了.实际上端点这东西是一个很虚的东西,它的身上充分体 现了我国军事思想中的声东击西的想法,即数据本身并不是在端点里,但是看上去却觉得仿佛在 端点里.这一切的谜团,让我们在storage_probe()函数里去慢慢解开吧. 梦开始的地方 对于整个usb-storage 模块,usb_stor_init()是它的开始,然而,对于U 盘驱动程序来说,它真正 驱使U 盘工作却是始于storage_probe(). 两条平行线只要相交,就注定开始纠缠一生,不管中间是否短暂分离. usbcore 为设备找到了适合 她的驱动程序,或者为驱动程序找到了他所支持的设备,但这只是表明双方的第一印象还可以,但 彼此是否真的适合对方还需要进一步的了解.毋庸置疑,了解对方的第一步是,知道她有哪些爱好, 她的生日,她的星座,喜欢吃什么,而U 盘driver 则会调用函数storage_probe()去认识对方,她 是个什么样的设备,她的生活习惯是?她的联系方式是?这里调用了四个函数 get_device_info,get_protocol,get_transport,get_pipes. 当然还有一些别人并不了解的 冬冬你也会知道,比如她的三围,这里对应的就是usb_stor_Bulk_man_lun(). 整个U 盘驱动这部大戏,由storage_probe 开始,由storage_disconnect 结束.其 中,storage_probe 这个函数占了相当大的篇幅.我们一段一段来看.这两个函数都来自 drivers/usb/storage/usb.c 中: 926 /* Probe to see if we can drive a newly-connected USB device */ 927 static int storage_probe(struct usb_interface *intf, 928 const struct usb_device_id *id) 929 { 930 struct us_data *us; 931 const int id_index = id - storage_usb_ids; 932 int result; 933 934 US_DEBUGP("USB Mass Storage device detected\n"); 935 936 /* Allocate the us_data structure and initialize the mutexes */ 937 us = (struct us_data *) kmalloc(sizeof(*us), GFP_KERNEL);

必须给各个地方取名,完了给各条大大小小的路取名,比如你要揭发你们那里的官员腐败,你要去<br />

24<br />

上访,你从某偏僻的小县城出发,要到北京来上访,那你的这个端点(endpoint)就是北京,而你得<br />

知道你来北京的路线,那这个从你们县城到北京的路线就算一条管道.有人好奇的问了,管道应该<br />

有两端吧,一个端点是北京,那另一个端点呢?答案是,这条管道有些特殊,就比如上访,我们只需要<br />

知道一端是北京,而另一端是哪里无所谓,因为不管你在哪里你都得到北京来上访.没听说过你在<br />

山西你可以上访,你要在宁夏还不能上访了,没这事对吧.<br />

严格来说,管道的另一端应该是usb 主机,即前面说的那个host,usb 协议里边也是这么说的,协<br />

议里边说pipes 代表着一种能力,怎样一种能力呢,在主机和设备上的端点之间移动数据,听上去<br />

挺玄的.因为事实上,usb 里边所有的数据传输都是有主机发起的.一切都是以主机为核心,各种设<br />

备紧紧围绕在主机周围.所以呢,usb core 里边很多函数就是,为了让usb host 能够正确的完成<br />

数据传输或者说传输调度,就得告诉host 这么一个pipe,换言之,它得知道自己这次调度的数据<br />

是传送给谁或者从谁那里传输过来.不过有人又要问了,比如说我要从U 盘里读一个文件,那我告<br />

诉usb host 某个端点能有用吗?那个文件又不是存放在一个端点里边,它不该是存放在U盘里边<br />

吗?这个就只能在后面的代码里去知道了.实际上端点这东西是一个很虚的东西,它的身上充分体<br />

现了我国军事思想中的声东击西的想法,即数据本身并不是在端点里,但是看上去却觉得仿佛在<br />

端点里.这一切的谜团,让我们在storage_probe()函数里去慢慢解开吧.<br />

梦开始的地方<br />

对于整个usb-storage 模块,usb_stor_init()是它的开始,然而,对于U 盘驱动程序来说,它真正<br />

驱使U 盘工作却是始于storage_probe().<br />

两条平行线只要相交,就注定开始纠缠一生,不管中间是否短暂分离. usbcore 为设备找到了适合<br />

她的驱动程序,或者为驱动程序找到了他所支持的设备,但这只是表明双方的第一印象还可以,但<br />

彼此是否真的适合对方还需要进一步的了解.毋庸置疑,了解对方的第一步是,知道她有哪些爱好,<br />

她的生日,她的星座,喜欢吃什么,而U 盘driver 则会调用函数storage_probe()去认识对方,她<br />

是个什么样的设备,她的生活习惯是?她的联系方式是?这里调用了四个函数<br />

get_device_info,get_protocol,get_transport,get_pipes. 当然还有一些别人并不了解的<br />

冬冬你也会知道,比如她的三围,这里对应的就是usb_stor_Bulk_man_lun().<br />

整个U 盘驱动这部大戏,由storage_probe 开始,由storage_disconnect 结束.其<br />

中,storage_probe 这个函数占了相当大的篇幅.我们一段一段来看.这两个函数都来自<br />

drivers/usb/storage/usb.c 中:<br />

926 /* Probe to see if we can drive a newly-connected USB device */<br />

927 static int storage_probe(struct usb_interface *intf,<br />

928 const struct usb_device_id *id)<br />

929 {<br />

930 struct us_data *us;<br />

931 const int id_index = id - storage_usb_ids;<br />

932 int result;<br />

933<br />

934 US_DEBUGP("USB Mass Storage device detected\n");<br />

935<br />

936 /* Allocate the us_data structure and initialize the mutexes */<br />

937 us = (struct us_data *) kmalloc(size<strong>of</strong>(*us), GFP_KERNEL);

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!