INQUIRY命令是最基本的一个SCSI命令。比如主机第一次探测设备时就要用INQUIRY命令来了解这是一个什么设备,如果SCSI总线上有一个插槽插了一个设备,那么SCSI主机就问它,你是SCSI磁盘,还是SCSI磁带,又或是SCSI的CD ROM呢?作为设备,它内部一定有一段固件程序,即所谓的firmware。它就在接收到主机的INQUIRY命令之后做出回答。
依据SCSI协议中规定的格式了。不仅仅INQUIRY命令,具体来说, 设备在受到INQUIRY命令查询时,它的相应遵从SCSI协议中规定的标准格式,标准格式规定了,响应数据必须至少包含36个字节。所以252行,如果data_len小于36,就不往下走了,返回吧。
INQUIRY命令就是查询,查询设备的一些基本信息。从软件的角度来说,在主机扫描时,或者说枚举时,向每一个设备发送这个命令,并且获得回答,驱动程序从此就会保存这些信息,因为这些信息之后可能都会用到或者说其中的一部分会被用到。sudo apt-get install sg3-utils 推荐的工具是sg_utils3,这是一个软件包,Linux中可以使用的软件包,到处都有,下了之后安装上,包含一个应用程序sg_inq,这其实就是给设备发送INQUIRY命令用的。
sg_inq /dev/sda
standard INQUIRY:
  PQual=0  Device_type=0  RMB=0  version=0x05  [SPC-3]
  [AERC=0]  [TrmTsk=0]  NormACA=0  HiSUP=0  Resp_data_format=2
  SCCS=0  ACC=0  TPGS=0  3PC=0  Protect=0  [BQue=0]
  EncServ=0  MultiP=0  [MChngr=0]  [ACKREQQ=0]  Addr16=0
  [RelAdr=0]  WBus16=0  Sync=0  Linked=0  [TranDis=0]  CmdQue=0
  [SPI: Clocking=0x0  QAS=0  IUS=0]
    length=96 (0x60)   Peripheral device type: disk
 Vendor identification: ATA     
 Product identification: ST1000LM048-2E71
 Product revision level: SDM1
 Unit serial number:             WDECXGDB
