如何使用 WinUSB 与 USB 设备 (USBDevice) 通信

it2022-05-13  69

选择 USB 设备的驱动程序模型

https://github.com/libusbx/libusbx/wiki/Windows-Backend

WinUSB does not support Windows 2003 ( 32bit/64bit )WinUSB does not support Windows XP 64 bit ( not officially support on 64bit Windows XP)WinUSB cannot be used to send an actual reset command to an USB device. This is a limitation of WinUSB.WinUSB does not support isochronous transfers.WinUSB cannot be used to set a device configuration that is different from the first one. This is a limitation of KMDF USB I/O Target.WinUSB does not support multiple concurrent applicationsWinUSB does not support USB 1.0 or USB 1.1If the USB Device Descriptor’s bcdUSB field is equal to 0x0100 or 0x0110, the hub driver will skip the query for the MS OS Descriptor and move to the “Serial Number String Descriptor Query” state

https://github.com/pbatard/libwdi/wiki/WCID-Devices

What is WCID? A WCID device, where WCID stands for "Windows Compatible ID", is an USB device that provides extra information to a Windows system, in order to facilitate automated driver installation and, in some circumstances, allow immediate access. WCID allows a device to be used by a Windows application almost as soon as it is plugged in, as opposed to the the usual scenario where an USB device that is neither HID nor Mass Storage requires end-users to perform a manual driver installation. As such, WCID can bring the 'Plug-and-Play' functionality of HID and Mass Storage to any USB device (that sports a WCID aware firmware). WCID is an extension of the WinUSB Device functionality, put forward by Microsoft during the Windows 8 Developer Preview. However, it uses capabilities (Microsoft OS Descriptors, or MODs) that have been part of Windows since Windows XP SP2. As of May 2012, an automated WinUSB WCID driver is provided on all platforms starting with Windows Vista. On Windows 8, it is native to the system (i.e. there's no need to fetch the driver online) whereas, for Vista and Windows 7, it will be obtained from the internet, through Windows Update. Microsoft Winusb Device Driver 1.0.0.0http://download.windowsupdate.com/msdownload/update/driver/drvs/2012/05/20484220_5f2718fc6d44c5ae61d4275d679bbf1ededf58e5.cab http://de.drivers.exdat.com/download/17651/20484220_5f2718fc6d44c5ae61d4275d679bbf1ededf58e5.cab The package provides the installation files for Microsoft WinUSB Device Driver version 1.0.0.0. In order to manually update your driver, follow the steps below (the next steps): 1. Go to Device Manager (right click on My Computer, choose Manage and then find Device Manager in the left panel) 2. Right click on the hardware device you wish to update and choose Update Driver Software 3. Choose to select the location of the new driver manually and browse to the folder where you downloaded the driver

 

 

制造 USB 设备的独立硬件供应商 (IHV) 必须经常为应用程序提供访问设备功能的途径。在过去,这意味着使用 Windows 驱动程序模型 (WDM) 为设备实现一个功能驱动程序,并将该驱动程序安装在设备栈中系统提供的协议驱动程序之上。Windows 驱动程序基础 (WDF) 现在是 USB 驱动程序的首选模型。

它为 IHV 提供 3 个选项来提供访问 USB 设备的途径:

使用 WDF 用户模式驱动程序框架 (UMDF) 实现用户模式驱动程序。

使用 WDF 内核模式驱动程序框架 (KMDF) 实现内核模式驱动程序。

WinUsb.sys 作为设备的功能驱动程序安装,并提供一个使用 WinUSB API <WinUsb.dll> 访问设备的应用程序。WinUSB 在 Windows XP 上不支持 WinUSB 选择性暂停

Windows 8 USB 驱动程序堆栈体系结构

该图分别显示了 USB 2.0 和 USB 3.0 的 USB 驱动程序堆栈。当设备附加到 xHCI 控制器时,Windows 会加载 USB 3.0 驱动程序堆栈。USB 3.0 堆栈是 Windows 8 中的新功能。

当设备连接到 eHCI、oHCI 或 uHCI 控制器时,Windows 会加载 USB 2.0 驱动程序堆栈。USB 2.0 驱动程序堆栈随 Windows XP Service Pack 1 (SP1) 及更高版本的 Windows 操作系统一起提供。

Windows 8 USB 驱动程序堆栈

对于自定义 USB 设备应该使用哪个设备安装程序类?

独立硬件供应商 IHV 必须使用与 USB 设备类型(而不是总线类型)相关的安装程序类。 如果要开发一个 Microsoft 还没有为其提供现有类 GUID 的设备类型,可以定义一个新的设备安装程序类

Windows 8 中定义了一个名为 USBDevice ( ClassGuid = {88BAE032-5A81-49f0-BC3D-A4FF138216D6} ) 的新安装程序类。 如果您正在开发一个设备类型,请将您的设备与 <USBDevice> 而不是 <安装程序类 USB> 关联。 USBDevice 类支持 Windows Vista 以及更高版本的操作系统。

安装程序类 USB ( ClassGuid = {36fc9e60-c465-11cf-8056-444553540000} ) 仅为 USB 主控制器和 USB 集线器保留,并且不能用于其他设备类别。 不正确地使用此安装程序类可能导致设备驱动程序无法通过 Windows 徽标测试。 

WinUSB 架构和模块

Windows USB (WinUSB) 是 Microsoft 提供的 USB 设备的通用驱动程序。

WinUSB 体系结构由内核模式驱动程序 (Winusb.sys) 和用户模式动态链接库 (Winusb.dll) 组成。

Winusb.sys 是一种内核模式驱动程序,可在 USB 设备的内核模式设备堆栈的协议驱动程序之上作为筛选器驱动程序或功能驱动程序进行安装。Winusb.dll 是一种公开 WinUSB 功能的用户模式 DLL。当 Winusb.sys 作为设备的功能驱动程序安装后,应用程序可以使用这些功能与其进行通信。

对于不要求自定义功能驱动程序的设备,Winusb.sys 可以在该设备的内核模式堆栈中作为功能驱动程序进行安装。随后,用户模式流程通过使用一组设备 I/O 控制请求调用 WinUSB 功能 ( WinUsb_Xxx 函数 )来与 Winusb.sys 进行通信。

 

上图显示了实施三个设备接口类的示例 WinUSB 配置,其中每个类都有单个注册设备接口:

Winusb.sys 的实例 1 注册设备接口 A,设备接口 A 支持用户模式驱动程序 (Usboem.dll)。Winusb.sys 的实例 2 注册设备接口 B,设备接口 B 支持通过使用系统服务 (SVCHOST) 与 Winusb.dll 进行通信的扫描仪的用户模式驱动程序 (Usbscan.exe)。Winusb.sys 的实例 3 注册设备接口 C,设备接口 C 支持固件更新实用程序 (Usbfw.exe)。

仅加载了 Winusb.sys 的一个实例。PDO 可以表示非复合设备(例如,上图中的示例 1),也可以表示复合设备上的接口或接口集合(例如,实例 2 和 3)。对于 USB 无线移动通信设备类 (WMCDC) 设备,PDO 甚至可以表示多个接口集合。所有用户模式应用程序都可以与 USB 堆栈进行通信,方法是加载 WinUSB 动态链接库 (Winusb.dll) 并调用由此模块公开的 WinUSB 功能。  

WinUSB 驱动程序 (Winusb.sys)

 

WinUSB 动态链接库 (Winusb.dll)

This section describes the following functions, exposed by Winusb.dll, which user-mode client drivers and applications can use to communicate with USB devices. WinUSB functions require Windows XP or later. You can use these functions in your C/C++ application to communicate with your USB device. Microsoft does not provide a managed API for WinUSB.

Routine Description WinUsb_Initialize Creates a WinUSB handle for the device specified by a file handle. WinUsb_Free Releases all of the resources that WinUsb_Initialize allocated. WinUsb_ControlTransfer Transmits control data over a default control endpoint. WinUsb_ReadPipe Reads data from the specified pipe. WinUsb_WritePipe Writes data to a pipe. WinUsb_GetOverlappedResult Retrieves the results of an overlapped operation on the specified file. WinUsb_ResetPipe Resets the data toggle and clears the stall condition on a pipe. WinUsb_AbortPipe Aborts all of the pending transfers for a pipe. WinUsb_FlushPipe Discards any data that is cached in a pipe. WinUsb_QueryPipe Retrieves information about a pipe that is associated with an interface. WinUsb_QueryDeviceInformation Retrieves information about the physical device that is associated with a WinUSB handle. WinUsb_GetDescriptor Gets the requested descriptor. WinUsb_GetAssociatedInterface Retrieves a handle for an associated interface. WinUsb_QueryInterfaceSettings Retrieves the interface descriptor for the specified alternate interface settings for a particular interface handle. WinUsb_GetCurrentAlternateSetting Gets the current alternate interface setting for an interface. WinUsb_SetCurrentAlternateSetting Sets the alternate setting of an interface. WinUsb_GetPowerPolicy Gets the power policy for a device. WinUsb_SetPowerPolicy Sets the power policy for a device. WinUsb_GetPipePolicy Gets the policy for a specific pipe (endpoint). WinUsb_SetPipePolicy Sets the policy for a specific pipe (endpoint). View Code /*++ Copyright (c) 2002 Microsoft Corporation Module Name: wusb.h Abstract: Public interface to winusb.dll Environment: Kernel Mode Only Notes: THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. Copyright (c) 2001 Microsoft Corporation. All Rights Reserved. Revision History: 11/19/2002 : created Authors: --*/ #ifndef __WUSB_H__ #define __WUSB_H__ #ifdef __cplusplus extern "C" { #endif #include <windows.h> #include <winusbio.h> typedef PVOID WINUSB_INTERFACE_HANDLE, *PWINUSB_INTERFACE_HANDLE; #pragma pack(1) typedef struct _WINUSB_SETUP_PACKET { UCHAR RequestType; UCHAR Request; USHORT Value; USHORT Index; USHORT Length; } WINUSB_SETUP_PACKET, *PWINUSB_SETUP_PACKET; #pragma pack() BOOL __stdcall WinUsb_Initialize( IN HANDLE DeviceHandle, OUT PWINUSB_INTERFACE_HANDLE InterfaceHandle ); BOOL __stdcall WinUsb_Free( IN WINUSB_INTERFACE_HANDLE InterfaceHandle ); BOOL __stdcall WinUsb_GetAssociatedInterface( IN WINUSB_INTERFACE_HANDLE InterfaceHandle, IN UCHAR AssociatedInterfaceIndex, OUT PWINUSB_INTERFACE_HANDLE AssociatedInterfaceHandle ); BOOL __stdcall WinUsb_GetDescriptor( IN WINUSB_INTERFACE_HANDLE InterfaceHandle, IN UCHAR DescriptorType, IN UCHAR Index, IN USHORT LanguageID, OUT PUCHAR Buffer, IN ULONG BufferLength, OUT PULONG LengthTransferred ); BOOL __stdcall WinUsb_QueryInterfaceSettings( IN WINUSB_INTERFACE_HANDLE InterfaceHandle, IN UCHAR AlternateInterfaceNumber, OUT PUSB_INTERFACE_DESCRIPTOR UsbAltInterfaceDescriptor ); BOOL __stdcall WinUsb_QueryDeviceInformation( IN WINUSB_INTERFACE_HANDLE InterfaceHandle, IN ULONG InformationType, IN OUT PULONG BufferLength, OUT PVOID Buffer ); BOOL __stdcall WinUsb_SetCurrentAlternateSetting( IN WINUSB_INTERFACE_HANDLE InterfaceHandle, IN UCHAR SettingNumber ); BOOL __stdcall WinUsb_GetCurrentAlternateSetting( IN WINUSB_INTERFACE_HANDLE InterfaceHandle, OUT PUCHAR SettingNumber ); BOOL __stdcall WinUsb_QueryPipe( IN WINUSB_INTERFACE_HANDLE InterfaceHandle, IN UCHAR AlternateInterfaceNumber, IN UCHAR PipeIndex, OUT PWINUSB_PIPE_INFORMATION PipeInformation ); BOOL __stdcall WinUsb_SetPipePolicy( IN WINUSB_INTERFACE_HANDLE InterfaceHandle, IN UCHAR PipeID, IN ULONG PolicyType, IN ULONG ValueLength, IN PVOID Value ); BOOL __stdcall WinUsb_GetPipePolicy( IN WINUSB_INTERFACE_HANDLE InterfaceHandle, IN UCHAR PipeID, IN ULONG PolicyType, IN OUT PULONG ValueLength, OUT PVOID Value ); BOOL __stdcall WinUsb_ReadPipe( IN WINUSB_INTERFACE_HANDLE InterfaceHandle, IN UCHAR PipeID, IN PUCHAR Buffer, IN ULONG BufferLength, OUT PULONG LengthTransferred, IN LPOVERLAPPED Overlapped ); BOOL __stdcall WinUsb_WritePipe( IN WINUSB_INTERFACE_HANDLE InterfaceHandle, IN UCHAR PipeID, IN PUCHAR Buffer, IN ULONG BufferLength, OUT PULONG LengthTransferred, IN LPOVERLAPPED Overlapped ); BOOL __stdcall WinUsb_ControlTransfer( IN WINUSB_INTERFACE_HANDLE InterfaceHandle, IN WINUSB_SETUP_PACKET SetupPacket, IN PUCHAR Buffer, IN ULONG BufferLength, OUT PULONG LengthTransferred, IN LPOVERLAPPED Overlapped ); BOOL __stdcall WinUsb_ResetPipe( IN WINUSB_INTERFACE_HANDLE InterfaceHandle, IN UCHAR PipeID ); BOOL __stdcall WinUsb_AbortPipe( IN WINUSB_INTERFACE_HANDLE InterfaceHandle, IN UCHAR PipeID ); BOOL __stdcall WinUsb_FlushPipe( IN WINUSB_INTERFACE_HANDLE InterfaceHandle, IN UCHAR PipeID ); BOOL __stdcall WinUsb_SetPowerPolicy( IN WINUSB_INTERFACE_HANDLE InterfaceHandle, IN ULONG PolicyType, IN ULONG ValueLength, IN PVOID Value ); BOOL __stdcall WinUsb_GetPowerPolicy( IN WINUSB_INTERFACE_HANDLE InterfaceHandle, IN ULONG PolicyType, IN OUT PULONG ValueLength, OUT PVOID Value ); BOOL __stdcall WinUsb_GetOverlappedResult( IN WINUSB_INTERFACE_HANDLE InterfaceHandle, IN LPOVERLAPPED lpOverlapped, OUT LPDWORD lpNumberOfBytesTransferred, BOOL bWait ); PUSB_INTERFACE_DESCRIPTOR __stdcall WinUsb_ParseConfigurationDescriptor( IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, IN PVOID StartPosition, IN LONG InterfaceNumber, IN LONG AlternateSetting, IN LONG InterfaceClass, IN LONG InterfaceSubClass, IN LONG InterfaceProtocol ); PUSB_COMMON_DESCRIPTOR __stdcall WinUsb_ParseDescriptors( IN PVOID DescriptorBuffer, IN ULONG TotalLength, IN PVOID StartPosition, IN LONG DescriptorType ); #ifdef __cplusplus } #endif #endif //__WUSB_H__

在 Windows 8 中,Microsoft 为 WinUSB 提供的信息 (INF) 文件 (Winusb.inf) 

包含 USB\MS_COMP_WINUSB(作为设备标识符字符串)。这可为 MS 操作系统描述符中拥有匹配的 WinUSB 兼容 ID 的那些设备自动加载 Winusb.sys 作为功能驱动程序。此类设备称为 WinUSB 设备。硬件制造商不需要为其 WinUSB 设备分发 INF 文件,从而使最终用户的驱动程序安装过程更为简单。

如果你是开发设备的 OEM 或独立硬件供应商 (IHV),想要将 Winusb.sys 用作功能驱动程序,并且想要自动加载驱动程序而不必提供自定义 INF,本主题中的信息对你适用。

什么是 WinUSB 设备

WinUSB 设备是一种通用串行总线 (USB) 设备,其 固件 定义了某些 Microsoft 操作系统 (OS) 特征描述符,这些描述符将兼容 ID 报告为 "WINUSB"。

WinUSB 设备的用途是让 Windows 将 Winusb.sys 作为设备的功能驱动程序载入,而无需自定义 INF 文件。对于 WinUSB 设备,你无须为设备分发 INF 文件,对最终用户而言,这大大简化了驱动程序安装过程。相反,如果你需要提供自定义 INF,则不应将设备定义为 WinUSB 设备和在 INF 中指定设备的硬件 ID。

Microsoft 提供了 Winusb.inf,其中包含将 Winusb.sys 作为 USB 设备的设备驱动程序安装所需的信息。

在 Windows 8 之前,要将 Winusb.sys 作为功能驱动程序加载,你需要提供自定义 INF。自定义 INF 指定设备特定的硬件 ID,同时包括内置 Winusb.inf 的部分。这些部分是实例化服务、复制内置二进制文件以及注册设备接口 GUID(应用程序查找设备和与设备通讯必须使用 GUID)所必需的。有关编写自定义 INF 的信息,请参阅 WinUSB (Winusb.sys) 安装。

在 Windows 8 中,内置 Winusb.inf 文件经过更新后可让 Windows 自动将 INF 与 WinUSB 设备匹配。

使用内置 Winusb.inf 安装 WinUSB 设备

在 Windows 8 中,内置 Winusb.inf 文件已更新。INF 包括引用称为 "USB\MS_COMP_WINUSB" 的兼容 ID 的安装部分。

[Generic.Section.NTamd64]

%USB\MS_COMP_WINUSB.DeviceDesc%=WINUSB,USB\MS_COMP_WINUSB

更新的 INF 还包括称为 "USBDevice" 的新安装程序类。"USBDevice" 安装程序类可供这些 Microsoft 未提供内置驱动程序的设备使用。通常,此类设备不属于定义良好的 USB 类(如音频、Bluetooth 等),并且需要自定义驱动程序。如果你的设备是 WinUSB 设备,则该设备很可能不属于 USB 类。因此,你的设备必须安装在 "USBDevice" 安装程序类下。更新的 Winusb.inf 便于实现该要求。注意,"USBDevice" 类不仅限于 WinUSB。如果你有设备的自定义驱动程序,则可在自定义 INF 中使用 "USBDevice" 安装程序类。

在设备枚举过程中,USB 驱动程序堆栈会从设备读取兼容 ID。如果兼容 ID 是 "WINUSB",Windows 会将其用作设备标识符,并在更新的内置 Winusb.inf 中查找匹配,然后将 Winusb.sys 作为设备的功能驱动程序加载。

对于 Windows 8 之前的 Windows 版本,更新的 Winusb.inf 可通过 Windows 更新提供。如果你的计算机配置为自动获取驱动程序更新,WinUSB 驱动程序将使用新的 INF 程序包进行安装,无需任何用户干预。

For versions of Windows earlier than Windows 8, the updated Winusb.inf is available through Windows Update. If your computer is configured to get driver update automatically, WinUSB driver will get installed without any user intervention by using the new INF package.

 

About using the USBDevice class: Do not use the "USB" setup class for unclassified devices. That class is reserved for installing controllers, hubs, and composite devices. Misusing the "USB" class can lead to significant reliability and performance issues. For unclassified devices, use "USBDevice".In Windows 8, to use "USBDevice" device class, simply add this to your INF.[Version] Class=USBDevice ClassGuid={88BAE032-5A81-49f0-BC3D-A4FF138216D6} In Device Manager you will see a new node USB Universal Serial Bus devices and your device appears under that node.In Windows 7, in addition to the preceding lines, you need to create these registry settings in the INF:[Version]Class=USBDeviceClassGuid={88BAE032-5A81-49f0-BC3D-A4FF138216D6} ;---------- Add Registry Section ---------- [USBDeviceClassReg] HKR,,,,"Universal Serial Bus devices" HKR,,NoInstallClass,,1 HKR,,SilentInstall,,1 HKR,,IconPath,%REG_MULTI_SZ%," %systemroot%\system32\setupapi.dll,-20"In Device Manager, you will see your device appear under USB Universal Serial Bus devices. However, the device class description is derived from the registry setting specified in your INF.--Eliyas Yakub, Microsoft Windows USB Core Team

 

; winusbcompat.inf; winusbcompat.cat; Copyright (c) Microsoft Corporation. All rights reserved. [Version] Signature="$Windows NT$" Class=USB Device ClassGuid={88BAE032-5A81-49f0-BC3D-A4FF138216D6} Provider=%WinPhone% CatalogFile=winusbcompat.cat DriverVer=05/11/2012,1.0 ; =============== Class section needed for downlevel OS =============== [ClassInstall32] AddReg = ClassInstall_AddReg [ClassInstall_AddReg] HKR,,,0,%ClassName% HKR,,IconPath,%REG_MULTI_SZ%,"%systemroot%\system32\setupapi.dll,-20" HKR,,NoInstallClass,,1 HKR,,BootCritical,,0 HKR,,Configurable,,1 ; ======================= End of Class section ======================== [DestinationDirs] DefaultDestDir = 12 [Manufacturer] %Generic.Mfg%=Generic.Section,NTx86,NTamd64,NTx86.6.0,NTamd64.6.0 ; =========================== Generic ================================= [Generic.Section.NTx86] ; Windows 2000 and XP %NULL.DeviceDesc%=NULL,USB\MS_COMP_WINUSB [Generic.Section.NTx86.6.0] ; Vista and later %USB\MS_COMP_WINUSB.DeviceDesc%=WinUsbDriver,USB\MS_COMP_WINUSB [Generic.Section.NTamd64] ; Windows 2000 and XP %NULL.DeviceDesc%=NULL,USB\MS_COMP_WINUSB [Generic.Section.NTamd64.6.0] ; Vista and later %USB\MS_COMP_WINUSB.DeviceDesc%=WinUsbDriver,USB\MS_COMP_WINUSB ; ======================= WinUsbDriver Sections ======================= [WinUsbDriver.NT] Include = Winusb.inf Needs = WINUSB.NT [WinUsbDriver.NT.Services] Include = Winusb.inf Needs = WINUSB.NT.Services ; =========================== NULL Sections =========================== [DummyReg] [NULL.NT] AddReg = DummyReg [NULL.NT.Services] AddService = , %NULL_SERVICE_INSTALL% ; ========================== Strings Section ========================== [Strings] ;Not localizable WinPhone="Windows Phone" REG_MULTI_SZ = 0x00010000 NULL_SERVICE_INSTALL = 0x00000002 ;Localizable Generic.Mfg="WinUsb Device" USB\MS_COMP_WINUSB.DeviceDesc="WinUsb Device" NULL.DeviceDesc="WinUsb Device (NULL)" ClassName = "Universal Serial Bus devices"

 

 

 

 

 

 

如何更改 WinUSB 设备的设备说明

对于 WinUSB 设备,设备管理器会显示“WinUsb 设备”作为设备说明。该字符串是从 Winusb.inf 派生出来的。如果有多个 WinUSB 设备,所有设备都会获得相同的设备说明。

为了分别标识和区分设备管理器中的设备,Windows 8 在设备类中提供了一个新的属性,指示系统优先使用设备报告的说明(在设备的 iProduct 字符串描述符中),而不是 INF 中的说明。Windows 8 中定义的 "USBDevice" 类设置此属性。换句话说,如果设备在 "USBDevice" 类下安装,系统会查询设备的设备说明,并将设备管理器字符串设置为通过查询检索到的任何字符串。在这种情况下,INF 中提供的设备说明将被忽略。 

新类属性在 Windows 的较早版本中不受支持。在较早版本的 Windows 上,若要自定义设备说明,你必须编写自己的自定义 INF。( 不能自动加载 Winusb.sys 作为功能驱动程序 )

如何配置 WinUSB 设备

USB 设备在固件中存储设备、设备接口和端点的标准描述符。 独立硬件供应商 (IHV) 还可以存储特定于类和供应商的描述符。 但是,这些描述符可以包含的信息类型有限。 

通常,IHV 必须使用 Windows Update 或 CD 之类的介质向他们的用户提供各种特定于设备的信息,比如图片、按钮、自定义驱动程序等等。

为了帮助 IHV 解决此问题,Microsoft 定义了 Microsoft 操作系统描述符。 IHV 可以使用这些描述符在固件中存储如今通常单独提供给客户的大部分信息。 支持 Microsoft 操作系统描述符的 Windows 版本使用控制请求检索信息,使用它安装和配置设备,无需任何用户交互

Microsoft OS 描述符是什么?Microsoft OS 描述符为 IHV 提供了一种方法,可以在设备固件中将各种特定于供应商的信息存储为 OS 功能描述符,而不是与设备分开提供给用户。可感知 Microsoft OS 描述符的 Windows 或 Windows 应用程序的版本可以使用控制请求从设备中检索该描述符,而无需其他的用户交互。尤其是,当初次插入设备时,Windows 可以自动检索该描述符,并使用该信息给用户提供更完美的“即插即用”体验。Windows 支持什么类型的 OS 功能描述符?任何作为功能描述符存储的信息必须符合 Microsoft 已定义的标准格式之一。未经 Microsoft 许可,不能定义或实现其他功能描述符。Microsoft 已经定义了以下功能描述符。

Genre  -- 0x0000此描述符是为 Windows 的未来版本设计的,现在还没有规范。

Extended Compat ID   -- 0x0004Windows 使用类和子类代码帮助找到适合于 USB 设备的默认驱动程序。但是,USB 设备工作组必须分配这些代码。这意味着实现了新功能的设备常常没有合适的类和子类代码,所以 Windows 无法使用该代码选择默认驱动程序。IHV 可以通过将该信息作为扩展的兼容 ID OS 功能描述符存储在固件中来避免此问题。然后 Windows 可以在设备插入时检索此信息,并使用它帮助确定加载哪个默认驱动程序。Extended Properties  -- 0x0005 目前,可以在两个层次上声明 USB 设备的属性:类层次和 devnode 层次。该扩展属性 OS 功能描述符允许供应商将其他属性(比如帮助页面、URL 和图标)存储在设备固件中。

 

哪些 Windows 版本支持 Microsoft OS 描述符?

描述符 Windows 版本 OS 字符串描述符 Windows XP SP1 及更高版本 扩展兼容 ID OS 功能描述符 Windows XP SP2 及更高版本 扩展属性 OS 功能描述符 Windows XP SP2 及更高版本 Genre OS 功能描述符 可能受未来的 Windows 版本支持

若要将 USB 设备标识为 WinUSB 设备,设备固件必须具有这些 Microsoft OS 描述符。

1) 支持 OS 字符串描述符

