你的春天夏天秋天冬天的歌有几个,我的冬天就几个。

看空的人啊,再有几个利好,在春天你会比冬天还想咬人!
明摆着缩股前破2000点时,4,6元西南还在护盘,st前都是在4.3元以上运行,也就是说40元好多人也没有赚钱只是平手。
评论该主题
作者:您目前是匿名发表 &
作者:,欢迎留言
热门美股吧1、2、3、4、5、6、7、8、9、10、11、12、13、14、15、16、17、18、19、20、
意见反馈回到顶部Hi,这是的腾讯微博,人海茫茫相遇不易,立即登录,别错过!
正在加载...
Copyright & 1998 - 2015 Tencent. All Rights Reserved3569人阅读
看完了get_transport()继续看get_protocol()函数和get_pipes()函数。仍然是来自drivers/usb/storage/usb.c中:
672 static int get_protocol(struct us_data *us)
674&& switch (us-&subclass) {
675&&& caseUS_SC_RBC:
676&&&&&&& us-&protocol_name = &Reduced Block Commands (RBC)&;
677&&&&&&& us-&proto_handler = usb_stor_transparent_scsi_
678&&&&&&&&
680&& case US_SC_8020:
681&&&&&&&& us-&protocol_name = &8020i&;
682&&&&&&&& us-&proto_handler = usb_stor_ATAPI_
683&&&&&&&& us-&max_lun = 0;
684&&&&&&&&
686&&& caseUS_SC_QIC:
687&&&&&&&& us-&protocol_name = &QIC-157&;
688&&&&&& us-&proto_handler = usb_stor_qic157_
689&&&&&&& us-&max_lun = 0;
690&&&&&&&&
692&&& caseUS_SC_8070:
693&&&&&& us-&protocol_name = &8070i&;
694&&&&&&& us-&proto_handler = usb_stor_ATAPI_
695&&&&& us-&max_lun= 0;
696&&&&&&&
698&&& caseUS_SC_SCSI:
699&&&&&& us-&protocol_name = &Transparent SCSI&;
700&&&&&&&& us-&proto_handler = usb_stor_transparent_scsi_
701&&&&&&&&
703&&& caseUS_SC_UFI:
704&&&&&&& us-&protocol_name = &Uniform Floppy Interface (UFI)&;
705&&&&&&&& us-&proto_handler = usb_stor_ufi_
706&&&&&&&
708 #ifdef CONFIG_USB_STORAGE_ISD200
709&& case US_SC_ISD200:
710&&&&&&& us-&protocol_name = &ISD200 ATA/ATAPI&;
711&&&&&&&& us-&proto_handler = isd200_ata_
712&&&&&&&
713 #endif
715&& default:
716&&&&&&& return -EIO;
718&&&& US_DEBUGP(&Protocol:%s\n&, us-&protocol_name);
719&&& return 0;
这段代码非常浅显易懂。根据us-&subclass来判断。对于U盘来说,spec里面规定了,它的SubClass是US_SC_SCSI,所以这里就是两句赋值语句:一个是令us的protocol_name为“Transparent SCSI”,另一个是令us的proto_handler为usb_stor_transparent_scsi_command,后者又是一个函数指针。
然后是get_pipes(),来自drivers/usb/storage/usb.c:
723 static int get_pipes(struct us_data *us)
725&&& structusb_host_interface *altsetting =
726&&&&&&&&&&&&&&&&us-&pusb_intf-&cur_
728&& struct usb_endpoint_descriptor*
729&& struct usb_endpoint_descriptor*ep_in = NULL;
730&& struct usb_endpoint_descriptor*ep_out = NULL;
731&&& structusb_endpoint_descriptor *ep_int = NULL;
734&& &* Find the first endpoint of each type we need.
735&&& &* We are expecting a minimum of 2endpoints - in and out (bulk).
736&&& &* An optional interrupt-in is OK(necessary for CBI protocol).
737&& &* We will ignore any others.
739& for (i = 0; i &altsetting-&desc.bNumE i++) {
740&&&&&&& ep = &altsetting-&endpoint[i].
742&&&&&&&& if (usb_endpoint_xfer_bulk(ep)) {
743&&&&&&&&&&&& if (usb_endpoint_dir_in(ep)) {
744&&&&&&&&&&&&&&&& if (!ep_in)
745&&&&&&&&&&&&&&&&&&& ep_in =
746&&&&&&&&&&&& } else {
747&&&&&&&&&&&&&&&&& if (!ep_out)
748&&&&&&&&&&&&&&&&&&&&& ep_out =
749&&&&&&&&&&&&& }
750&&&&&& }
752&&&&&&& else if (usb_endpoint_is_int_in(ep)) {
753&&&&&&&&&& if (!ep_int)
754&&&&&&&&&&&&&&& ep_int =
755&&&&&&& }
758&& if (!ep_in || !ep_out ||(us-&protocol == US_PR_CBI && !ep_int)) {
759&&&&&&& US_DEBUGP(&Endpoint sanity check failed! Rejectingdev.\n&);
760&&&&&&&& return -EIO;
763&& /* Calculate and store the pipevalues */
764&& us-&send_ctrl_pipe =usb_sndctrlpipe(us-&pusb_dev, 0);
765&&& us-&recv_ctrl_pipe= usb_rcvctrlpipe(us-&pusb_dev, 0);
766&& us-&send_bulk_pipe =usb_sndbulkpipe(us-&pusb_dev,
767&&&&&&&&&&&&&&&&ep_out-&bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
768&& us-&recv_bulk_pipe =usb_rcvbulkpipe(us-&pusb_dev,
769&&&&&&&&&&&&&&&&ep_in-&bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
770&& if (ep_int) {
771&&&&&& us-&recv_intr_pipe = usb_rcvintpipe(us-&pusb_dev,
772&&&&&&&&&&&&&& ep_int-&bEndpointAddress& USB_ENDPOINT_NUMBER_MASK);
773&&&&&&&& us-&ep_bInterval = ep_int-&bI
775&& return 0;
这个函数应该可以说是比较复杂的一个。请容我慢慢给您道来。
726行,us-&pusb_intf,可还记得,在associate_dev中赋的值,如不记得请回过去查一下。没错,us-&pusb_intf就是我们故事中最开始一再提到的interface(指针)。而它的成员cur_altsetting,就是当前的设置。在讲associate_dev时也已经遇到过,它是一个structusb_host_interface的结构体指针。现在这里用另一个指针临时代替一下,altsetting。接下来会用到它的成员:desc和endpoint。
回顾structusb_host_interface,可以看到它两个成员:struct usb_interface_descriptor desc和struct usb_host_endpoint *endpoint。其中,desc不用多说,正是这个接口的接口描述符,而endpoint这个指针记录的是几个端点,它们以数组的形式被存储,而endpoint指向数组头。这些都是在USB Core枚举时就设置好了,我们无需操任何心,只需拿来使用就是了。这里给出struct usb_host_endpoint的定义,来自include/linux/usb.h:
59 struct usb_host_endpoint {
60&&& structusb_endpoint_descriptor&
61&&&& structlist_head&&&&&&&&&&&&&&&urb_
62&&&& void&&&&&&&&&&&&&&&&&&&&&&&&&&&*
63&& struct ep_device&&&&&&&&&&&&&&&*ep_&&&&&&& /* For sysfs info */
65&& unsigned char *&& /* Extra descriptors */
接着定义了几个struct usb_endpoint_descriptor的结构体指针。顾名思义,这就是对应端点的描述符。其定义来自于include/linux/usb/ch9.h:
312 /* USB_DT_ENDPOINT: Endpoint descriptor */
313 struct usb_endpoint_descriptor {
314& __u8&bL
315&&& __u8& bDescriptorT
317&&&& __u8& bEndpointA
318&&&& __u8& bmA
319&&& __le16wMaxPacketS
320&&& __u8& bI
322&& /* NOTE:& these two are _only_ in audio endpoints. */
323&& /* use USB_DT_ENDPOINT*_SIZE inbLength, not sizeof. */
324&&& __u8& bR
325&& __u8& bSynchA
326 } __attribute__ ((packed));
至此,四大描述符一一亮相,在继续讲之前,我们先来小结一下:究竟什么是描述符?每个USB设备都有四大描述符,这里拿U盘来举例。听说过Flash Memory吗?Intel、三星,这些都是做Flash Memory的,当然通常人们就简称Flash。Flash在U盘中扮演什么角色?Flash是用来给用户存储数据的,而U盘中的Flash就相当于PC中的硬盘,存储数据主要就靠它。那么除了给用户存储数据以外,设备自己还需要存储一些设备本身固有的信息,比如设备姓甚名谁?谁生产的?还有一些信息,比如该设备有几种配置,有几个接口,等许多特性。
这个世界上,除了Flashmemory外,还有一个东西叫做EEPROM,也是用来存储的,它是EEPROM的前身,而Flash是基于EEPROM技术发展起来的一种低成本的ROM产品。
EEPROM和Flash相同,都是需要电擦除,但EEPROM可以按字节擦除,而不像Flash那样一次擦除一个block,这样在只需改动很少数据的情况下使用EEPROM就很方便了。因此EEPROM的这一特性使它的电路要复杂一些,并且集成度不高,一个bit需要两个管子:一个用来储存电荷信息,一个充当开关。所以EEPROM的成本高,Flash简化了一些电路,成本降低了很多。
因此,在USB设备中通常会有一个Flash芯片,以及一个EEPROM芯片。Flash用于为客户存储数据,而EEPROM用来存储设备本身的信息。这就是为什么当Intel把Flash芯片卖给摩托罗拉之后,客户看到的手机厂商是摩托罗拉而不是Intel,因为我们虽然在做Flash时把我们的厂商ID写在了Flash上,但是对于最终的成品对外来看,提供的信息都是来自EEPROM,所以当你把USB设备通过USB接口连到电脑上去,电脑上如果能显示厂家,那么一定是最终的包装厂家,而不可能是那块Flash的厂家。而EEPROM里边写什么?按什么格式写?这正是USB
spec规定的,这种格式就是一个个描述符的格式。设备描述符、配置描述符、接口描述符、端点描述符,以及其他一些某一些类别的设备特有的描述符,比如Hub描述符都是很规范的,尤其对于这四种标准的描述符,每个USB设备都是规规矩矩地支持的。所以USB Core层可以用一段相同的代码把它们都给读出来,而不用再让我们设备驱动程序去自己读了,这就是权力集中的好处,反正大家都要做的事情,干脆让上头一起做了好了。
739行到756行,循环,bNumEndpoints就是接口描述符中的成员,表示这个接口有多少个端点,不过这其中不包括0号端点,0号端点是任何一个USB设备都必须是提供的,这个端点专门用于进行控制传输,即它是一个控制端点。正因为如此,所以即使一个设备没有进行任何设置,USB主机也可以开始跟它进行一些通信,因为即使不知道其他端点,但至少知道它一定有一个0号端点,或者说一个控制端点。
此外,通常USB Mass Storage会有两个批量端点,用于批量传输,即所谓的批量传输。我们日常的读写U盘里的文件,就是属于批量传输。所以毫无疑问,对于Mass Storage设备来说,批量传输是它的主要工作方式,道理很简单,我们使用U盘就是用来读写文件的。和这些描述符打交道无非就是为了帮助我们最终实现读写文件的工作,这才是每一个USB存储设备真正的使命。
于是我们来看这段循环到底在干什么,altsetting-&endpoint[i].desc,对照struct usb_host_endpoint这个结构体的定义可知,desc正是一个struct usb_endpoint_descriptor的变量。刚刚定义了四个这种结构体的指针,ep,ep_in,ep_out和ep_int,很简单,就是用来记录端点描述符的,ep_in用于Bulk-IN,ep_out用于Bulk-OUT,ep_int用于记录中断端点(如果有的话)。而ep,只是一个临时指针。
我们看structusb_endpoint_descriptor,在它的成员中,bmAttributes表示属性,总共8位,其中bit1和bit0共同称为Transfer Type,即传输类型,00表示控制,01表示等时,10表示批量,11表示中断。因此通过比较这些成员,就可以判断该端点的传输类型,这个函数usb_endpoint_xfer_bulk()定义于include/linux/usb.h中:
571 static inline int usb_endpoint_xfer_bulk(conststruct usb_endpoint_ descriptor *epd)
573&&& return((epd-&bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
574&&&&&&&&&&&&&&&&USB_ENDPOINT_XFER_BULK);
而USB_ENDPOINT_XFERTYPE_MASK这个宏定义于include/linux/usb/ch9.h中:
338 #define USB_ENDPOINT_XFERTYPE_MASK&&&&& 0x03&&& /* in bmAttributes */
339 #define USB_ENDPOINT_XFER_CONTROL&&&&&& 0
340 #define USB_ENDPOINT_XFER_ISOC&&&&& 1
341 #define USB_ENDPOINT_XFER_BULK&&&&& 2
342 #define USB_ENDPOINT_XFER_INT&&&&&& 3
从上面的注释可以看出,742行就是判断这个端点描述符描述的是不是一个批量端点。如果是,继续比较。我们先看bEndpointAddress,这个struct usb_endpoint_descriptor中的另一个成员,也是8个bit,或者说1个Byte,其中bit7表示这个端点的方向,0表示OUT,1表示IN。OUT与IN是对主机而言,OUT就是从主机到设备,IN就是从设备到主机。因此比较这个成员就可以判断端点的方向,干这件事的函数usb_endpoint_dir_in()也来自include/linux/usb.h:
549 static inline int usb_endpoint_dir_in(conststruct usb_endpoint_ descriptor *epd)
551 return ((epd-&bEndpointAddress&USB_ENDPOINT_DIR_MASK)==USB_DIR_IN);
而宏USB_DIR_IN和USB_ENDPOINT_DIR_MASK仍然来自include/linux/usb_ch9.h:
48 #define USB_DIR_OUT&&&&&&&&&&&&&&&&&&&&0&&&&&&&&&&&&&&/* to device */
49 #define USB_DIR_IN&&&&&&&&&&&&&&&&&&&&&0x80&&&&&&&&&&&/* to host */
336 #define USB_ENDPOINT_DIR_MASK&&&&&&&&&& 0x80
所以这里意思很明显,就是为了让ep_in和ep_out指向该指的endpoint descriptor。
而接下来752行,usb_endpoint_is_int_in()来自include/linux/usb.h:
646 static inline int usb_endpoint_is_int_in(conststruct usb_endpoint_ descriptor *epd)
648&& return (usb_endpoint_xfer_int(epd)&& usb_endpoint_dir_in(epd));
有了前面两个函数作为基础,这个函数就不用再说了。总之,752行中else if的作用就是如果这个端点是中断端点,那么就让ep_int指向它。我们说了,每一类USB设备其上面有多少端点有何种端点都是不确定的,都得遵守该类设备的规范,而USB Mass Storage的规范中规定了,一个USB Mass Storage设备至少应该有两个批量端点,控制端点显然是必需的。毋庸置疑,另外,可能会有一个中断端点,这种设备支持CBI协议,即Control/Bulk/Interrupt协议。我们也说过了,U盘遵守的是Bulk-only协议,它不需要有中断端点。
758行到761行这段代码,没什么好说的,就是判断ep_in或者ep_out是否存在,或者是遵守CBI协议但是没有中断端点,这些都是不合理的,当然就会出错!
剩下一小段代码,我们下节再看。需要说的是,这个函数结束之后我们将开始最精彩的部分,它就是伟大的usb_stor_acquire_resources()。黑暗即将过去,黎明已经带我们上路。让我们共同期待吧。同时,我们小结一下,此前我们花了很大的篇幅来为usb_stor_acquire_resources()做铺垫,那我们来回顾一下,它究竟做了哪些事情?
首先我们从storage_probe出发,一共调用了五个函数,它们是assocaite_dev,get_device_info,get_transport,get_protocol,get_pipes。我们这样做的目的是什么?很简单,就是为了建立一个数据结构,它就是传说中的struct us_data,它的名字叫做us。我们把它建立了起来,为它申请了内存,为它的各个元素赋了值,目的就是为了让以后我们可以很好地利用它。
这五个函数都不难,你一定也会写。难的是如何去定义struct us_data,别忘了这个数据结构是写代码的同志们专门为usb-storage模块而设计的。所谓编程,无非就是数据结构加上算法。没错,这个定义于drivers/usb/storage/usb.h中的数据结构长达60行,关于她的成员,我们还有很多没遇到,不过别急,后面会遇到的。好了,虽然get_pipes还有一小段没讲,但是我们可以提前和这5个函数说再见了,席慕蓉说过,若不得不分离,也要好好地说声再见,也要在心里存着一份感谢,谢谢她给你一份记忆。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1945476次
积分:21923
积分:21923
排名:第121名
原创:296篇
评论:1991条
文章:40篇
阅读:188892
文章:25篇
阅读:387244
(1)(1)(1)(1)(1)(1)(4)(5)(9)(6)(4)(1)(1)(5)(4)(1)(8)(11)(6)(4)(4)(11)(18)(26)(37)(51)(25)(29)(20)日期:我爱你春天,寒冷的冬天过去了,春天又悄然无息地来到了。小草发芽了,仿佛想要一夜之间长大。花坛中,花儿们争奇斗艳,生怕落后了别人。迎春花上,那细长的枝条才开出金灿灿的花。倒着看像一个小喇叭,又像一串串美丽的项链。那些深红色的花儿是几株腊梅,你看那些腊梅花,比叶儿早来了,一簇一簇地开满了枝头。
旗台旁的梧桐树使劲地摆动着身子,好像正在跳舞。这时,一阵阵春风柔柔地。暖暖地吹在脸上,给人一种温馨的感觉。
校园中的柳树开出了新芽,春风吹来,柳树舒展着长长的枝条,好似美丽的少女梳理着自己的头发。
一只只活泼...寒冷的冬天过去了的相关内容日期:天气寒冷,宝宝不爱洗澡怎么办 每天洗澡能让宝宝彻底清洁,可是,如果他不喜欢洗澡或者不适合洗澡呢?你怎么让你的宝宝全身上下干干净净? 1、小手先洗净 宝宝的小手是仰慕者的最爱,谁都喜欢握住柔软的小手,传递无限的爱意,可是,此时不受欢迎的细菌也随着抚摸传递了,然日期:寒冷的天气与小儿防病须知 由于近日气温急剧下降,孩子出门稍不注意往往易受风寒而患上呼吸道感染。因此防寒保暖对于预防感冒、支气管炎等呼吸道疾病的发生很重要。平时多注意锻炼身体、增强体质,是预防呼吸道感染的好方法。让孩子用温水而不用热水洗四肢、洗脸,能使孩子日期:搓搓手D宝宝冬天的健康操 冬季天气冷,经常搓擦双手对于孩子来说好处不仅仅在于暖手,它的好处可能你想都想不到: ?防冻疮 孩子的血液循环多欠佳,一旦气温低于10℃而又缺乏运动或有效的保暖措施时,很容易在手指、手背...日期:冬天有多少危险(下) (接上文) 冻伤 易冻伤部位:耳朵、鼻子、脸颊、手指和脚趾。 症状:皮肤如腊状、坚硬,呈灰白色或蜡黄色;感觉麻木或有灼烧感。情况严重的话,皮肤会变成蓝色或紫色,甚至起水泡。如果出现以上症状,应该立即到医院就诊。 处理方法: * 与轻度冻伤的日期:冬天有多少危险(上) 刮风了!下雪了!冬天又到了!冷空气并不能让孩子乖乖地呆在家里,白雪、冰面在他们眼里都是游戏的天堂。你要做的就是让寒冷和伤害远离孩子,给他一个快乐的冬天! 即便是冰天雪地,也会成为孩子游戏的乐园。那么为孩子的...日期:冬天谨防煤气中毒 冬天到了,许多家庭用上了煤球炉取暖,提醒你在家里生火炉要当心煤气中毒。煤气是指一氧化碳,它无色无味。煤气中毒多数发生在用煤球炉取暖的家庭。主要原因是: 1、 冬季用煤炉,室内未装通风设施。 2、 煤炉密封不严漏气。 3、 煤炉使用...日期:冬天,舒服做月子 冬天坐月子,听起来好像是件“美差”,外面寒风刺骨,屋里却是暖洋洋的,但是只有温度的“支持”就行了吗?当然不是,新妈妈还需要清洁...
&最新内容- - - - - - - - - - - - &&热点推荐
精品专题-  -  - -  -  - -  -  - -  -  - -  -  - -  -  - -  -  - -  -  - -  -  -
英语学习- -  -  - -  -  - -  -  - - -  -  - -  -  - -  -  - - -  -  -
数学学习-  - - -
 - - - - - - - -

我要回帖

更多关于 冬天里的春天 的文章

 

随机推荐