源码解析与测试指南)
示例工程【免费下载链接】Windows-driver-samplesThis repo contains driver samples prepared for use with Microsoft Visual Studio and the Windows Driver Kit (WDK). It contains both Universal Windows Driver and desktop-only driver samples.项目地址https://gitcode.com/gh_mirrors/wi/Windows-driver-samples点击查看免费下载本篇技术指南以 Windows-driver-samples 仓库中的 usb/kmdf_fx2 示例为核心系统讲解如何用 Kernel-Mode Driver FrameworkKMDF为 OSR USB-FX2 学习套件编写一个完整的 USB 函数驱动程序Function Driver涵盖设备架构、驱动源码逐模块解析、IOCTL 接口设计、批量/中断传输实现、电源管理选择性挂起与远程唤醒、ETW 统一跟踪以及配套测试工具 osrusbfx2.exe 的完整命令行用法。读完本文你将掌握基于 KMDF 的 USB 驱动从枚举设备 → 选择配置 → 创建队列 → 收发数据 → 事件跟踪的完整开发与调试路径并可直接照搬示例的命令在真实 FX2 板卡上做读写与回环验证。示例概览KMDF 如何驱动一块 USB 学习板osrusbfx2 是 WDK 中经典的 KMDF USB 驱动示例面向 OSR USB-FX2 Learning Kit 编写目标是演示如何对 USB 设备执行批量Bulk传输与中断Interrupt传输。示例工程包含三部分源码位置分别为目录内容说明usb/kmdf_fx2/driver内核驱动源码KMDF 函数驱动本体usb/kmdf_fx2/exe控制台测试程序驱动与设备测试应用 osrusbfx2.exeusb/kmdf_fx2/deviceMetadata设备元数据包安装设备前需先部署到系统此外 usb/kmdf_fx2/inc 存放内核态与用户态共享的头文件public.h定义设备接口 GUID 与 IOCTLprototypes.h提供原型usb/kmdf_fx2/kmdf_fx2.sln 是 Visual Studio 解决方案入口。设备硬件架构从 README 的 Overview 可知该设备基于 Cypress EZ-USB FX2 开发套件CY3681的开发板1 个接口Interface、3 个端点EndpointInterrupt IN、Bulk OUT、Bulk IN与源码 osrusbfx2.h 中的端点索引宏一一对应INTERRUPT_IN_ENDPOINT_INDEX 0中断输入端点位于描述符第 0 位BULK_OUT_ENDPOINT_INDEX 1批量输出端点BULK_IN_ENDPOINT_INDEX 2批量输入端点固件支持厂商命令查询/设置 LED 条形图Bar Graph显示、查询/设置 7 段数码管7-Segment显示、查询拨码开关Toggle Switch状态。这些命令对应的厂商请求码定义在 osrusbfx2.h宏请求码含义USBFX2LK_READ_7SEGMENT_DISPLAY0xD4读取 7 段显示状态USBFX2LK_READ_SWITCHES0xD6读取拨码开关状态USBFX2LK_READ_BARGRAPH_DISPLAY0xD7读取条形图状态USBFX2LK_SET_BARGRAPH_DISPLAY0xD8设置条形图状态USBFX2LK_IS_HIGH_SPEED0xD9查询是否高速模式USBFX2LK_REENUMERATE0xDA触发设备重新枚举USBFX2LK_SET_7SEGMENT_DISPLAY0xDB设置 7 段显示状态中断端点特性README 明确说明实现于 interrupt.c发送一个 8 位值表示拨码开关组合状态在启动、从挂起suspend恢复以及开关组合变化时发送固件不做防抖de-bounce一次开关变化可能产生多个字节位序与面板标签相反例如0x80对应面板上标记为 1 的开关。批量端点特性配置为回环loopback模式设备把数据从 IN 端点搬移到 OUT 端点不修改数据内容、也不自行产生数据端点始终双缓冲double buffered最大包大小取决于速度全速Full Speed64 字节高速High Speed512 字节。Universal Windows Driver 合规性README 强调该示例构建的是Universal Windows DriverUWD驱动只使用 OneCoreUAP 中包含的 API 与 DDI因此可以面向 Windows 10/11 全系列设备含 IoT Core进行部署。这意味着驱动中不会引用桌面版 Windows 专有的内核 API所有 WDF 调用WdfUsbTargetDevice*、WdfIoQueue*等都属于可通用化接口。驱动与设备元数据还可以配合微软官方的Custom driver access示例工作——通过设备元数据将设备接口标记为 Restricted并声明自定义能力Custom Capability使 UWP 设备应用可通过Windows.Devices.Custom命名空间访问该接口。驱动源码巡览从 DriverEntry 到数据通路driver 目录职责总览README 的 Code tour 将驱动功能归纳如下每一项都能在源码中找到对应实现加载驱动并响应 PnP/Power 事件可安装、卸载、禁用、启用、挂起、恢复系统创建设备上下文通过WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, GetDeviceContext)osrusbfx2.h把上下文类型绑定到 WDFDEVICE 对象注册EvtPrepareHardware回调初始化 USB 设备将接口标记为 Restricted仅允许有特权的 UWP 设备应用访问创建默认并行队列接收设置条形图显示的 IOCTL从请求中取内存句柄并发送厂商命令到 USB 设备在默认队列上注册读/写事件取内存、格式化请求并发送到 USB 目标创建两个独立顺序队列分别直接分发读、写请求*kmdf_fx2 only启用 wait-wake 与选择性挂起*kmdf_fx2 only配置 USB 目标连续读取器异步读取中断端点上的拨码开关状态*kmdf_fx2 only支持额外的 IOCTL读写 7 段显示、拨码开关、重置与重新枚举设备*kmdf_fx2 only创建 ETW Provider记录两个事件日志事件及读/写开始-停止事件*kmdf_fx2 onlyWPP 跟踪。*kmdf_fx2 only标注的能力顺序队列、电源管理、连续读取器、额外 IOCTL、ETW Provider说明这是 osrusbfx2 示例区别于其他基础 USB 示例的进阶内容。设备上下文结构驱动状态的中枢驱动把所有设备实例相关信息集中存放在DEVICE_CONTEXT结构osrusbfx2.h中typedef struct _DEVICE_CONTEXT { WDFUSBDEVICE UsbDevice; // USB 设备句柄 WDFUSBINTERFACE UsbInterface; // 已选配置的接口句柄 WDFUSBPIPE BulkReadPipe; // 批量输入管道 WDFUSBPIPE BulkWritePipe; // 批量输出管道 WDFUSBPIPE InterruptPipe; // 中断管道 WDFWAITLOCK ResetDeviceWaitLock;// 串行化 ResetDevice 的等待锁 UCHAR CurrentSwitchState; // 连续读取器保存的最新开关状态 WDFQUEUE InterruptMsgQueue; // 手动分发的中断消息队列 ULONG UsbDeviceTraits; // 设备特征速度/自供电/远程唤醒 WDFMEMORY DeviceNameMemory; // 设备友好名内存事件日志用 PCWSTR DeviceName; WDFMEMORY LocationMemory; // 设备位置字符串内存 PCWSTR Location; } DEVICE_CONTEXT, *PDEVICE_CONTEXT;注意WDFWAITLOCK的使用README 与源码注释均指出除了用等待锁串行化ResetDevice()调用另一种更WDF 风格的做法是创建顺序队列并把 Reset IOCTL 转发过去Device.c。EvtDeviceAdd创建设备对象与四类 I/O 队列OsrFxEvtDeviceAddDevice.c是驱动的核心装配函数从源码结构看其执行序列如下用WDF_PNPPOWER_EVENT_CALLBACKS_INIT注册EvtDevicePrepareHardware、EvtDeviceD0Entry、EvtDeviceD0Exit、EvtDeviceSelfManagedIoFlushWdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered)设置缓冲型 I/OWdfDeviceCreate创建设备对象WdfDeviceSetPnpCapabilities设置SurpriseRemovalOK WdfTrue避免用户态弹窗创建默认并行队列WdfIoQueueDispatchParallel注册EvtIoDeviceControl处理 IOCTL创建读顺序队列WdfIoQueueDispatchSequential并注册EvtIoRead、EvtIoStop然后WdfDeviceConfigureRequestDispatching(device, queue, WdfRequestTypeRead)把 Read 请求直接分派到该队列创建写顺序队列并注册EvtIoWrite、EvtIoStop用WdfDeviceConfigureRequestDispatching(..., WdfRequestTypeWrite)分派 Write 请求创建手动分发队列WdfIoQueueDispatchManual作为InterruptMsgQueue专门停放等待中断发生的 IOCTL_GET_INTERRUPT_MESSAGE 请求并显式设置PowerManaged WdfFalse该队列不直接访问设备可在设备空闲时继续停放请求WdfDeviceCreateDeviceInterface注册GUID_DEVINTERFACE_OSRUSBFX2设备接口WdfWaitLockCreate创建 Reset 等待锁。关于 EvtIoStop源码注释解释了 SDVStatic Driver Verifier的__analysis_assume使用原因——该驱动不长期持有请求、也不转发给其他驱动因此框架等待所有驱动持有的请求完成后再进入低功耗/移除是正确的默认行为Device.c。设备接口 GUID 与 Restricted 属性设备接口 GUID 定义在 public.h// {573E8C73-0CB4-4471-A1BF-FAB26C31D384} DEFINE_GUID(GUID_DEVINTERFACE_OSRUSBFX2, 0x573e8c73, 0xcb4, 0x4471, 0xa1, 0xbf, 0xfa, 0xb2, 0x6c, 0x31, 0xd3, 0x84);在OsrFxEvtDeviceAdd中驱动通过g_pIoSetDeviceInterfacePropertyData运行时解析的IoSetDeviceInterfacePropertyData函数指针避免直接链接引入版本依赖执行两件关键事设置DEVPKEY_DeviceInterface_Restricted DEVPROP_TRUE把接口标记为受限使普通应用无法打开在 RS2NTDDI_WIN10_RS2条件下设置DEVPKEY_DeviceInterface_UnrestrictedAppCapabilities为字符串microsoft.hsaTestCustomCapability_q536wpkpf5cy2向设备接口实例添加自定义能力允许 Windows 商店设备应用通过Windows.Devices.Custom访问Device.c。这两处属性也可以改由 INF 声明README/源码注释提到 INF 中 OsrUsb Interface installation 节驱动内设置与 INF 声明二选一。EvtDevicePrepareHardware选择配置与管道初始化OsrFxEvtDevicePrepareHardwareDevice.c是 USB 驱动初始化的标准场所调用链为WdfUsbTargetDeviceCreateWithParameters使用USBD_CLIENT_CONTRACT_VERSION_602创建 USB 设备句柄仅在第一次 PrepareHardware 时创建资源重平衡重启时复用句柄重新选择接口WdfUsbTargetDeviceRetrieveInformation读取 USBD 版本、端口与设备能力高速/自供电/远程唤醒存入UsbDeviceTraitsSelectInterfacesDevice.cWDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE选择单接口配置WdfUsbTargetDeviceSelectConfig执行配置选择遍历NumberConfiguredPipes个管道用WdfUsbInterfaceGetConfiguredPipe取回管道句柄对每个管道调用WdfUsbTargetPipeSetNoMaximumPacketSizeCheck允许读取少于最大包大小的数据并按类型填入InterruptPipe/BulkReadPipe/BulkWritePipe三个管道必须全部找到否则返回STATUS_INVALID_DEVICE_STATE关键失败分支若配置选择失败且设备非高速即插在 USB 1.1 端口会写 ETW 事件EventWriteSelectConfigFailure——OSR FX2 板的 Interrupt 端点描述符不符合 USB 规范Windows 检测后会返回错误这正对应 README 中Failure to start the OSR device on a USB 1.1 controller事件若设备支持远程唤醒WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE调用OsrFxSetPowerPolicy设置电源策略OsrFxConfigContReaderForInterruptEndPoint配置中断管道连续读取器。电源策略选择性挂起与 wait-wakeOsrFxSetPowerPolicyDevice.c同时设置两类电源策略S0 空闲策略WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(idleSettings, IdleUsbSelectiveSuspend)IdleTimeout 1000010 秒调用WdfDeviceAssignS0IdleSettings——即启用 USB 选择性挂起设备空闲 10 秒后进入低功耗Sx 唤醒策略WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(wakeSettings)后调用WdfDeviceAssignSxWakeSettings——启用 wait-wake系统睡眠时设备可远程唤醒系统。配合电源管理EvtDeviceD0Entry中通过WdfIoTargetStart显式启动中断管道 I/O 目标连续读取器不会自动投递请求必须由驱动启动EvtDeviceD0Exit中用WdfIoTargetStop(..., WdfIoTargetCancelSentIo)停止并取消在途请求EvtDeviceSelfManagedIoFlush则在设备移除前冲刷中断消息队列中的挂起请求Device.c。连续读取器异步读取拨码开关interrupt.c 演示了 KMDF 的continuous reader连续读取器用法WDF_USB_CONTINUOUS_READER_CONFIG_INIT指定完成回调OsrFxEvtUsbInterruptPipeReadComplete、上下文和传输长度sizeof(UCHAR)每次读 1 字节对应 8 位开关状态WdfUsbTargetPipeConfigContinuousReader完成配置框架默认向目标端点排队 2 个请求WDF_USB_CONTINUOUS_READER_CONFIG_INIT允许配置最多 10 个见源码注释完成回调中保存CurrentSwitchState并调用OsrUsbIoctlGetInterruptMessage完成挂起的中断消息 IOCTL读取失败回调OsrFxEvtUsbInterruptReadersFailed清空状态并完成挂起请求返回TRUE表示重试读取。源码注释特别提醒OSR USB 设备在从低功耗恢复时也会产生一个中断消息因此若中断消息 IOCTL 在设备进入低功耗后才发出挂起的 IOCTL 可能在用户拨动开关前就被完成——若这是不希望的行为应在 D0Entry 维护状态变量区分上电引起的中断。IOCTL 接口设计public.h 完整定义了驱动暴露的 IOCTL 集全部基于CTL_CODE(FILE_DEVICE_OSRUSBFX2, IOCTL_INDEX n, ...)IOCTL_INDEX 0x800FILE_DEVICE_OSRUSBFX2 65500IOCTL方法访问作用IOCTL_OSRUSBFX2_GET_CONFIG_DESCRIPTOR0METHOD_BUFFEREDFILE_READ获取配置描述符IOCTL_OSRUSBFX2_RESET_DEVICE1METHOD_BUFFEREDFILE_WRITE复位设备端口IOCTL_OSRUSBFX2_REENUMERATE_DEVICE3METHOD_BUFFEREDFILE_WRITE触发设备重新枚举IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY4METHOD_BUFFEREDFILE_READ读取条形图状态BAR_GRAPH_STATEIOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY5METHOD_BUFFEREDFILE_WRITE设置条形图状态IOCTL_OSRUSBFX2_READ_SWITCHES6METHOD_BUFFEREDFILE_READ读取拨码开关状态SWITCH_STATEIOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY7METHOD_BUFFEREDFILE_READ读取 7 段显示UCHARIOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY8METHOD_BUFFEREDFILE_WRITE设置 7 段显示UCHARIOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE9METHOD_OUT_DIRECTFILE_READ挂起等待下一次中断消息SWITCH_STATEBAR_GRAPH_STATE与SWITCH_STATE都是位域联合体public.h每个位对应一个条形/开关可整体作为 UCHAR 使用BarsAsUChar/SwitchesAsUChar并以#pragma pack(1)紧凑打包。在 ioctl.c 中OsrFxEvtIoDeviceControl按 IOCTL 分发GET_CONFIG_DESCRIPTOR先以NULL缓冲区调用WdfUsbTargetDeviceRetrieveConfigDescriptor获取所需大小预期返回STATUS_BUFFER_TOO_SMALL再用WdfRequestRetrieveOutputBuffer取输出缓冲完成填充GET/SET_BAR_GRAPH_DISPLAY、GET/SET_7_SEGMENT通过WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR构造厂商控制传输方向BmRequestDeviceToHost/BmRequestHostToDevice目标BmRequestToDevice请求码对应上表经WdfUsbTargetDeviceSendControlTransferSynchronously同步发送控制传输超时由DEFAULT_CONTROL_TRANSFER_TIMEOUT 5 * -1 * WDF_TIMEOUT_TO_SEC5 秒决定osrusbfx2.hGET_SWITCH_STATE同步厂商控制传输读取开关GET_INTERRUPT_MESSAGEWdfRequestForwardToIoQueue转发到InterruptMsgQueue挂起等待连续读取器回调OsrUsbIoctlGetInterruptMessage时完成ioctl.cRESET_DEVICEResetDevice先WdfWaitLockAcquire加锁StopAllPipes停止三个管道 I/O 目标WdfUsbTargetDeviceResetPortSynchronously复位端口再StartAllPipes恢复、释放锁ioctl.cREENUMERATE_DEVICE构造USBFX2LK_REENUMERATE厂商请求同步发送成功后写 ETW 事件EventWriteDeviceReenumeratedioctl.c。批量读/写请求格式化与异步完成bulkrwr.c 实现读写通路OsrFxEvtIoReadbulkrwr.c校验Length TEST_BOARD_TRANSFER_BUFFER_SIZE64 KB定义于 osrusbfx2.h→WdfRequestRetrieveOutputMemory取内存 →WdfUsbTargetPipeFormatRequestForRead格式化请求该调用会校验管道类型、设置传输标志、创建 URB→ 设置完成例程 →WdfRequestSend异步发送到BulkReadPipe的 I/O 目标OsrFxEvtIoWrite对称流程目标为BulkWritePipe完成例程从PWDF_USB_REQUEST_COMPLETION_PARAMS提取实际传输字节数并WdfRequestCompleteWithInformation完成请求每个读/写开始、停止与失败都调用EventWriteReadStart/ReadStop/ReadFail、EventWriteWriteStart/WriteStop/WriteFail用于 ETW 计时分析OsrFxEvtIoStop处理挂起/清除语义挂起时WdfRequestStopAcknowledge清除时WdfRequestCancelSentRequestbulkrwr.c。ETW 事件与 WPP 跟踪驱动同时使用两套跟踪机制WPP 软件跟踪trace.h声明跟踪宏各 .c 文件通过#include *.tmh接入可用 traceview 等工具查看驱动内部调试输出ETW 事件日志清单文件 osrusbfx2.man 描述事件由 MC.EXE 生成fx2Events.h见 osrusbfx2.h。README 明确三个事件写入事件日志添加设备例程失败EventWriteFailAddDevice、OSR 设备在 USB 1.1 控制器上启动失败EventWriteSelectConfigFailure、重新枚举设备 IOCTL 被调用EventWriteDeviceReenumerated另加读/写开始-停止事件用于测量耗时。事件在源码中的触发位置均可查证OsrFxEvtDeviceAdd失败分支Device.c、SelectInterfaces失败分支Device.c、ReenumerateDeviceioctl.c。测试应用 osrusbfx2.exe命令行全集usb/kmdf_fx2/exe 目录下的控制台测试程序 osrusbfx2.exe 用CM_Get_Device_Interface_List*系列 API 枚举GUID_DEVINTERFACE_OSRUSBFX2接口并打开设备然后按命令行选项发起读、写或 IOCTL 请求源码见 testapp.c。README 给出的完整命令行选项如下选项含义-r [n]读取 n 字节-w [n]写入 n 字节-c [n]迭代次数默认 1-v显示详细读取数据-p操作条形图、拨码开关、7 段显示-a执行异步 I/O 操作-u转储 USB 配置与管道信息从 testapp.c 源码可补充若干默认值测试缓冲BUFFER_SIZE 1024字节NUM_ASYNCH_IO 100G_ReadLen/G_WriteLen默认 512迭代计数G_IterationCount默认 1。操作 7 段显示、拨码开关与条形图运行osrusbfx2.exe -p会进入交互菜单选项 1–11 分别对应设置/清除条形图、读写 7 段、读取开关、复位与重新枚举设备。README 给出的完整菜单如下1. Light bar 2. Clear bar 3. Light entire bar graph 4. Clear entire bar graph 5. Get bar graph state 6. Get switch state 7. Get switch interrupt message 8. Get 7 segment state 9. Set 7 segment state 10. Reset the device 11. Re-enumerate the device 12. Exit Selection:该菜单与 testapp.c 中的INPUT_FUNCTION枚举一一对应LIGHT_ONE_BAR 1…REENUMERATE_DEVICE 11。选项 7Get switch interrupt message比较特殊它发出IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE请求被驱动挂起到InterruptMsgQueue直到中断端点传来开关状态变化消息才完成返回。复位与重新枚举设备在-p菜单中选10复位设备走IOCTL_OSRUSBFX2_RESET_DEVICE→ 停止管道 →WdfUsbTargetDeviceResetPortSynchronously→ 重启管道选11重新枚举设备走IOCTL_OSRUSBFX2_REENUMERATE_DEVICE→ 发送USBFX2LK_REENUMERATE厂商命令让设备重新接入总线。批量端点读写典型命令与双缓冲原理README 给出以下可直接复制的命令osrusbfx2.exe -r 64从批量 IN 端点读 64 字节osrusbfx2.exe -w 64向批量 OUT 端点写 64 字节osrusbfx2.exe -r 64 -w 64 -c 100 -v先写 64 字节到 OUT 端点Pipe 1再从 IN 端点Pipe 2读 64 字节比较读写缓冲是否一致一致则重复 100 次osrusbfx2.exe -a以异步 I/O 方式无限循环读写设备。双缓冲的行为约束README 原文要点务必理解批量端点始终双缓冲按工作速度全速/高速缓冲区为 64/512 字节。读请求在缓冲区为空时不会完成写请求在缓冲区满时不会完成。做同步读时务必确保端点缓冲中有数据——例如对运行在全速模式的设备发送 512 字节写请求由于端点双缓冲总容量为 256 字节前 256 字节填满缓冲后写请求会在 USB 栈中等待缓冲被清空此时再开一个应用实例读 512 字节两个请求才会都成功完成。换句话说测试中先写后读并用 -c 循环比对正是利用回环设备把写入的数据原样搬回从而验证批量通路完整性的标准手法。显示描述符-u 输出解读运行osrusbfx2.exe -u会转储配置、接口与端点描述符。设备运行在高速模式时的输出README 原样 USB_CONFIGURATION_DESCRIPTOR bLength 0x9, decimal 9 bDescriptorType 0x2 ( USB_CONFIGURATION_DESCRIPTOR_TYPE ) wTotalLength 0x27, decimal 39 bNumInterfaces 0x1, decimal 1 bConfigurationValue 0x1, decimal 1 iConfiguration 0x4, decimal 4 bmAttributes 0xa0 ( USB_CONFIG_BUS_POWERED ) MaxPower 0x32, decimal 50 ----------------------------- USB_INTERFACE_DESCRIPTOR #0 bLength 0x9 bDescriptorType 0x4 ( USB_INTERFACE_DESCRIPTOR_TYPE ) bInterfaceNumber 0x0 bAlternateSetting 0x0 bNumEndpoints 0x3 bInterfaceClass 0xff bInterfaceSubClass 0x0 bInterfaceProtocol 0x0 bInterface 0x0 ------------------------------ USB_ENDPOINT_DESCRIPTOR for Pipe00 bLength 0x7 bDescriptorType 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE ) bEndpointAddress 0x81 ( INPUT ) bmAttributes 0x3 ( USB_ENDPOINT_TYPE_INTERRUPT ) wMaxPacketSize 0x49, decimal 73 bInterval 0x1, decimal 1 ------------------------------ USB_ENDPOINT_DESCRIPTOR for Pipe01 bLength 0x7 bDescriptorType 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE ) bEndpointAddress 0x6 ( OUTPUT ) bmAttributes 0x2 ( USB_ENDPOINT_TYPE_BULK ) wMaxPacketSize 0x200, decimal 512 bInterval 0x0, decimal 0 ------------------------------ USB_ENDPOINT_DESCRIPTOR for Pipe02 bLength 0x7 bDescriptorType 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE ) bEndpointAddress 0x88 ( INPUT ) bmAttributes 0x2 ( USB_ENDPOINT_TYPE_BULK ) wMaxPacketSize 0x200, decimal 512 bInterval 0x0, decimal 0设备运行在全速模式时的输出仅两处不同README 原样 USB_CONFIGURATION_DESCRIPTOR bLength 0x9, decimal 9 bDescriptorType 0x2 ( USB_CONFIGURATION_DESCRIPTOR_TYPE ) wTotalLength 0x27, decimal 39 bNumInterfaces 0x1, decimal 1 bConfigurationValue 0x1, decimal 1 iConfiguration 0x3, decimal 3 bmAttributes 0xa0 ( USB_CONFIG_BUS_POWERED ) MaxPower 0x32, decimal 50 ----------------------------- USB_INTERFACE_DESCRIPTOR #0 bLength 0x9 bDescriptorType 0x4 ( USB_INTERFACE_DESCRIPTOR_TYPE ) bInterfaceNumber 0x0 bAlternateSetting 0x0 bNumEndpoints 0x3 bInterfaceClass 0xff bInterfaceSubClass 0x0 bInterfaceProtocol 0x0 bInterface 0x0 ------------------------------ USB_ENDPOINT_DESCRIPTOR for Pipe00 bLength 0x7 bDescriptorType 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE ) bEndpointAddress 0x81 ( INPUT ) bmAttributes 0x3 ( USB_ENDPOINT_TYPE_INTERRUPT ) wMaxPacketSize 0x49, decimal 73 bInterval 0x1, decimal 1 ------------------------------ USB_ENDPOINT_DESCRIPTOR for Pipe01 bLength 0x7 bDescriptorType 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE ) bEndpointAddress 0x6 ( OUTPUT ) bmAttributes 0x2 ( USB_ENDPOINT_TYPE_BULK ) wMaxPacketSize 0x40, decimal 64 bInterval 0x0, decimal 0 ------------------------------ USB_ENDPOINT_DESCRIPTOR for Pipe02 bLength 0x7 bDescriptorType 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE ) bEndpointAddress 0x88 ( INPUT ) bmAttributes 0x2 ( USB_ENDPOINT_TYPE_BULK ) wMaxPacketSize 0x40, decimal 64 bInterval 0x0, decimal 0对比两组输出可验证 README 中的设备规格高速模式批量端点wMaxPacketSize 0x200512 字节全速模式为0x4064 字节中断端点 Pipe00 在两种模式下都是0x4973 字节、bInterval 1接口包含 3 个端点、厂商类bInterfaceClass 0xff、总线供电bmAttributes 0xa0。注意高速中断端点的wMaxPacketSize73 字节并不完全符合 USB 规范——这正是 README 提到的OSR FX2 板在 USB 1.1 端口上启动失败事件的根源也解释了SelectInterfaces中的特殊错误分支。设备元数据部署与驱动测试usb/kmdf_fx2/deviceMetadata 目录包含设备元数据包B4D697F5-1C56-4807-ACCD-B28C09D37FF0.devicemetadata-ms。README 明确指出安装设备前必须先把设备元数据复制到系统。元数据包的作用是建立设备与受限设备接口 自定义能力的关联从而允许 Custom driver access 示例或你基于Windows.Devices.Custom编写的 UWP 应用访问该接口有关如何更新与部署设备元数据可参考 Custom driver access 示例中的说明。驱动测试有两种途径Custom driver access 示例作为正式的端到端测试方法验证受限接口的授权访问链路osrusbfx2.exe 测试应用本文上一节详述的命令行工具直接枚举驱动注册的接口并发起读写/IOCTL。统一跟踪Unified Tracing查看驱动事件驱动使用Event Tracing for WindowsETW记录事件。要查看事件必须先安装 Provider 清单。在提升权限的命令提示符中运行wevtutil im osrusbfx2.man注册清单后系统即可获得事件解码所需路径信息。OSR 事件日志位于事件查看器的Event Viewer\Applications and Services Logs\OSRUSBFx2\Operational channel通道通过 osrusbfx2.exe 触发一次设备重新枚举就会向该日志写入一个事件。使用系统自带工具 logman / tracerpt启动跟踪logman start sample -o osrusbfx2.etl -ets -p OSRUSBFX2产生活动运行测试应用例如osrusbfx2.exe -a停止跟踪Logman stop sample查看跟踪文件tracerpt -of csv OSRUSBFX2.etl-p OSRUSBFX2指定 Provider 名与清单中的 Provider 名称对应-o指定输出 ETL 文件-ets表示直接使用事件跟踪会话。使用 XperfWindows Performance Toolkit启动跟踪xperf -start sample -f osrusbfx2.etl -on OSRUSBFX2产生活动运行osrusbfx2.exe -a停止跟踪xperf -stop sample查看跟踪文件xperfview OSRUSBFX2.etl借助驱动写入的EventWriteReadStart/ReadStop、EventWriteWriteStart/WriteStop事件可以精确测量每次批量读/写的时间开销——这是 README 推荐的性能观测方法。工程构建与安装要点用 Visual Studio 打开 kmdf_fx2.sln需安装 WDK驱动工程 osrusbfx2.vcxproj 会生成驱动二进制测试工程 osrusbfx2.vcxproj 生成 osrusbfx2.exe驱动 INF 模板为 osrusbfx2.inx构建时由 Stampinf 处理生成 .inf仓库还提供 exe/test.cmd 辅助测试脚本具体用法可查看脚本内容安装驱动前先部署 deviceMetadata 元数据包否则受限接口无法被授权应用访问由于接口被标记为 Restricted普通控制台程序直接打开设备会失败osrusbfx2.exe 之所以可用是因为示例的受限设置面向 Custom driver access 链路设计——若要在本地直接跑通测试应用需结合实际部署的元数据与能力声明情况配置环境。小结一份可以照着抄的 KMDF USB 驱动范本osrusbfx2 示例的工程价值在于它把 KMDF USB 驱动的所有关键知识点压缩在一个可编译、可测试的小工程里设备初始化EvtDevicePrepareHardwareSelectInterfaces的标准姿势I/O 模型默认并行队列IOCTL 两个顺序队列读/写 手动队列挂起等待中断的分工异步传输WdfUsbTargetPipeFormatRequestForRead/WriteWdfRequestSend 完成例程中断数据continuous reader 免去驱动自行管理重读的繁琐电源管理选择性挂起10 秒空闲超时 wait-wake D0Entry/D0Exit 启停管道控制传输厂商请求封装为WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR同步发送可观测性ETW 事件日志.man 清单 WPP 跟踪双轨并行用户态配合附送完整命令行测试工具与设备元数据包开箱即可验证。无论你是要写自己的第一个 USB 函数驱动还是想研究 KMDF 批量/中断传输与电源管理的成熟写法都可以把 usb/kmdf_fx2 作为起点先按 README 的命令在 FX2 学习板上跑通回环读写再对照本文的源码定位表逐文件深入最后用wevtutil imlogman/xperf观察驱动行为即可完成从能跑到看懂再到能改的完整闭环。赞分享示例工程【免费下载链接】Windows-driver-samplesThis repo contains driver samples prepared for use with Microsoft Visual Studio and the Windows Driver Kit (WDK). It contains both Universal Windows Driver and desktop-only driver samples.项目地址https://gitcode.com/gh_mirrors/wi/Windows-driver-samples点击查看免费下载相关推荐Windows-driver-samples USB驱动UMDF2与KMDF USB设备开发对比Windows driver samples USB驱动UMDF2与KMDF USB设备开发对比 你是否在开发USB设备驱动时纠结选择用户模式还是内核模式本示例工程使用 OSR FX2 学习套件掌握 DCHU 通用驱动设计Windows-driver-samples 中的三套 INF 打包方案详解使用 OSR FX2 学习套件掌握 DCHU 通用驱动设计Windows driver samples 中的三套 INF 打包方案详解 导读 本篇文章以 ge示例工程Windows 驱动示例Toaster 系列 KMDF 驱动开发实战部署、构建与源码解析Windows 驱动示例Toaster 系列 KMDF 驱动开发实战部署、构建与源码解析 本篇文章基于 Windows driver samples 仓库示例工程上一篇Citra输入设置手柄与键盘配置下一篇Spring Data Vavr支持函数式编程集合类型应用指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考