找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2172

积分

0

好友

303

主题
发表于 昨天 12:46 | 查看: 6| 回复: 0

在上一篇文章中,我们介绍了 Windows 平台上的 USB Device Emulation (UDE) 技术。这是一项非常有趣的技术,它允许我们在没有物理 USB 硬件的情况下,在系统中模拟出一个完整的 USB 主机控制器,以及连接到其端口的虚拟 USB 设备。从本文开始,本系列文章将带大家一步步实现如何使用 UDE 技术来模拟一个 USB 摄像头。

作为整个模拟过程的第一步,我们需要先创建一个虚拟的 USB 主机控制器以及一个与之关联的 USB 根集线器。这篇文章就将详细介绍如何完成这基础但关键的一步。

实现这一功能,需要我们编写一个 UDE 客户端驱动 (UDE Client Driver) 。这个驱动本质上仍然是一个 WDF 驱动,它负责模拟 USB 主机控制器和挂载在其上的设备。与普通 WDF 驱动的区别在于,我们需要额外调用由 UDE 类扩展框架 (Udecx) 提供的 API 来完成虚拟控制器的创建。

我们可以借助 Visual Studio 的 WDF 驱动模板快速生成基础的驱动框架代码,然后在此基础上添加我们的逻辑。本示例中将驱动命名为 VirtualUVC,生成的项目结构如下所示。

VirtualUVC驱动项目解决方案文件结构

首先,我们需要修改驱动的 INF 配置文件。由于目标是模拟 USB 主机控制器,我们将驱动的设备类别(Class)设置为 USB,并将设备描述(DeviceDesc)修改为 VirtualUSBHostController。这样,在安装驱动后,设备管理器的“通用串行总线控制器”类别下就会出现一个名为 VirtualUSBHostController 的设备。

VirtualUVC驱动INF配置文件内容

接下来是核心的驱动代码编写。熟悉 WDF 驱动开发的同学都知道,关键的实现在于 EvtDriverDeviceAdd 回调函数。在我们的驱动中,这个函数对应的是 VirtualUVCCreateDevice。下图展示了该函数的关键步骤,具体细节我们在下文展开。

VirtualUVC驱动中创建设备的核心C语言代码

创建一个虚拟的 USB 主机控制器 主要包含以下几个步骤:

  1. 初始化 Udecx:首先,在已经设置好必要 PnP 回调函数的基础上,调用 UdecxInitializeWdfDeviceInit 函数,传入 WDF 框架提供的 WDFDEVICE_INIT 指针。
  2. 创建设备对象:接着,调用 WdfDeviceCreate 函数。这个函数创建的 WDF 设备对象,就代表了我们要模拟的 虚拟USB主机控制器
  3. 创建设备接口:为了让用户态应用程序能识别并操作这个控制器,我们需要为设备对象创建并注册一个设备接口。这个接口的 GUID 必须是微软定义的 GUID_DEVINTERFACE_USB_HOST_CONTROLLER
  4. 注册UDE回调:最后,调用 UdecxWdfDeviceAddUsbDeviceEmulation 函数,并向 Udecx 框架注册一个名为 EvtUdecxWdfDeviceQueryUsbCapability 的回调函数。UDE 客户端驱动必须通过这个回调,将 虚拟USB主机控制器 所支持的功能报告给 Udecx 框架和操作系统。

创建好虚拟控制器后,我们还需要为其创建一个用于处理 IO 请求的队列,主要用来响应上层应用程序发送的 IOCTL 控制代码。

初始化WDF队列的C语言代码

如前所述,驱动在创建虚拟控制器后会暴露一个 GUID_DEVINTERFACE_USB_HOST_CONTROLLER 设备接口。应用程序会通过此接口打开设备并发送与 USB 主机控制器相关的 IOCTL。为了处理这些请求,驱动需要注册 EvtIoDeviceControl 回调函数(即示例中的 VirtualUVCEvtIoDeviceControl)。

在这个函数的实现中,我们有一个便捷的选择:将大部分标准 USB 主机控制器 IOCTL 直接转发给 Udecx 框架处理,而不是自己处理。转发的方法是调用 UdecxWdfDeviceTryHandleUserIoctl 函数。如果 Udecx 识别并处理了该 IOCTL(例如获取设备描述符的请求),此函数会返回 TRUE;否则返回 FALSE。对于 Udecx 不处理的请求,驱动可以简单地调用 WdfRequestComplete 并返回一个失败状态码来完成请求。

处理设备控制请求IOCTL的C语言代码

完成以上代码后,这个 UDE 客户端驱动就已经能够模拟出一个 USB 主机控制器 以及一个 USB 根集线器 (USB Root Hub) 。由于该驱动不依赖于真实的物理硬件,我们需要使用 devcon 工具,通过指定设备ID的方式来安装它,命令如下:

devcon install VirtualUVC.inf Root\VirtualUVC

安装成功后,在 Windows 的设备管理器中,你就能看到这个虚拟的 USB 主机控制器设备。

设备管理器中的VirtualUSBHostController设备属性

并且,这个虚拟控制器上已经连接好了一个 USB 根集线器。

设备管理器中虚拟USB主机控制器下的USB根集线器属性

我们可以使用 USBTreeView 这类工具来更直观地查看设备树。该工具能正确识别出这个 虚拟USB主机控制器 及其附带的 USB 根集线器。值得注意的是,这个根集线器上已经具备了两个可用的 USB 端口,为后续挂载虚拟设备做好了准备。

USBTreeView工具显示的虚拟USB主机控制器树状结构

USBTreeView工具显示的USB根集线器详细信息

至此,虽然我们编写的核心逻辑代码并不多,但已经成功地借助 Udecx 框架,在系统中完整地模拟出了 USB 主机控制器USB 根集线器 以及其物理端口。这为后续模拟更复杂的 USB 设备(如摄像头)奠定了坚实的基础。在下一篇文章中,我们将在这个虚拟的 USB 主机控制器 端口上挂载一个 USB 摄像头设备,并实现其基本功能。

如果你对 Windows 驱动开发、网络/系统底层技术或 USB 协议栈感兴趣,欢迎在 云栈社区 交流分享更多实践经验与资源。




上一篇:企业注册功能PostgreSQL SQL注入实战:从报错到文件读写与命令执行
下一篇:Open-AutoGLM 部署运行笔记
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-11 20:16 , Processed in 0.378448 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表