如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30,...

27
如何使用 WinUSB USB 设备通信 March 30, 2009 翻译:Leon Lee[email protected]摘要 制造 USB 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的 途径。 从历史上看,这意味着使用 Windows®驱动程序模型(WDM)为设备实现 功能驱动程序,并将驱动程序安装在系统提供的协议驱动程序之上的设备堆栈 中。 Windows Driver FoundationWDF)现在是 USB 驱动程序的首选模型。 它为 I HV 提供三种选项来提供对 USB 设备的访问: 使用 WDF 用户模式驱动框架(UMDF)实现一个用户模式驱动 使用 WDF 内核模式驱动框架实现一个内核模式驱动 安装 WinUsb.sys 作为设备的功能驱动,提供一个应用程序来使用 WinUSB API 访问设备 本白皮书提供了何时使用每个选项的指导原则,并包括如何将 WinUsb.sys 安装为 设备的功能驱动程序并使用 WinUSB API 与设备进行通信的详细演练。 这些信息支持以下操作系统: Windows 7 Windows Server® 2008 Windows Vista® Windows XP 这里讨论的参考资料和资源列在本文末尾。 有关最新信息,请参阅: http://www.microsoft.com/whdc/connect/usb/winusb_howto.mspx

Transcript of 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30,...

Page 1: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

如何使用 WinUSB 与 USB 设备通信

March 30, 2009