使用sg_inq命令可以查询到关于这块U盘的基本信息。实际上sg_inq可以查询所有SCSI设备的信息,因为INQUIRY本来就是一个标准的SCSI命令。当然以上这些信息中,我们之后用得到的大概也就是Vendor ID,Product ID,Product revision,以及length,device type--disk。
void fill_inquiry_response(struct us_data *us, unsigned char *data,unsigned int data_len)
{
    if (data_len < 36) /* You lose. */ 响应数据必须至少包含36个字节
        return;
    memset(data+8, ' ', 28);
    if (data[0]&0x20) { /* USB device currently not connected. Return
                  peripheral qualifier 001b ("...however, the
                  physical device is not currently connected
                  to this logical unit") and leave vendor and
                  product identification empty. ("If the target
                  does store some of the INQUIRY data on the
                  device, it may return zeros or ASCII spaces
                  (20h) in those fields until the data is
                  available from the device."). */
    } else {
        u16 bcdDevice = le16_to_cpu(us->pusb_dev->descriptor.bcdDevice);
        int n;
        n = strlen(us->unusual_dev->vendorName);
        memcpy(data+8, us->unusual_dev->vendorName, min(8, n));
        n = strlen(us->unusual_dev->productName);
        memcpy(data+16, us->unusual_dev->productName, min(16, n));
//如果不是20h,比如传递进来的data[0]就是0,data[8]开始的8个字节可以保存厂商相关的信息,us->unusual_dev->vendorName,就是把其中的vendorName复制到data数组中来,但是如果vendorName超过8个字符了那可不行,只取前8个就行了。productName也是一样的方法,复制到data数组中来,协议中规定了,从16开始存放productName,不能超过16个字符,那么“Flash Disk”也没有问题。
        data[32] = 0x30 + ((bcdDevice>>12) & 0x0F);
        data[33] = 0x30 + ((bcdDevice>>8) & 0x0F);
        data[34] = 0x30 + ((bcdDevice>>4) & 0x0F);
        data[35] = 0x30 + ((bcdDevice) & 0x0F);
    }
//us->pusb_dev->descriptor.bcdDevice,struct us_data中有一个成员struct usb_device *pusb_dev,而struct usb_device中有一个成员struct usb_device_descriptordescriptor,而structusb_device_descriptor中的成员__u16 bcdDevice,表示制造商指定的产品的版本号,规定是用版本号,制造商id和产品id来标志一个设备。bcdDevice一共16位,是以bcd码的方式保存的信息,也就是说,每4位代表一个十进制的数,比如00110110 1001 0111就代表的3697。而在SCSI标准的INQUIRY data中,data[32]到data[35]被定义为保存这四个数,并且要求以ASCII码的方式保存。ASCII码中48对应咱们日常的0,49对应1,50对应2,也就是说得在现有数字的基础上加上48,或者说加上0x30。这就是290行到293行所表达的意思。
    usb_stor_set_xfer_buf(data, data_len, us->srb);
//一切准备好了之后,我们就可以把data数组,这个包含36个字符的信息发送到SCSI命令指定的位置了,即srb指定的位置。usb_stor_set_xfer_buf要干的工作。
}
判断data[0]是否是20h,SCSI协议中规定了,标准的INQUIRY data的data[0],总共有8个bit。其中bit7~bi5被称为peripheral qualifier(三位),而bit4~bit0被称为perpheral device type(五位),它们代表了不同的含义,但是20h就表示peripheral qualifier这个外围设备限定符为001b,而peripheral device type这个外围设备类型则为00h。查阅SCSI协议可知,后者代表的是设备类型为磁盘,或者说直接访问设备,前者代表的是目标设备的当前LUN支持这种类型。然而,实际的物理设备并没有连接在当前LUN上。在data[36]中,从data[8]一直到data[35]这28个字节保存的都是厂商和产品的信息。SCSI协议中写了,如果设备中保存这些信息,那么它可以暂时先返回0x20h,因为现在是系统poweron时期或者是reset期间,要尽量减少延时,于是fill_inquiry_response()就会把data[8]到data[35]都给设置成0。等到保存在设备上的这些信息可以读了再去读。
static int usb_stor_control_thread(void * __us)
{
fill_inquiry_response(us, data_ptr, 36);
//先解释一下之前定义data_ptr[36]时初始化的前8个元素。它们的含义都和scsi协议规定的对应。data_ptr[0]不用说了,data_ptr[1]被赋为0x80,这表明这个设备是可移除的,data_ptr[2]被赋为0x02这说明设备遵循SCSI-2协议,data_ptr[3]被赋为0x02,说明数据格式遵循国际标准化组织所规定的格式,而data_ptr[4]被称为additional length,附加参数的长度,即除了用这么一个标准格式的数据响应之外,可能还会返回更多的一些信息。这里设置的是0x1F。
}

