Monado OpenXR Runtime
Loading...
Searching...
No Matches
pssense_protocol.h
Go to the documentation of this file.
1// Copyright 2023, Collabora, Ltd.
2// Copyright 2023, Jarett Millard
3// Copyright 2026, Beyley Cardellio
4// SPDX-License-Identifier: BSL-1.0
5/*!
6 * @file
7 * @brief PlayStation Sense controller prober and driver code.
8 * @author Jarett Millard <jarett.millard@gmail.com>
9 * @author Beyley Cardellio <ep1cm1n10n123@gmail.com>
10 * @ingroup drv_pssense
11 */
12
13#pragma once
14
15#include "xrt/xrt_byte_order.h"
16
17#include "math/m_api.h"
18
19
20#pragma pack(push, 1)
21
22// @todo Remove when clang-format is updated in CI
23// clang-format off
24// IMU ticks are in thirds of a microsecond, so 1 tick = 333.333... nanoseconds
25#define NS_TO_IMU_TICKS(ns) (((uint64_t)(ns) * 3) / 1000)
26#define IMU_TICKS_TO_NS(ticks) (((uint64_t)(ticks) * 1000) / 3)
27
28#define PERIOD_ID_TO_DURATION_NS(period_id) (time_duration_ns)(IMU_TICKS_TO_NS(150LLU * (uint64_t)period_id + 1250))
29// @note: the +1 is to ensure things round correctly when dealing with converting to and back
30#define DURATION_NS_TO_PERIOD_ID(duration_ns) (uint8_t)(((NS_TO_IMU_TICKS(duration_ns + 1) - 1250) / 150LLU) & 0xFF)
31// clang-format on
32
33#define STABLE_MIN_PERIOD_ID 20
34
35#define MIN_PERIOD_ID 1
36#define MAX_PERIOD_ID 42
37
38#define PCM_SAMPLE_RATE 3000
39#define PCM_HAPTIC_BUF_SIZE 32
40
41const uint8_t INPUT_REPORT_ID = 0x31;
42const uint8_t OUTPUT_REPORT_ID = 0x31;
43const uint8_t OUTPUT_REPORT_TAG = 0x10;
44const uint8_t CALIBRATION_DATA_FEATURE_REPORT_ID = 0x05;
45
46#define CALIBRATION_DATA_PART_ID_1 0
47#define CALIBRATION_DATA_PART_ID_2 0x81
48
49const uint8_t INPUT_REPORT_CRC32_SEED = 0xa1;
50const uint8_t OUTPUT_REPORT_CRC32_SEED = 0xa2;
51const uint8_t FEATURE_REPORT_CRC32_SEED = 0xa3;
52
53//! Gyro read value range is +-32768.
54const double PSSENSE_GYRO_SCALE_DEG = 180.0 / 1024;
55//! Accelerometer read value range is +-32768 and covers +-8 g.
57
58const uint8_t CHARGE_STATE_DISCHARGING = 0x00;
59const uint8_t CHARGE_STATE_CHARGING = 0x01;
60const uint8_t CHARGE_STATE_FULL = 0x02;
61const uint8_t CHARGE_STATE_ABNORMAL_VOLTAGE = 0x0A;
62const uint8_t CHARGE_STATE_ABNORMAL_TEMP = 0x0B;
63const uint8_t CHARGE_STATE_CHARGING_ERROR = 0x0F;
64
65#define INPUT_REPORT_LENGTH 78
66/*!
67 * HID input report data packet.
68 */
70{
71 uint8_t report_id;
72 uint8_t bt_header;
73 uint8_t thumbstick_x;
74 uint8_t thumbstick_y;
75 uint8_t trigger_value;
76 uint8_t trigger_proximity;
77 uint8_t squeeze_proximity;
78 uint8_t unknown1[2]; // Always 0x0001
79 uint8_t buttons[3];
80 uint8_t unknown2; // Always 0x00
81 __le32 seq_no;
82 __le16 gyro[3];
83 __le16 accel[3];
84 __le32 imu_ticks;
85 uint8_t temperature;
86 uint8_t unknown3[7];
87 uint8_t trigger_feedback_state;
88 uint8_t trigger_feedback_mode;
89 uint8_t battery_state; // High bits charge level 0x00-0x0a, low bits battery state
90 uint8_t plug_state; // Flags for USB data and/or power connected
91 __le32 host_timestamp;
92 __le32 device_timestamp_ticks;
93 uint8_t unknown4[4];
94 uint8_t aes_cmac[8];
95 uint8_t unknown5;
96 uint8_t crc_failure_count;
97 uint8_t padding[7];
98 __le32 crc;
99};
100static_assert(sizeof(struct pssense_input_report) == INPUT_REPORT_LENGTH, "Incorrect input report struct length");
101
102#define PS5_OUTPUT_REPORT_LENGTH 78
103
104enum pssense_output_settings_flag1
105{
106 PSSENSE_OUTPUT_SETTINGS_FLAG1_UNK0 = 1 << 0,
107 PSSENSE_OUTPUT_SETTINGS_FLAG1_RUMBLE_EMULATION = 1 << 1,
108 PSSENSE_OUTPUT_SETTINGS_FLAG1_ADAPTIVE_TRIGGER_ENABLE = 1 << 2,
109 PSSENSE_OUTPUT_SETTINGS_FLAG1_INTENSITY_INCREASE_SET_ENABLE = 1 << 3,
110 PSSENSE_OUTPUT_SETTINGS_FLAG1_INTENSITY_REDUCTION_SET_ENABLE = 1 << 4,
111 PSSENSE_OUTPUT_SETTINGS_FLAG1_UNK5 = 1 << 5,
112 PSSENSE_OUTPUT_SETTINGS_FLAG1_UNK6 = 1 << 6,
113 PSSENSE_OUTPUT_SETTINGS_FLAG1_UNK7 = 1 << 7,
114};
115
116#define OUTPUT_SETTINGS_ENABLE_VIBRATION_BITS \
117 (PSSENSE_OUTPUT_SETTINGS_FLAG1_UNK0 | PSSENSE_OUTPUT_SETTINGS_FLAG1_RUMBLE_EMULATION)
118
119#define OUTPUT_SETTINGS_VIBRATE_MODE_HIGH_120HZ 0x00
120// 0x20
121#define OUTPUT_SETTINGS_VIBRATE_MODE_LOW_60HZ (PSSENSE_OUTPUT_SETTINGS_FLAG1_UNK5)
122// 0x40
123#define OUTPUT_SETTINGS_VIBRATE_MODE_CLASSIC_RUMBLE (PSSENSE_OUTPUT_SETTINGS_FLAG1_UNK6)
124// 0x60
125#define OUTPUT_SETTINGS_VIBRATE_MODE_DIET_RUMBLE \
126 (PSSENSE_OUTPUT_SETTINGS_FLAG1_UNK5 | PSSENSE_OUTPUT_SETTINGS_FLAG1_UNK6)
127
129{
130 PSSENSE_OUTPUT_SETTINGS_FLAG2_UNK0 = 1 << 0,
131 PSSENSE_OUTPUT_SETTINGS_FLAG2_UNK1 = 1 << 1,
132 //! Used to mark whether to read the status LED enable bool or not.
134 PSSENSE_OUTPUT_SETTINGS_FLAG2_UNK3 = 1 << 3,
135 PSSENSE_OUTPUT_SETTINGS_FLAG2_UNK4 = 1 << 4,
136 PSSENSE_OUTPUT_SETTINGS_FLAG2_UNK5 = 1 << 5,
137 PSSENSE_OUTPUT_SETTINGS_FLAG2_UNK6 = 1 << 6,
138 PSSENSE_OUTPUT_SETTINGS_FLAG2_UNK7 = 1 << 7,
139};
140
141enum pssense_adaptive_trigger_mode
142{
143 TRIGGER_FEEDBACK_MODE_OFF = 0x05,
144
145 // simple versions of other effects, shouldn't be used
146 TRIGGER_FEEDBACK_MODE_SIMPLE_FEEDBACK = 0x01,
147 TRIGGER_FEEDBACK_MODE_SIMPLE_WEAPON = 0x02,
148 TRIGGER_FEEDBACK_MODE_SIMPLE_VIBRATION = 0x06,
149
150 // limited versions of official
151 TRIGGER_FEEDBACK_MODE_LIMITED_FEEDBACK = 0x11,
152 TRIGGER_FEEDBACK_MODE_LIMITED_WEAPON = 0x12,
153
154 // official ones found through reverse engineering
155 TRIGGER_FEEDBACK_MODE_FEEDBACK = 0x21,
156 TRIGGER_FEEDBACK_MODE_SLOPE_FEEDBACK = 0x22, // aka Bow
157 TRIGGER_FEEDBACK_MODE_WEAPON = 0x25,
158 TRIGGER_FEEDBACK_MODE_VIBRATION = 0x26,
159
160 // unofficial ones found through fuzzing firmware
161 TRIGGER_FEEDBACK_MODE_GALLOPING = 0x23,
162 TRIGGER_FEEDBACK_MODE_MACHINE = 0x27,
163};
164
166{
167 uint8_t mode; // See enum pssense_adaptive_trigger_mode
168 union {
169 uint8_t raw_parameters[10];
170 };
171};
172
173enum pssense_led_sync_phase
174{
175 // initializing
176 LED_SYNC_PHASE_INIT = 0,
177 // ???
178 LED_SYNC_PHASE_PRESCAN = 1,
179 // ???
180 LED_SYNC_PHASE_BROAD = 2,
181 // ???
182 LED_SYNC_PHASE_BG = 3,
183 // ???
184 LED_SYNC_PHASE_STABLE = 4,
185 // used during passthrough to prevent LEDs from bleeding into it
186 LED_SYNC_PHASE_LED_ALL_OFF = 5,
187 // probably 100% duty cycle?
188 LED_SYNC_PHASE_LED_ALL_ON = 6,
189 // probably also 100% duty cycle?
190 LED_SYNC_PHASE_DEBUG = 7,
191};
192
194{
195 uint8_t phase;
196 uint8_t sequence_number;
197 uint8_t period_id;
198 //! The position, in IMU ticks, @ref NS_PER_IMU_TICK
200 //! The length, in thirds of a nanosecond.
202 uint8_t led_blink[4];
203};
204
206{
207 //! See enum pssense_output_settings_flag1
208 uint8_t flag1;
209 //! See enum pssense_output_settings_flag2
210 uint8_t flag2;
211 //! Vibration amplitude from 0x00-0xff. Sending 0 turns vibration off.
213 //! Sony driver sometimes sets to 0x82.
214 uint8_t unk0;
215 //! Settings for the adaptive trigger
217 //! Time of packet send, in host time, in microseconds
219 //! Settings of the tracking LEDs.
221 //! Lower 4 bits for haptics reduction, upper 4 bits for trigger reduction. Decreases in 12.5% increments.
223 //! Whether to enable the status LED or not.
225 uint8_t unk1[2];
226};
227static_assert(sizeof(struct pssense_output_settings) == 38, "Incorrect output settings struct length");
228
229/**
230 * HID output report data packet matching the PS5 layout, with PCM haptics.
231 *
232 * Reference:
233 * https://github.com/BnuuySolutions/PSVR2Toolkit/blob/b6ffe9f03cb2456d9d07aea74e839d9c5fd188f5/projects/psvr2_openvr_driver_ex/sense_controller.h#L44
234 */
236{
237 uint8_t report_id;
238 uint8_t seq_no_mode; // High bits only; low bits are always 0
239 uint8_t tag; // Needs to be 0x10 for this report
240 struct pssense_output_settings settings;
241 uint8_t counter;
242 uint8_t haptics[PCM_HAPTIC_BUF_SIZE];
243 __le32 crc;
244};
245static_assert(sizeof(struct pssense_ps5_output_report) == PS5_OUTPUT_REPORT_LENGTH,
246 "Incorrect output report struct length");
247
248#define FEATURE_REPORT_LENGTH 64
249#define CALIBRATION_DATA_LENGTH 116
250
251/**
252 * HID output report data packet.
253 */
255{
256 uint8_t report_id;
257 uint8_t part_id;
258 uint8_t data[CALIBRATION_DATA_LENGTH / 2];
259 __le32 crc;
260};
261static_assert(sizeof(struct pssense_feature_report) == FEATURE_REPORT_LENGTH, "Incorrect feature report struct length");
262
263#pragma pack(pop)
#define MATH_GRAVITY_M_S2
Standard gravity acceleration constant.
Definition m_api.h:53
C interface to math library.
pssense_output_settings_flag2
Definition pssense_protocol.h:129
@ PSSENSE_OUTPUT_SETTINGS_FLAG2_STATUS_LED_SET_ENABLE
Used to mark whether to read the status LED enable bool or not.
Definition pssense_protocol.h:133
const double PSSENSE_ACCEL_SCALE
Accelerometer read value range is +-32768 and covers +-8 g.
Definition pssense_protocol.h:56
const double PSSENSE_GYRO_SCALE_DEG
Gyro read value range is +-32768.
Definition pssense_protocol.h:54
HID output report data packet.
Definition pssense_protocol.h:255
HID input report data packet.
Definition pssense_protocol.h:70
Definition pssense_protocol.h:194
__le32 cycle_position
The position, in IMU ticks, NS_PER_IMU_TICK.
Definition pssense_protocol.h:199
__le32 cycle_length
The length, in thirds of a nanosecond.
Definition pssense_protocol.h:201
Definition pssense_protocol.h:166
Definition pssense_protocol.h:206
uint8_t flag2
See enum pssense_output_settings_flag2.
Definition pssense_protocol.h:210
struct pssense_led_settings led_settings
Settings of the tracking LEDs.
Definition pssense_protocol.h:220
__le32 host_timestamp_send_time_us
Time of packet send, in host time, in microseconds.
Definition pssense_protocol.h:218
uint8_t status_led_enable
Whether to enable the status LED or not.
Definition pssense_protocol.h:224
uint8_t vibration_amplitude
Vibration amplitude from 0x00-0xff. Sending 0 turns vibration off.
Definition pssense_protocol.h:212
uint8_t flag1
See enum pssense_output_settings_flag1.
Definition pssense_protocol.h:208
struct pssense_output_adaptive_trigger_settings trigger_settings
Settings for the adaptive trigger.
Definition pssense_protocol.h:216
uint8_t trigger_haptics_reduction
Lower 4 bits for haptics reduction, upper 4 bits for trigger reduction. Decreases in 12....
Definition pssense_protocol.h:222
uint8_t unk0
Sony driver sometimes sets to 0x82.
Definition pssense_protocol.h:214
HID output report data packet matching the PS5 layout, with PCM haptics.
Definition pssense_protocol.h:236
Endian-specific byte order defines.