翻译:Leon Lee([email protected]

摘要

制造 USB 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

途径。 从历史上看,这意味着使用 Windows®驱动程序模型(WDM)为设备实现

功能驱动程序,并将驱动程序安装在系统提供的协议驱动程序之上的设备堆栈

中。 Windows Driver Foundation(WDF)现在是 USB 驱动程序的首选模型。 它为 I

HV 提供三种选项来提供对 USB 设备的访问:

• 使用 WDF用户模式驱动框架(UMDF)实现一个用户模式驱动

• 使用 WDF 内核模式驱动框架实现一个内核模式驱动

• 安装 WinUsb.sys 作为设备的功能驱动,提供一个应用程序来使用 WinUSB API

访问设备

本白皮书提供了何时使用每个选项的指导原则,并包括如何将 WinUsb.sys 安装为

设备的功能驱动程序并使用 WinUSB API 与设备进行通信的详细演练。

这些信息支持以下操作系统:

Windows 7

Windows Server® 2008

Windows Vista®

Windows XP

这里讨论的参考资料和资源列在本文末尾。

有关最新信息,请参阅:

http://www.microsoft.com/whdc/connect/usb/winusb_howto.mspx

Page 2: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

如何使用 WinUSB 与 USB 设备通信 ‐ 2

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

免责声明:这是一份初步文件,可能会在此处所述软件的最终商业版本发布之前发生重大变化。

本文档中包含的信息代表 Microsoft Corporation 在发布之日所讨论的问题中的当前观点。 由于 Microso

ft 必须对不断变化的市场条件做出响应,因此不应将其解释为 Microsoft 的承诺,Microsoft 不能保证在

发布日期之后提供的任何信息的准确性。

本白皮书仅供参考。对于本文档中的信息,MICROSOFT 不做任何明示,暗示或法定的担保。

遵守所有适用的版权法是用户的责任。在不限制版权的情况下,本文档的任何部分均不得复制,存储或引

入检索系统,也不得以任何形式或任何方式(电子,机械,影印,录制或其他方式)或任何形式目的,未

经微软公司明确的书面许可。

Microsoft 可能拥有涵盖本文档主题的专利,专利申请,商标,版权或其他知识产权。除 Microsoft 提供的

任何书面许可协议明确规定外,本文档的提供并不授予您对这些专利,商标,版权或其他知识产权的任何

许可。

除非另有说明,否则此处描述的示例公司,组织,产品,域名,电子邮件地址,徽标,人员,地点和事件

均为虚构,且与任何真实的公司,组织,产品,域名,电子邮件地址,标识,人员,地点或事件是打算或

应该推断的。

©2009 Microsoft Corporation。版权所有。

Microsoft,MSDN,Windows,Windows Server 和 Windows Vista是微软公司在美国和/或其他国家的注

册商标或商标。

此处提及的实际公司和产品的名称可能是其各自所有者的商标。

版本历史

Date Change

March 30, 2009 Added additional information for communicating with endpoints.

December 6, 2007 Added a section on DFU to the WinUSB FAQ.

Removed the note from Table 1 indicating that WinUSB does not support WinU

SB selective suspend on Windows XP.

August 30, 2007 Created

Page 3: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

如何使用 WinUSB 与 USB 设备通信 ‐ 3

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

目录

简介 .................................................................................................................................. 4

WinUSB、UMDF 和 KMDF 功能摘要 .............................................................................. 5

USB 设备访问支持指南 .................................................................................................. 6

WinUSB 简介 .................................................................................................................... 6

WinUSB 常见问题 ............................................................................................................ 7

如何安装 WinUsb.sys 作为功能驱动程序 ...................................................................... 8

如何使用 WinUSB API ................................................................................................... 12

获得设备句柄和初始化 WinUSB............................................................................... 13

获得设备路径 ........................................................................................................... 13

获得设备的文件句柄 ............................................................................................... 15

初始化 WinUSB .......................................................................................................... 16

配置设备.................................................................................................................... 16

与端点通信................................................................................................................ 18

控制请求 ................................................................................................................... 19

WinUSB I/O请求 ..................................................................................................... 20

WinUSB写入请求 .................................................................................................... 20

缺省 WinUSB 写入行为 ............................................................................................. 21

WinUSB 读请求 ......................................................................................................... 21

缺省的 WinUSB 读行为 ............................................................................................. 22

管道策略 ................................................................................................................... 22

WinUSB 电源管理 ..................................................................................................... 25

选择性挂起 ............................................................................................................... 25

检测空闲 ................................................................................................................... 25

更多的功能建议 ............................................................................................................ 26 总结 ................................................................................................................................ 26

资源 ................................................................................................................................ 26

Page 4: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

如何使用 WinUSB 与 USB 设备通信 ‐ 4

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

简介

制造 USB 设备的独立硬件供应商(IHV)通常必须提供应用程序访问设备功能的方

式。 从历史上看,这意味着使用 Windows®驱动程序模型(WDM)为设备实现功

能驱动程序,并将驱动程序安装在系统提供的协议驱动程序(如 Usbhub.sys 或 Us

bccgp.sys)之上的设备堆栈中。 功能驱动程序公开应用程序用于获取设备文件句

柄的设备接口。 然后他们可以使用该句柄通过调用 Windows API 函数(如 ReadFil

e 和 DeviceIoControl)来与驱动程序进行通信。

驱动程序是提供访问 USB 设备的最灵活方式,并允许任何应用程序(包括多个并

发应用程序)访问该设备。 但是,驱动程序需要大量的开发工作,并且某些设备

非常简单,不需要完全支持自定义功能驱动程序。 例如,诸如机器控制器或数据

记录器之类的设备通常仅由专门为关联设备编写的单个应用程序来访问。 在这些

情况下,WinUSB 提供了一个更简单的替代方案来实现自定义 USB 驱动程序。

WinUSB 是与 Windows Driver Foundation(WDF)同时开发的,可用于 Windows XP

和更高版本的 Windows。 它包括内核模式驱动程序 WinUsb.sys,它是 USB 驱动程

序的 WDF 用户模式驱动程序框架(UMDF)支持的组成部分。 但是,对于仅由单

个应用程序访问的 USB 设备,供应商通常可以将 WinUsb.sys 安装为设备的功能驱

动程序,而不是实施自定义驱动程序。 然后,应用程序可以使用 WinUSB API 配

置设备并访问其端点。

对于那些需要自定义功能驱动程序功能的 USB 设备,首选的方法是 WDF。 WDF

编程模型和设备驱动程序接口(DDI)使 WDF USB 驱动程序比等效的 WDM 驱动

程序更容易实现。 您可以通过以下任何一种方式实现 WDF USB 驱动程序:

• Use the kernel‐mode driver framework (KMDF) to implement kernel‐mode USB driv

ers for any USB device for Windows 2000 and later.

• 使用内核模式驱动框架(KMDF)使用任何 USB 设备的 Windows 2000 及以后

版本的内核模式的 USB 驱动程序

本白皮书介绍了如何选择提供应用程序访问 USB 设备的最佳方式,并回答了关于

WinUSB 的一些常见问题。 本文的大部分内容是详细的演练(包括代码示例),介

绍如何将 WinUsb.sys 安装为 USB 设备的功能驱动程序,以及如何使用 WinUSB API

与应用程序通信。

本文中的示例基于 OSR USB FX2 学习套件设备,但您可以轻松将此过程扩展到其

他 USB 设备。 图 1 是 FX2 器件的简化图,并显示了其主要功能。

Page 5: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

如何使用 WinUSB 与 USB 设备通信 ‐ 5

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

WinUSB、UMDF和 KMDF 功能摘要

表 1 总结了 WinUSB,UMDF USB 驱动程序和 KMDF USB 驱动程序的功能。

表 1. WDF USB 特性支持

需求 WinUSB UMDF KMDF

支持多个并发应用程序. No Yes Yes

隔离应用程序地址空间和驱动程序地址空间 No Yes No

支持批量,中断和控制传输。 Yes Yes Yes

支持同步传输。 No No Yes

支持在 USB 驱动程序上安装内核模式驱动程序,例如

过滤驱动程序。

No No Yes

支持选择性挂起和等待/唤醒 Yes Yes Yes

表 2 总结了不同版本的 Windows 支持哪些 WDF 选项。

表 2. WDF USB Windows 支持

需求 WinUSB UMDF KMDF

Windows Vista and later Yes1 Yes1 Yes

Windows Server 2003 No No Yes

Windows XP Yes2 Yes2 Yes

Windows 2000 No No Yes3

Notes: 1.WinUSB 和 UMDF 仅在 x86 和 x64 版本的 Windows 上受支持。 2.Windows XP SP2 或更高版本支持 WINUSB 和 UMDF。 3 . Windows 2000 Service Pack 4 或更高版本支持 KMDF。

USB 插座

USB 芯片

灯条

拨动开关

LED 面板

远程唤醒开关

图 1. OSR USB FX2 学习套件

Page 6: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

如何使用 WinUSB 与 USB 设备通信 ‐ 6

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

USB 设备访问支持指南

一般来说,从最简单的方法 WinUSB 开始,只有在必要时才会转向更复杂的解决

方案。

如果您的设备不支持同步传输,并且只能通过单个应用程序访问,则应用程序可

以使用 WinUSB 配置设备并访问其端点。 例如,WinUSB 是电子气象站的首选方

法,只能通过与设备一起打包的应用程序访问。 WinUSB 也可用于诊断与设备的

通讯以及刷新固件。

某些类型的设备需要自定义功能驱动程序。 例如,您必须为多个并发应用程序访

问的设备实现驱动程序。 实施 WDF USB 驱动程序的一般指导原则如下:

• UMDF 是首选方法,适用于大多数 USB 设备。 例如,UMDF 驱动程序是音乐

播放器或串行加密狗的首选选项。

• 具有 UMDF 不支持的功能或必须在 Windows XP 之前版本的 Windows 上运行

的设备需要 KMDF 驱动程序。 例如,USB 网络适配器需要 KMDF 驱动程序,

因为驱动程序向上必须与内核模式网络接口设备标准(NDIS)堆栈进行通

信。 这种通信只能从内核模式完成。 支持同步传输的设备也需要 KMDF 驱动

程序。

有关如何实现 UMDF 和 KMDF 驱动程序的详细讨论,请参阅 Microsoft Press 出版

的《Developing Drivers with the Windows Driver Foundation》或 WHDC 的“Windows

Driver Foundation”网页。 本白皮书的其余部分专门介绍 WinUSB。

WinUSB简介

WinUSB 包含两个主要组件:

• WinUsb.sys 是内核模式驱动程序,可以作为过滤驱动或功能驱动程序安装,位

于 USB 设备的内核模式设备堆栈中的协议驱动程序之上。

• WinUsb.dll 是公开 WinUSB API 的用户模式 DLL。 当它作为设备的功能驱动程

序安装时,应用程序可以使用此 API 与 WinUsb.sys 进行通信。

对于不需要定制功能驱动程序的设备,可以将 WinUsb.sys 作为功能驱动程序安装

在设备的内核模式堆栈中。 然后,用户模式进程可以通过一组设备 I / O 控制请求

与 WinUsb.sys 进行通信。

由 WinUSB.dll 公开的 WinUSB API 简化了这个通信过程。替代构建设备 I / O 控制

请求来执行标准的 USB 操作 ‐ 例如配置设备,发送控制请求以及将数据传入或传

出设备,应用程序调用等效的 WinUSB API 函数来实现。

Page 7: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

如何使用 WinUSB 与 USB 设备通信 ‐ 7

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

在内部,WinUsb.dll 使用应用程序传递给 WinUSB 函数的数据来构造合适的设备 I /

O 控制请求,并将请求发送给 WinUsb.sys 进行处理。 当请求完成时,WinUSB 函

数将 WinUsb.sys 返回的任何信息(例如来自读取请求的数据)传回给调用进程。

使用 WinUSB API 与设备通信比实现驱动程序简单得多,但具有以下相应限制:

• WinUSB API 一次只允许一个应用程序与设备进行通信。 如果多个应用程序必

须能够与设备同时通信,则必须实现功能驱动程序。

• WinUSB API 不支持流入或流出同步端点的数据流。 等时传输需要一个内核模

式功能驱动程序。

• WinUSB API 不支持已具有内核模式支持的设备。 这种设备的例子包括调制解

调器和网络适配器,它们分别由电话 API(TAPI)和 NDIS 支持。

• 对于多功能设备,可以使用设备的 INF 分别为每个 USB 功能指定一个内置内

核模式驱动程序或 WinUsb.sys。 但是,您只能为特定功能指定其中一个选

项,而不能同时指定这两个选项。

WinUsb.sys 也是 UMDF 功能驱动程序和相关设备之间的链接的关键部分。 WinUs

b.sys 作为上层过滤器驱动程序安装在设备的内核模式堆栈中。 应用程序与设备的

UMDF 功能驱动程序通信以发出读取,写入或设备 I / O 控制请求。 驱动程序与框

架交互,该框架将请求传递给 WinUsb.sys,WinUsb.sys 处理请求并将其传递给协

议驱动程序并最终传递给设备。 任何响应都会通过反向路径返回。 WinUsb.sys 也

可用作设备堆栈的即插即用和电源所有者(PPO:Plug and Play and power owne

r)。

WinUSB 常见问题

This FAQ answers several common questions about WinUSB.

这个 FAQ 回答一些关于 WinUSB 的常见问题

哪些版本的 Windows 支持 WinUSB?

WinUSB is supported by:

• All Windows Vista SKUs.

• All client SKUs of the 32‐bit versions of Windows XP SP2 and later service packs.

注意:WinUSB不是 Windows XP原生支持的,必须使用 WinUSB安装程序安装。具

体情况,参阅本文后面的“How to Install WinUsb.sys as a Function Driver”

WinUSB 支持哪些 USB 特性?

表 3 显示了 Windows Vista 和 Windows XP 中的 WinUSB 支持哪些高级 USB 功能。

表 3. WinUSB 支持特性

特性 Windows XP Windows Vista

设备 I/O 控制请求 Supported Supported

Page 8: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

如何使用 WinUSB 与 USB 设备通信 ‐ 8

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

等时传输 Not supported Not supported

批量、控制和中断传输 Supported Supported

选择性挂起 Supported Supported

远程唤醒 Supported Supported

怎么获得重新分发 WinUSB 的许可?

WinUSB 以共同安装程序包 WinUSBCoInstaller.dll 的形式包含在 Windows Driver Kit

(WDK)中。 单独的 x86 和 x64 系统的 DLL 在 WinDDK\BuildNumber\Redist\Winus

b 文件夹下。 这些 DLL 已经被签名。 IHV 可以重新分发这些 DLL。

WinUSB 是否支持 USB 设备的 DFU 配置文件?

Microsoft 尚未实施固件更新的特定驱动程序。 WinUSB 不支持主机启动的重置端

口和循环端口操作。 但是,有些设备公开了供应商定义的控制代码以启动重置。

在这种情况下,您可以使用 WinUSB 通过向设备发送包含供应商定义的控制代码

的控制传输请求来启动重置。 有关如何使用 WinUSB 发送控制传输请求的讨论,

请参阅本文后面的“控制请求”。

如何报告 WinUSB 错误或提出功能请求?

要报告错误或提出功能请求,请使用 http://support.microsoft.com 联系您的 Micros

oft 技术客户经理或产品支持工程师。

如何安装 WinUsb.sys 作为功能驱动程序

在您的应用程序可以使用 WinUSB API 与设备进行通信之前,您必须安装 WinUsb.s

ys 作为设备的功能驱动程序。 为此,请创建一个包含以下内容的包:

• WinUSB 联合安装程序,在目标系统上安装 WinUSB(如有必要)。

WDK 包含三个版本的联合安装程序:一个用于 x86 系统,一个用于 x64 系

统,另一个用于安腾系统。 他们都被命名为 WinUSBCoInstaller.dll 并位于 Win

DDK\BuildNumber\redist\winusb 文件夹的相应子目录中。

• KMDF 联合安装程序,如果需要,可以在目标系统上安装正确版本的 KMD

F。

此共同安装程序是必需的,因为 WinUsb.sys 依赖于 KMDF。 本白皮书提到的

WinUSB 版本依赖 KMDF 版本 1.5,相关联合安装程序是 WdfCoInstaller01005.dl

l。 x86 和 x64 版本的 WdfCoInstaller01005.dll 包含在 WDK 下 WinDDK\BuildNu

mber\redist\wdf 文件夹下。

• 将设备的功能驱动程序安装为 WinUsb.sys 的 INF。

• 包的签名目录文件。

Page 9: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

如何使用 WinUSB 与 USB 设备通信 ‐ 9

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

需要此文件才能在 x64 版本的 Windows Vista 上安装 WinUSB。 有关如何创建

和测试已签名的目录文件的更多信息,请参阅 WHDC 网站上的“内核模式代码

签名演练”。

注意: 随着新的 WDF 版本发布,联合安装程序名称将更改为反映 WDF 版本号。

例如,WDF 1.7 版目前正在开发中,该版本的 KMDF 联合安装程序名为 WdfCoInst

aller01007.dll。

以下示例是一个简单的 INF,它将 WinUsb.sys 安装为 Fx2 设备的功能驱动程序: [Version] Signature = "$Windows NT$" Class = MyDeviceClass ClassGuid={78A1C341-4539-11d3-B88D-00C04FAD5171} Provider = %ProviderName% CatalogFile=MyCatFile.cat

; ================== 类部分 =====================

[ClassInstall32] Addreg=MyDeviceClassReg [MyDeviceClassReg] HKR,,,0,%ClassName% HKR,,Icon,,-1

; ========== 制造商/型号部分 ===========

[Manufacturer] %ProviderName% = MyDevice_WinUSB,NTx86,NTamd64,NTia64 [MyDevice_WinUSB.NTx86] %USB\MyDevice.DeviceDesc% =USB_Install, USB\VID_0547&PID_1002 [MyDevice_WinUSB.NTamd64] %USB\MyDevice.DeviceDesc% =USB_Install, USB\VID_0547&PID_1002 [MyDevice_WinUSB.NTia64] %USB\MyDevice.DeviceDesc% =USB_Install, USB\VID_0547&PID_1002

; =================== 安装 ===================

;[1] [USB_Install] Include=winusb.inf Needs=WINUSB.NT

;[2] [USB_Install.Services] Include=winusb.inf AddService=WinUSB,0x00000002,WinUSB_ServiceInstall

;[3] [WinUSB_ServiceInstall] DisplayName = %WinUSB_SvcDesc% ServiceType = 1 StartType = 3 ErrorControl = 1 ServiceBinary = %12%\WinUSB.sys ;[4] [USB_Install.Wdf] KmdfService=WINUSB, WinUsb_Install

Page 10: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

How to

Use WinUSB to Communicate with a USB Device ‐ 10

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

[WinUSB_Install] KmdfLibraryVersion=1.5 ;[5] [USB_Install.HW] AddReg=Dev_AddReg [Dev_AddReg] HKR,,DeviceInterfaceGUIDs,0x10000,"{b35924d6-3e16-4a9e-9782- 5524a4b79bac}"

;[6] [USB_Install.CoInstallers] AddReg=CoInstallers_AddReg CopyFiles=CoInstallers_CopyFiles

[CoInstallers_AddReg] HKR,,CoInstallers32,0x00010000,"WdfCoInstaller01005.dll,WdfCoInstaller ","WinUSBCoInstaller.dll" [CoInstallers_CopyFiles] WinUSBCoInstaller.dll WdfCoInstaller01005.dll [DestinationDirs] CoInstallers_CopyFiles=11

; ================= 源介质部分 ===================== ;[7]

[SourceDisksNames] 1 = %DISK_NAME%,,,\i386 2 = %DISK_NAME%,,,\amd64 3 = %DISK_NAME%,,,\ia64 [SourceDisksFiles.x86] WinUSBCoInstaller.dll=1 WdfCoInstaller01005.dll=1 [SourceDisksFiles.NTamd64] WinUSBCoInstaller.dll=2 WdfCoInstaller01005.dll=2

[SourceDisksFiles.ia64] WinUSBCoInstaller.dll=3 WdfCoInstaller01005.dll=3

; =================== 字符串 ===================

[Strings] ProviderName="MyWinUsbTest" USB\MyDevice.DeviceDesc="Test using WinUSB only" WinUSB_SvcDesc="WinUSB Test" DISK_NAME="My Install Disk" ClassName="MyDeviceClass"

此 INF 可用于大多数 USB 设备,并进行一些简单的修改。

通常,您应该将节名称中的“USB_Install”更改为适当的 DDInstall值。 您还应该直

接更改版本、制造商和型号部分,例如提供设备的适当的制造商名称、已签名的

产品目录文件的名称、正确的设备类别、供应商标识符(VID)和产品标识符(PI

D)。

示例中以粗体显示了应该更改的设备特定值。 可能需要更改的值(例如依赖于版

本号的值)以斜体显示。

注意:有关 USB 设备类别的更多信息,请参阅 WDK 中的“支持的 USB 类别”。

Page 11: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

How to

Use WinUSB to Communicate with a USB Device ‐ 11

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

除了以下列表中列出的特定于设备的值和几个问题之外,您可以使用这些部分和

指令而无需进行修改,以便为任何 USB 设备安装 WinUSB。 以下注释对应于 INF

中的编号注释。

1. 在 Windows Vista 系统上安装 WinUSB 需要 USB_Install 部分中的 Include 和 Ne

eds 指令。 Windows XP 系统忽略这些指令。 这些指令不应该被修改。

2. USB_Install.Services 部分中的 Include 指令包含为 WinUSB 提供的系统 INF。 如

果 WinUSB 联合安装程序没有安装此 INF,则会安装此 INF。 AddService 指令

指定 WinUsb.sys 作为设备的功能驱动程序。 这些指令不应该被修改。

3. WinUSB_ServiceInstall 部分包含用于将 WinUsb.sys 作为服务安装的数据。 本

部分不应修改。

4. USB_Install.Wdf 部分中的 KmdfService 指令将 WinUsb.sys 作为内核模式服务进

行安装。 引用的 WinUSB_Install 部分指定 KMDF 库的版本。 本示例基于 Wind

ows Vista 版本的 WDK(build 6000),其中包括 KMDF 版本 1.5。 更高版本的

WinUSB 可能需要更高版本的 KMDF 版本。

5. USB_Install.HW 是 INF 中的关键部分。 它为您的设备指定设备接口全球唯一标

识符(GUID)。 AddReg 指令将接口 GUID 放入标准注册表值中。 当 WinUsb.sy

s 作为设备的功能驱动程序加载时,它读取注册表值并使用指定的 GUID 来表

示设备接口。 您应该将本例中的 GUID 替换为您为设备专门创建的 GUID。 如

果设备的协议更改,则应该创建一个新的设备接口 GUID。

6. USB_Install.CoInstallers 部分(包括引用的 AddReg 和 CopyFiles 部分)包含用

于安装 WinUSB 和 KMDF 的共同安装程序并将它们与设备关联的数据和说明。

大多数 USB 设备可以不加修改地使用这些部分和指令。

7. Windows 的 x86 和 x64 版本有单独的联合安装程序。 本示例将它们在磁盘上

分别存储在名为 i386 和 amd64 的文件夹中。 图 2(下一页)显示了一个 IHV

驱动程序包可能包含的内容的示例。

注意:每个联合安装程序都有 free 版和 checked 版。 使用 free 版在 free 版本

的 Windows 上安装 WinUSB,包括所有零售版本。 使用具有“_chk”后缀的 che

cked 版本 ‐ 在 checked 版的 Windows 上安装 WinUSB

INF 通常还包含用于安装关联应用程序的指令。

像任何其他驱动程序一样安装 WinUsb.sys。 最简单的方法是插入设备并使用添加

新硬件向导或设备管理器通过使用本节中讨论的 INF 安装驱动程序。 有关 INF 以

及如何安装设备驱动程序的更多详细信息,请参阅 WDK 中的“设备和驱动程序安

装”。

Page 12: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

How to

Use WinUSB to Communicate with a USB Device ‐ 12

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

图 2.驱动程序包内容示例

如何使用 WinUSB API

如果 USB 设备使用 WinUsb.sys 作为其功能驱动程序,则相关应用程序将通过调用

各种 WinUSB API 函数与设备进行通信。 要在应用程序中使用 WinUSB API:

• 包含 WinUsb.h。WDK 里有,在 WINDDK\BuildNumber\inc\ddk 下

• 将 WinUsb.lib 添加到您的应用程序的库列表。 WinUsb.lib 包含在 WDK 中。 Wi

ndows XP 的版本位于 WINDDK\BuildNumber\lib\wxp\i386 下。 对于 Windows Vi

sta,每种支持的 CPU 架构都有独立的 WinUsb.lib 版本。 它们位于 WINDDK\Bu

ildNumber\lib\wlh 文件夹下。

• 包括 Usb100.h,它也位于 WINDDK\BuildNumber\inc\ddk 下。 这个头文件不是

必需的,但它包含一些有用的宏的声明。

要访问设备,应用程序必须:

1. 使用设备接口 GUID 获得设备的句柄

2. 使用这个剧本来初始化 WinUSB.

3. 使用 WinUSB API配置设备

4. 使用 WinUSB API 跟端点通信

本节介基于访问 Fx2 设备的简单应用程序来显示如何执行这些关键任务。

Page 13: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

How to

Use WinUSB to Communicate with a USB Device ‐ 13

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

获得设备句柄和初始化 WinUSB

要使用 WinUSB API,您必须首先获取设备的文件句柄并使用该句柄来初始化 Win

USB。 该过程的前两个步骤与用于获取任何设备的文件句柄的步骤类似:

1. 使用设备接口 GUID 获取设备路径。 正确的 GUID 是您在用于安装 WinUsb.sys

的 INF 中指定的 GUID。

2. 用步骤 1 中的设备路径获取设备的文件句柄。

3. 将文件句柄传递给 WinUsb_Initialize 以初始化 WinUSB 并获取 WinUSB 句柄。

当您调用 WinUSB API 函数时,您使用设备的 WinUSB 句柄来识别设备,而不

是设备的文件句柄。

获得设备路径

The application’s GetDevicePath function, which is shown in the following example, use

s the device interface GUID to obtain the device path. It is similar to the Setup API code

that is used for most devices, but is included here for completeness. For more informati

on, see “Setup API” on MSDN. Note that some code—mostly routine errorhandling cod

e—has been omitted for clarity:

下例中显示的应用程序的 GetDevicePath 函数使用设备接口 GUID 获取设备路径。

它与用于大多数设备的 Setup API 代码类似,但为了完整起见,此处包含此代码。

有关更多信息,请参阅 MSDN 上的“Setup API”。 请注意,为清晰起见,一些代码

(主要是常规错误处理代码)已被省略:

Page 14: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

How to

Use WinUSB to Communicate with a USB Device ‐ 14

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

BOOL GetDevicePath(LPGUID InterfaceGuid, PCHAR DevicePath, size_t BufLen) { BOOL bResult = FALSE; HDEVINFO deviceInfo; SP_DEVICE_INTERFACE_DATA interfaceData; PSP_DEVICE_INTERFACE_DETAIL_DATA detailData = NULL; ULONG length; ULONG requiredLength=0; HRESULT hr; //[1] deviceInfo = SetupDiGetClassDevs(InterfaceGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); ...//Error handling code omitted. // [2]

interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); bResult = SetupDiEnumDeviceInterfaces(deviceInfo, NULL, InterfaceGuid, 0, &interfaceData); ...//Error handling code omitted. // [3] SetupDiGetDeviceInterfaceDetail(deviceInfo, &interfaceData, NULL, 0, &requiredLength, NULL); detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) LocalAlloc(LMEM_FIXED, requiredLength); if(NULL == detailData) { SetupDiDestroyDeviceInfoList(deviceInfo); r

eturn FALSE; } detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); length = requiredLength;

