WinUSB 是 Windows 随附的 USB 设备的通用驱动程序。WinUSB 包括:
- 内核模式驱动程序 (Winusb.sys);
- 公开 winusb.h 中所述的 WinUSB 函数的用户模式动态链接库 (Winusb.dll)。 借助这些函数,你可以使用用户模式软件管理 USB 设备;
默认情况下,Winusb.sys 作为上层筛选器驱动程序安装在设备的内核模式堆栈中。 应用与设备的 UMDF 函数驱动程序通信,以发出读取、写入或设备 I/O 控制请求。 在此配置中,Winusb.sys 充当设备堆栈的即插即用和电源所有者。还可以安装 Winusb.sys 作为 USB 设备的功能驱动程序。
Windows 7 在基于 x86、基于 x64 和基于 Itanium 的系统上支持 WinUSB。 较新版本的 Windows 在基于 x86 和基于 x64 的系统上支持 WinUSB。WinUSB 支持在 Windows 8 中开始的常时等量传输。
WinUSB 体系结构和模块
WinUSB 由两个主要组件组成:
- Winusb.sys是一种内核模式驱动程序,可以作为筛选器或函数驱动程序安装,位于 USB 设备的内核模式设备堆栈中的协议驱动程序之上;
- Winusb.dll是公开 WinUSB 函数的用户模式 DLL。 当Winusb.sys安装为设备的函数驱动程序时,应用程序可以使用这些函数与它进行通信;
对于不需要自定义函数驱动程序的设备,Winusb.sys可以作为函数驱动程序安装在设备的内核模式堆栈中。 然后用户模式进程可以使用一组设备 I/O 控制请求或通过调用 WinUSB 函数来与Winusb.sys通信。
下图显示了包含多个 Winusb.sys 实例的 USB 驱动程序堆栈。
上图显示了一个实现三个设备接口类的示例 WinUSB 配置,每个类都有一个已注册的设备接口:
- Winusb.sys实例 1 注册设备接口 A,该接口支持用户模式驱动程序 (Usboem.dll) ‘’
- Winusb.sys的实例 2 注册了设备接口 B,该接口支持使用系统服务 (SVCHOST) 与Winusb.dll通信的扫描程序 (Usbscan.exe) 的用户模式驱动程序。
- Winusb.sys 实例 3 注册设备接口 C,它支持固件更新实用工具 (Usbfw.exe) ‘’
Winusb.sys只加载了一个实例。 PDO 可以表示非复合设备 (例如关系图) 中的实例 1,也可以表示复合设备上的接口或接口集合 (例如实例 2 和 3) 。 对于 (WMCDC) 设备的 USB 无线移动通信设备类,PDO 甚至可以表示多个接口集合。
任何用户模式应用程序都可以通过加载 WinUSB 动态链接库 (Winusb.dll) 并调用此模块公开的 WinUSB 函数来与 USB 堆栈通信。
面向开发人员的 WinUSB (Winusb.sys) 安装
对于某些通用串行总线 (USB) 设备(例如只能通过单个应用程序访问的设备),你可以在设备的内核模式堆栈中安装 WinUSB (Winusb.sys),将其作为 USB 设备的功能驱动程序,而不是实现驱动程序。
不使用 INF 文件自动安装 WinUSB OEM 或独立硬件供应商 (IHV) 可以构建设备,以便在 Windows 8 及更高版本的操作系统上自动安装 Winusb.sys。 此类设备称为 WinUSB 设备,无需编写引用内置 Winusb.inf 的自定义 INF 文件。
连接 WinUSB 设备时,系统自动读取设备信息并加载 Winusb.sys。
通过指定系统提供的设备类别来安装 WinUSB
连接设备时,你可能会注意到 Windows 自动加载 Winusb.sys,如果 IHV 已将设备定义为 WinUSB 设备。 否则,请按照以下说明加载驱动程序:
- 将设备插入主机系统;
- 打开设备管理器并找到设备;
- 选择并按住(或右键单击)设备,然后从上下文菜单中选择“更新驱动程序软件…”;
- 在向导中,选择“浏览我的计算机以查找驱动程序软件”;
- 选择“从计算机的设备驱动程序列表中选择”;
- 从设备类别的列表中,选择“通用串行总线设备”;
- 向导显示“WinUsb 设备”。 选择此项以加载驱动程序;
如果“通用串行总线设备”没有出现在设备类别列表中,则需要使用自定义 INF 安装驱动程序。 前面的过程并没有为应用(UWP 应用或 Windows 桌面应用)添加访问设备的设备接口 GUID。 必须按照此过程手动添加 GUID。
- 按照上述过程中的说明加载驱动程序;
- 使用 guidgen.exe 等工具生成设备的设备接口 GUID;
- 在此项下找到设备的注册表项:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\<VID_vvvv&PID_pppp>;
- 在“设备参数”项下,添加名为“DeviceInterfaceGUID”的字符串注册表项或名为“DeviceInterfaceGUIDs”的多字符串项。 将值设置为你在步骤 2 中生成的 GUID;
- 断开设备与系统的连接,然后将其重新连接到同一个物理端口。 注意:如果更改物理端口,则必须重复步骤 1 到步骤 4;
编写用于 WinUSB 安装的自定义 INF
驱动程序包中有一个 .inf 文件,该文件可将 Winusb.sys 安装为 USB 设备的功能驱动程序。
以下示例 .inf 文件显示了对大多数 USB 设备的 WinUSB 安装,并进行了一些修改,例如将节名称中的 USB_Install 更改为适当的 DDInstall 值。 还应根据需要更改版本、制造商和型号部分。 例如,提供适当的制造商的名称、签名的目录文件的名称、正确的设备类别以及设备的供应商标识符 (VID) 和产品标识符 (PID)。
另请注意,安装程序类设置为“USBDevice”。 对于不属于其他类且不是 USB 主机控制器或集线器的设备,供应商可以使用“USBDevice”安装程序类。
如果要将 WinUSB 安装为 USB 复合设备中某个功能的功能驱动程序,则必须在 INF 中提供与该功能关联的硬件 ID。 可以从“设备管理器”中的 devnode 的属性获取该功能的硬件 ID。 硬件 ID 字符串格式为“USB\VID_vvvv&PID_pppp”。
以下 INF 将 WinUSB 作为 OSR USB FX2 板的功能驱动程序安装在基于 x64 的系统上。
从 Windows 10 1709 版开始,Windows 驱动程序工具包提供 InfVerif.exe,你可以使用它来测试驱动程序 INF 文件,以确保没有语法问题并且 INF 文件是通用的。
;
;
; Installs WinUsb
;
[Version]
Signature = "$Windows NT$"
Class = USBDevice
ClassGUID = {88BAE032-5A81-49f0-BC3D-A4FF138216D6}
Provider = %ManufacturerName%
CatalogFile = WinUSBInstallation.cat
DriverVer = 09/04/2012,13.54.20.543
PnpLockdown = 1
; ========== Manufacturer/Models sections ===========
[Manufacturer]
%ManufacturerName% = Standard,NTamd64
[Standard.NTamd64]
%DeviceName% =USB_Install, USB\VID_0547&PID_1002
; ========== Class definition (for Windows 8 and earlier versions)===========
[ClassInstall32]
AddReg = ClassInstall_AddReg
[ClassInstall_AddReg]
HKR,,,,%ClassName%
HKR,,NoInstallClass,,1
HKR,,IconPath,%REG_MULTI_SZ%,"%systemroot%\system32\setupapi.dll,-20"
HKR,,LowerLogoVersion,,5.2
; =================== Installation ===================
[USB_Install]
Include = winusb.inf
Needs = WINUSB.NT
[USB_Install.Services]
Include =winusb.inf
Needs = WINUSB.NT.Services
[USB_Install.HW]
AddReg=Dev_AddReg
[USB_Install.Wdf]
KmdfService=WINUSB, WinUsb_Install
[WinUsb_Install]
KmdfLibraryVersion=1.11
[Dev_AddReg]
HKR,,DeviceInterfaceGUIDs,0x10000,"{9f543223-cede-4fa3-b376-a25ce9a30e74}"
; [DestinationDirs]
; If your INF needs to copy files, you must not use the DefaultDestDir directive here.
; You must explicitly reference all file-list-section names in this section.
; =================== Strings ===================
[Strings]
ManufacturerName=""
ClassName="Universal Serial Bus devices"
DeviceName="Fx2 Learning Kit Device"
REG_MULTI_SZ = 0x00010000
仅在设备 INF 文件中包含 ClassInstall32 部分,以安装新的自定义设备安装程序类。 已安装类中的设备的 INF 文件(无论系统提供的是设备安装程序类还是自定义类)都不能包含 ClassInstall32 部分。
除特定于设备的值以及以下列表中所述的几个问题之外,还可以使用这些部分和指令来安装适用于任何 USB 设备的 WinUSB。 这些列表项描述了上述 .inf 文件中的 Includes 和 Directives。
- USB_Install:安装 WinUSB 需要 USB_Install 部分中的 Include 和 Needs 指令。 不应修改这些指令;
- USB_Install.Services:USB_Install.Services 部分中的 Include 指令包含系统提供的 WinUSB .inf (Winusb.inf)。 如果目标系统上尚未安装此 .inf 文件,则该文件由 WinUSB 辅助安装程序安装。 Needs 指令指定 Winusb.inf 中的部分,其中包含将 Winusb.sys 安装为设备的功能驱动程序所需的信息。 不应修改这些指令;
- USB_Install.HW:此部分是 .inf 文件中的键。 它指定设备的设备接口全局唯一标识符 (GUID)。 AddReg 指令在标准注册表值中设置指定的接口 GUID。 当 Winusb.sys 作为设备的功能驱动程序加载时,它将读取注册表值 DeviceInterfaceGUIDs 项,并使用指定的 GUID 来表示设备接口。 在此示例中,应将 GUID 替换为专门为设备创建的 GUID。 如果设备的协议发生更改,请创建新的设备接口 GUID;
注意 用户模式软件必须调用 SetupDiGetClassDevs 才能枚举与在 DeviceInterfaceGUIDs 项下指定的某个设备接口类关联的已注册设备接口。 SetupDiGetClassDevs 返回了设备的设备句柄,然后用户模式软件必须将设备句柄传递给 WinUsb_Initialize 例程,以获取设备接口的 WinUSB 句柄。
以下 INF 将 WinUSB 作为 OSR USB FX2 板的功能驱动程序安装在基于 x64 的系统上。 示例显示了带有 WDF 辅助安装程序的 INF。
- USB_Install.CoInstallers:此部分包括引用的 AddReg 和 CopyFiles 部分,其中包含安装 WinUSB 和 KMDF 辅助安装程序并将其与设备关联的数据和说明。 大多数 USB 设备无需修改即可使用这些部分和指令。
- Windows 基于 x86 和基于 x64 的版本具有单独的辅助安装程序。
每个辅助安装程序都有免费版和经过检查的版本。 使用免费版本可在 Windows 免费版本(包括所有零售版)上安装 WinUSB。 使用经过检查的版本(带有“chk”后缀)在经过检查的 Windows 版本上安装 WinUSB。
每次 Winusb.sys 加载时,它都会注册一个设备接口,该设备接口具有在 DeviceInterfaceGUIDs 项下的注册表中指定的设备接口类。
HKR,,DeviceInterfaceGUIDs, 0x10000,"{D696BFEB-1734-417d-8A04-86D01071C512}"
如果使用 Windows XP 或 Windows Server 2003 的可再分发 WinUSB 包,请确保不要在卸载软件包中卸载 WinUSB。 其他 USB 设备可能正在使用 WinUSB,因此其二进制文件必须保留在共享文件夹中。