为了让 USB 驱动程序堆栈了解设备支持扩展的特征描述符,设备必须定义存储在字符串索引 0xEE 处的 OS 字符串描述符。在枚举过程中,驱动程序堆栈查询字符串描述符。如果存在描述符,驱动程序堆栈会假定设备包含一个或多个 OS 特征描述符和检索这些特征描述符所需要的数据。

检索的字符串描述符具有 bMS_VendorCode 字段值。该值表示 USB 驱动程序堆栈必须用来检索扩展特征描述符的供应商代码。

#define bMS_VendorCode              ( 0x01 ) // "MSFT100" : index : 0xEE : langId : 0x0000 const U8 OS_StringDescritpor[ ] = { 0x12, 0x03, 'M', 0, 'S', 0, 'F', 0, 'T', 0, '1', 0, '0', 0, '0', 0, bMS_VendorCode, 0 }; HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\usbflags\<VVVVPPPPRRRR>osvc : 01 01

Indicates whether the operating system queried the device for Microsoft-Defined USB Descriptors. If the previously-attempted OS descriptor query was successful, the value contains the vendor code from the OS string descriptor.

0x0000: The device did not provide a valid response to the Microsoft OS string descriptor request.

0x01xx: The device provided a valid response to the Microsoft OS string descriptor request, where xx is the bMS_VendorCode contained in the response.

