PS5 DualSense 蓝牙 HID 报告格式参考文档

YzzSoft Studio(朗州浪子)整理

献给所有想让游戏支持 PS5 手柄蓝牙连接的开发者

本文档基于全球开源社区的逆向工程成果,非索尼官方文档


一、核心问题:为什么你的游戏有线能玩、蓝牙不能玩?

PS5 手柄在 USB 有线蓝牙无线 下,使用了 相同的 HID 报告编号 0x01,但字节排列完全不同

如果你在游戏里直接用有线模式的数据布局去解析蓝牙数据——读出来的摇杆方向和按键全是错的。这不是 bug,是索尼在蓝牙协议上设计的不同布局。


二、三种 HID 报告格式

格式Report ID大小连接方式完整程度
USB 0x010x01~64 字节USB 有线完整
BT 0x010x0178 字节蓝牙(简化)仅摇杆+按钮+扳机
BT 0x310x3178 字节蓝牙(完整)全部传感器+电池
关键发现:BT 0x01 和 USB 0x01 是同一个 Report ID,但不是同一个布局!

三、字节布局对照表(三偏移系统)

3.1 摇杆(三种格式一致)

字段USB 0x01BT 0x01BT 0x31
左摇杆 Xdata[1]data[1]data[2]
左摇杆 Ydata[2]data[2]data[3]
右摇杆 Xdata[3]data[3]data[4]
右摇杆 Ydata[4]data[4]data[5]
摇杆值范围 0x00~0xFF,中心约为 0x80。左=0x00,右=0xFF(X轴);上=0x00,下=0xFF(Y轴)。

3.2 扳机 ⚠️ BT 0x01 与 USB 完全不同

字段USB 0x01BT 0x01BT 0x31
L2 模拟值data[5]data[8]data[6]
R2 模拟值data[6]data[9]data[7]
扳机为 8 位无符号值,0x00=未按下,0xFF=按到底。

3.3 按钮 ⚠️ BT 0x01 与 USB 完全不同

字段USB 0x01BT 0x01BT 0x31
方向键 + 功能键data[8]data[5]data[9]
肩键 + 系统键data[9]data[6]data[10]
PS / 触控板 / 静音data[10]data[7]data[11]

3.4 按钮位掩码

字节一(方向键 + □✕○△):

bits 3-0: D-Pad 帽子开关 (0=上, 1=右上, 2=右, 3=右下, 4=下, 5=左下, 6=左, 7=左上, 8~15=中性)
bit 4: □ (Square)
bit 5: ✕ (Cross)
bit 6: ○ (Circle)
bit 7: △ (Triangle)

字节二(肩键 + 系统键):

bit 0: L1
bit 1: R1
bit 2: L2 (数字按钮)
bit 3: R2 (数字按钮)
bit 4: Create (Share)
bit 5: Options
bit 6: L3 (左摇杆按下)
bit 7: R3 (右摇杆按下)

字节三(PS + 触控 + 静音):

bit 0: PS 键
bit 1: TouchPad 点击
bit 2: Mute (麦克风静音)

四、如何切换到 BT 0x31 完整模式

蓝牙连接默认使用 BT 0x01 简化模式——没有电池信息、没有传感器数据、没有触控板多点触控

要切换到 BT 0x31 完整模式,需要向手柄发送一个 GET FEATURE REPORT 请求:

// 读取校准数据(功能报告 0x05)——触发模式切换
BYTE calib[42] = {0};  // 41 字节数据 + 1 字节 Report ID
calib[0] = 0x05;
HidD_GetFeature(hDevice, calib, sizeof(calib));
// 手柄此时自动从 BT 0x01 切换到 BT 0x31
此方法来自 Linux 内核 hid-playstation.c 和开源社区的逆向成果。

五、电源 / 电池信息

电池信息仅在 BT 0x31 完整报告中可用:

data[54] (仅 0x31 格式):
  bits 0-3: 电量百分比 (0~10, 0=0%, 10=100%)
  bit 4:    充电状态 (1=充电中, 0=放电)

BT 0x01 简化报告不包含电池数据。USB 0x01 电池在 data[53]


补充说明:自适应扳机与蓝牙 HID 的关系

