翻译截下的USB Endpoint初始化过往数据

简介:

前阵子调试平台的mass-storage function, 想借机把USB Initialization过程了解清楚. 以前的理解都是基于代码的, PC机那边会怎么响应完全是黑盒, 不可见的. 而在初始化过程中不能加入break point, 否则请求超时后, 即使单步调试最后把请求的数据发回, 也被主机认为初始化失败. 因此只能在endpoint的XmitData和ReceiveData函数里添加调试信息把数据都打印出来, 然后根据USB协议还原成REQUEST和PACKET.

    在设备Attach后, 果如所料, client产生了一个EP0 out packet completed的中断, 从device controller的IST分流到EP0 IST中处理,  EP0 IST在确定是setup packet后, 从data register读了32bit进来, 并根据协议分解了该request:  
    Endpoint Zero Setup bmRequestType = 0x80, bRequest=0x6,  wValue=0x100,wIndex=0x0,wLength=0x40.
    其中0x80=设备到主机/标准请求类型/设备接受, 0x6=Get_Descriptor, 0x100=Device_Descriptor. 
    下面EP0就XmitData了, 每次写32bit, 分5次写完0x12byte. 注意由于EP0的MaxPacketSize=16byte, 所以第一次IST中写了16byte, 第二次再写2byte. 
    msb 0020  0112  lsb
          1000  0000 
          FFFF   0453 
          0201  0000
          03F4  0100   
    按照协议翻译出来就是bLength=0x12, bDescriptorType=0x1(device descriptor), bcdUSB=0x0200(protocol 2.0), bDeviceClass=0, bDeviceSubClass=0, bDeviceProtocol=0x0, bMaxPacketSize=0x10(16byte), idVendor=0x0453(Microsoft), idProduct=0xffff(OEM), bcdDevice=0, iManufacturer=1, iProduct=2, iSerialNumber=0, bNumConfigurations=1.  后面的就没有用了. 注意iManufacturer, iProduct, iSerialNumber, 这个决定了后面GetString请求里wValue掉低字节的值和所获得string的关系. 如果发送的device descriptor不足18byte的话, host会再次发送get device descriptor的request直至host收全了这18byte.

    第二步host就发过来Get Config Descriptor的请求了, 此时client需将该config下的所有interface和endpoint描述符全部发送给host. 但这其中又分了两步. 首先是纯粹地get config descriptor: 
    Endpoint Zero Setup bmRequestType = 0x80, bRequest=0x6, wValue=0x200,wIndex=0x0,wLength=0x9
    0x80=设备到主机/标准请求/设备接受, 0x6=GetDescriptor, 0x200=Config_Descriptor. 注意到Length=9正好为config descriptor的长度.
    这时client返回数据如下:
 0020  0209
 C000  0101
 C000  0100
    翻译出来bLength=9, bDescriptorType=2(config descriptor), wTotalLength=0x20(该配置返回的数据总长度,包括其下interface, endpoint descriptor的总长度), 后面的就先不看了,没有意义. host主要就是想索取这个wTotalLength以决定下一次需要获取多少长度.
    马上host再发了一个get config descriptor, 
    Endpoint Zero Setup bmRequestType = 0xx80, bRequest=0x6, wValue=0x200,wIndex=0x0,wLength=0xff
    它倒聪明, 对wTotalLength看都不看, 直接给了个0xff长度, 有多少要多少.
    client就老老实实填满0x20byte发过去了
 0020  0209 CONFIG: bLength=9, bDescriptorType=2(config), wTotalLength=0x20,
 C000  0101 bNumInterface=1, bConfigurationValue=1, iConfiguration=0, bmAttributes=0xC0(self-powered)
 0004  0900 bMaxPower=0   //  INTERFACE: bLength=9, bDescriptorType=4(interface), bInterfaceNumber=0
 0608  0200 bNumEndpoints=2(except ep0, bulk-only transport), bInterfaceClass=8(mass storage class), bInterfaceSubClass=6(SCSI)
 0507  0050 bInterfaceProtocol=0x50(bulk-only transport), iInterface=0. // ENDPOINT1: bLength=7, bDescriptorType=5(endpoint)
 0040  0281 bEndpointAddress=0x81(ep1, in), bmAttributes=2(bulk, non-sync, data), wMaxPacketSize=0x40(64byte), 
 0205  0700 bInterval=0(ignore for bulk ep). // ENDPOINT2: bLength=7, bDescriptorType=5, bEndpointAddress=2(ep2, out)
 0000  4002 bmAttributes=2(bulk, non-sync, data), wMaxPacketSize=0x40, bInterval=0
   最后还得SendControlStatusHandshake.

    接下来是Endpoint Zero Setup bmRequestType = 0xx80, bRequest=0x6, wValue=0x300,wIndex=0x0,wLength=0xff,  host想要get string descriptor(wValue高八位=0x3)了,这回wValue低八位=0, 对应SupportedLanguage. CLIENT返回了04090304, 翻译出来是bLength=4, bDescriptorType=3(string), wLANGID=0409(english-only).

    下面这个要发的就多了 Endpoint Zero Setup bmRequestType = 0xx80, bRequest=0x6, wValue=0x302,wIndex=0x409,wLength=0xff. 
    这里wValue低八位=2, 对应Product String. 只见CLIENT发了N多数据过去, 把这些数据按照ASCII编码翻译过来,就是体现在host端的device name了.

    理论上还应该有get manufacturer string descriptor和get serial number string descriptor的过程, 但在这次调试中没有看到. 最终mass storage client由于没有store objet而在OpenStore函数的CreateFile处失败了.


