第二十四篇:SuperSpeed/HighSpeed USB的ISO传输
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>>
Interval | Polling period (2Interval-1) |
---|---|
1 | 1; Data is transferred every bus interval. |
2 | 2; Data is transferred every second bus interval. |
3 | 4; Data is transferred every fourth bus interval. |
4 | 8; Data is transferred every eighth bus interval. |
对于FULL SPEED, polling period一直为一个FRAME一次.
第二, 如下表, 对于不同的polling period, 传输包的个数也有限制:
Polling period | Number of Packets for high speed/SuperSpeed |
---|---|
1 | Multiple of 8 |
2 | Multiple of 4 |
3 | Multiple of 2 |
4 | Any |
第三, 对于一个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.
Important
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, 该规则不适用.
![](/assets/blank.gif)
![](/assets/blank.gif)
似乎, 从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传输相关推荐
- 第二十四篇:可靠信号机制
前言 曾经的 UNIX 系统中,信号的不可靠的.什么是不可靠?就是信号丢失呗.那什么是信号丢失?就是当系统正在处理某个事务的时候,如果收到了某个信号,但它不能及时处理这个信号,那么只能忽略掉此信号. ...
- Python之路【第二十四篇】Python算法排序一
什么是算法 1.什么是算法 算法(algorithm):就是定义良好的计算过程,他取一个或一组的值为输入,并产生出一个或一组值作为输出.简单来说算法就是一系列的计算步骤,用来将输入数据转化成输出结果. ...
- SpringBoot第二十四篇: springboot整合docker
这篇文篇介绍,怎么为 springboot程序构建一个docker镜像.docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源.Docker 可以让开发者打包他们的 ...
- setitimer 创建两个定时器_JavaScript第二十四篇 高级定时器(下)
数组分块 所谓数组分块,就是当你发现某个循环占用了大量时间,同时对于上述两个问题,你的回答都是"否",那么你就可以使用定时器分割这个循环. 思路是结合定时器进行递归调用定时器 基本 ...
- JavaScript第二十四篇 高级定时器(下)
数组分块 所谓数组分块,就是当你发现某个循环占用了大量时间,同时对于上述两个问题,你的回答都是"否",那么你就可以使用定时器分割这个循环. 思路是结合定时器进行递归调用定时器 基本 ...
- flask第二十四篇——模板【6】自定义过滤器
请关注孟船长的公众号:自动化测试实战 大家想了解其他过滤器可以参考这里: http://jinja.pocoo.org/docs/dev/templates/#builtin-filters ---- ...
- “约见”面试官系列之常见面试题第二十四篇之vue-router使用(建议收藏)
开发的时候有时候会遇到一种情况,比如 :点击这个链接跳转到其他组件的情况,通常会跳转到新的页面,蛋是,我们不想跳转到新页面,只在当前页面切换着显示,那么就要涉及到路由的嵌套了,也可以说是子路由的使用. ...
- 【Java成王之路】EE初阶第二十四篇: Servlet
Sevlet Servlet 是什么 Servlet 是一种实现动态页面的技术. 是一组 Tomcat 提供给程序猿的 API, 帮助程序猿简单高效的开发一 个 web app. Tomcat 是一个 ...
- 第二十四篇 -- 学习第二十九天打卡20190720
学习书籍<剑桥商务英语中级词汇精选>乱序版 Day05 Day25spectrum ['spektrəm] n.范围:领域:光谱:声谱例:This large group of resea ...
- 第二十六篇:USB3.0高带宽ISO(48KBytes/125us)实战
USB3.1技术已经推出, 10Gbps的速率足以满足数据, HD视频传输的要求. 要步入USB3.1的研发, 还得将USB3.0的基础打扎实. 微软提供的SUPER MUTT只包含一个接口0, 其下 ...
最新文章
- Linux的企业-Mfs高可用corosync+pacemaker+fence+iscci
- tomcat 相关以及安装时遇到的一些问题整理
- linux免密登录_Linux SSH免密钥登录总结
- 添加到界面前获取尺寸
- 走进javascript——DOM事件
- 计算机系统结构试卷及答案
- android 开源 视频播放器,安卓视频播放器——ijkPlayer(Bilibili开源)-Go语言中文社区...
- 使用百度的地图生成器部署到https域名
- linux addr2line使用手册,addr2line 命令使用方法
- openStack开源云repo db local or on-line 实战部署之Ruiy王者归来
- 快门光圈感光度口诀_摄影:一张图让你明白什么叫光圈、快门、感光度、景深、ISO。...
- golang--channal与select
- 大三下,我们该做什么?一篇被转万次的日志,你值得一看
- 计算机基础2,计算机基础总结2
- 微服务--应对每秒上万并发下的参数优化实战(实战经验)
- HCIE课程笔记18-局域网二层技术
- 垃圾收集 (Garbage Collection,GC)
- npm介绍与cnpm介绍
- AOP技术介绍--(.Net中关于AOP的实现)
- buuctf MISC菜刀666
热门文章
- MySQL InnoDB 存储引擎写入磁盘(落盘)的原理\MySQL怎么保证持久性、原子性?(MySQL中是如何实现事务提交和回滚的)\隔离性
- C#自学29—简体字繁体字转换
- 租用GPU服务器跑深度学习模型心得
- Proxy的常见使用——正向代理的使用及配置总结
- 基于GNN网络的session推荐模型(知识图谱技术在推荐场景的应用)
- 卧槽!被蜜雪冰城洗脑了!
- 三、青龙面板 添加企业微信应用推送消息
- 今天是没有python的一天(大物实验‘利用牛顿环测量曲率半径’报告和大物复习)
- 单片机中code、data、idata、xdata等关键字意思
- SimpleMind Pro 1.29.1 小巧的思维导图工具