395 US_SC_DEVICE, US_PR_DEVICE, NULL, 396 US_FL_FIX_INQUIRY ), 常用掌上电脑的同志们不会对Sony 的这些PEG 产品陌生吧. 彼岸花的传说(六) 七年前,在那个千禧年里,凭借获得金鸡奖最佳女主角的章子怡姐姐说:"我长得挺漂 亮,又是单身,男人不可能对我没兴趣!"是的,古人云,男人分两种,一种是好色,一种是十分好色.所以章子怡 这话一点没错.不过,对于大多数80 后来说,他们早已不再像十年前那么另类,那么出格,因为他们生活压力 很重,他们很老实,很现实,一个显而易见的事实,yy 章子怡不如老老实实的学Linux.虽然很多人对两者都 有 兴趣.但至少学会了后者,可以混口饭吃,谁叫我们都是知识混子呢. 此时,镜头一转,我们继续接着上一节往下看.fill_inquiry_response(),这个函数来自 drivers/usb/storage/usb.c 中, 240 /* 241 * fill_inquiry_response takes an unsigned char array (which must 242 * be at least 36 characters) and populates the vendor name, 243 * product name, and revision fields. Then the array is copied 244 * into the SCSI command's response buffer (oddly enough 245 * called request_buffer). data_len contains the length <strong>of</strong> the 246 * data array, which again must be at least 36. 247 */ 248 249 void fill_inquiry_response(struct us_data *us, unsigned char *data, 250 unsigned int data_len) 251 { 252 if (data_lenunusual_dev->vendorName, 267 strlen(us->unusual_dev->vendorName) > 8 ? 8 : 268 strlen(us->unusual_dev->vendorName));
269 memcpy(data+16, us->unusual_dev->productName, 270 strlen(us->unusual_dev->productName) > 16 ? 16 : 271 strlen(us->unusual_dev->productName)); 272 data[32] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>12) & 0x0F); 273 data[33] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>8) & 0x0F); 274 data[34] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>4) & 0x0F); 275 data[35] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice) & 0x0F); 276 } 277 278 usb_stor_set_xfer_buf(data, data_len, us->srb); 279 } 故事发生的太突然,会让人产生幻觉. 本来我们正儿八经用来处理scsi 命令的函数是后面将要讲的 proto_handler(),但想不到我们在这里开始接触scsi 命令了.理由正是因为像Sony 这几款PEG 产品做 的 不好,连最基本的scsi 命令INQUIRY 都不支持,完了又想在Linux 中使用,那没办法了,Sony 毕竟是大公 司,连欧洲冠军杯都是他们家和喜力给赞助的,开源社区没有必要得罪他们,所以就准备一个函数来fix 这个 问题吧,毫无疑问,这属于硬件上的一个bug. 那么什么是INQUIRY 命令?曾经也提过,INQUIRY 命令是最最基本的一个SCSI 命令,比如主机第一 次探测设备的时候就要用INQUIRY命令来了解这是一个什么设备,比如scsi 总线上有一个插槽插了一个设 备,那么scsi 主机就问它,你是scsi 磁盘呢,还是scsi 磁带,又或是scsi 的CD ROM 呢?作为设备,它内部 一 定有一段固件程序,即所谓的firmware.它就在接收到主机的INQUIRY 命令之后作出回答.具体应该怎么 回答?当然是依据scsi 协议里规定的格式了.不仅仅INQUIRY 命令,对于每一个命令都应该如此.只要对方 问:天王盖地虎.你作为设备就该回答,宝塔镇河妖.这其实就好比我们对对联,人家问天恢弘,地恢弘,天地恢 弘,就得对你妈的,他妈的,你他妈的.这都是不成文的规矩,而开发scsi 的人把这些写成了规范,它就变成了 成文的规矩了.具体来说, 设备在受到INQUIRY 命令查询时,她的相应遵从scsi 协议里面规定的标准格 式, 标准格式规定了,响应数据必须至少包含36 个字节,所以252 行,如果data_len 小于36,那就甭往下走了, 返回吧.您违规了. 如果你对scsi 协议很陌生,还是没有明白INQUIRY 命令究竟是做什么,那么推荐一个工具给你,你可以 试一试,以便有个直观的印象,其实INQUIRY 命令就是如其字面意思一样,查询,查询设备的一些基本信息, 从软件的角度来说,在主机扫描的时候,或者说枚举的时候,向每一个设备发送这个命令,并且获得回答,驱动 程序从此就会保存这些信息,因为这些信息之后可能都会用到或者说其中的一部分会被用到.这里推荐的工 具是sg_utils3,这是一个软件包,Linux 中可以使用的软件包,到处都有下,下了之后安装上,然后它包含一 个应用程序sg_inq,这其实就是给设备发送INQUIRY 命令用的,用法如下所示: 130 [root@localhost ~]# sg_inq -36 /dev/sda standard INQUIRY: PQual=0 Device_type=0 RMB=1 version=0x02 [SCSI-2] [AERC=0] [TrmTsk=0] NormACA=0 HiSUP=0 Resp_data_format=2
- 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 and 60:
storage 会有两个bulk 端点,用
- Page 61 and 62:
比如说,复旦大学,有一个主
- 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: 中 看到如下的定义: UNUSUAL_
- 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