bResult = SetupDiGetDeviceInterfaceDetail(deviceInfo, &interfaceData, detailData, length, &requiredLength, NULL);

Page 15: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

How to

Use WinUSB to Communicate with a USB Device ‐ 15

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

if(FALSE == bResult) {

LocalFree(detailData); return FALSE;

} // [4]

hr = StringCchCopy(DevicePath, BufLen, detailData->DevicePath); if(FAILED(hr))

{ SetupDiDestroyDeviceInfoList(deviceInfo); LocalFree(detailData); } LocalFree(detailData); return bResult; }

基本的程序如下:

1. 通过将您在 INF 中定义的设备接口 GUID 传递给 SetupDiGetClassDevs 来获取设

备信息集的句柄。 该函数返回一个 HDEVINFO 句柄。

2. 调用 SetupDiEnumDeviceInterfaces 来枚举系统的设备接口来获得您的设备接

口的信息,要做到这一点:

• 设置 SP_DEVICE_INTERFACE_DATA 结构的 cbSize 成员为结构的大小来初始

化这个结构

• 传递步骤 1 得到的 HDEVINFO 句柄、设备的接口 GUID和初始化过的 SP_DE

VICE_INTERFACE_DATA 结构的引用给 SetupDiEnumDeviceInterfaces

3. 调用 SetupDiGetDeviceInterfaceDetail 来获得设备接口的详细数据。这些信息

