如何编写第一个 USB 客户端驱动程序 (KMDF)

本文将使用 Microsoft Visual Studio 提供的 USB 内核模式驱动程序模板来编写一个基于内核模式驱动程序框架 (KMDF) 的简单客户端驱动程序。 生成并安装客户端驱动程序后,你将在设备管理器中查看客户端驱动程序,并在调试器中查看驱动程序输出。

有关模板生成的源代码的说明,请参阅了解 USB 客户端驱动程序的 KMDF 模板代码

先决条件

要开发、调试和安装内核模式驱动程序,需要使用两台计算机:

  • 运行 Windows 7 或更高版本 Windows 操作系统的主计算机。 主计算机是开发环境,可在这里编写和调试驱动程序。
  • 运行 Windows Vista 或更高版本 Windows 的目标计算机。 目标计算机上有要调试的内核模式驱动程序。

开始之前,请确保符合以下要求:

软件要求

  • 主计算机托管着开发环境并安装了 Visual Studio。
  • 主计算机已安装最新的 Windows 驱动程序工具包 (WDK)。 该工具包包括开发、生成和调试 KMDF 驱动程序所需的标头、库、工具、文档和调试工具。 要获取最新版本的 WDK,请参阅下载 Windows 驱动程序工具包 (WDK)
  • 主计算机已安装最新版本的 Windows 调试工具。 可以从 WDK 获取最新版本,也可以下载并安装 Windows 调试工具
  • 目标计算机运行的是 Windows Vista 或更高版本的 Windows。
  • 主计算机和目标计算机已配置内核调试。 有关详细信息,请参阅在 Visual Studio 中设置网络连接

硬件要求

获取要为其编写客户端驱动程序的 USB 设备。 在大多数情况下,你都会收到一个 USB 设备及其硬件规格。 该规范描述了设备功能和支持的供应商命令。 使用规范确定 USB 驱动程序的功能和相关设计决策。

如果还不熟悉 USB 驱动程序开发,请使用 OSR USB FX2 学习工具包来研究 WDK 中包含的 USB 示例。 可从 OSR Online 获取学习工具包。 它包含 USB FX2 设备和实施客户端驱动程序所需的所有硬件规格。

还可以获得 Microsoft USB 测试工具 (MUTT) 设备。 MUTT 硬件可从 JJG Technologies购买。 设备未安装固件。 要安装固件,请从此网站下载 MUTT 软件包并运行 MUTTUtil.exe。 更多信息,请参阅软件包随附的文档。

步骤 1:使用 Visual Studio USB 驱动程序模板生成 KMDF 驱动程序代码

有关生成 KMDF 驱动程序代码的说明,请参阅根据模板编写 KMDF 驱动程序中的步骤。

对于 USB 专用代码,请在 Visual Studio 中选择以下选项:

  1. 在“新建项目”对话框中,在顶部的搜索框中输入 USB
  2. 在中间窗格中,选择“内核模式驱动程序,USB (KMDF)”
  3. 选择下一步
  4. 输入项目名称,选择保存位置,然后选择“创建”。

以下屏幕截图显示了 USB 内核模式驱动程序模板的“新建项目”对话框。

Visual Studio 新项目选项。

visual studio 新项目选项的第二个屏幕。

本文假定 Visual Studio 项目的名称为“MyUSBDriver_”。 它包含以下文件:

文件 说明
Public.h 提供客户端驱动程序和与 USB 设备通信的用户应用程序共享的通用声明。
<Project name>.inf 包含在目标计算机上安装客户端驱动程序所需的信息。
Trace.h 声明跟踪函数和宏。
Driver.h; Driver.c 声明并定义驱动程序入口点和事件回调例程。
Device.h; Device.c 声明并定义准备硬件事件的事件回调例程。
Queue.h; Queue.c 声明并定义用于由框架队列对象引发的事件的回调例程。

步骤 2:修改 INF 文件,添加有关设备的信息

