windows USB 设备驱动开发-USB 等时传输
客户端驱动程序可以生成 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 驱动程序堆栈忽略其他值。
下表显示了高速和超高速传输的 间隔 和计算轮询周期:
- 每个总线速度的数据包数有哪些限制。
在 URB 中,对于一个全速设备,最多只能发送 255 个常时等量数据包;适用于高速和超高速设备的 URB 中的 1024 个数据包。 在 URB 中发送的数据包数必须是每个帧中数据包数的倍数。
请考虑 wMaxPacketSize 为 1,023 的示例全速端点。 对于此示例,应用程序提供了 25,575 字节的缓冲区。 该缓冲区的传输需要 25 个常时等量数据包 (25575/1023) 。
请考虑一个高速端点示例,其端点描述符中指示了以下特征。
- wMaxPacketSize 为 1,024;
- 位 12..11 指示另外两个事务;
- 间隔 为 1;
客户端驱动程序选择配置后,常时常量管道的 MaximumPacketSize 指示 3,072 字节 (总事务 * wMaxPacketSize) 。 其他事务允许客户端驱动程序在每个微帧中传输 3,072 个字节,在一个帧中传输总共 24,576 个字节。 下图显示了在一个微帧中传输常量数据包的频率,以便进行高速传输。
请考虑一个示例 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 个用于保存剩余字节的区块。 此图显示了轮询间隔以及通过超速传输常量数据包传输的字节数。
生成常时等量传输的请求:
- 获取每个常量数据包的大小;
- 确定每帧的常时等量数据包数;
- 计算保存整个传输缓冲区所需的常时等量数据包数;
- 分配 URB 结构以描述传输的详细信息;
- 指定每个常量数据包的详细信息,例如数据包偏移量;
本文中的此示例简化了常量传输的 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 = 24552Total 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 = 21504Total 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 = 315000Total 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 255NTSTATUS 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 transfersif (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 numberOfPacketsPerFramentStatus = 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 transferntStatus = 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/writesfor (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
相关文章:

windows USB 设备驱动开发-USB 等时传输
客户端驱动程序可以生成 USB 请求块 (URB) 以在 USB 设备中向/从常时等量端点传输数据。虽然USB设备一向以非等时传输出名,USB提供的是一种串行数据,而非等时,但是USB仍然设计了等时传输的机制,但根据笔者的经验,等时传…...
【文件共享 windows和linux】Windows Server 2016上开启文件夹共享,并在CentOS 7.4上访问和下载文件
要在Windows Server 2016上开启文件夹共享,并在CentOS 7.4上访问和下载文件,请按照以下步骤操作: 在Windows Server 2016上开启文件夹共享: 启用SMB服务: 打开“服务器管理器”。选择“文件和存储服务” > “共享…...

【知网CNKI-注册安全分析报告】
前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 暴力破解密码,造成用户信息泄露短信盗刷的安全问题,影响业务及导致用户投诉带来经济损失,尤其是后付费客户,风险巨大,造成亏损无底洞…...

【Python_GUI】tkinter常用组件——文本类组件
文本时窗口中必不可少的一部分,tkinter模块中,有3种常用的文本类组件,通过这3种组件,可以在窗口中显示以及输入单行文本、多行文本、图片等。 Label标签组件 Label组件的基本使用 Label组件是窗口中比较常用的组件,…...

zdppy+onlyoffice+vue3解决文档加载和文档强制保存时弹出警告的问题
解决过程 第一次排查 最开始排查的是官方文档说的 https://api.onlyoffice.com/editors/troubleshooting#key 解决方案。参考的是官方的 https://github.com/ONLYOFFICE/document-server-integration/releases/latest/download/Python.Example.zip 基于Django的Python代码。 …...
C语言从头学31——与字符串变量相关的几个函数
strlen、strcpy、strcat、strcmp、sprintf这些函数都是与字符串相关的,除了sprintf是定义在stdio.h中外,其余几个都定义在string.h中,比较新的编译器版本stdio.h中已经含有string.h的内容,所以编程时不需要再包含string.h这个头文…...
Laravel批量插入数据:提升数据库操作效率的秘诀
Laravel批量插入数据:提升数据库操作效率的秘诀 Laravel作为PHP的现代Web应用框架,提供了优雅而简洁的方法来处理数据库操作。批量插入数据是数据库操作中常见的需求,尤其是在处理大量数据时,批量插入可以显著提高性能。本文将详…...
OpenCV:解锁计算机视觉的魔法钥匙
OpenCV:解锁计算机视觉的魔法钥匙 在人工智能与图像处理的世界里,OpenCV是一个响当当的名字。作为计算机视觉领域的瑞士军刀,OpenCV以其丰富的功能库、跨平台的特性以及开源的便利性,成为了开发者手中不可或缺的工具。本文将深入…...

手写简单模拟mvc
目录结构: 两个注解类: Controller: package com.heaboy.annotation;import java.lang.annotation.*;/*** 注解没有功能只是简单标记* .RUNTIME 运行时还能看到* .CLASS 类里面还有,构建对象久没来了,这个说明…...

【FreeRTOS】同步互斥与通信 FreeRTOS提供的方法
目录 各类方法的对比队列事件组信号量互斥量任务通知 各类方法的本质 使用全局变量可以实现通信,但是使用全局变量会有一些缺陷。 那我们怎么保证通信的正确性呢??? 我们需要引入很多互斥的方法。除了互斥之外,还需要高…...
Kafka 面试题指南
Kafka 面试题指南 本文档提供了一份详细的 Kafka 面试题指南,涵盖了 Kafka 的核心概念、架构、配置、操作和实际应用场景等方面的内容。希望通过这份指南能够帮助你在 Kafka 面试中取得成功。 目录 Kafka 基础知识 什么是 Kafka?Kafka 的主要特点是什…...

2024年7月5日 (周五) 叶子游戏新闻
老板键工具来唤去: 它可以为常用程序自定义快捷键,实现一键唤起、一键隐藏的 Windows 工具,并且支持窗口动态绑定快捷键(无需设置自动实现)。 卸载工具 HiBitUninstaller: Windows上的软件卸载工具 《乐高地平线大冒险》为何不登陆…...
热门开源项目推荐:探索开源世界的精彩
热门开源项目推荐 随着开源程序的发展,越来越多的程序员开始关注并加入开源大模型的行列。开源不仅为个人学习和成长提供了绝佳的平台,也为整个技术社区带来了创新和进步。无论你是初学者还是经验丰富的开发者,参与开源项目都能让你受益匪浅…...

Codeforces Round #956 (Div. 2) and ByteRace 2024(A~D题解)
这次比赛也是比较吃亏的,做题顺序出错了,先做的第三个,错在第三个数据点之后,才做的第二个(因为当时有个地方没检查出来)所以这次比赛还是一如既往地打拉了 那么就来发一下题解吧 A. Array Divisibility …...

基于YOLOv9的脑肿瘤区域检测
数据集 脑肿瘤区域检测,我们直接采用kaggle公开数据集,Br35H 数据中已对医学图像中脑肿瘤位置进行标注 数据集我已经按照YOLO格式配置好,数据内容如下 数据集中共包含700张图像,其中训练集500张,验证集200张 模型训…...

阿里云 ECS 服务器的安全组设置
阿里云 ECS 服务器的安全组设置 缘由安全组多个安全组各司其职一些常见的IP段百度 IP 段华为云 IP 段搜狗蜘蛛 IP 段阿里云 IP 段 。。。 缘由 最近公司规模缩减,原有的托管在 IDC 机房的服务器,都被处理掉了,所有代码都迁移到了阿里云的云服…...

昇思25天学习打卡营第15天|应用实践之ShuffleNet图像分类
基本介绍 今天的应用实践的领域是计算机视觉领域,更确切的说是图像分类任务,不过,与昨日不同的是,今天所使用的模型是ShuffleNet模型。ShuffleNetV1是旷视科技提出的一种计算高效的CNN模型,和MobileNet, SqueezeNet等一…...
怀庄之醉适合搭配什么食物?
怀庄之醉作为一种独特的佳酿,其丰富的香气和层次感使其能够与多种食物搭配,提升餐饮体验。以下将具体探讨怀庄之醉适合搭配的食物类型,并分析为何这些搭配能够带来卓越的味觉享受。 一、肉类佳肴 怀庄之醉因其浓郁的口感,特别适…...

Java | Leetcode Java题解之第223题矩形面积
题目: 题解: class Solution {public int computeArea(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2) {int area1 (ax2 - ax1) * (ay2 - ay1), area2 (bx2 - bx1) * (by2 - by1);int overlapWidth Math.min(ax2, bx2) -…...

基于单片机的空调控制器的设计
摘 要 : 以单片机为核心的空调控制器因其体积小 、 成本低 、 功能强 、 简便易行而得到广泛应用 。 本设计通过 AT89S52 控制DS18&a…...

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...