为什么必须将 OS 字符串描述符存储在索引 0xEE 上?一台支持 Microsoft OS 描述符的设备必须包含一个 OS 字符串描述符,存储在字符串索引 0xEE 位置。该 OS 字符串描述符是一个标准的 USB 字符串描述符,具有以下功能:1) 其存在表明该设备包含一个或多个 OS 功能描述符。2) 它包含检索相关的 OS 功能描述符所需的数据。3) 它包含一个签名字段,该字段可将 OS 字符串描述符和其他 IHV 可能选择存储在 0xEE 的字符串别开来。4) 它包含一个允许未来修改 Microsoft OS 描述符的版本号。如果在 0xEE 没有字符串描述符,或者该索引位置的字符串描述符不是有效的 OS 字符串描述符,则 Windows 假设该设备不包含任何 OS 功能描述符

 

2) 设置兼容 ID 特征描述符

匹配内置 Winusb.inf 和加载 WinUSB 驱动程序模块所需要的扩展兼容 ID OS 特征描述符

扩展兼容 ID OS 特征描述符包含紧跟一个或多个功能部分的标题部分,具体取决于是否是复合设备。标题部分指定整个描述符的长度、功能部分的数量以及版本号。对于非复合设备,标题后紧跟一个仅与设备的接口关联的功能部分。该部分的 compatibleID 字段必须指定 "WINUSB" 作为字段值。复合设备有多个功能部分。每个功能部分的 compatibleID 字段必须指定 "WINUSB"