以 SP_DEVICE_INTERFACE_DETAIL_DATA 结构返回

• 因为 SP_DEVICE_INTERFACE_DETAIL_DATA 结构的大小可变,您必须首先以

DeviceInterfaceDetailData 参数为空调用 SetupDiGetDeviceInterfaceDetail 来

得到正确的缓冲区大小。

• 函数在 requiredlength参数里返回正确的缓冲区大小,使用这个值来正

确分配 SP_DEVICE_INTERFACE_DETAIL_DATA结构需要的内存

• 传递初始化的结构的引用再次调用 SetupDiGetDeviceInterfaceDetail,当函

数返回时,结构包含了接口的详细信息。

4. 设备路径在 SP_DEVICE_INTERFACE_DETAIL_DATA 结构的 DevicePath 成员里。

获得设备的文件句柄

应用程序的 OpenDevice 函数(在以下示例中显示)通过将设备路径传递给 Create

File 来获取设备的文件句柄。

1. 调用 GetDevicePath 实用程序函数以获取设备路径。 上一节讨论了 GetDeviceP

ath。

Page 16: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

How to

Use WinUSB to Communicate with a USB Device ‐ 16

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

2. 将设备路径传递给 CreateFile 以获取设备的文件句柄。 本示例获取支持对设备

的同步读取和写入访问的文件句柄。 有关如何为异步 I / O 打开文件句柄的详

