BCB如何用DeviceIoControl枚举USB设备及向USB设备发指令?

sam200401 2010-02-20 10:22:49
BCB如何用DeviceIoControl枚举USB设备及向USB设备发指令?
我有一个USB设备,知其的GUID号,但发现如其与其他U盘GUID一样的,现需要用这个GUID号找到这个设备,并向设备发指令(我有指令)让设备返回结果。我在站内找到一些DeviceIoControl的贴,多为VC写的,在转为BCB时出现好多问题,不够全面。现希望大虾们可以抽空为小弟用BCB写个例发给我(5748945@QQ.COM),感激不尽!

命令与返回结果如下:
0xe0: Read capacity
pc指定返回长度8,opcode 后面16byte全0
Device返回数据:
0-3Byte:Number of total Sector(Big endian)
4-7Byte:Sector size.
...全文
1376 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhourenyun 2010-04-01
  • 打赏
  • 举报
回复
这个是WDK安装后的实例
我是装在C盘
这两个实例都是可以枚举USB设备的。
zhourenyun 2010-03-30
  • 打赏
  • 举报
回复
看你的驱动有没有支持DEVICEIOCONTROL的控制码。
====
例子1:
C:\WINDDK\7600.16385.0\src\usb\usbview
DDK下的一个USB view可以枚举USB的设备,你参考下 (里面有枚举USB设备)。
例子2:
C:\WINDDK\7600.16385.0\src\usb\usbsamp\exe
DDK下另外一个枚举USB设备的参考,可以学习下。
sam200401 2010-03-30
  • 打赏
  • 举报
回复
"C:\WINDDK\7600.16385.0\src\usb"在那里有下的?



[Quote=引用 4 楼 zhourenyun 的回复:]
看你的驱动有没有支持DEVICEIOCONTROL的控制码。
====
例子1:
C:\WINDDK\7600.16385.0\src\usb\usbview
DDK下的一个USB view可以枚举USB的设备,你参考下 (里面有枚举USB设备)。
例子2:
C:\WINDDK\7600.16385.0\src\usb\usbsamp\exe
DDK下另外一个枚举USB设备的参考,可……
[/Quote]
sam200401 2010-03-09
  • 打赏
  • 举报
回复
谢谢楼上的回复,
但我要的内容不是这个,
我要具体一点的程式范围。
xjq2003 2010-03-04
  • 打赏
  • 举报
回复
USB设备枚举全纪录



在编写这部分程序之前,首先需要了解有关USB协议,重点是USB数据通信结构、11条标准请求命令和标准USB描述符。

因为嵌入式设备的软硬件是密切相关的,所以还需做的准备工作是了解选用的USB芯片及主控MCU的性能。



一.硬件篇

USB芯片

作用:

1. 管理和实现USB物理层的差模信号

2. 以寄存器的形式提供各种端点(如控制端点,中断端点,大批量传输端点,同步传输端点)

3. 提供状态寄存器,配置寄存器,存储寄存器,中断寄存器,控制寄存器

4. 电源管理(提供3.3V的电源)

5. 实现某些协议层功能(如CRC校验/产生,PID校验/产生,同步模式的识别,并行串行转换等)

固件就是以这些硬件资源作为基础来实现USB设备功能的,其中,端点是需要重点学习的对象,需要熟练掌握与之相关的状态寄存器,配置寄存器,存储寄存器,中断寄存器

MCU主控芯片

作用:

1. 实现USB设备的功能

2. 处理USB芯片产生的中断,解析SETUP包,处理标准请求和厂商请求



二.软件篇

USB设备端固件程序,枚举部分是全部程序的基础和重心,只有主机对设备枚举成功后,主机才能和设备进行正常的通信

USB的枚举过程分为4个状态.

1.接入态

v主机检测到USB设备插上,击活端口,并发送复位命令(保持10ms)

2.默认态

v主机使用默认地址读取设备描述符 (GET_DESCRIPTOR)

v主机分配给设备一个总在线的唯一地址 (SET_ADDRESS)

3.地址态

v主机从新的地址获取设备描述符(GET_DESCRIPTOR)

v主机获取所有设备的配置描述符(GET_DESCRIPTOR)

4.配置态

v主机设置描述符(设备,配置) (SET_CONFIGURATION)

v主机读取配置状态(可选) (GET_CONFIGURATION)

v主机读取接口状态(可选) (GET_INTERFACE)



三.实践篇

在枚举阶段的固件编写中,我主要参考PHILIPS公司提供的D12型 USB芯片代码(有参考比自己从零开始要容易很多).由于该代码是基于51单片机编写的,与我所用的16位单片机在性能和结构上有较大差异,因此在固件移植过程中,所遇到的问题大多来源于此.



下面是我在移植过程中碰到的四个主要问题。



第一个问题,出现在默认态阶段,主机用默认地址读取设备描述符。当MCU收到USB芯片产生的中断时,无法正确读出USB芯片中断寄存器中的值。

这个问题发生在整个枚举过程的一开始,准确的说是第一步,所以我开始怀疑MCU与USB芯片的通信是否真正建立;而在此前,我对它们之间的通信能力一直深信不疑;因为我曾经用MCU发出测试专用指令来读取USB芯片的ID值,并且正确地读到了USB芯片的ID值,从理论上讲MCU与USB的通信已经建立.解决这个问题大约用了半天时间,后来我在MCU读中断寄存器命令后加了一段延时程序,问题得到解决,即中断产生后MCU正确读出了USB芯片中断寄存器的值