// "WINUSB\0\0" : wIndex : 0x0004 const U8 WINUSB_ExtendedCompatId_Descritpor[ ] = { 0x28, 0x00, 0x00, 0x00, // dwLength 0x00, 0x01, // bcdVersion 0x04, 0x00, // wIndex 0x01, // bCount 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved[7] 0x00, // bFirstInterfaceNumber 0x01, // RESERVED ( 0x01 ) 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compactiableID[8] 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // subCompactiableID[8] 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Reserved[6] };

3) 注册设备接口 GUID

注册设备接口 GUID 所需要的扩展属性 OS 特征描述符。需要使用 GUID 从应用程序或服务查找设备、配置设备以及执行 I/O 操作。在以前版本的 Windows 中,设备接口 GUID 注册通过自定义 INF 完成。从 Windows 8 开始,你的设备应使用扩展属性 OS 特征描述符报告接口 GUID。扩展属性 OS 特征描述符包含紧跟一个或多个自定义属性部分的标题部分。标题部分描述整个扩展属性描述符,包含其总长度、版本号以及自定义属性部分的数量。若要注册设备接口 GUID,使用 GUID 生成唯一的设备接口 GUID, 请添加将 

bPropertyName 字段设置为 "DeviceInterfaceGUID" 且将 wPropertyNameLength 设置为 40 字节的自定义属性部分。 bPropertyData 字段设置为该 GUID,如 "{8FE6D4D7-49DD-41E7-9486-49AFC6BFE475}"。注意,GUID 指定为 Unicode 字符串,且字符串长度为 78 字节(包括 Null 终止符)。在设备枚举过程中,USB 驱动程序堆栈随后从扩展属性 OS 特征描述符检索 DeviceInterfaceGUID 值,并在设备硬件注册表项中注册设备。应用程序通过使用 SetupDiXxx API 检索该值。