细信息,请参阅 MSDN 上的“CreateFile Function”参考页面。 一定要设置 FILE_F

LAG_OVERLAPPED 标志。 WinUSB 取决于这个设置:

HANDLE OpenDevice(BOOL bSync) { HANDLE hDev = NULL; char devicePath[MAX_DEVPATH_LENGTH]; BOOL retVal; retVal = GetDevicePath( (LPGUID) &GUID_DEVINTERFACE_OSRUSBFX2, devicePath, si zeof(deviceName)); ...//Error-handling code omitted. hDev = CreateFile(devicePath, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL); ...//Error-handling code omitted. return hDev; }

初始化 WinUSB

在前一节中获得的句柄是该设备的文件句柄。 但是,WinUSB API 使用 WinUSB 句

柄来标识目标设备,而不是文件句柄。 要获取 WinUSB 句柄,请将文件句柄传递

给 WinUsb_Initialize 以初始化 WinUSB。 该函数返回设备的 WinUSB 句柄。

以下示例使用 OpenDevice 实用程序函数获取的文件句柄初始化 WinUSB,如前一

节中所述。 然后它存储相应的 WinUSB 句柄,以便以后用于私人定义的全局结构

中: deviceHandle = OpenDevice(TRUE); bResult = WinUsb_Initialize(deviceHandle, &usbHandle); if(bResult) { devInfo.winUSBHandle = usbHandle; }

配置设备

应用程序初始化 WinUSB 后,必须配置 USB 设备。 该过程类似于 USB 设备驱动程

序使用的过程。 但是,它是通过调用 WinUSB API 函数而不是 WDF 框架库或任何

Windows WDM USB 客户端支持例程来完成的。

应用程序的 InitializeDevice 函数(在以下示例中显示)配置 Fx2 设备。 它还包括

上例中初始化 WinUSB 的代码:

Page 17: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

How to

Use WinUSB to Communicate with a USB Device ‐ 17

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

BOOL Initialize_Device() { BOOL bResult; WINUSB_INTERFACE_HANDLE usbHandle; USB_INTERFACE_DESCRIPTOR ifaceDescriptor; WINUSB_PIPE_INFORMATION pipeInfo; UCHAR speed; ULONG length; deviceHandle = OpenDevice(TRUE); bResult = WinUsb_Initialize(deviceHandle, &usbHandle); //[1] if(bResult) { devInfo.winUSBHandle = usbHandle; length = sizeof(UCHAR); bResult = WinUsb_QueryDeviceInformation(devInfo.winUSBHandle, DEVICE_SPEED, &length, &speed); } //[2] if(bResult) { devInfo.deviceSpeed = speed; bResult = WinUsb_QueryInterfaceSettings(devInfo.winUSBHandle, 0, &ifaceDescriptor); } if(bResult) { for(int i=0;i<ifaceDescriptor.bNumEndpoints;i++)

{ 、/[3]

bResult = WinUsb_QueryPipe(devInfo.winUSBHandle, 0, (UCHAR) i, &pipeInfo); //[4] if(pipeInfo.PipeType == UsbdPipeTypeBulk && USB_ENDPOINT_DIRECTION_IN(pipeInfo.PipeId)) { devInfo.bulkInPipe = pipeInfo.PipeId; } else if(pipeInfo.PipeType == UsbdPipeTypeBulk && USB_ENDPOINT_DIRECTION_OUT(pipeInfo.PipeId)) { devInfo.bulkOutPipe = pipeInfo.PipeId; } else if(pipeInfo.PipeType == UsbdPipeTypeInterrupt) { devInfo.interruptPipe = pipeInfo.PipeId; } else { bResult = FALSE;

break; } } }