在生成驱动程序之前,必须使用设备信息(特别是硬件 ID 字符串)来修改模板 INF 文件。

在“解决方案资源管理器”的“驱动程序文件”下,双击 INF 文件。

在 INF 文件中,可以提供制造商和供应商名称、设备安装程序类等信息。 必须提供的一项信息是设备的硬件标识符。

要提供硬件 ID 字符串,请执行以下操作:

  1. 将 USB 设备连接到主计算机,让 Windows 枚举设备。

  2. 打开“设备管理器”,然后打开设备的属性。

  3. 在“详细信息”选项卡上,选择“属性”下的“硬件 ID”。

    设备的硬件 ID 将显示在列表框中。 选中并按住(或右键单击),然后复制硬件 ID 字符串。

  4. 将下面一行中的 USB\VID_vvvv&PID_pppp 替换为硬件 ID 字符串。

    [Standard.NT$ARCH$] %MyUSBDriver_.DeviceDesc%=MyUSBDriver__Device, USB\VID_vvvv&PID_pppp

步骤 3:生成 USB 客户端驱动程序代码

要生成驱动程序,请执行以下操作:

  1. 在 Visual Studio 中打开驱动程序项目或解决方案
  2. 在“解决方案资源管理器”中选择并按住(或右键单击)解决方案,然后选择“配置管理器”。
  3. 在“配置管理器”中,选择与感兴趣的生成类型相对应的“活动解决方案配置”(例如“调试”或“发布”)和“活动解决方案平台”(例如 Win32)。
  4. 从“生成”菜单中,选择“生成解决方案”。

有关详细信息,请参阅生成驱动程序

步骤 4:配置用于测试和调试的计算机

要测试和调试驱动程序,需要在主计算机上运行调试器,在目标计算机上运行驱动程序。 到目前为止,你已经在主计算机上使用 Visual Studio 生成了驱动程序。 接下来需要配置目标计算机。 要配置目标计算机,请按照为驱动程序部署和测试配置计算机中的说明执行操作。

步骤 5:启用内核调试跟踪

模板代码包含多条跟踪消息 (TraceEvents),可帮助对函数调用进行跟踪。 源代码中的所有函数都包含跟踪消息,用于标记例程的进入和退出。 对于错误,跟踪消息包含错误代码和一个有意义的字符串。 由于驱动程序项目启用了 WPP 跟踪,因此在生成过程中创建的 PDB 符号文件包含了跟踪消息格式说明。 如果为 WPP 跟踪配置了主计算机和目标计算机,驱动程序就可以向文件或调试器发送跟踪消息。

配置主计算机以便进行 WPP 跟踪:

  1. 从 PDB 符号文件中提取跟踪消息格式说明,以便创建跟踪消息格式 (TMF) 文件。

    可以使用 Tracepdb.exe 来创建 TMF 文件。 该工具位于 WDK 的 <安装文件夹>Windows Kits\10.0\bin\<architecture> 文件夹中。 以下命令将为驱动程序项目创建 TMF 文件。

    tracepdb -f <PDBFiles> -p <TMFDirectory>

    -f 选项指定 PDB 符号文件的位置和名称。 -p 选项指定由 Tracepdb 创建的 TMF 文件的位置。 有关详细信息,请参阅 Tracepdb 命令

    在指定位置可看到三个文件(项目中每个 .c 文件一个)。 它们会被赋予 GUID 文件名。

  2. 在调试器中键入以下命令:

    1. .load Wmitrace

      加载 Wmitrace.dll 扩展。

    2. .chain

      验证调试器扩展是否已加载。

    3. !wmitrace.searchpath +<TMF 文件位置>

      将 TMF 文件的位置添加到调试器扩展的搜索路径中。

      输出如下所示:

      Trace Format search path is: 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE;c:\drivers\tmf'