// L"DeviceInterfaceGUID" : wIndex = 0x0005 // L"{12345678-1234-1234-1234-123456789ABC}" const U8 WINUSB_ExtendedProperty_InterfaceGUID_Descritpor[ ] = { 0x8E, 0x00, 0x00, 0x00, // dwTotalSize = Header + All sections 0x00, 0x01, // bcdVersion 0x05, 0x00, // wIndex 0x01, 0x00, // wCount 0x84, 0x00, 0x00, 0x00, // dwSize -- this section 0x01, 0x00, 0x00, 0x00, // dwPropertyDataType 0x28, 0x00, // wPropertyNameLength 'D', 0x00, 'e', 0x00, // bProperytName : WCHAR : L"DeviceInterfaceGUID" 'v', 0x00, 'i', 0x00, // bProperytName : WCHAR 'c', 0x00, 'e', 0x00, // bProperytName : WCHAR 'I', 0x00, 'n', 0x00, // bProperytName : WCHAR 't', 0x00, 'e', 0x00, // bProperytName : WCHAR 'r', 0x00, 'f', 0x00, // bProperytName : WCHAR 'a', 0x00, 'c', 0x00, // bProperytName : WCHAR 'e', 0x00, 'G', 0x00, // bProperytName : WCHAR 'U', 0x00, 'I', 0x00, // bProperytName : WCHAR 'D', 0x00, 0x00, 0x00, // bProperytName : WCHAR 0x4E, 0x00, 0x00, 0x00, // dwPropertyDataLength : 78 Bytes = 0x0000004E '{', 0x00, '1', 0x00, // bPropertyData : WCHAR : L"{12345678-1234-1234-1234-123456789ABC}" '2', 0x00, '3', 0x00, // bPropertyData '4', 0x00, '5', 0x00, // bPropertyData '6', 0x00, '7', 0x00, // bPropertyData '8', 0x00, '-', 0x00, // bPropertyData '1', 0x00, '2', 0x00, // bPropertyData '3', 0x00, '4', 0x00, // bPropertyData '-', 0x00, '1', 0x00, // bPropertyData '3', 0x00, '4', 0x00, // bPropertyData '4', 0x00, '-', 0x00, // bPropertyData '1', 0x00, '2', 0x00, // bPropertyData '3', 0x00, '4', 0x00, // bPropertyData '-', 0x00, '1', 0x00, // bPropertyData '2', 0x00, '3', 0x00, // bPropertyData '4', 0x00, '5', 0x00, // bPropertyData '6', 0x00, '7', 0x00, // bPropertyData '8', 0x00, '9', 0x00, // bPropertyData 'A', 0x00, 'B', 0x00, // bPropertyData 'C', 0x00, '}', 0x00, // bPropertyData 0x00, 0x00 // bPropertyData };

 