《Linux那些事儿之我是USB》我是U盘(29)彼岸花的传说(六)--总结相关推荐

  1. 【转】Linux那些事儿之我是U盘(33)彼岸花的传说(一)

    彼岸花,花语是悲伤的回忆. 很久很久以前,城市的边缘开满了大片大片的曼珠沙华,它的花香有一种魔力,可以让人想起自己前世的事情.守护曼珠沙华的是两个妖精,一个是花妖叫曼珠,一个是叶妖叫沙华.他们守侯了几 ...

  2. Linux那些事儿之我是U盘(33)彼岸花的传说(一)

    彼岸花,花语是悲伤的回忆. 很久很久以前,城市的边缘开满了大片大片的曼珠沙华,它的花香有一种魔力,可以让人想起自己前世的事情.守护曼珠沙华的是两个妖精,一个是花妖叫曼珠,一个是叶妖叫沙华.他们守侯了几 ...

  3. 《Linux那些事儿之我是USB》我是U盘(22)彼岸花的传说(一)

    彼岸花,花语是悲伤的回忆. 很久很久以前,城市的边缘开满了大片大片的曼珠沙华,它的花香有一种魔力,可以让人想起自己前世的事情.守护曼珠沙华的是两个妖精,一个是花妖叫曼珠,一个是叶妖叫沙华.他们守候了几 ...

  4. Linux那些事儿 之 戏说USB(19)设备

    转载地址:http://blog.csdn.net/fudan_abc/article/details/1807800 第一眼看到struct usb_device这个结构,我仿佛置身于衡山路的酒吧里 ...

  5. 【转】Linux那些事儿 之 戏说USB(19)设备

    第一眼看到struct usb_device这个结构,我仿佛置身于衡山路的酒吧里,盯着舞池里扭动的符号,眼神迷离. 交大里苟了几年,毕业了又是住在学校附近的徐虹北路上,沿着虹桥路走过去,到徐家汇不过1 ...

  6. Linux那些事儿 之 戏说USB(5)我是谁

    我是谁?USB一遍一遍问着自己,当然它不会真的是一颗树.USB只是Linux庞大家族里的一个小部落,host controller是它们的族长,族里的每个USB设备都需要被系统识别,被我们识别.虽然清 ...

  7. Linux那些事儿 之 戏说USB(3)我是一棵树

    从拓扑上来看,USB子系统并不以总线的方式来部署,它是一颗由几个点对点的连接构成的树. 它主要包括了USB连接.USB host controller和USB device三个部分.而USB devi ...

  8. Linux那些事儿 之 戏说USB(33)字符串描述符

    关于字符串描述符,前面的前面已经简单描述过了,地位仅次于设备/配置/接口/端点四大描述符,那四大设备必须得支持,而字符串描述符对设备来说则是可选的. 这并不是就说字符串描述符不重要,对咱们来说,字符串 ...

  9. Linux那些事儿 之 戏说USB(25)设备的生命线(八)

    回到struct usb_hcd,继续努力的往下看. 7行,又见kref,usb主机控制器的引用计数.struct usb_hcd也有自己专用的引用计数函数,看drivers/usb/core/hcd ...

最新文章

  1. 2019秋季PAT甲级_C++题解
  2. 6kyu Persistent Bugger
  3. SAP HANA Hint简介
  4. phpcms文件结构
  5. sql 中实现打乱数据的排序
  6. 通过Java Hipster升级Spring Security OAuth和JUnit测试
  7. 你从未见过的 HTML5 动画效果
  8. linux操作系统之条件变量
  9. layui radio 赋初始值
  10. 设置 cmd 窗口默认为快速编辑(quickedit)
  11. SpringCloud_03_Feign入门示例
  12. walking机器人仿真教程-激光导航-TEB算法导航
  13. java http 401_401 API请求状态错误
  14. 一米霜降肥牛,煎饼果子,all you can eat 牛油串串
  15. Exp9 Web安全基础 20164302 王一帆
  16. american主板网卡灯关机后还亮_七彩虹主板设置概述.pdf
  17. failed to connect to ‘192.168.*.*:5555‘: Connection refused
  18. 数据库系统概论(第四版)习题解答
  19. office出现应用程序错误无法正常启动(0xc0000142)
  20. python制作录屏软件_【Python成长之路】用python制作一款录屏小工具(1)

热门文章

  1. 利用python进行Landsat8数据的辐射定标
  2. python统计字母a的个数_32个经典Python小例子测测你的基础知识(11-20)
  3. Javascript开发者必备的工具软件
  4. 第七章---内置模块
  5. 池水含盐问题C++仿真
  6. 开源视频、音频截取软件
  7. 元宇宙四象限是什么?线上应用、线下应用、虚拟世界、镜像世界?
  8. php禁止视频自动播放,分享新浪视频禁止自动播放的方法
  9. TensorFlow实战:TensorFlow中的CNN
  10. 机器学习算法笔记-聚类