结一下,此前我们花了很大的篇幅来为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 个函数 说 再见了,席慕蓉说过,若不得不分离,也要好好的说声再见,也要在心里存着一份感谢,谢谢她给你一份记忆. 通往春天的管道 1990 年,两伊战争,电台里报道早间新闻,播音员说:各位听众朋友,昨天伊拉克截断了科威特的两条输卵管 道.(输油管道) 此时,树无语天无语人无语. 一年后,公元1991 年,一个芬兰人写了一个叫做Linux 的操作系统,他也觉得这位播音员很有趣,给听众朋 友们带来了欢乐.于是为了纪念这件经典的口误,这个芬兰人在Linux 中引入了管道这么一个概念,并且他 把 管道用在很多地方,文件系统中,设备驱动中,于是后来我们看到在Linux 中有了各种各样的管道,不过,没有 58 输油管道,更没有输卵管道.但是相同的是,所有的管道都是用来传输东西的,只不过有些管道传输的是实实 在在的物质,而有些管道传输的是数据. 眼下我们在usb 代码中看到的管道就是用来传输数据,用来通信. 通信是双方的,不可能自言自语对吧.而 在 usb 的通信中,一方肯定是主机,即host,另一方是什么?是设备吗?在你少不更事的岁月里,你可以说是设 备, 你可以说主机和设备进行通信.但是,现在,当你已经长大,当你已经成熟,在这样一个激情燃烧的岁月里,你 应该说得更确切一点.真正和主机进行通信的是设备内的端点.关于端点,我们也可以专业一点说,从硬件上 来看它是实实在在存在的,它被实现为一种FIFO,支持多少个端点是接口芯片的一个重要指标.而从概念上 来说,端点是主机和usb 设备之间通信流的终点.主机和设备可以进行不同种类的通信,或者说数据传输,首 先,设备连接在usb 总线上,usb 总线为了分辨每一个设备,给每一个设备编上号,然后为了实现多种通信, 设 备方于是提供了端点,端点多了,自然也要编上号,而让主机最终和端点去联系. 鲁迅先生说得好,世上本没有管道,端点多了,也就有了管道. 这句话说得相当好,非常有道理,两个字,犀利!没错,我们知道,usb 的世界里,有四种管道,它们对应usb 世 界 中的四种传输方式,控制传输对应控制管道,中断传输对应中断管道,批量传输对应批量管道,等时传输对应 等时管道.每一个usb 世界中的设备要在usb 世界里生存,就得有它生存的管道.而管道的出现,正是为了让 我们分辨端点,或者说连接端点.记得网友唐伯虎点蚊香曾经说过,主机与端点之间的数据链接就称为管道.
比如说,复旦大学,有一个主校区,也可以说是教学区,(当然也包括一些实验室),上课什么的都得去教学区,把 教学区看作主机,那么与其相对的是,另外有很多学生宿舍楼,宿舍楼多了,就给每个楼编上号,比如1 号楼,2 号楼,...,36 号楼,..,每幢楼算一个设备,比如说你在淘宝网上买了一套阿玛尼外套(当然,肯定是假的,也就 一两百的那种),你让人家给你快递过来,人家问你你住哪?你说你住复旦大学,但如果你只说你在复旦大学, 那么送快递那哥们可能先得赶到复旦大学正门,或者学生宿舍区的正门,然后人家肯定就得问,你是哪幢楼哪 间房?比如你说你是36 号楼201,好,那么像201 这么一个数字呢,就对应端点号,最终那套外套要到达的就 是端点201,而不仅仅是36 号楼,对吧,假如人家要是送到36 号楼下就把外套给扔地上了你肯定得跟他急. 那么在这个例子里,复旦主校区是主机,每幢宿舍楼算一个设备,你住的那间宿舍就算端点.那么pipe 呢?pipe 很难与现实中的某一实物对应,不能说她是复旦正门通往宿舍的某条路,而应该按别的方式理解. 她 包含很多东西,你可以把她比作快递的货物上面贴得那张标签,比如她上面写了收货人的地址,包括多少号楼 多少号房,在usb 里面,就是设备号和端点号,知道了这两个号,货物就能确定它的目的地,而usb 主机就能 知 道和她通信的是哪个端点.而pipe 除了包含着两个号以外,还包含其它一些信息,比如她包含了通信的方向, 也就是说,你能从那张标签上得知36 号楼201 这个是收件人呢还是寄件人,虽然现实中不需要写明,因为 快 递员肯定知道你是收件人,他没事才不会和寄件人联系呢.再比如,pipe 里还包含了pipe的类型,比如你快 递 是从深圳递过来,那么怎么递就得看了,快递公司肯定提供不同类型的服务,有的快有的慢,有的可能还有保 险什么的,看你出多少钱,让你选择不同的服务类型,同样pipe 也如此,因为usb 设备的端点有不同的类型, 所以pipe 里就包含了一个字段来记录这一点,这个字段称为pipe type.好,让我们来看看实际的pipe 吧. 来看这些宏,头一个闪亮登场的是usb_sndctrlpipe,定义于include/linux/usb.h 中,咱们先把这一堆冬 冬相关的代码给列出来. 1104 static inline unsigned int __create_pipe(struct usb_device *dev, unsigned int endpoint) 1105 { 1106 return (dev->devnum
- Page 1 and 2:
摘要 ............................
- Page 3 and 4:
迷雾重重的Bulk 传输(二)....
- Page 5 and 6:
引子 也许是在复旦养成了
- Page 7 and 8:
usb.h datafab.h dpcm.h initializers
- Page 9 and 10: 的Linux 内核划分为许许多
- Page 11 and 12: 目录下执行make 了.Ok,make 之
- Page 13 and 14: 只 是一个usb 接口.这些口
- Page 15 and 16: 中也定义了这么一些数据
- Page 17 and 18: 511 * @driver: the driver model cor
- Page 19 and 20: 233 .owner = THIS_MODULE, 234 .name
- Page 21 and 22: 91 * construct these entries. Each
- Page 23 and 24: 324 struct usb_host_config *actconf
- Page 25 and 26: 22 88 * @class_dev: driver model's
- Page 27 and 28: 必须给各个地方取名,完了
- Page 29 and 30: 26 136 trans_cmnd transport; /* tra
- Page 31 and 32: 944 init_MUTEX_LOCKED(&(us->sema));
- Page 33 and 34: 147 #if !defined(CONFIG_BLK_DEV_UB)
- Page 35 and 36: 124 #define USB_DEVICE_ID_MATCH_DEV
- Page 37 and 38: intf 来代替. us 之所以重要,
- Page 39 and 40: 睡眠,那就得用GPF_ATOMIC,这
- Page 41 and 42: 504 if (msg >= 0 && !(unusual_dev->
- Page 43 and 44: 179 } 180 181 static struct us_unus
- Page 45 and 46: 711 /* Submitted by Hartmut Wahl */
- Page 47 and 48: 3. useProtocol 为US_SC_DEVICE, use
- Page 49 and 50: Bus 004 Device 001: ID 0000:0000 Bu
- Page 51 and 52: 993 result = get_pipes(us); 994 if
- Page 53 and 54: 631 us->transport_reset = usb_stor_
- Page 55 and 56: 659 us->max_lun = 0; 660 break; 661
- Page 57 and 58: 740 /* Calculate and store the pipe
- Page 59: storage 会有两个bulk 端点,用
- Page 63 and 64: 1079 #define PIPE_ISOCHRONOUS 0 108
- Page 65 and 66: 782 us->unusual_dev->initFunction(u
- Page 67 and 68: 630 * each frame is in the fields o
- Page 69 and 70: 716 * Bulk URBs may 717 * use the U
- Page 71 and 72: 802 int number_of_packets; /* (in)
- Page 73 and 74: 先说互斥锁.它诞生于这样
- Page 75 and 76: 920 US_DEBUGP("GetMaxLUN command re
- Page 77 and 78: 148 /* set up data structures for t
- Page 79 and 80: 90 * @wValue: matches the USB wValu
- Page 81 and 82: 830 void *transfer_buffer, 831 int
- Page 83 and 84: 25 { 26 x->done = 0; 27 init_waitqu
- Page 85 and 86: 都会过期,我开始怀疑,在这
- Page 87 and 88: 是实际长度,要么就是不成
- Page 89 and 90: 87 258 行,usb_pipeendpoint,定义
- Page 91 and 92: 对爱你的人掘了一条无法
- Page 93 and 94: Type: Direct-Access ANSI SCSI revis
- Page 95 and 96: 416 /* 417 * this defines our host
- Page 97 and 98: 69 * Ioctl interface 70 * 71 * Stat
- Page 99 and 100: 155 * "is this a new device" checks
- Page 101 and 102: 241 char *proc_name; 242 243 /* 244
- Page 103 and 104: 328 * True if the low-level driver
- Page 105 and 106: 可以看到这个函数的参数
- Page 107 and 108: 451 short unsigned int max_sectors;
- Page 109 and 110: 地 说明了为啥咱们要显式
- Page 111 and 112:
usb_stor_acquire_resources()函数
- Page 113 and 114:
341 } 342 343 /* reject if target !
- Page 115 and 116:
内核的核心位置,kernel/exit.c
- Page 117 and 118:
1023 dissociate_dev(us); 1024 retur
- Page 119 and 120:
917 行,再次判断设备有没有
- Page 121 and 122:
181 182 /* fail the command if we a
- Page 123 and 124:
83 struct timer_list eh_timeout; /*
- Page 125 and 126:
123 两个scsi_done,一个是struct
- Page 127 and 128:
56 jiffie count on our counter, the
- Page 129 and 130:
中 看到如下的定义: UNUSUAL_
- Page 131 and 132:
269 memcpy(data+16, us->unusual_dev
- Page 133 and 134:
一切准备好了之后,我们就
- Page 135 and 136:
238 (sg->offset + *offset) & (PAGE_
- Page 137 and 138:
所以对于那些不能相应INQUI
- Page 139 and 140:
239 行对unsigned int sglen 赋值
- Page 141 and 142:
请求,所以这里就判断abort
- Page 143 and 144:
112 case GPCMD_READ_HEADER: what =
- Page 145 and 146:
到北京,每每只有在夜深人
- Page 147 and 148:
580 /* 581 * If we have a failure,
- Page 149 and 150:
666 memcpy(srb->cmnd, old_cmnd, MAX
- Page 151 and 152:
950 struct bulk_cb_wrap *bcb = (str
- Page 153 and 154:
1034 /* get the status again */ 103
- Page 155 and 156:
426 /* store the actual length of t
- Page 157 and 158:
后她会给host 返回一个CSW.CB
- Page 159 and 160:
296 } 297 298 US_DEBUGP("-- transfe
- Page 161 and 162:
491 * scatter-gather or not, and ac
- Page 163 and 164:
迷雾重重的 Bulk 传输(五) us
- Page 165 and 166:
然后把她赋给了result.而us->
- Page 167 and 168:
而bcs->Status,标志命令执行
- Page 169 and 170:
就必须设置US_FL_IGNORE_RESIDUE
- Page 171 and 172:
485 }; 486 这是一个字符数组
- Page 173 and 174:
srb->sense_buffer 里边的东西.S
- Page 175 and 176:
一个类似的函数,名叫usb_sto
- Page 177 and 178:
这种命令应该由mid level 来
- Page 179 and 180:
Disk /dev/sda: 146.1 GB, 1461631057
- Page 181 and 182:
through to the most significant bit
- Page 183 and 184:
1192 USB_TYPE_CLASS | USB_RECIP_INT
- Page 185 and 186:
315 行,scsi_report_device_reset(),
- Page 187 and 188:
285 US_DEBUGP("No reset during disc
- Page 189 and 190:
229 /* Wait for the aborted command
- Page 191 and 192:
两个函数中需要判断它,一
- Page 193 and 194:
associate_dev()相对应.我们来
- Page 195 and 196:
束for 死循环,从而usb_stor_con
- Page 197 and 198:
317 for (i = 1; i < us->host->max_i