爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      windows USB 设备驱动开发-USB 等时传输

      首页 知识中心 软件开发 文章详情页

      windows USB 设备驱动开发-USB 等时传输

      2024-09-10 08:20:51 阅读次数:30

      驱动程序

      客户端驱动程序可以生成 USB 请求块 (URB) 以在 USB 设备中向/从常时等量端点传输数据。虽然USB设备一向以非等时传输出名,USB提供的是一种串行数据,而非等时,但是USB仍然设计了等时传输的机制,但根据笔者的经验,等时传输也许使用1394更好一些。

      通用串行总线 (USB) 设备可以支持常时等量端点,以稳定速率传输依赖于时间的数据,例如音频/视频流。 若要传输数据,客户端驱动程序会发出请求,以将数据读取或写入常量端点。 因此,主机控制器启动常时等量传输,该传输通过定期轮询设备来发送或接收数据。

      对于高速和全速设备,轮询通过使用 (IN/OUT) 令牌数据包来完成。 当端点准备好发送数据时,设备将通过发送数据来响应其中一个 IN 令牌数据包。 若要写入设备,主机控制器会发送 OUT 令牌数据包,后跟数据包。 主机控制器或设备不发送任何握手数据包,因此无法保证传递。 由于主机控制器不会尝试重试传输,因此如果发生错误,数据可能会丢失。

      对于常时等量传输,主机控制器在总线上保留特定时间段。 为了管理常时等量端点的保留时间,将时间划分为连续的逻辑间隔,称为 总线间隔。 总线间隔的单位取决于总线速度。

      • 对于全速,总线间隔是 帧。 帧的长度为 1 毫秒。
      • 对于高速和超高速,总线间隔是微帧。 微帧的长度为 125 微秒。 八个连续的微帧构成一个高速或超高速帧。

      常时等量传输基于数据包。 这里的术语 常时等量数据包 是指在一个总线间隔内传输的数据量。 端点的特征决定了每个数据包的大小是固定的,由端点的特征决定。

      客户端驱动程序通过为请求创建 URB 并将 URB 提交到 USB 驱动程序堆栈来启动常时等量传输。 请求由 USB 驱动程序堆栈中的某个较低驱动程序处理。 收到 URB 后,USB 驱动程序堆栈将执行一组验证并计划请求的事务。 对于全速,要在每个总线间隔内传输的常时等量数据包包含在线路上的单个事务中。 某些高速设备允许在一个总线间隔内进行多个事务。 在这种情况下,客户端驱动程序可以在单个请求中发送或接收常量数据包中的更多数据 (URB) 。 SuperSpeed 设备支持多个事务和突发传输,允许每个总线间隔更多的字节数。 

      准备工作

      在创建常时等量传输请求之前,必须具有有关为常时等量端点打开的管道的信息。

      使用 Windows 驱动程序模型 (WDM) 例程的客户端驱动程序在USBD_INTERFACE_LIST_ENTRY数组的某个USBD_PIPE_INFORMATION结构中具有管道信息。 客户端驱动程序在驱动程序的上一个请求中获取了该数组,以选择设备中的配置或接口。

      Windows 驱动程序框架 (WDF) 客户端驱动程序必须获取对框架的目标管道对象的引用,并调用 WdfUsbTargetPipeGetInformation 以获取 WDF_USB_PIPE_INFORMATION 结构中的管道信息。

      根据管道信息确定这组信息:

      • 主机控制器可以向每个数据包中的管道发送多少数据。

      客户端驱动程序可以在请求中发送的数据量不能超过主机控制器可从端点发送或接收的最大字节数。 最大字节数由 USBD_PIPE_INFORMATION 和 WDF_USB_PIPE_INFORMATION 结构的 MaximumPacketSize 成员指示。 USB 驱动程序堆栈在选择配置或选择接口请求期间设置 MaximumPacketSize 值。

      对于全速设备, MaximumPacketSize 派生自端点描述符的 wMaxPacketSize 字段的前 11 位,该字段指示端点可以在事务中发送或接收的最大字节数。 对于全速设备,控制器为每个总线间隔发送一个事务。

      在高速常时等量传输中,如果端点允许,主机控制器可以在总线间隔内发送其他事务。 其他事务数由设备设置,并在 wMaxPacketSize 的位 12..11 中指示。 该数字可以是 0、1 或 2。 如果 12..11 指示 0,则端点不支持每个微帧的其他事务。 如果数字为 1,则主机控制器可以发送额外的事务 (每个微帧) 总共两个事务;2 表示每个微帧) 两个事务 (总共三个事务。 由 USB 驱动程序堆栈设置的 MaximumPacketSize 值包括可在其他事务中发送的字节数。

      对于 SuperSpeed 常时等时传输,USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR (的某些值请参阅 Usbspec.h) 非常重要。 USB 驱动程序堆栈使用这些值来计算总线间隔内的最大字节数。

      端点配套描述符的等时常量.Mult 字段。 在 SuperSpeed 等时常量传输中, (与高速设备) 的附加事务称为突发事务。 Mult 值指示端点支持的突发事务的最大数目。 在一个服务间隔内,最多可以有三个突发事务 (索引为 0 到 2) 。

      端点配套描述符的 bMaxBurst 字段。 此值指示单个突发事务中可以存在的 wMaxPacketSize 区块数。 突发事务中最多可以有 16 个区块, (索引为 0 到 15) 。

      wBytesPerInterval 指示主机在总线间隔内可以发送或接收的总字节数。 尽管每个总线间隔的最大字节数可以计算为 (bMaxBurst+1) * (Mult+1) * wMaxPacketSize,但 USB 3.0 规范建议改用 wBytesPerInterval 值。 wBytesPerInterval 值必须小于或等于该计算值。

      对于客户端驱动程序,前面所述的值仅供信息使用。 驱动程序必须始终使用端点描述符的 MaximumPacketSize 值来确定传输缓冲区的布局。

      • 端点多久发送或接收一次数据?

      Interval 成员用于确定端点可以发送或接收数据的频率。 设备设置该值,客户端驱动程序无法更改该值。 USB 驱动程序堆栈使用另一个数字来确定将常时等量数据包插入数据流的频率:从 Interval 值派生的轮询周期。

      对于全速传输, 间隔 和轮询周期值始终为 1;USB 驱动程序堆栈忽略其他值。

      下表显示了高速和超高速传输的 间隔 和计算轮询周期:

      windows USB 设备驱动开发-USB 等时传输

      • 每个总线速度的数据包数有哪些限制。

      在 URB 中,对于一个全速设备,最多只能发送 255 个常时等量数据包;适用于高速和超高速设备的 URB 中的 1024 个数据包。 在 URB 中发送的数据包数必须是每个帧中数据包数的倍数。

      windows USB 设备驱动开发-USB 等时传输

      请考虑 wMaxPacketSize 为 1,023 的示例全速端点。 对于此示例,应用程序提供了 25,575 字节的缓冲区。 该缓冲区的传输需要 25 个常时等量数据包 (25575/1023) 。

      请考虑一个高速端点示例,其端点描述符中指示了以下特征。

      • wMaxPacketSize 为 1,024;
      • 位 12..11 指示另外两个事务;
      • 间隔 为 1;

      客户端驱动程序选择配置后,常时常量管道的 MaximumPacketSize 指示 3,072 字节 (总事务 * wMaxPacketSize) 。 其他事务允许客户端驱动程序在每个微帧中传输 3,072 个字节,在一个帧中传输总共 24,576 个字节。 下图显示了在一个微帧中传输常量数据包的频率,以便进行高速传输。

      windows USB 设备驱动开发-USB 等时传输
      请考虑一个示例 SuperSpeed 端点,其特征在端点和 SuperSpeed 端点点配套描述符中指示:

      • wMaxPacketSize 为 1,024;
      • bMaxBurst 为 15;
      • 间隔 为 1;
      • Isochronous.Mult 为 2;
      • wBytesPerInterval 为 45000;

      在前面的示例中,即使最大字节数可以计算为 wMaxPacketSize * (bMaxBurst +1) * (Mult + 1) 导致 49,152 个字节,设备也会将值限制为 45,000 字节的 wBytesPerInterval 值。 该值也反映在 MaximumPacketSize 45,000 中。 客户端驱动程序只能使用 MaximumPacketSize 值。 在此示例中,请求可分为三个突发事务。 前两个突发事务各包含 16 个 wMaxPacketSize 区块。 最后一个突发事务包含 12 个用于保存剩余字节的区块。 此图显示了轮询间隔以及通过超速传输常量数据包传输的字节数。

      windows USB 设备驱动开发-USB 等时传输
      生成常时等量传输的请求:

      1. 获取每个常量数据包的大小;
      2. 确定每帧的常时等量数据包数;
      3. 计算保存整个传输缓冲区所需的常时等量数据包数;
      4. 分配 URB 结构以描述传输的详细信息;
      5. 指定每个常量数据包的详细信息,例如数据包偏移量;

      本文中的此示例简化了常量传输的 USBSAMP 实现。 该示例计算传输所需的总帧数。 根据可以在帧中发送的数据量,传输缓冲区划分为较小的区块大小字节。

      以下过程详细说明了上述步骤,并演示了客户端驱动程序可用于生成和发送高速常时等量端点的等时等传输请求的计算和例程。 过程中使用的值基于前面所述的示例端点特征。

      步骤 1:获取常量数据包的大小

      通过检查管道的 MaximumPacketSize 值来确定常时等量数据包的大小。

      对于全速传输,常时等量数据包的大小是可以在一帧中传输的字节数。 对于高速和超高速传输,常量数据包的大小是可在一个微帧中传输的字节总数。 这些值在管道的 MaximumPacketSize 中指示。

      在示例中, MaximumPacketSize 为每帧 1023 字节, (全速) ;每个微帧 3072 字节 (高速) ;每个微帧 45,000 字节 (SuperSpeed) 。

       备注 MaximumPacketSize 值指示常量数据包允许的最大大小。 客户端驱动程序可以将每个常量数据包的大小设置为小于 MaximumPacketSize 值的任何值。

      步骤 2:确定每帧常时等量数据包数

      对于全速传输,在每个帧中传输一个常量数据包。

      对于高速和超高速传输,此值必须派生自 Interval 值。 在示例中,间隔为 1。 因此,常时等量数据包数必须为每帧 8 个。

      步骤 3:计算保存整个传输缓冲区所需的常时等量数据包数

      计算传输整个缓冲区所需的常时等量数据包数。 此值可以通过将传输缓冲区的长度除以常时等量数据包的大小来计算。

      在此示例中,我们假设每个常时等量数据包的大小为 MaximumPacketSize ,传输缓冲区长度是 MaximumPacketSize 值的倍数。

      例如,对于全速传输,提供的 25,575 字节的缓冲区需要 25 个常量数据包 (25575/1023) 。 对于高速传输,大小为 24,576 的缓冲区分为 8 个常量数据包, (24576 /3072) 进行传输。 对于 SuperSpeed,大小为 360,000 字节的缓冲区适合 8 个常量数据包, (360000/45000) 。

      客户端驱动程序应验证以下要求:

      • 常时等量数据包数必须是每帧数据包数的倍数。
      • 对于全速设备,进行传输所需的常时等量数据包的最大数目不得超过 255 个;1024,适用于高速或超高速设备。
      步骤 4:分配 URB 结构以描述传输的详细信息

      1.在非分页池中分配 URB 结构:

      如果客户端驱动程序使用 WDM 例程,则驱动程序必须调用USBD_IsochUrbAllocate(如果你有适用于Windows 8的 Windows 驱动程序工具包 (WDK) )。 客户端驱动程序可以使用 例程来面向 Windows Vista 和更高版本的 Windows 操作系统。 如果没有用于Windows 8的 WDK,或者客户端驱动程序适用于早期版本的操作系统,可以通过调用 ExAllocatePoolWithTag 在堆栈上或非分页池中分配结构。

      WDF 客户端驱动程序可以调用 WdfUsbTargetDeviceCreateIsochUrb 方法,为 URB 结构分配内存。

      2.URB 结构的 UrbIsochronousTransfer 成员指向描述常量传输详细信息的 _URB_ISOCH_TRANSFER 结构。 按如下所示初始化以下 UrbIsochronousTransfer 成员:

      • 将 UrbIsochronousTransfer.Hdr.Length 成员设置为 URB 的大小。 若要获取 URB 的大小,请调用 GET_ISO_URB_SIZE 宏并指定数据包数。
      • 将 UrbIsochronousTransfer.Hdr.Function 成员设置为 URB_FUNCTION_ISOCH_TRANSFER。
      • 将 UrbIsochronousTransfer.NumberOfPackets 成员设置为常量数据包数。
      • 将 UrbIsochronousTransfer.PipeHandle 设置为与端点关联的管道的不透明句柄。 确保管道句柄是通用串行总线 (USB) 驱动程序堆栈使用的 USBD 管道句柄。

      若要获取 USBD 管道句柄,WDF 客户端驱动程序可以调用 WdfUsbTargetPipeWdmPipeHandle 方法,并将 WDFUSBPIPE 句柄指定为框架的管道对象。 WDM 客户端驱动程序必须使用在 USBD_PIPE_INFORMATION 结构的 PipeHandle 成员中获取的相同句柄。

      • 指定传输方向。 将 UrbIsochronousTransfer.TransferFlags 设置为 USBD_TRANSFER_DIRECTION_IN,以便从设备) 读取常时等量 IN 传输 (; (写入设备) ,USBD_TRANSFER_DIRECTION_OUT常量 OUT 传输。
      • 在 UrbIsochronousTransfer 中指定USBD_START_ISO_TRANSFER_ASAP标志。TransferFlags。 标志指示 USB 驱动程序堆栈在下一个适当的帧中发送传输。 客户端驱动程序首次为此管道发送常时等量 URB 时,驱动程序堆栈会尽快在 URB 中发送常时等量数据包。 USB 驱动程序堆栈跟踪要用于该管道上的后续 URL 的下一帧。 如果在发送使用 USBD_START_ISO_TRANSFER_ASAP 标志的后续常时常量 URB 时出现延迟,驱动程序堆栈会将该 URB 的部分或所有数据包视为延迟,并且不会传输这些数据包。

      如果堆栈在完成该管道的上一个 URB 后未收到 1024 帧的常量 URB,USB 驱动程序堆栈将重置其USBD_START_ISO_TRANSFER_ASAP启动帧跟踪。 可以指定起始帧,而不是指定USBD_START_ISO_TRANSFER_ASAP标志。 。

      • 指定传输缓冲区及其大小。 可以在 UrbIsochronousTransfer.TransferBuffer 或用于描述 UrbIsochronousTransfer.TransferBufferMDL 中的缓冲区的 MDL 中设置指向缓冲区的指针。

      若要检索传输缓冲区的 MDL,WDF 客户端驱动程序可以调用 WdfRequestRetrieveOutputWdmMdl 或 WdfRequestRetrieveInputWdmMdl,具体取决于传输的方向。

      步骤 5:指定传输中每个常时等量数据包的详细信息

      USB 驱动程序堆栈分配的新 URB 结构足够大,用于保存有关每个常时等量数据包的信息,但不包含数据包中包含的数据。 在 URB 结构中, UrbIsochronousTransfer.IsoPacket 成员是 一个USBD_ISO_PACKET_DESCRIPTOR 数组,用于描述传输中每个常时等量数据包的详细信息。 数据包必须是连续的。 数组中的元素数必须是 URB 的 UrbIsochronousTransfer.NumberOfPackets 成员中指定的常时等量数据包数。

      对于高速传输,数组中的每个元素都与一个微帧中的一个常量数据包相关联。 对于全速,每个元素都与一帧中传输的一个常量数据包相关联。

      对于每个元素,指定从请求的整个传输缓冲区开始的每个常时等量数据包的字节偏移量。 可以通过设置 UrbIsochronousTransfer.IsoPacket[i] 来指定该值。偏移 成员。 USB 驱动程序堆栈使用指定的值来跟踪要发送或接收的数据量。

      设置 Full-Speed 传输的偏移量

      例如,这些是全速传输缓冲区的数组条目。 在全速模式下,客户端驱动程序有一个帧用于传输一个常量数据包,最大为 1,023 个字节。 25,575 字节的传输缓冲区可以容纳 25 个常时等量数据包,每个数据包长度为 1,023 个字节。 整个缓冲区总共需要 25 帧。

      Frame 1 IsoPacket [0].Offset = 0 (start address)
      Frame 2 IsoPacket [1].Offset = 1023
      Frame 3 IsoPacket [2].Offset = 2046
      Frame 4 IsoPacket [3].Offset = 3069
      ...
      Frame 25 IsoPacket [24].Offset = 24552
      
      Total length transferred is 25,575 bytes.
      设置 High-Speed 传输的偏移量

      例如,这些是高速传输缓冲区的数组条目。 该示例假定缓冲区为 24,576 字节,客户端驱动程序有一个帧用于传输 8 个常量数据包,每个包长 3,072 个字节。

      Microframe 1 IsoPacket [0].Offset = 0 (start address)
      Microframe 2 IsoPacket [1].Offset = 3072
      Microframe 3 IsoPacket [2].Offset = 6144
      Microframe 4 IsoPacket [3].Offset = 9216
      Microframe 5 IsoPacket [4].Offset = 12288
      Microframe 6 IsoPacket [5].Offset = 15360
      Microframe 7 IsoPacket [6].Offset = 18432
      Microframe 8 IsoPacket [7].Offset = 21504
      
      Total length transferred is 24,576 bytes.
      设置超速传输的偏移量

      例如,这是 SuperSpeed 的数组偏移量。 一个帧中最多可以传输 45,000 个字节。 大小为 360,000 的传输缓冲区适合 8 个微帧

      Microframe 1 IsoPacket [0].Offset = 0 (start address)
      Microframe 2 IsoPacket [1].Offset = 45000
      Microframe 3 IsoPacket [2].Offset = 90000
      Microframe 4 IsoPacket [3].Offset = 135000
      Microframe 5 IsoPacket [4].Offset = 180000
      Microframe 6 IsoPacket [5].Offset = 225000
      Microframe 7 IsoPacket [6].Offset = 270000
      Microframe 8 IsoPacket [7].Offset = 315000
      
      Total length transferred is 360,000 bytes.

      UrbIsochronousTransfer.IsoPacket[i]。Length 成员并不表示常时等量 URB 的每个数据包的长度。 IsoPacket[i]。长度 由 USB 驱动程序堆栈更新,以指示从设备接收的实际字节数,用于常量 IN 传输。 对于常时等量 OUT 传输,驱动程序堆栈会忽略 IsoPacket[i] 中设置的值。长度。

      指定传输的起始 USB 帧编号

      URB 的 UrbIsochronousTransfer.StartFrame 成员指定传输的起始 USB 帧编号。 客户端驱动程序提交 URB 的时间和 USB 驱动程序堆栈处理 URB 的时间之间始终存在延迟。 因此,客户端驱动程序应始终指定一个晚于驱动程序提交 URB 时当前帧的起始帧。 若要检索当前帧编号,客户端驱动程序可以将URB_FUNCTION_GET_CURRENT_FRAME_NUMBER请求发送到 USB 驱动程序堆栈 (_URB_GET_CURRENT_FRAME_NUMBER) 。

      对于常时等量传输,当前帧与 StartFrame 值之间的绝对差必须小于 USBD_ISO_START_FRAME_RANGE。 如果 StartFrame 不在适当的范围内,则 USB 驱动程序堆栈会将 URB 标头的状态成员 (看到 _URB_HEADER) 设置为USBD_STATUS_BAD_START_FRAME并放弃整个 URB。

      URB 中指定的 StartFrame 值指示传输 URB 的第一个常时等量数据包的帧编号。 后续数据包的帧编号取决于端点的总线速度和轮询周期值。 例如,对于全速传输,第一个数据包在 StartFrame 中传输;第二个数据包在 StartFrame+1 中传输,依此类移。 USB 驱动程序堆栈以全速度以帧为单位传输常时等量数据包的方式如下所示:

      Frame (StartFrame)   IsoPacket [0]
      Frame (StartFrame+1) IsoPacket [1]
      Frame (StartFrame+2) IsoPacket [2]
      Frame (StartFrame+3) IsoPacket [3]
      ...

      对于间隔值为 1 的高速设备,帧编号每八个微帧更改一次。 USB 驱动程序堆栈在帧中高速传输等时等量数据包的方式如下所示:

      Frame (StartFrame) Microframe 1 IsoPacket [0]
      ...
      Frame (StartFrame) Microframe 8 IsoPacket [7]
      Frame (StartFrame+1) Microframe 1 IsoPacket [8]
      ...
      Frame (StartFrame+1) Microframe 8 IsoPacket [15]
      Frame (StartFrame+2) Microframe 1 IsoPacket [16]
      ...
      Frame (StartFrame+2) Microframe 8 IsoPacket [23]

      当 USB 驱动程序堆栈处理 URB 时,驱动程序会丢弃 URB 中帧数低于当前帧号的所有常时等量数据包。 驱动程序堆栈将每个丢弃数据包的数据包描述符 的状态 成员设置为USBD_STATUS_ISO_NA_LATE_USBPORT、USBD_STATUS_ISO_NOT_ACCESSED_BY_HW或USBD_STATUS_ISO_NOT_ACCESSED_LATE。 即使丢弃了 URB 中的某些数据包,驱动程序堆栈也会尝试仅传输帧号高于当前帧号的数据包。

      有效 StartFrame 成员的检查在高速传输中稍微复杂一些,因为 USB 驱动程序堆栈将每个常量数据包加载到高速微帧中;但是,StartFrame 中的值是指 1 毫秒 (全速) 帧数,而不是微帧。 例如,如果 URB 中记录的 StartFrame 值比当前帧少一个,则驱动程序堆栈可以丢弃多达 8 个数据包。 丢弃的数据包的确切数量取决于与常时等量管道关联的轮询周期。

      等时等量传输示例

      下面的代码示例演示如何为全速、高速和超高速传输的常时等量传输创建 URB。

      #define MAX_SUPPORTED_PACKETS_FOR_HIGH_OR_SUPER_SPEED 1024
      #define MAX_SUPPORTED_PACKETS_FOR_FULL_SPEED 255
      
      NTSTATUS CreateIsochURB  ( PDEVICE_OBJECT         DeviceObject,
                                PUSBD_PIPE_INFORMATION  PipeInfo,
                                ULONG                   TotalLength,
                                PMDL                    RequestMDL,
                                PURB                    Urb)
      {
          PDEVICE_EXTENSION        deviceExtension;
          ULONG                    numberOfPackets;
          ULONG                    numberOfFrames;
          ULONG                    isochPacketSize = 0;
          ULONG                    transferSizePerFrame;
          ULONG                    currentFrameNumber;
          size_t                   urbSize;
          ULONG                    index;
          NTSTATUS                 ntStatus;
      
          deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
      
          isochPacketSize = PipeInfo->MaximumPacketSize;
      
          // For high-speed transfers
          if (deviceExtension->IsDeviceHighSpeed || deviceExtension->IsDeviceSuperSpeed)
          {
              // Ideally you can pre-calculate numberOfPacketsPerFrame for the Pipe and
              // store it in the pipe context.
      
              switch (PipeInfo->Interval)
              {
              case 1:
                  // Transfer period is every microframe (eight times a frame).
                  numberOfPacketsPerFrame = 8;
                  break;
      
              case 2:
                  // Transfer period is every 2 microframes (four times a frame).
                  numberOfPacketsPerFrame = 4;
                  break;
      
              case 3:
                  // Transfer period is every 4 microframes (twice in a frame).
                  numperOfPacketsPerFrame = 2;
                  break;
      
              case 4:
              default:
                  // Transfer period is every 8 microframes (once in a frame).
                  numberOfPacketsPerFrame = 1;
                  break;
              }
      
              //Calculate the number of packets.
              numberOfPackets = TotalLength / isochPacketSize;
      
              if (numberOfPackets > MAX_SUPPORTED_PACKETS_FOR_HIGH_OR_SUPER_SPEED)
              {
                  // Number of packets cannot be  greater than 1021.
                  ntStatus = STATUS_INVALID_PARAMETER;
                  goto Exit;
              }
      
              if (numberOfPackets % numberOfPacketsPerFrame != 0)
              {
      
                  // Number of packets should be a multiple of numberOfPacketsPerFrame
                  ntStatus = STATUS_INVALID_PARAMETER;
                  goto Exit;
              }
      
          }
          else if (deviceExtension->IsDeviceFullSpeed)
          {
              //For full-speed transfers
              // Microsoft USB stack only supports bInterval value of 1 for
              // full-speed isochronous endpoints.
      
              //Calculate the number of packets.
              numberOfPacketsPerFrame = 1;
      
              numberOfPackets = TotalLength / isochPacketSize;
      
              if (numberOfPackets > MAX_SUPPORTED_PACKETS_FOR_FULL_SPEED)
              {
                  // Number of packets cannot be greater than 255.
                  ntStatus = STATUS_INVALID_PARAMETER;
                  goto Exit;
              }
          }
      
          // Allocate an isochronous URB for the transfer
          ntStatus = USBD_IsochUrbAllocate (deviceExtension->UsbdHandle,
              numberOfPackets,
              &Urb);
      
          if (!NT_SUCCESS(ntStatus))
          {
              ntStatus = STATUS_INSUFFICIENT_RESOURCES;
              goto Exit;
          }
      
          urbSize = GET_ISO_URB_SIZE(numberOfPackets);
      
          Urb->UrbIsochronousTransfer.Hdr.Length = (USHORT) urbSize;
          Urb->UrbIsochronousTransfer.Hdr.Function = URB_FUNCTION_ISOCH_TRANSFER;
          Urb->UrbIsochronousTransfer.PipeHandle = PipeInfo->PipeHandle;
      
          if (USB_ENDPOINT_DIRECTION_IN(PipeInfo->EndpointAddress))
          {
              Urb->UrbIsochronousTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_IN;
          }
          else
          {
              Urb->UrbIsochronousTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_OUT;
          }
      
          Urb->UrbIsochronousTransfer.TransferBufferLength = TotalLength;
          Urb->UrbIsochronousTransfer.TransferBufferMDL = RequestMDL;
          Urb->UrbIsochronousTransfer.NumberOfPackets = numberOfPackets;
          Urb->UrbIsochronousTransfer.UrbLink = NULL;
      
          // Set the offsets for every packet for reads/writes
      
          for (index = 0; index < numberOfPackets; index++)
          {
              Urb->UrbIsochronousTransfer.IsoPacket[index].Offset = index * isochPacketSize;
          }
      
          // Length is a return value for isochronous IN transfers.
          // Length is ignored by the USB driver stack for isochronous OUT transfers.
      
          Urb->UrbIsochronousTransfer.IsoPacket[index].Length = 0;
          Urb->UrbIsochronousTransfer.IsoPacket[index].Status = 0;
      
          // Set the USBD_START_ISO_TRANSFER_ASAP. The USB driver stack will calculate the start frame.
          // StartFrame value set by the client driver is ignored.
          Urb->UrbIsochronousTransfer.TransferFlags |= USBD_START_ISO_TRANSFER_ASAP;
      
      Exit:
      
          return ntStatus;
      }

      11111

      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://blog.csdn.net/m0_72813396/article/details/140193492,作者:sului,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:windows USB 设备驱动开发-USB主控制开发(二)

      下一篇:windows USB 驱动开发-URB结构

      相关文章

      2025-03-11 09:36:54

      Android 体系结构

      Android 体系结构

      2025-03-11 09:36:54
      Android , 编译 , 驱动程序
      2024-12-05 08:49:57

      Linux源码阅读笔记17-资源分配及总线系统

      Linux提供通用框架,用于在内存中构建数据结构。这些结构描述了系统中可用的资源,使得内核代码能够管理和分配资源。

      2024-12-05 08:49:57
      内核 , 总线 , 数据结构 , 节点 , 设备 , 驱动程序
      2024-12-05 08:49:45

      Linux源码学习笔记01-Linux内核源码结构

      Linux源码学习笔记01-Linux内核源码结构

      2024-12-05 08:49:45
      Linux , 代码 , 内核 , 文件系统 , 源码 , 进程 , 驱动程序
      2024-09-10 08:20:45

      windows USB 设备驱动开发-USB主控制开发(二)

      UCX 执行根中心管理。 它模拟和管理虚拟控制与中断端点。 当主控制器驱动程序创建根中心对象时,UCX 会创建这些虚拟端点。

      2024-09-10 08:20:45
      windows , 驱动开发 , 驱动程序
      2024-09-10 08:20:36

      windows USB 设备驱动开发-使用 USB ETW 跟踪中的活动 ID GUID

      USB 驱动程序堆栈 (2.0 和 3.0) 是 ETW 事件跟踪提供程序。 在 Windows 7 中,从 USB 驱动程序堆栈捕获事件跟踪时,可以从其他提供程序(如其他驱动程序和应用程序)捕获跟踪。 然后,可以读取合并的日志 (假设已为提供程序的事件跟踪) 创建了 Netmon 分析程序。

      2024-09-10 08:20:36
      驱动开发 , 驱动程序
      2024-09-10 08:20:36

      windows USB 设备驱动开发-Windows 的 USB 事件跟踪

      Windows 事件跟踪(ETW)是操作系统提供的通用高速跟踪设施。 它使用在内核中实现的缓冲和日志记录机制,为用户模式应用程序和内核模式设备驱动程序引发的事件提供跟踪机制。

      2024-09-10 08:20:36
      事件 , 驱动开发 , 驱动程序
      2024-09-10 08:20:36

      windows USB 设备驱动开发-USB ETW 和Netmon

      可以使用 Microsoft 网络监视器(也称为 Netmon)查看 USB ETW 事件跟踪。 Netmon 不会自动分析跟踪。 它需要 USB ETW 分析程序。 USB ETW 分析程序是用网络监视器分析程序语言 (NPL) 编写的文本文件,用于描述 USB ETW 事件跟踪的结构。 分析程序还定义 USB 特定的列和筛选器。 这些分析程序使 Netmon 成为分析 USB ETW 跟踪的最佳工具。

      2024-09-10 08:20:36
      枚举 , 驱动开发 , 驱动程序
      2024-09-10 08:20:36

      windows USB 设备驱动开发-开发Type C接口的驱动程序(三)

      如果 USB Type-C 硬件实现 USB Type-C 或电源传送 (PD) 物理层,但未实现供电所需的状态机,则需要编写 USB Type-C 端口控制器驱动程序。

      2024-09-10 08:20:36
      客户端 , 驱动开发 , 驱动程序
      2024-04-22 06:40:24

      2023驱动保护学习 -- 通过代码实现驱动加载

      2023驱动保护学习 -- 通过代码实现驱动加载

      2024-04-22 06:40:24
      句柄 , 驱动程序
      2024-04-22 06:40:24

      2023驱动保护学习 -- 通过代码实现驱动卸载

      2023驱动保护学习 -- 通过代码实现驱动卸载

      2024-04-22 06:40:24
      缓存 , 驱动程序
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5240241

      查看更多

      最新文章

      Android 体系结构

      2025-03-11 09:36:54

      Linux源码阅读笔记17-资源分配及总线系统

      2024-12-05 08:49:57

      Linux源码学习笔记01-Linux内核源码结构

      2024-12-05 08:49:45

      windows USB 设备驱动开发-USB主控制开发(二)

      2024-09-10 08:20:45

      windows USB 设备驱动开发-使用 USB ETW 跟踪中的活动 ID GUID

      2024-09-10 08:20:36

      windows USB 设备驱动开发-Windows 的 USB 事件跟踪

      2024-09-10 08:20:36

      查看更多

      热门文章

      解决无法访问G盘损坏是否将其格式化的方法

      2023-08-02 07:14:21

      2023驱动保护学习 -- 通过代码实现驱动加载

      2024-04-22 06:40:24

      2023驱动保护学习 -- 通过代码实现驱动卸载

      2024-04-22 06:40:24

      2023驱动保护学习 -- 应用层与驱动层读写操作(二)

      2024-04-22 06:40:24

      windows USB 设备驱动开发-USB ETW 和Netmon

      2024-09-10 08:20:36

      windows USB 设备驱动开发-Windows 的 USB 事件跟踪

      2024-09-10 08:20:36

      查看更多

      热门标签

      java Java python 编程开发 代码 开发语言 算法 线程 Python html 数组 C++ 元素 javascript c++
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      windows USB 设备驱动开发-Windows 的 USB 事件跟踪

      windows USB 设备驱动开发-使用 USB ETW 跟踪中的活动 ID GUID

      windows USB 设备驱动开发-USB主控制开发(二)

      Linux源码学习笔记01-Linux内核源码结构

      2023驱动保护学习 -- 通过代码实现驱动加载

      2023驱动保护学习 -- 通过代码实现驱动卸载

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号