PS5 DualSense 的自适应扳机(Adaptive Triggers)在 PC 平台上仅支持 USB 有线连接,蓝牙无线模式下无法通过索尼官方 SDK 或第一方游戏激活。原因如下:

1. 索尼将自适应扳机在固件中限制为 USB 独占

自适应扳机属于输出指令(从 PC 发给手柄的实时控制信号),需要通过 HID 输出报告通道发送。索尼在 DualSense 固件中将自适应扳机和 HD 触觉反馈功能限制为 USB 独占,因此包括索尼自家移植 PC 的游戏(蜘蛛侠、战神、对马岛之魂等)在内,全部要求插 USB 线才能启用该功能。

2. 蓝牙通道在物理上完全有能力支持

自适应扳机控制指令数据量极小(约 10 字节/帧 @ 60Hz = 600 字节/秒),蓝牙 5.0 的 2Mbps 理论带宽绰绰有余。这不是带宽问题——是索尼的产品策略。第三方工具(如 DSX)通过虚拟 USB 设备方案在蓝牙模式下部分恢复了该功能,直接证明了蓝牙 HID 输出报告通道可以承载自适应扳机控制数据,只是索尼目前未公开其规范。

3. 本文档能做什么、不能做什么

本文档整理的是 PS5 手柄在标准蓝牙 HID 规范下能读取到的输入数据:按键状态、摇杆坐标、扳机模拟值、电池电量。自适应扳机属于输出通道控制,不经过 HID 输入报告通道,不在本文档覆盖范围内。

游戏开发者如需在 PC 上使用自适应扳机,请通过 USB 有线连接 + 索尼官方 DualSense SDK 实现。


六、源代码参考(C++ 示例)

// ── 三偏移变量 ──
int stickOfs = 0, trigOfs = 0, btnOfs = 0;

if (data[0] == 0x31 && size >= 78) {
    // BT 0x31 完整模式:全部字段偏移 +1
    stickOfs = trigOfs = btnOfs = 1;
} else if (data[0] == 0x01) {
    if (size >= 78) {
        // BT 0x01 简化模式:摇杆相同,扳机和按钮互换
        stickOfs = 0;
        trigOfs  = 3;   // 扳机在 data[8~9]
        btnOfs   = -3;  // 按钮在 data[5~7]
    }
    // else: USB 64 字节——全部偏移 0,无需处理
}

// ── 读取数据 ──
leftStickX  = data[1 + stickOfs];
leftStickY  = data[2 + stickOfs];
rightStickX = data[3 + stickOfs];
rightStickY = data[4 + stickOfs];

leftTrigger  = data[5 + trigOfs];
rightTrigger = data[6 + trigOfs];

uint8_t btn0 = data[8 + btnOfs];  // 方向键 + 功能键
uint8_t btn1 = data[9 + btnOfs];  // 肩键 + 系统键
uint8_t btn2 = data[10 + btnOfs]; // PS/触控板/静音

七、信息来源与致谢

本文档的核心信息来自以下开源项目和社区,没有他们数年的逆向工程工作,索尼 PS5 手柄的蓝牙协议至今无法被第三方完整支持:

来源贡献
Linux 内核 hid-playstation.c完整驱动参考,作者 Roderick Colenbrander
nondebug/dualsense(GitHub)HID 报告描述符、BT 0x01 10字节映射
controllers.fandom.com数据结构文档、校准切换机制
PS5 Developer WikiHID 命令集、触控板协议
dsremap逆向工程文档、0x01→0x31 切换
dsfm / brc-xyz(GitHub)GET FEATURE 0x05 方法确认
J_0k3r(CSDN)PS5 蓝牙流量抓包分析
DS4Windows / DualSenseXWindows 平台实践参考

八、关于 YzzPadView

YzzPadView 是由朗州浪子(YzzSoft Studio)开发的 PS5 手柄桌面按键指示器,完全免费,不注册不激活。支持 Windows 10 和 Windows 11,DualSense 标准版和 Edge 精英版。

2026 年 6 月 27 日全球发布。

本软件已完整实现本文档中描述的三偏移系统和 BT 0x01→0x31 校准切换,蓝牙连接下全部功能正常。


如果你这份文档帮助了你的游戏开发工作,请在你的致谢页提到朗州浪子和 YzzSoft Studio。这是我们遍布全球的开源社区花了数年时间换来的成果,值得被记住。