第二十四篇:SuperSpeed/HighSpeed USB的ISO传输
来源:互联网 发布:手机淘宝客怎么看 编辑:程序博客网 时间:2024/05/18 23:57
WDK 7600.16385.1中关于USB ISO传输的驱动例子, 是针对于USB2.0与USB1.1的, 即HS与FS.
这个例子没有非常特别之处, 但对于USB2.0的ISO传输的数据分割算法, 还是挺有意思的.
根据MSDN参考文章:
http://msdn.microsoft.com/en-us/library/windows/hardware/hh406225.aspx
<<How to transfer data to USB isochronous endpoints>>
第二, 如下表, 对于不同的polling period, 传输包的个数也有限制:
第三, 对于一个URB, iso packet的限制
- wBytesPerInterval indicates the total number of bytes that the host can send or receive in a bus interval. Even though the maximum number of bytes per bus interval can be calculated as (bMaxBurst+1) * (Mult+1) *wMaxPacketSize, the USB 3.0 specification recommends using the wBytesPerInterval value instead.
- ThewBytesPerInterval value must be less than or equal to that calculated value.
2. 未圆整前包的个数
numberOfPackets = (TotalLength + packetSize - 1) / packetSize;
3. 将包的个数, 向上圆整到符合Number of Packets for high speed/SuperSpeed的要求, 这里以interval 1, 8 packets/bus interval为例
if(0 == (numberOfPackets % 8)) {
actualPackets = numberOfPackets;
}
else {
//
// we need multiple of 8 packets only.
//
actualPackets = numberOfPackets +
(8 - (numberOfPackets % 8));
}
4. 得到实际平均每个包中的数据量
minDataInEachPacket = TotalLength / actualPackets;
5. 如果实际平均每个包的数据量 == packetSize, 说明实际包的个数, 并没有因为第3步, 而有所增加
if(minDataInEachPacket == packetSize) {
numberOfPacketsFilledToBrim = actualPackets;
dataLeftToBeDistributed = 0;
}
else {
6. 由于第三步, 实际包的个数比第二步算出来的个数, 有所增加, 所以, minDataInEachPacket小于packetSize.
dataLeftToBeDistributed = TotalLength -
(minDataInEachPacket * actualPackets);
numberOfPacketsFilledToBrim = dataLeftToBeDistributed /
(packetSize - minDataInEachPacket);
dataLeftToBeDistributed -= (numberOfPacketsFilledToBrim *
(packetSize - minDataInEachPacket));
}
1. 包的个数nPackets中, 满包的有numberOfPacketsFilledToBrim个, 而且, 有一个包, 是minDataInEachPacket+dataLeftToBeDistributed, 剩余包的数据量为minDataInEachPacket
stageSize = packetSize * numberOfPacketsFilledToBrim;
stageSize += (minDataInEachPacket *
(nPackets - numberOfPacketsFilledToBrim));
stageSize += dataLeftToBeDistributed;
}
else {
2. 所有包均为满包:
stageSize = packetSize * nPackets;
}
TotalLength = 8193
packetSize = 8
Step 1
Step 2
numberOfPackets = (8193 + 8 - 1) / 8 = 1025
Step 3
actualPackets = 1025 + 7 = 1032
Step 4
minDataInEachPacket = 8193 / 1032 = 7 bytes
Step 5
dataLeftToBeDistributed = 8193 - (7 * 1032) = 969.
Step 6
numberOfPacketsFilledToBrim = 969 / (8 - 7) = 969.
Step 7
dataLeftToBeDistributed = 969 - (969 * 1) = 0.
最后, 说一下这个算法的问题:
实际运行过程中, 会导致 babble error, 所以, 最后, 笔者将USBSamp的算法改成另外一种.
比如, 如果一个ISO IN EP的MAX PACKET SIZE = 768, 且其extra transaction 是2, 刚其MaximumPacketSize为768*3 = 2304.
为了符合interval =1, 包的个数为8的倍数的要求, 刚以18432为读写请求:
结果如下:
1. request 18432, actual read 18432
8 packets, each 2304 bytes, 每个ISO PAKCET的OFFSET也均为2304的整数倍
2. request 18431, actual read 17664
最后一个transaction的767 bytes没有收到, 最后一个PACKET收到1536 bytes
7 packets 2304, one packet 2303,每个ISO PAKCET的OFFSET也均为2304的整数倍
最后一个iso packet USBD_STATUS = USBD_STATUS_BABBLE_DETECTED 0xC0000012
这里的BABBLE ERROR, 应该就是buffer只有767 bytes, 但DEVICE回了768 bytes所导致的.
IsoPacket[0].offset = 0 IsoPacket[0].Length = 2304 IsoPacket[0].Status = 0
UsbSamp:
IsoPacket[1].offset = 2304 IsoPacket[1].Length = 2304 IsoPacket[1].Status = 0
UsbSamp:
IsoPacket[2].offset = 4608 IsoPacket[2].Length = 2304 IsoPacket[2].Status = 0
UsbSamp:
IsoPacket[3].offset = 6912 IsoPacket[3].Length = 2304 IsoPacket[3].Status = 0
UsbSamp:
IsoPacket[4].offset = 9216 IsoPacket[4].Length = 2304 IsoPacket[4].Status = 0
UsbSamp:
IsoPacket[5].offset = 11520 IsoPacket[5].Length = 2304 IsoPacket[5].Status = 0
UsbSamp:
IsoPacket[6].offset = 13824 IsoPacket[6].Length = 2304 IsoPacket[6].Status = 0
UsbSamp:
IsoPacket[7].offset = 16128 IsoPacket[7].Length = 1536 IsoPacket[7].Status = c0000012
3. request 18433, actual read 0
16个PACKETS
一个1153 BYTES, 15个1152 BYTES
OFFSET为:
urb header status C0000B00
UsbSamp:
subReqContext
UsbSamp:
IsoPacket[0].offset = 0 IsoPacket[0].Length = 768 IsoPacket[0].Status = c0000011
UsbSamp:
IsoPacket[1].offset = 1153 IsoPacket[1].Length = 768 IsoPacket[1].Status = c0000011
UsbSamp:
IsoPacket[2].offset = 2305 IsoPacket[2].Length = 768 IsoPacket[2].Status = c0000011
UsbSamp:
IsoPacket[3].offset = 3457 IsoPacket[3].Length = 768 IsoPacket[3].Status = c0000011
UsbSamp:
IsoPacket[4].offset = 4609 IsoPacket[4].Length = 768 IsoPacket[4].Status = c0000011
UsbSamp:
IsoPacket[5].offset = 5761 IsoPacket[5].Length = 768 IsoPacket[5].Status = c0000011
UsbSamp:
IsoPacket[6].offset = 6913 IsoPacket[6].Length = 768 IsoPacket[6].Status = c0000011
UsbSamp:
IsoPacket[7].offset = 8065 IsoPacket[7].Length = 768 IsoPacket[7].Status = c0000011
UsbSamp:
IsoPacket[8].offset = 9217 IsoPacket[8].Length = 768 IsoPacket[8].Status = c0000011
UsbSamp:
IsoPacket[9].offset = 10369 IsoPacket[9].Length = 768 IsoPacket[9].Status = c0000011
UsbSamp:
IsoPacket[10].offset = 11521 IsoPacket[10].Length = 768 IsoPacket[10].Status = c0000011
UsbSamp:
IsoPacket[11].offset = 12673 IsoPacket[11].Length = 768 IsoPacket[11].Status = c0000011
UsbSamp:
IsoPacket[12].offset = 13825 IsoPacket[12].Length = 768 IsoPacket[12].Status = c0000011
UsbSamp:
IsoPacket[13].offset = 14977 IsoPacket[13].Length = 768 IsoPacket[13].Status = c0000011
UsbSamp:
IsoPacket[14].offset = 16129 IsoPacket[14].Length = 768 IsoPacket[14].Status = c0000011
UsbSamp:
IsoPacket[15].offset = 17281 IsoPacket[15].Length = 768 IsoPacket[15].Status = c0000011
其中c0000011为USBD_STATUS_XACT_ERRO, C0000B00为USBD_STATUS_ISOCH_REQUEST_FAILED
如果, 再改变一下APP的请求长度, 比如7*2304 = 16128
结果如下:
1. request 16128, read 0 bytes
8 packets, each 2016 bytes
urb header status C0000B00
IsoPacket[0].offset = 0 IsoPacket[0].Length = 1536 IsoPacket[0].Status = c0000012
UsbSamp:
IsoPacket[1].offset = 2016 IsoPacket[1].Length = 1536 IsoPacket[1].Status = c0000012
UsbSamp:
IsoPacket[2].offset = 4032 IsoPacket[2].Length = 1536 IsoPacket[2].Status = c0000012
UsbSamp:
IsoPacket[3].offset = 6048 IsoPacket[3].Length = 1536 IsoPacket[3].Status = c0000012
UsbSamp:
IsoPacket[4].offset = 8064 IsoPacket[4].Length = 1536 IsoPacket[4].Status = c0000012
UsbSamp:
IsoPacket[5].offset = 10080 IsoPacket[5].Length = 1536 IsoPacket[5].Status = c0000012
UsbSamp:
IsoPacket[6].offset = 12096 IsoPacket[6].Length = 1536 IsoPacket[6].Status = c0000012
UsbSamp:
IsoPacket[7].offset = 14112 IsoPacket[7].Length = 1536 IsoPacket[7].Status = c0000012
2. request 16129, read 0 bytes
1 packet 2017, 7 packet 2016
urb header status C0000B00
UsbSamp:
subReqContext
UsbSamp:
IsoPacket[0].offset = 0 IsoPacket[0].Length = 1536 IsoPacket[0].Status = c0000012
UsbSamp:
IsoPacket[1].offset = 2017 IsoPacket[1].Length = 1536 IsoPacket[1].Status = c0000012
UsbSamp:
IsoPacket[2].offset = 4033 IsoPacket[2].Length = 1536 IsoPacket[2].Status = c0000012
UsbSamp:
IsoPacket[3].offset = 6049 IsoPacket[3].Length = 1536 IsoPacket[3].Status = c0000012
UsbSamp:
IsoPacket[4].offset = 8065 IsoPacket[4].Length = 1536 IsoPacket[4].Status = c0000012
UsbSamp:
IsoPacket[5].offset = 10081 IsoPacket[5].Length = 1536 IsoPacket[5].Status = c0000012
UsbSamp:
IsoPacket[6].offset = 12097 IsoPacket[6].Length = 1536 IsoPacket[6].Status = c0000012
UsbSamp:
IsoPacket[7].offset = 14113 IsoPacket[7].Length = 1536 IsoPacket[7].Status = c0000012
3.
request 16127, read 0 bytes
1 packet 2022, 7 packet 2015
urb header status C0000B00
UsbSamp:
subReqContext
UsbSamp:
IsoPacket[0].offset = 0 IsoPacket[0].Length = 1536 IsoPacket[0].Status = c0000012
UsbSamp:
IsoPacket[1].offset = 2022 IsoPacket[1].Length = 1536 IsoPacket[1].Status = c0000012
UsbSamp:
IsoPacket[2].offset = 4037 IsoPacket[2].Length = 1536 IsoPacket[2].Status = c0000012
UsbSamp:
IsoPacket[3].offset = 6052 IsoPacket[3].Length = 1536 IsoPacket[3].Status = c0000012
UsbSamp:
IsoPacket[4].offset = 8067 IsoPacket[4].Length = 1536 IsoPacket[4].Status = c0000012
UsbSamp:
IsoPacket[5].offset = 10082 IsoPacket[5].Length = 1536 IsoPacket[5].Status = c0000012
UsbSamp:
IsoPacket[6].offset = 12097 IsoPacket[6].Length = 1536 IsoPacket[6].Status = c0000012
UsbSamp:
IsoPacket[7].offset = 14112 IsoPacket[7].Length = 1536 IsoPacket[7].Status = c0000012
综上实验所示, 只要一个iso packet的buffer size小于ep 的MaximumPacketSize, 则ISO就会产生BABBLE ERROR.
但该结论只适用于ISO IN, 对于ISO OUT, 该规则不适用.
似乎, 从3 TRANSACTIONS的EP来讲, 如果数据达到了2个 TRANSACTIONS, 则为BABBLE, 如果只达到了一个,甚至更少, 则为XACT. 当然, 这只是笔者根据这几个情况得出的结论, 正确性有待考证.
最后, 笔者将该算法去除, 在符合polling period = 1, 2, 4, 8对packets(1, 2, 4, 8)的要求的情况下, 能够接受任意长度的ISO IN传输.
具体实现为:
所有的OFFSET设置为MaximumPacketSize的整数倍, 在SYS空间中申请一块NON PAGED POOL, 这块BUFFER的长度, 向上圆整到MaximumPacketSize的整数倍(如8*n, 4*n, 2*n, 1*n倍), ISO IN 的数据先存放在SYS空间的这块BUFFER中, 安排一个WORK ITEM, 在WORK ITEM中, 最后将数据COPY到用户空间的BUFFER中, COPY长度为用户请求的长度, 这样解决了BABBLE ERROR的问题(事实上, 也同时解决了XACT ERROR的问题).
- 第二十四篇:SuperSpeed/HighSpeed USB的ISO传输
- usb的bulk传输
- OpenBSD挂载cdrom, iso, usb的方法
- usb音频传输的优劣
- Create bootable USB drives 制作iso转usb的启动盘
- 第二十四篇:JAVA代理
- usb传输
- 第二十四题 求取树的深度
- 第二十四讲 if语句的嵌套
- usb的传输和四种传输方式
- USB的四种传输类型
- SD 卡与 USB的传输
- STM32的 USB传输(双缓冲)
- STM32的 USB传输(双缓冲)
- USB传输方式的一些总结
- usb的包结构和传输类型
- USB设备的4种传输方式
- USB的四种传输模式
- hdu 3068 最长回文(manacher算法)
- CC++初学者编程教程(12) 基于rhel6.3的Oracle数据库学习环境搭建
- 将对象保存为文件
- getchar()的一些知识
- 工作记录--linux文件系统/环境变量
- 第二十四篇:SuperSpeed/HighSpeed USB的ISO传输
- 泛型Generics
- C语言static语句的详细说明
- XCode 无法识别 iOS 设备的解决办法
- (一)autoCode代码生成器介绍
- 2014全新增强版迅捷PDF转换器介绍
- TCP协议与UDP协议的区别
- jsoncpp简单示例
- 关于相对布局RelativeLayout的各种属性介绍