我分析原因是MCU发送命令的速度太快,当发送了读USB中断寄存器值命令后,就迅速发送取数据命令,而USB芯片的速度要慢的多,在MCU读数据时还未来得及把数据准备好。之前我读取USB芯片ID值的测试指令是循环发出的,刚开始虽然数据没准备好,但随着指令的循环发出,后面指令自然可以把前面指令准备的数据发出。



第二个问题出现在默认态阶段,主机用默认地址读取设备描述符。MCU收到USB芯片产生的中断,却无法进入到正确的中断服务程序。

在第一个问题解决后,立刻又出现了这一问题。通过串口监控,我很快发现,解析中断信息的程序中,有一段程序的功能是互换一个BYTE数据的高低字节位,这一功能主要是针对51单片机数据存放的结构与USB接口芯片的数据结构高低位颠倒而设置的。通过实验我发现:这款16位单片机也不具有51单片机的这一特点,所以只要去掉这段高低字节互换的程序,问题就解决了。



第三个问题,出现在地址态阶段,主机获取设备描述符。USB设备响应主机要求,发送16字节的设备描述符给主机,主机不能收到。

因为16字节的数据是通过MCU发送到USB芯片,再由USB芯片发送到

主机的。所以需要判断数据是在哪一个环节没有被正确传输的。我利用串口监测到: MCU收到主机的读中断(读取设备描述符命令)后,会送出了16字节的设备描述符到USB芯片;但是用BUS HOUND(一种基于主机端的USB总线监视软件)监视主机端发现:主机并没有收到这16字节的数据。因此我判断问题出在数据从MCU到USB芯片这一环节——即由MCU发出的设备描述符没有被USB芯片接收到。通过实验,我发现USB芯片没有接收到MCU发来的数据是因为USB芯片的速度较慢,对它来说,每一笔由MCU发出的数据在数据线上保持的时间太短,以致USB芯片无法将数据存放到其寄存器中。当改变MCU的相关设置,延长数据在数据线上保持的时间后,问题得以解决。



第四个问题,出现在配置态阶段,主机设置描述符。通过BUS HOUND监视,主机在SET_CONFIGURATION后停止枚举。

这个问题是我碰到的最难解决的困难,难就难在一直找不出主机停止枚举的原因,不知道问题产生在哪个环节。通过BUS HOUND可以清楚地看到:主机发出了正确的SET_CONFIGURATION命令,接下来USB设备只需回送一个空包(数据为0)通知主机已收到该命令;可是主机的枚举过程进行到这里却戛然而止。为什么?难道是设备没有发出应答空包,或者是主机没有收到应答空包,还是设备回送的空包有错误?我大约用了5天时间来找支持这些假设的理由。不过,除了证明假设不成立外,一无所获。

第六天,在一次检查BUS HOUND的数据时终于有了新发现。我发现:在SET_CONFIGURATION命令之前,主机发出了GET_DESCRIPTOR来获取全部的描述符合集共46字节数据,设备回复的描述符中在第20多字节时多了一个0字节;不过我并不清楚是否是这个问题对下一步产生了影响,在我看来只要主机在枚举过程中发出了下一步枚举命令,那就表明在此之前的枚举都是正确的(后来的事实证明情况并非如此),后一步的枚举不成功应该与前一步无关。但是因为我再也找不到任何可疑之处,所以只好去寻找那一个字节的0是从哪里来的?又经过了一天的摸索,终于找到了问题的症结。我的描述符数据是以结构体的形势存放的,当MCU收到主机发出的获取描述复命令时,就通过指针的指示将结构体中的数据发出。这些数据大多数是CHAR型,少数几个是INT型(症结),对16位单片机来说INT型数据存放是从偶地址开始的,因此,一旦在INT型的数据前有奇数个CHAR型数据,那就天下大乱了,INT型数据会空出一个奇数的地址位,从其后的偶数地址位开始存放数据。这样中间就多出1位的0字节数据。因此当主机那边收到时这笔数据时,从这一位起其后的数据就全部错位了。当我把INT型数据改用2个CHAR型表述时,一切就正常了; 同时,在此之后的SET_CONFIGURATION也能顺利进行下去,直到枚举结束。

看来枚举的 GET_DESCRIPTOR阶段如果主机得不到正确得描述符信息,并不会影响该阶段的枚举,而是对SET_CONFIGURATION阶段产生影响,使枚举无法继续。我想这应该是由主机端驱动程序来决定的。

非常幸运,利用BUS HOUND观察到的有限数据中,在最后的几字就出现了异常,否则,这个问题不知道要困扰我多久(BUS HOUND可以显示主机端接收到设备发来的数据,但数据的长度仅为32个字节)





写在最后

对设备端固件开发而言,如果有专用的USB总线分析仪是最好不过了,不但能监视到主机端收发的数据,而且可以监视到设备端收发的数据,这样,开发的效率会大大提高,开发时间可以大大降低。但如果开发条件像我一样有限,至少应该保证有串口和BUS HOUND这种USB总线监视工具(从网上可以下载),其中,串口可以在枚举的开始阶段使用,监控MCU的相关数据;BUS HOUND则可以在枚举的后期发挥更大的作用,因为此时传输的数据量较大,串口已不太适合作为监视工具了。

此外,在USB设备的枚举程序编写中,我遇到的最大挑战来自于8位单片机与16位单片机的结构上的差别,比如数据存取速度,数据高低字节的存放次序,数据类型与存放地址相关的特点等。从我前面列出的问题来看,大部分问题均源自于此;因此在学习某种单片机时,就要准确地掌握不同类型的MCU特性,这样就一定可以降低开发难度,缩短开发时间。

1,221

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