本文转自Walzer博客园博客,原文链接:http://www.cnblogs.com/walzer/archive/2006/02/05/325558.html,如需转载请自行联系原作者

相关文章
WRF模式案例运行初体验--飓风示例全过程记录
本文主要记录一下首次学习WRF并运行官网案例的全过程。
WRF模式案例运行初体验--飓风示例全过程记录
|
内存技术
USB摄像头描述符参数获取和来源分析(下)
USB摄像头描述符参数获取和来源分析(下)
84 0
|
6月前
|
编解码 安全 测试技术
APP测试类型
APP测试类型
|
Linux C++
基于ARM-contexA9-Linux驱动开发:如何获取板子上独有的ID号
基于ARM-contexA9-Linux驱动开发:如何获取板子上独有的ID号
127 0
|
编解码
USB摄像头描述符参数获取和来源分析(上)
USB摄像头描述符参数获取和来源分析
151 0
|
API Perl
IP - 射频数据转换器 -05- API使用指南 - ADC状态指示函数
IP - 射频数据转换器 -05- API使用指南 - ADC状态指示函数
287 0
IP - 射频数据转换器 -05- API使用指南 - ADC状态指示函数
硬件开发笔记(十): 硬件开发基本流程,制作一个USB转RS232的模块(九):创建CH340G/MAX232封装库sop-16并关联原理图元器件
有了原理图,可以设计硬件PCB,在设计PCB之间还有一个协同优先动作,就是映射封装,原理图库的元器件我们是自己设计的。为了更好的表述封装设计过程,本文描述了CH340G和MAX232芯片封装创建(SOP-16),并将原理图的元器件关联引脚封装。
硬件开发笔记(十): 硬件开发基本流程,制作一个USB转RS232的模块(九):创建CH340G/MAX232封装库sop-16并关联原理图元器件
硬件开发笔记(九): 硬件开发基本流程,制作一个USB转RS232的模块(八):创建asm1117-3.3V封装库并关联原理图元器件
有了原理图,可以设计硬件PCB,在设计PCB之间还有一个协同优先动作,就是映射封装,原理图库的元器件我们是自己设计的。为了更好的表述封装设计过程,本文描述了一个创建asm1117-3.3V封装,将原理图的元器件关联引脚封装。
硬件开发笔记(九): 硬件开发基本流程,制作一个USB转RS232的模块(八):创建asm1117-3.3V封装库并关联原理图元器件
|
Python API 数据格式
带你读《Python网络编程(原书第2版)》之三:API和意图驱动网络
本书是一本实用型的基础技术实践工具书,技术性较强,如果你想快速了解计算机网络管理、网络安全、自动化运维、Python Web搭建、网络测试相关的知识,本书很适合你。本书涵盖的知识点主要是网络运维相关技术,在学习完所有的章节之后,读者能对网络的管理有初步的了解。每个章节的后面部分都是有一定难度的扩展资源,循序渐进,帮助读者提升网络运维能力。
|
物联网 API
手把手学IOT服务端API编程[10、保存设备属性]|MVP讲堂
本教程旨在介绍服务器端的API编程接口,基于php脚本的sdk,希望对物联网服务器端有编程需求的有所帮助。阿里云MVP手把手教你!有演示视频,千万别错过!
1464 0