return bResult; }

Page 18: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

How to

Use WinUSB to Communicate with a USB Device ‐ 18

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

基本程序如下:

1. 如果必要,调用 WinUsb_QueryDeviceInformation 获得设备的速度。这个函数

返回 3个值:LowSpeed (0x01)、FullSpeed (0x02)、或者 HighSpeed (0x03)

2. 将设备的接口句柄传递给 WinUsb_QueryInterfaceSettings 以获取相应的接口描

述符。 WinUSB 句柄对应于第一个接口。 由于 Fx2 设备仅支持一个无替代设置

的接口,因此 AlternateSettingNumber参数设置为零,并且该函数仅被调用一

次。 如果设备支持多个接口,则调用 WinUsb_GetAssociatedInterface 以获取

关联接口的接口句柄。

WinUsb_QueryInterfaceSettings 返回一个 USB_INTERFACE_DESCRIPTOR 结构,

其中包含有关该接口的信息。 该结构尤其包含接口中端点的数量。

3. 要获取有关每个端点的信息,请为每个接口上的每个端点调用一次WinUsb_

QueryPipe。 WinUsb_QueryPipe返回一个 WINUSB_PIPE_INFORMATI

ON 结构,其中包含有关指定端点的信息。 Fx2 设备有一个带有三个端点的

接口,因此函数的 AlternateInterfaceNumber 参数设置为 0,PipeIndex 参

数的值从 0 到 2 变化。

4. 要确定管道类型,检查 WINUSB_PIPE_INFORMATION 结构里的 PipeInfo 成员。

这个成员被设置为枚举 USBD_PIPE_TYPE 的其中一个值:UsbdPipeTypeContro

l、UsbdPipeTypeIsochronous、UsbdPipeTypeBulk、或者 UsbdPipeTypeInterrup

t。

Fx2 器件支持的三个端点是一个中断管道、一个批量输入管道和一个批量输出

管道,因此 PipeInfo 将设置为 UsbdPipeTypeInterrupt 或 UsbdPipeTypeBulk。

UsbdPipeTypeBulk 值标识批量管道,但不提供方向。 该信息编码在管道地址

的高位中,该地址存储在 WINUSB_PIPE_INFORMATION 结构的 PipeId 成员中。

确定方向的最简单方法是将 PipeId值传递给 Usb100.h 中的以下宏之一:

• 如果方向是输入,USB_ENDPOINT_DIRECTION_IN 返回 TRUE。

• 如果方向是输入,USB_ENDPOINT_DIRECTION_OUT 返回 TRUE。

应用程序使用 PipeId 值来标识调用 WinUSB 函数(如 WinUsb_ReadPipe)时所

需的管道,因此该示例存储了所有三个 PipeId 值供以后使用。

与端点通信

当你知道设备端点的 PipeId 值后,可以与设备进行通信。 本文讨论如何发出控

制、读取和写入请求。

Page 19: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

How to

Use WinUSB to Communicate with a USB Device ‐ 19

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

控制请求

所有 USB 设备除了与接口关联的端点外,还有一个控制端点。 控制端点的主要目

的是提供应用程序可用来配置设备的默认端点。 但是,设备也可以将控制端点用

于设备特定目的。 Fx2 设备使用控制端点来控制灯条和七段数字显示。

控制命令包括一个 8 字节的设置数据包(其中包含一个指定特定请求的请求代

码)和一个可选的数据缓冲区。 请求代码和缓冲区格式由供应商定义。 要发出控

制请求:

1. 如果需要,分配一个缓冲区

2. 构造一个设置包

3. 调用 WinUsb_ControlTransfer 来发出请求和缓冲区到控制端点

下面例子显示的程序的 SetBar 函数发出了一个控制请求到 Fx2 设备,控制灯条上

的灯光 BOOL SetBar(HWND hWnd) { BOOL bResult; ULONG bytesReturned; WINUSB_SETUP_PACKET setupPacket; UCHAR lightedBars = 0; //[1] numBars =8;

for(int i = 0;i<numBars; i++) { if((int) SendMessage(hwndSetBarCheckBox[i], BM_GETCHECK, 0,0)) { lightedBars += 1 << (UCHAR) i; } } //[2]

setupPacket.RequestType = 0; //Host to Device setupPacket.Request = SET_BARGRAPH_DISPLAY; setupPacket.Index = 0;

setupPacket.Length = sizeof(UCHAR); setupPacket.Value = 0;

//[3]

bResult = WinUsb_ControlTransfer(devInfo.winUSBHandle, setupPacket, &lightedBars,

sizeof(UCHAR), &bytesReturned,

NULL); return bResult;

}

用来设置灯条的代码是 0xD8,为方便起见,将其定义为 SET_BARGRAPH_DISPLA

Y。发出请求的过程如下:

Page 20: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

How to

Use WinUSB to Communicate with a USB Device ‐ 20

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

1. 将数据加载到缓冲区中。 该设备需要一个 1 字节的数据缓冲区,通过设置适

当的位来指定哪些元件应点亮。 该应用程序的用户界面(UI)包含一组八个 C

heckBox 控件,用于指定灯条的哪些元素应该点亮。 该示例查询用户界面以确

定应点亮哪些灯并在缓冲区中设置适当的位。

2. 通过将值分配给 WINUSB_SETUP_PACKET 结构构建一个设置数据包:

• RequestType 成员指定请求方向。 它被设置为 0,表示主机到设备的数据

传输。 对于设备到主机的传输,请将 RequestType 设置为 1。

• Request 成员被设置为该请求的供应商定义的代码,0xD8。 为了方便起

见,它被定义为 SET_BARGRAPH_DISPLAY。

• Length成员被设置为数据缓冲区的大小。

• Index和 Value成员对这个请求不是必需的,因此被设置为 0

3. 通过将设备的 WinUSB 句柄、设置数据包和数据缓冲区传递给 WinUsb_Control

Transfer 来传输请求。 该函数返回传送给设备的字节数。

WinUSB I/O请求

Fx2 设备具有可分别用于读取和写入请求的批量输入和批量输出端点。 这两个端

点配置为回环(loopback),因此设备只是将数据从大容量输入端点移动到大容量输