在枚举过程中,USB 驱动程序堆栈会读取扩展属性特征描述符并在该项下创建注册表项。 

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Enum\USB\<Device Identifier>\<Instance Identifier>\Device Parameters

DeviceInterfaceGUID : {12345678-1234-1344-1234-123456789ABC}

启用或禁用 WinUSB 电源管理功能

在 Windows 8 之前,要配置 WinUSB 的电源管理功能,你必须在自定义 INF 的 HW.AddReg 部分中编写注册表项值。在 Windows 8 中,你可以在设备中指定电源设置。你可以通过扩展属性 OS 特征描述符报告值,从而为该设备启用或禁用 WinUSB 中的功能。可配置的功能有两个:选择性挂起和系统唤醒。 选择性挂起允许设备在闲置时进入低能耗状态。系统唤醒是指在系统处于低能耗状态时,设备唤醒系统的功能。

属性名描述DeviceIdleEnabled此值设置为 1 表示设备在闲置时可关闭(选择性挂起)。DefaultIdleState此值设置为 1 表示设备在闲置时可挂起(默认情况下)。DefaultIdleTimeout此值设置为 5000 毫秒表示确定设备处于闲置状态所需等待的毫秒时长。UserSetDeviceIdleEnabled此值设置为 1 允许用户控制设备启用或禁用 USB 选择性挂起的功能。设备“电源管理”属性页面上的复选框“允许计算机关闭此设备以节约电源”,用户可选中或取消选中该复选框以启用或禁用 USB 选择性挂起。SystemWakeEnabled

