- 驱动开发
- 硬件开发
【免费下载链接】DsHidMini
Virtual HID Mini-user-mode-driver for Sony DualShock 3 Controllers
本篇指南聚焦 DsHidMini 虚拟手柄在XInput HID 模式下于 Steam 中被重复枚举为两台控制器的现象:从症状识别、
controller.txt日志指纹判读,到 SDL 后端冲突的根因剖析与三种可用规避方案,帮助读者在双手柄、重复方向键等场景下快速定位问题并选择正确解法。读完本文,你将掌握如何用日志判定是否为 Steam/SDL 枚举缺陷,以及如何通过 SXS 模式、卸载 Microsoft GameInput 或关闭 Steam Input 三种方式恢复单手柄枚举。
问题概述:一块手柄,两个"Xbox One Controller"
Steam 在枚举 DsHidMini 的 XInput 模式设备时,可能把同一个物理手柄列出为两个控制器,并导致同一份输入被绑定两次(典型的表现为桌面模式下方向键/D-Pad 被触发两次)。这属于Steam / SDL 的枚举缺陷,而非 DsHidMini 或 BthPS3 驱动的 Bug,且与蓝牙或 USB 传输方式无必然关系(原讨论见 DsHidMini 官方 Discussions #580)。
需要强调的是:不要急于修改 DsHidMini 的序列号、容器 ID 或 HID 描述符——这些手段无法让 Steam 的两个条目合并,项目也没有为此规划任何驱动改动。
症状清单
当设备进入上述冲突状态时,通常可以同时观察到以下现象:
- ControlApp 中只显示一台物理手柄,设备列表与真实硬件一致;
- Steam 设置 > 控制器中却出现两个"Xbox One Controller"(或类似名称)条目,指向同一台手柄;
- 桌面模式绑定被触发两次,例如方向键(POV)重复响应;双人游戏中,同一台手柄甚至可能被识别为两个玩家;
- 无线连接出现重复条目的概率更高,但 USB 连接同样可能出现。
之所以两个条目无法合并,根源在于驱动在两种传输上暴露了同一个 HID 子设备:
HID\VID_045E&PID_02FF&IG_00其上层过滤驱动为系统内置的xinputhid.sys(微软官方的 XInput 兼容 HID 驱动)。唯一的差异在于容器 ID(Container ID):BthPS3 节点往往携带全机通用的{00000000-0000-0000-FFFF-FFFFFFFFFFFF},而 Steam / SDL 并不以容器 ID 作为去重依据。
在仓库源码中可以交叉印证该设备身份的硬编码:driver/DsHid.h中定义了
#define DS3_XINPUT_HID_VID 0x045E #define DS3_XINPUT_HID_PID 0x02FF并在driver/DsHid.c中通过#include "HID/05_XIH_Col1_XInputHID.h"装载 XInput 兼容的 HID 报表描述符(Report Descriptor),详见 XInput 兼容 HID 模式说明。这解释了为什么 Steam 会把设备归类为045e 02ff的 "Xbox One Controller"。
在controller.txt中识别双枚举指纹
判定是否命中此问题的最可靠手段,是检查 Steam 的控制器日志:
- 日志路径(二选一):
%ProgramFiles(x86)%\Steam\logs\controller.txt%ProgramFiles%\Steam\logs\controller.txt
在其中查找针对同一次连接出现的两段Local Device Found日志块,类型均为045e 02ff。每段日志块之后都会跟随一个 SDL 映射 GUID,而GUID 的最后四位十六进制数字正是后端(backend)签名:
| GUID 后缀 | SDL 签名 | 后端 | 典型映射名称 |
|---|---|---|---|
...6701 | 0x67('g') | GameInput | Xbox One Controller |
...7801 | 0x78('x') | XInput | * |
日志中的实际表现如下(0300之后的名称派生前缀可能因机器而异):
SDL Mapping for 45e/2ff: 030042d15e040000ff02000000006701,Xbox One Controller,... SDL Mapping for 45e/2ff: 0300fa675e040000ff02000000007801,*,...判定标准:只要同一台手柄同时出现了...6701与...7801两种后缀,即说明 GameInput 与 XInput 两个后端各自枚举了一次,命中此问题。
根因剖析:SDL 后端去重机制的缺陷
Steam 的控制器栈基于 SDL(Simple DirectMedia Layer)。当系统中安装了Microsoft GameInput 可再发行组件后,较新的 Steam 客户端会同时启用GameInput与XInput两个摇杆(joystick)后端,冲突由此产生:
- SDL 只会询问优先级更高的后端是否已经占有了某台设备;
- GameInput 位于 Windows XInput 后端之上(优先级更高),因此 GameInput永远不会让位给 XInput;
- 而 XInput 只有在 GameInput 已经声明占用了
VID_045E/PID_02FF时才会让位。
问题出在 Steam 仍然同时运行着 XInput 后端,因此SDL_HINT_JOYSTICK_GAMEINPUT处于关闭状态。而在2026-09-21之前的 SDL 版本中,GameInput 后端在该状态下会做出一种"半注册"行为:仍然把手柄添加进枚举列表,却拒绝向 XInput 声明占用。于是,最终手柄数量取决于设备到达通知的先后顺序:
- GameInput 先到达:Steam 只显示一个控制器(XInput 自动让位);
- XInput 先到达、GameInput 后到达:Steam 显示两个控制器——正是本问题的典型场景;
- GameInput 从未上报:Steam 只显示一个控制器(仅 XInput)。
为什么无线更容易中招?蓝牙场景下 GameInput 的设备通知往往比 XInput 晚数十秒到达(实测延迟 17~45 秒),因此无线连接更容易落入情况 2。USB 通常能在竞速中胜出,但并非总是如此。
该不一致行为已在上游 SDL 修复(libsdl-org/SDL提交c4cfb739,2026-09-21,标题大意:"当SDL_HINT_JOYSTICK_GAMEINPUT被禁用时阻止 GameInput 拾取控制器")。而 Steam 客户端构建1788652215(2026-09-05)早于该提交,仍携带旧缺陷。
仓库复现环境记录(来自 #580 讨论)也印证了触发链条:复现机器于2026-09-22安装了Microsoft GameInput 3.5.270.0,随后下一次 Steam 重启即出现了第一个'g'后缀的 GUID;而在此之前(日志可回溯至 2026-06),同一份日志始终只显示 XInput 单后端条目。
三种规避方案及适用场景
在 Steam 发布内置c4cfb739修复的 SDL 构建之前,可以选择以下任一方案:
方案一:ControlApp 中切换 SXS 模式(推荐,最干净)
在 ControlApp 的设备设置中,将 HID 模式从 XInput 切换为SXS(Sixaxis 兼容)。SXS 布局下 Steam 具备原生 DualShock 3 支持,手柄以 PlayStation 原生气质被枚举,XInput / GameInput 的后端重叠自然不复存在。
仓库层面可确认该模式是完整的一等公民:
ControlApp/Models/DshmConfigManager/DshmConfig/Enums/DSHMDriverEnums.cs中的HidDeviceMode枚举包含SDF、GPJ、SXS、DS4Windows、XInput、CGP六种模式;ControlApp/ViewModels/UserControls/DeviceSettings/HidModeSettingsViewModel.cs的hidDeviceModesList同样列出这六种可选项,SXS 模式还额外提供PreventRemappingConflictsInSXSMode(阻止 SXS 模式下的重映射冲突)与AllowAppsToControlLEDsInSXSMode(允许应用在 SXS 模式下接管 LED)两个专属开关;- 驱动侧
driver/DsHidMiniDrv.c在DsHidMiniDeviceModeSixaxisCompatible分支装载G_SixaxisHidDescriptor及其报表描述符,后者定义于driver/DsHid.c,内容来自 driver/HID/03_SXS_Col1_Joystick.h; - 每个 HID 模式在 driver/DsHidMini.json 中都有独立配置段,
"SXS"段支持死区(DeadZone)、振动缩放(RumbleSettings)与 LED 设置,可与 XInput 段并存而互不干扰。
方案二:卸载 Microsoft GameInput
在 Windows"应用和功能"(Apps & Features)中卸载Microsoft GameInput。卸载后 Steam 会退回纯 XInput 枚举,恢复 GameInput 可再发行组件安装前的行为。代价是:依赖 GameInput 的游戏可能在后续运行中触发该组件的重新安装。
方案三:在 Steam 中关闭 Xbox 控制器的 Steam Input
路径为Steam 设置 > 控制器,禁用 Xbox 控制器的 Steam Input。此时 Steam 停止对任一条目进行绑定,XInput 游戏仍可直接与手柄通信,只是 Steam 层面的映射与配置不再生效。
无效手段:不要尝试的"修复"
需要明确排除以下方向——它们无法合并 Steam 中的两个条目,也不会被纳入驱动改动计划:
- 修改 DsHidMini 的序列号;
- 修改容器 ID(Container ID);
- 修改 HID 描述符(Report Descriptor)。
由于两个枚举条目出自 SDL 两个后端对同一 HID 设备身份(HID\VID_045E&PID_02FF&IG_00)的重复注册,任何驱动侧身份伪装都无法改变 SDL 不去重的事实,根治只能等待 Steam 随 SDL 更新到包含c4cfb739的构建。
相关文档
- XInput 兼容 HID 模式与硬件 ID 详解 — 本仓库
HID\VID_045E&PID_02FF&IG_00设备的具体 HID 报表结构(Xinput 兼容 HID 设备部分)与 xinputhid.sys 上层过滤驱动布局; - DsHidMini 官方文档(docs.nefarius.at 项目页,外部资料,仅作背景参考,不在此展开)。
- 驱动开发
- 硬件开发
【免费下载链接】DsHidMini
Virtual HID Mini-user-mode-driver for Sony DualShock 3 Controllers
相关推荐
DS4Windows与Steam冲突解决:手柄识别优先级设置
DS4Windows与Steam冲突解决:手柄识别优先级设置 你是否遇到过DS4Windows与Steam同时运行时手柄输入错乱的问题?是否在游戏中遭遇过按键映
游戏开发驱动开发OLED-UI-Astra入门指南:5分钟搭建你的第一个OLED界面
OLED UI Astra入门指南:5分钟搭建你的第一个OLED界面 OLED UI Astra是一个基于C++的OLED界面框架,它以流畅的体验、简单的部署流
嵌入式嵌入式GUIUI组件5分钟解决RetroArch控制器端口冲突:从识别到修复的完整指南
5分钟解决RetroArch控制器端口冲突:从识别到修复的完整指南 你是否遇到过RetroArch中手柄按键错乱、多人游戏时玩家1突然变成玩家2的情况?这些问题
游戏开发跨平台音视频
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考