出端点。 它不会更改数据的值或创建任何新数据,因此读取请求会读取最近写入

请求发送的数据。

WinUSB写入请求

WinUSB 具有用于发送写入和读取请求的单独函数:WinUsb_WritePipe 和 WinUsb

_ReadPipe。 应用程序的 WriteToDevice 函数(在以下示例中显示)将一个简单的

字符串写入 Fx2 设备: BOOL WriteToDevice(HWND hWnd) { USHORT bufSize = 12; UCHAR szBuffer[12]; BOOL bResult; ULONG bytesWritten; //[1] SendMessage(hwndWriteEdit, EM_GETLINE, 0, (LPARAM) szBuffer); //[2]

bResult = WinUsb_WritePipe(devInfo.winUSBHandle, devInfo.bulkOutPipe, szBuffer, 24, &bytesWritten, NULL); return bResult; }

Page 21: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

How to

Use WinUSB to Communicate with a USB Device ‐ 21

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

要发送一个写入请求:

1. 创建一个缓冲区并填入要写入设备的数据。 该示例从应用程序的用户界面上

的 Edit 控件获取 12 个字符的 Unicode 字符串。

应用程序负责适当地管理缓冲区的大小。

只要应用程序不使用 RAW_IO,缓冲区大小就没有限制。 如有必要,WinUSB

会将缓冲区分成适当大小的块。 对于 RAW_IO,缓冲区的大小受控制器的限

制。 对于读取请求,缓冲区必须是最大数据包大小的倍数。

2. 通过调用 WinUsb_WritePipe 将缓冲区写入设备。 传递接口句柄,大容量输出

管道的 PipeId 值和缓冲区。 在这种情况下,接口句柄是 WinUSB 句柄。 该函

数在 bytesWritten 参数中返回实际写入设备的字节数。

WinUsb_WritePipe 的最后一个参数 Overlapped设置为 NULL 以请求同步操

作。 要执行异步写入,,Overlapped应该是指向 OVERLAPPED 结构的指针。

缺省 WinUSB 写入行为

零长度写入被转发到堆栈。 如果传输长度大于最大传输长度,WinUSB 会将请求

分成较小的最大传输长度请求并连续提交。

WinUSB 读请求

读取操作与写入操作类似。 传递给 WinUsb_ReadPipe 接口句柄、大容量端点的 Pi

peId 值和适当大小的空缓冲区。 当函数返回时,缓冲区包含从设备读取的数据。

读取的字节数在函数的 bytesRead参数中返回。 以下示例从 Fx2 设备读取字符

串,并将其显示在应用程序界面上的 Static 控件中: BOOL ReadFromDevice(HWND hWnd) { USHORT bufSize = 12; UCHAR szBuffer[12]; BOOL bResult; ULONG bytesRead; bResult = WinUsb_ReadPipe(devInfo.winUSBHandle,

devInfo.bulkInPipe, szBuffer,

24, &bytesRead,

NULL); SendMessage(hwndReadStatic, WM_SETTEXT, 0, (LPARAM) szBuffer); return bResult; }

Page 22: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

How to

Use WinUSB to Communicate with a USB Device ‐ 22

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

缺省的 WinUSB 读行为

零长度读取会立即成功完成,不会发送到堆栈。 如果传输长度大于最大传输长

度,WinUSB 会将请求分成较小的最大传输长度请求并连续提交。 如果传输长度

不是端点的 MaxPacketSize 的倍数,则 WinUSB 会将传输大小增加到 MaxPacketSiz

e 的下一个倍数。 如果设备返回的数据比请求的数据多,WinUSB 将保存超出的数

据。 如果数据仍然来自先前的读取,则 WinUSB 会将其复制到下一个读取的开始

位置,并在必要时完成读取。

管道策略

WinUSB 允许通过可应用于管道(端点)的策略修改其默认行为。 使用策略可以

帮助 IHV 调整 WinUSB 以使其设备与其功能最佳匹配。 表 4 提供了 WinUSB 支持

的管道策略列表。

表 4. WinUSB 管道策略

策略编号 策略名称 缺省

0x01 SHORT_PACKET_TERMINATE Off

0x02 AUTO_CLEAR_STALL Off

0x03 PIPE_TRANSFER_TIMEOUT 5 seconds for control, 0 for others

0x04 IGNORE_SHORT_PACKETS Off

0x05 ALLOW_PARTIAL_READS On

0x06 AUTO_FLUSH Off

0x07 RAW_IO Off

0x09 RESET_PIPE_ON_RESUME Off

表 5 提供了有关何时应使用每个管道策略的信息,并描述了每个策略启用时的结

果行为。

表 5.管道策略行为

策略 何时使用 行为

SHORT_PACKET_TERMINATE • 如果您的设备要求使用

短数据包终止 OUT 传输

(大多数设备不需要此

设置),请使用此选项。

• 此策略仅适用于批量和

中断 OUT 端点(在 IN 端

点上设置此策略不起作

用)。

• 如果启用,所有对端点的写

入都会以短数据包终止。

Page 23: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

How to

Use WinUSB to Communicate with a USB Device ‐ 23

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

AUTO_CLEAR_STALL • 如果希望失败的传输不

离开处于停滞状态的端

• 仅用于批量和中断 IN 端

• 只有在禁用 RAW_IO 时

将多个读取挂接到端点

时,此策略通常才有

用。

• 如果启用,当 IN 传输失败并

返回 STATUS_CANCELLED

或 STATUS_DEVICE_NOT_C

ONNECTED 以外的状态时,

WinUSB 会在完成传输失败

之前重置端点。

• 如果禁用,则后续到端点的

传输将失败,直到通过调用

WinUsb_ResetPipe()手

动重置端点。

• 启用或禁用此策略之间没有

显着的性能差异。

策略 何时使用 行为

PIPE_TRANSFER_TIMEOUT • 如果您希望在特定时间

内完成传输的端点,请

使用此功能。

• 如果设置为 0,传输将无限期

地延时直到它们被手动取消

或它们正常完成。

• 如果设置为非零值,则在请

求发送到核心 USB 堆栈时请

求计时器启动(在 WinUSB

队列中请求不超时)。 当定时

器到期时,请求被取消。

• 由于管理定时器,因此性能

受到轻微影响。

IGNORE_SHORT_PACKETS • 如果您不想让短数据包

完成读取请求(这很少

见),请使用它。

• 此策略仅适用于禁用 RA

W_IO 的批量和中断 IN

端点。

• 只有在发生错误,取消请求

或接收到所有请求的字节时

才能完成读取。

ALLOW_PARTIAL_READS • •如果您的设备可以合法

发送比请求更多的数据

(仅在您请求 MaxPacke

tSize 的非整数倍时才可

能)。

• 如果应用程序想要读取

几个字节以确定要读取

• 如果禁用并且设备返回的数

据超出请求的数量,则请求

完成并显示错误。

• 如果启用,WinUSB 将立即成

功完成零字节的读取请求,

并且不会将请求发送到堆

栈。

Page 24: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

How to