此值设置为 1 允许用户控制设备从低能耗状态唤醒系统的功能。如果启用,“允许此设备唤醒计算机”复选框将显示在设备电源管理属性页面中。用户可选中或取消选中此复选框以启用或禁用 USB 系统唤醒。

例如,要在设备上启用选择性挂起,请添加一个自定义属性部分,将 bPropertyName 字段设置为 Unicode 字符串,并将 "DeviceIdleEnabled" 和 wPropertyNameLength 设置为 36 字节。 将 bPropertyData 字段设置为 "0x00000001"。这些属性值会存储为 little-endian 32 位整数。

在枚举过程中,USB 驱动程序堆栈会读取扩展属性特征描述符并在该项下创建注册表项。 

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Enum\USB\<Device Identifier>\<Instance Identifier>\Device Parameters

DeviceIdleEnabled : 0x00000001

 

 

成功枚举 USB Device

 

 

枚举过程

80 06 00 01 00 00 40 00 : GET_DESCRIPTOR - device 12 01 00 02 ff ff ff 40 ff ff ff ff 00 01 01 02 03 01 ----------- | | serial number 00 05 01 00 00 00 00 00 : SET_ADDRESS | product string ** 80 06 00 01 00 00 12 00 : GET_DESCRIPTOR - device 12 01 00 02 ff ff ff 40 ff ff ff ff 00 01 01 02 03 01 80 06 00 02 00 00 ff 00 : GET_DESCRIPTOR - configuration 09 02 20 00 01 01 00 80 fa 09 04 00 00 02 ff ff ff ff 07 05 81 02 40 00 00 07 05 02 02 40 00 00 80 06 ee 03 00 00 12 00 : GET_DESCRIPTOR - string : OS ***** 12 03 4d 00 53 00 46 00 54 00 31 00 30 00 30 00 01 00 : "MSFT100" ** bMS_VendorCode 80 06 03 03 09 04 ff 00 : GET_DESCRIPTOR - string : serial number 16 03 30 00 31 00 32 00 33 00 34 00 35 00 36 00 37 00 38 00 39 00 : "0123456789" c0 01 00 00 04 00 10 00 : CompactID - Header 28 00 00 00 00 01 04 00 01 00 00 00 00 00 00 00 c0 01 00 00 04 00 28 00 : CompactID - Header + Function 28 00 00 00 00 01 04 00 01 00 00 00 00 00 00 00 00 01 57 49 4e 55 53 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ****"WINUSB"***** *********************** 80 06 00 03 00 00 ff 00 : GET_DESCRIPTOR - string : language ID 04 03 09 04 80 06 02 03 09 04 ff 00 : GET_DESCRIPTOR - string : product 16 03 55 00 53 00 42 00 20 00 44 00 65 00 76 00 69 00 63 00 65 00 : "USB Device" 80 06 00 06 00 00 0a 00 : GET_DESCRIPTOR - device_qualifier stall c1 01 00 00 05 00 0a 00 : Property - Header 8e 00 00 00 00 01 05 00 01 00 c1 01 00 00 05 00 8e 00 : Property - Header + Data : L"DeviceInterfaceGUID" 8e 00 00 00 00 01 05 00 01 00 84 00 00 00 01 00 00 00 28 00 44 00 65 00 76 00 69 00 63 00 65 00 49 00 6e 00 74 00 65 00 72 00 66 00 61 00 63 00 65 00 47 00 55 00 49 00 44 00 00 00 4e 00 00 00 : L"{12345678-1234-1234-1234-123456789ABC" 7b 00 31 00 32 00 33 00 34 00 35 00 36 00 37 00 38 00 2d 00 31 00 32 00 33 00 34 00 2d 00 31 00 33 00 34 00 34 00 2d 00 31 00 32 00 33 00 34 00 2d 00 31 00 32 00 33 00 34 00 35 00 36 00 37 00 38 00 39 00 41 00 42 00 43 00 7d 00 00 00 80 06 00 01 00 00 12 00 : GET_DESCRIPTOR - device 12 01 00 02 ff ff ff 40 ff ff ff ff 00 01 01 02 03 01 80 06 00 02 00 00 09 00 : GET_DESCRIPTOR - configuration only 09 02 20 00 01 01 00 80 fa 80 06 00 02 00 00 20 00 : GET_DESCRIPTOR - configuration full 09 02 20 00 01 01 00 80 fa 09 04 00 00 02 ff ff ff ff 07 05 81 02 40 00 00 07 05 02 02 40 00 00 80 00 00 00 00 00 02 00 : GET_STATUS - device 01 00 : Self Power 00 09 01 00 00 00 00 00 : SET_CONFIGURATION **

自定义 Winusb.inf 安装 WinUSB.sys 作为设备的功能驱动程序

若要使用 WinUSB 作为设备的功能驱动程序,请创建一个驱动程序包。该驱动程序包必须包含下列文件:

WinUSB 辅助安装程序 (Winusbcoinstaller.dll)KMDF 辅助安装程序 (WdfcoinstallerXXX.dll)用来安装 Winusb.sys 作为设备的功能驱动程序的 .inf 文件。签名的数据包目录文件。 在 x64 版本的 Windows Vista 上安装 WinUSB 时需要此文件。

A. 编写 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 作为基于 x64 系统上 OSR USB FX2 主板的功能驱动程序。

; ; ; 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 ; ========== Manufacturer/Models sections =========== [Manufacturer] %ManufacturerName% = Standard,NTamd64 [Standard.NTamd64]
转载请注明原文地址: https://win8.8miu.com/read-1493348.html

最新回复(0)