要配置目标计算机以便进行 WPP 跟踪,请执行以下操作:

  1. 确保在目标计算机上安装了 Tracelog 工具。 该工具位于 WDK 的 <安装文件夹>Windows Kits\8.0\Tools\<arch> 文件夹中。 有关详细信息,请参阅 Tracelog 命令语法

  2. 打开命令窗口并以管理员身份运行。

  3. 输入以下命令:

    tracelog -start MyTrace -guid #c918ee71-68c7-4140-8f7d-c907abbcb05d -flag 0xFFFF -level 7-rt -kd

    该命令将启动名为 MyTrace 的跟踪会话。

    guid 参数指定跟踪提供程序(即客户端驱动程序)的 GUID。 可以从 Visual Studio Professional 2019 项目中的 Trace.h 获取 GUID。 另一种方法是键入以下命令,在 .guid 文件中指定 GUID。 文件包含连字符格式的 GUID:

    tracelog -start MyTrace -guid c:\drivers\Provider.guid -flag 0xFFFF -level 7-rt -kd

    键入以下命令即可停止跟踪会话:

    tracelog -stop MyTrace

步骤 6:在目标计算机上部署驱动程序

  1. 在“解决方案资源管理器”窗口中,选择并按住(或右键单击)*<项目名称>*Package,然后选择“属性”。
  2. 在左窗格中,导航到配置属性>驱动程序安装>部署
  3. 选中“启用部署”,然后选中“导入到驱动程序存储区”。
  4. 远程计算机名称中,指定目标计算机的名称。
  5. 选择“安装并验证”
  6. 选择“确定”。
  7. 在“调试”菜单上,选择“开始调试”或按键盘上的 F5

注意

不要在“硬件 ID 驱动程序更新”下指定设备的硬件 ID。 硬件 ID 只能在驱动程序信息 (INF) 文件中指定。

有关在 Visual Studio 中将驱动程序部署到目标系统的详细信息,请参阅将驱动程序部署到测试计算机

也可以使用“设备管理器”在目标计算机上安装驱动程序。 如果要通过命令提示符安装驱动程序,可以使用这些实用工具:

  • PnPUtil

    此工具随 Windows 一起提供。 它位于 Windows\System32 中。 可以使用此实用工具将驱动程序添加到驱动程序存储区中。

    C:\>pnputil /a m:\MyDriver_.inf
    Microsoft PnP Utility
    
    Processing inf : MyDriver_.inf
    Driver package added successfully.
    Published name : oem22.inf
    

    有关详细信息,请参阅 PnPUtil 示例

  • DevCon Update

    此工具随 WDK 提供。 可以用它来安装和更新驱动程序。

    devcon update c:\windows\inf\MyDriver_.inf USB\VID_0547&PID_1002\5&34B08D76&0&6
    

步骤 7:在“设备管理器”中查看驱动程序

  1. 输入以下命令,打开“设备管理器”:

    devmgmt
    
  2. 验证“设备管理器”是否显示了以下节点的节点:

    示例

    MyUSBDriver_Device

步骤 8:在调试器中查看输出

Visual Studio 会首先在“输出”窗口中显示进度。 然后会打开“调试器即时窗口”。 验证主计算机调试器中是否出现了跟踪消息。 输出结果应如下所示,其中“MyUSBDriver_”是驱动程序模块的名称:

[3]0004.0054::00/00/0000-00:00:00.000 [MyUSBDriver_]MyUSBDriver_EvtDriverContextCleanup Entry
[1]0004.0054::00/00/0000-00:00:00.000 [MyUSBDriver_]MyUSBDriver_EvtDriverDeviceAdd Entry
[1]0004.0054::00/00/0000-00:00:00.000 [MyUSBDriver_]MyUSBDriver_EvtDriverDeviceAdd Exit
[0]0004.0054::00/00/0000-00:00:00.000 [MyUSBDriver_]DriverEntry Entry
[0]0004.0054::00/00/0000-00:00:00.000 [MyUSBDriver_]DriverEntry Exit