Use WinUSB to Communicate with a USB Device ‐ 24

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

的总字节数,请使用

它。

• 此策略仅对批量和中断 I

N 端点有效。

• 如果启用并且设备返回的数

据超出请求的数量,则 WinU

SB 将保存超出的数据并将其

预加载到下一个读取请求。

AUTO_FLUSH • •如果您的设备可以发送

比请求更多的数据,并

且应用程序不需要超出

所请求的任何额外数据

(可能仅在请求 MaxPac

ketSize 的非整数倍时才

可用)。

• •此策略仅对启用了 ALL

OW_PARTIAL_READS 策

略的批量和中断 IN 端点

有效。

• If an endpoint returns more bytes than requested, WinUSB discards those bytes without error.

• 如果端点返回的字节数多于

请求的数量,WinUSB 会丢弃

这些字节而不会报错。

• •如果 ALLOW_PARTIAL_READS

被禁用,则不起作用。

策略 何时使用 行为

RAW_IO • 如果读取性能是优先

级,并且应用程序向同

一端点提交多个同时读

取,则使用此选项。

• 此策略仅对批量和中断 I

N 端点有效(在 OUT 端

点上设置策略不起作

用)。

• 对端点的请求不是 MaxPacket

Size 的整数倍数失败。

• 对端点的请求大于最大传输

大小(可通过 MAXIMUM_T

RANSFER_SIZE 管道策略检

索)失败。

• 对端点的所有格式正确的读

取立即发送到堆栈,以便在

宿主控制器中进行调度。

• 提交多个读取请求时会发生

显著的性能提升。

• 一次传输的最后一个数据包

与下一次传输的第一个数据

包之间的延迟减少。

RESET_PIPE_ON_RESUME • Use if the device does not preserve its data toggle state across suspend.

• This policy is valid only for

bulk and interrupt endpoi

nts.

• 在从挂起恢复时,WinUSB 会

在请求发送到端点之前重置

端点。

Page 25: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

How to

Use WinUSB to Communicate with a USB Device ‐ 25

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

• 如果设备在挂起期间不

保留其数据切换状态,

请使用此选项。

• 此策略仅适用于批量和

中断端点。

有关 WinUSB 策略的更多信息,请参阅“WinUsb_GetPipePolicy”和 WDK 中的“WinU

sb_SetPipePolicy”。

WinUSB 电源管理

WinUSB 使用 KMDF 状态机进行电源管理。 电源策略通过调用 WinUsb_SetPowerP

olicy 以及在注册表中设置的默认值进行管理。 要允许设备唤醒系统,必须添加 D

WORD 注册表值 SystemWakeEnabled 并将其设置为非零值。 设备“属性”页面中的

复选框会自动启用,以便用户可以覆盖该设置。

选择性挂起

选择性挂起可以通过多个系统或 WinUSB 设置中的任何一个禁用。 单个设置不能

强制 WinUSB 启用选择性挂起。 以下电源策略设置会影响选择性挂起的行为:

AUTO_SUSPEND

当设置为 0,不能选择性挂起设备。

SUSPEND_DELAY

设置设备空闲和 WinUSB 请求设备选择性挂起之间的时间。

以下注册表项影响选择性挂起的行为:

DeviceIdleEnabled

当设置为 0,不能选择性挂起设备。

DeviceIdleIgnoreWakeEnable

当设置为非零值,挂起设备,即使它不支持 RemoteWake.

UserSetDeviceIdleEnabled

设置为非零值时,在设备属性页面启用允许用户覆盖空闲默认值的复选框。

DefaultIdleState

设置 AUTO_SUSPEND 电源策略设置的默认值。 此注册表项用于启用或禁用选

择性挂起,当句柄未对设备打开时。

DefaultIdleTimeout

设置 SUSPEND_DELAY 电源策略设置的默认状态

检测空闲

所有写入和控制传输都强制设备进入 D0 电源状态并重置空闲计时器。 IN 端点队

列不受电源管理,当提交读取请求时会唤醒设备。 但是,在读取请求挂起时,设

备可能会空闲。

Page 26: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

How to

Use WinUSB to Communicate with a USB Device ‐ 26

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

更多的功能建议

请将您的附加附加信息和功能请求提交给 [email protected]。 一些可

能的未来功能包括以下内容:

• 等时端点支持。

• USB3 功能扩展。

总结

通过使用 WinUSB,IHV 为其 USB 硬件设备提供了坚实的 Windows 驱动程序解决

方案。 WinUSB 支持 Windows XP 及更高版本的 Windows,并支持 Windows 的 32

位和 64 位版本。 现有的 Windows 32 位和 64 位应用程序可以轻松修改以利用 Wi

nUSB API。 WinUSB 消除了所有与驱动程序有关的问题,并让 IHV 为他们的 USB

设备提供 Windows 驱动程序解决方案的时间要少得多,而且比编写自己的 Windo

ws 驱动程序少得多。

资源

Windows Hardware Developer Central (WHDC): Kernel‐Mode Code Signing Wal

kthrough http://www.microsoft.com/whdc/winlogo/drvsign/kmcs_walkthrough.

mspx

Windows Driver Foundation (WDF) http://www.microsoft.com/whd

c/driver/wdf/default.mspx

Writing USB Drivers with WDF http://www.microsoft.com/whdc/dri

ver/wdf/USB_WDF.mspx

Windows Driver Kit:

Device and Driver Installation http://go.microsoft.com/fwlink/?LinkI

d=98295 Device and Driver Installation Design Guide http://go.mi

crosoft.com/fwlink/?LinkId=146855

Finish‐Install Actions (Windows Vista and later) http://go.microsoft.

com/fwlink/?LinkId=146856 Finish‐Install Wizard Pages http://go.microsoft.com/fwlink/?LinkId=

146857

Supported USB Classes http://go.microsoft.com/fwlink/?LinkId=982

97

USB http://go.microsoft.com/fwlink/?LinkId=98298

WinUSB http://go.microsoft.com/fwlink/?LinkId=98299

Page 27: 如何使用 WinUSB 与USB 备通信 · 2018-05-06 · 如何使用WinUSB与USB备通信 March 30, 2009 翻译:Leon Lee(liyi@pansafe.com) 摘要 制造US 设备的独立硬件供应商(IHV)通常必须为应用程序提供访问设备功能的

How to

Use WinUSB to Communicate with a USB Device ‐ 27

March 30, 2009 © 2009 Microsoft Corporation. All rights reserved.

WinUSB User‐Mode Client Support Routines http://go.microsoft.co

m/fwlink/?LinkId=98300

WinUsb_GetPipePolicy http://go.microsoft.com/fwlink/?LinkId=146

858

WinUsb_SetPipePolicy http://go.microsoft.com/fwlink/?LinkId=146

859

MSDN:

CreateFile Function http://go.microsoft.com/fwlink/?LinkId=98294

Setup API http://go.microsoft.com/fwlink/?LinkId=98296

Microsoft Press:

Developing Drivers with the Windows Driver Foundation http://ww

w.microsoft.com/MSPress/books/10512.aspx