tangled
alpha
login
or
join now
matrixfurry.com
/
monado
0
fork
atom
The open source OpenXR runtime
0
fork
atom
overview
issues
pulls
pipelines
d/pssense: Basic 3DoF pose tracking from IMU data
Jarett Millard
2 years ago
f1bc1000
e7c2c048
+277
-32
3 changed files
expand all
collapse all
unified
split
src
xrt
drivers
pssense
pssense_driver.c
pssense_interface.h
include
xrt
xrt_defines.h
+274
-32
src/xrt/drivers/pssense/pssense_driver.c
···
1
// Copyright 2023, Collabora, Ltd.
0
2
// SPDX-License-Identifier: BSL-1.0
3
/*!
4
* @file
···
24
#include "util/u_trace_marker.h"
25
26
#include "pssense_interface.h"
0
0
0
27
28
#include <stdio.h>
29
···
37
#define PSSENSE_WARN(p, ...) U_LOG_XDEV_IFL_W(&p->base, p->log_level, __VA_ARGS__)
38
#define PSSENSE_ERROR(p, ...) U_LOG_XDEV_IFL_E(&p->base, p->log_level, __VA_ARGS__)
39
40
-
DEBUG_GET_ONCE_LOG_OPTION(pssense_log, "PSSENSE_LOG", U_LOGGING_WARN)
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
41
42
/*!
43
* Indices where each input is in the input list.
···
64
PSSENSE_INDEX_TRIGGER_PROXIMITY,
65
PSSENSE_INDEX_THUMBSTICK,
66
PSSENSE_INDEX_THUMBSTICK_CLICK,
67
-
PSSENSE_INDEX_THUMBSTICK_TOUCH
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
68
};
69
70
/*!
···
72
*/
73
struct pssense_data_packet
74
{
75
-
uint8_t header;
0
76
uint8_t thumbstick_x;
77
uint8_t thumbstick_y;
78
uint8_t trigger_value;
79
uint8_t trigger_proximity;
80
uint8_t squeeze_proximity;
81
-
uint8_t reserved;
82
-
uint8_t seq_no;
83
uint8_t buttons[3];
0
0
0
0
0
0
0
0
0
0
0
84
};
85
86
/*!
···
88
*/
89
struct pssense_input_state
90
{
91
-
uint64_t timestamp;
92
-
uint8_t seq_no;
93
94
bool ps_click;
95
bool share_click;
···
112
bool thumbstick_click;
113
bool thumbstick_touch;
114
struct xrt_vec2 thumbstick;
0
0
0
115
};
116
117
/*!
···
138
//! Input state parsed from most recent packet
139
struct pssense_input_state state;
140
0
0
0
141
struct
142
{
143
bool button_states;
0
144
} gui;
145
};
146
0
0
0
0
0
0
0
0
0
0
0
0
0
147
/*!
148
* Reads one packet from the device, handles time out, locking and checking if
149
* the thread has been told to shut down.
150
*/
151
static bool
152
-
pssense_read_one_packet(struct pssense_device *pssense, uint8_t *buffer, size_t size)
153
{
154
os_thread_helper_lock(&pssense->controller_thread);
155
···
169
PSSENSE_ERROR(pssense, "Failed to read device '%i'!", ret);
170
return false;
171
}
172
-
if (ret != (int)size) {
0
173
PSSENSE_ERROR(pssense, "Unexpected HID packet size %i (expected %zu)", ret, size);
174
return false;
175
}
···
180
return false;
181
}
182
183
-
static void
184
pssense_parse_packet(struct pssense_device *pssense,
185
struct pssense_data_packet *data,
186
struct pssense_input_state *input)
187
{
188
-
input->timestamp = os_monotonic_get_ns();
189
-
input->seq_no = data->seq_no;
0
0
0
0
0
0
0
0
0
0
190
191
input->ps_click = (data->buttons[1] & 16) != 0;
192
input->squeeze_touch = (data->buttons[2] & 8) != 0;
···
217
input->trigger_click = (data->buttons[0] & 128) != 0;
218
input->thumbstick_click = (data->buttons[1] & 8) != 0;
219
}
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
220
}
221
222
static void *
···
228
229
union {
230
uint8_t buffer[sizeof(struct pssense_data_packet)];
231
-
struct pssense_data_packet input;
232
} data;
233
-
struct pssense_input_state input = {0};
234
235
-
while (os_hid_read(pssense->hid, data.buffer, sizeof(data), 0) > 0) {
236
-
// Empty queue first
0
0
0
237
}
238
239
-
// Now wait for a package to sync up, it's discarded but that's okay.
240
-
if (!pssense_read_one_packet(pssense, data.buffer, sizeof(data))) {
241
-
return NULL;
242
-
}
243
-
244
-
while (pssense_read_one_packet(pssense, data.buffer, sizeof(data))) {
245
-
pssense_parse_packet(pssense, (struct pssense_data_packet *)data.buffer, &input);
246
-
os_mutex_lock(&pssense->lock);
247
-
pssense->state = input;
248
-
os_mutex_unlock(&pssense->lock);
249
}
250
251
return NULL;
···
262
// Now that the thread is not running we can destroy the lock.
263
os_mutex_destroy(&pssense->lock);
264
0
0
265
// Remove the variable tracking.
266
u_var_remove_root(pssense);
267
···
282
os_mutex_lock(&pssense->lock);
283
284
for (uint i = 0; i < (uint)sizeof(enum pssense_input_index); i++) {
285
-
pssense->base.inputs[i].timestamp = (int64_t)pssense->state.timestamp;
286
}
287
pssense->base.inputs[PSSENSE_INDEX_PS_CLICK].value.boolean = pssense->state.ps_click;
288
pssense->base.inputs[PSSENSE_INDEX_SHARE_CLICK].value.boolean = pssense->state.share_click;
···
310
os_mutex_unlock(&pssense->lock);
311
}
312
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
313
#define SET_INPUT(NAME) (pssense->base.inputs[PSSENSE_INDEX_##NAME].name = XRT_INPUT_PSSENSE_##NAME)
314
315
int
···
335
XRT_PROBER_STRING_PRODUCT, //
336
product_name, //
337
sizeof(product_name)); //
338
-
if (ret != 0) {
339
U_LOG_E("Failed to get product name from Bluetooth device!");
340
return -1;
341
}
342
343
enum u_device_alloc_flags flags = U_DEVICE_ALLOC_TRACKING_NONE;
344
-
struct pssense_device *pssense = U_DEVICE_ALLOCATE(struct pssense_device, flags, 13, 1);
345
-
346
PSSENSE_DEBUG(pssense, "PlayStation Sense controller found");
347
-
pssense->base.destroy = pssense_device_destroy;
348
-
pssense->base.update_inputs = pssense_device_update_inputs;
349
pssense->base.name = XRT_DEVICE_PSSENSE;
350
snprintf(pssense->base.str, XRT_DEVICE_NAME_LEN, "%s", product_name);
0
0
0
0
0
0
0
0
0
351
352
pssense->log_level = debug_get_log_option_pssense_log();
353
pssense->hid = hid;
···
385
SET_INPUT(THUMBSTICK);
386
SET_INPUT(THUMBSTICK_CLICK);
387
SET_INPUT(THUMBSTICK_TOUCH);
0
0
388
389
ret = os_mutex_init(&pssense->lock);
390
if (ret != 0) {
···
407
return -1;
408
}
409
0
0
0
0
0
0
410
u_var_add_root(pssense, pssense->base.str, false);
411
u_var_add_log_level(pssense, &pssense->log_level, "Log level");
412
···
436
u_var_add_ro_f32(pssense, &pssense->state.thumbstick.y, "Thumbstick Y");
437
u_var_add_bool(pssense, &pssense->state.thumbstick_click, "Thumbstick Click");
438
u_var_add_bool(pssense, &pssense->state.thumbstick_touch, "Thumbstick Touch");
0
0
0
0
0
439
440
out_xdevs[0] = &pssense->base;
441
return 1;
···
1
// Copyright 2023, Collabora, Ltd.
2
+
// Copyright 2023, Jarett Millard
3
// SPDX-License-Identifier: BSL-1.0
4
/*!
5
* @file
···
25
#include "util/u_trace_marker.h"
26
27
#include "pssense_interface.h"
28
+
#include "math/m_mathinclude.h"
29
+
#include "math/m_space.h"
30
+
#include "math/m_imu_3dof.h"
31
32
#include <stdio.h>
33
···
41
#define PSSENSE_WARN(p, ...) U_LOG_XDEV_IFL_W(&p->base, p->log_level, __VA_ARGS__)
42
#define PSSENSE_ERROR(p, ...) U_LOG_XDEV_IFL_E(&p->base, p->log_level, __VA_ARGS__)
43
44
+
DEBUG_GET_ONCE_LOG_OPTION(pssense_log, "PSSENSE_LOG", U_LOGGING_INFO)
45
+
46
+
#define DEG_TO_RAD(DEG) (DEG * M_PI / 180.)
47
+
48
+
static struct xrt_binding_input_pair simple_inputs_pssense[4] = {
49
+
{XRT_INPUT_SIMPLE_SELECT_CLICK, XRT_INPUT_PSSENSE_TRIGGER_VALUE},
50
+
{XRT_INPUT_SIMPLE_MENU_CLICK, XRT_INPUT_PSSENSE_OPTIONS_CLICK},
51
+
{XRT_INPUT_SIMPLE_GRIP_POSE, XRT_INPUT_PSSENSE_GRIP_POSE},
52
+
{XRT_INPUT_SIMPLE_AIM_POSE, XRT_INPUT_PSSENSE_AIM_POSE},
53
+
};
54
+
55
+
static struct xrt_binding_profile binding_profiles_pssense[1] = {
56
+
{
57
+
.name = XRT_DEVICE_SIMPLE_CONTROLLER,
58
+
.inputs = simple_inputs_pssense,
59
+
.input_count = ARRAY_SIZE(simple_inputs_pssense),
60
+
.outputs = NULL,
61
+
.output_count = 0,
62
+
},
63
+
};
64
65
/*!
66
* Indices where each input is in the input list.
···
87
PSSENSE_INDEX_TRIGGER_PROXIMITY,
88
PSSENSE_INDEX_THUMBSTICK,
89
PSSENSE_INDEX_THUMBSTICK_CLICK,
90
+
PSSENSE_INDEX_THUMBSTICK_TOUCH,
91
+
PSSENSE_INDEX_GRIP_POSE,
92
+
PSSENSE_INDEX_AIM_POSE,
93
+
};
94
+
95
+
const uint8_t HID_PACKET_REPORT_ID = 0x31;
96
+
const uint8_t CALIBRATION_DATA_FEATURE_REPORT_ID = 0x05;
97
+
const uint8_t CALIBRATION_DATA_PART_ID_1 = 0;
98
+
const uint8_t CALIBRATION_DATA_PART_ID_2 = 0x81;
99
+
100
+
/**
101
+
* Gyro read value range is +-32768.
102
+
*/
103
+
const double PSSENSE_GYRO_SCALE_DEG = 180.0 / 1024;
104
+
/**
105
+
* Accelerometer read value range is +-32768 and covers +-8 g.
106
+
*/
107
+
const double PSSENSE_ACCEL_SCALE = MATH_GRAVITY_M_S2 / 4096;
108
+
109
+
/**
110
+
* 16-bit little-endian int
111
+
*/
112
+
struct pssense_i16_le
113
+
{
114
+
uint8_t low;
115
+
uint8_t high;
116
+
};
117
+
118
+
/**
119
+
* 32-bit little-endian int
120
+
*/
121
+
struct pssense_i32_le
122
+
{
123
+
uint8_t lowest;
124
+
uint8_t lower;
125
+
uint8_t higher;
126
+
uint8_t highest;
127
};
128
129
/*!
···
131
*/
132
struct pssense_data_packet
133
{
134
+
uint8_t report_id;
135
+
uint8_t bt_header;
136
uint8_t thumbstick_x;
137
uint8_t thumbstick_y;
138
uint8_t trigger_value;
139
uint8_t trigger_proximity;
140
uint8_t squeeze_proximity;
141
+
uint8_t unknown1[2]; // Always 0x0001
0
142
uint8_t buttons[3];
143
+
uint8_t unknown2; // Always 0x00
144
+
struct pssense_i32_le seq_no;
145
+
struct pssense_i16_le gyro[3];
146
+
struct pssense_i16_le accel[3];
147
+
uint8_t unknown3[3];
148
+
uint8_t unknown4; // Increments occasionally
149
+
uint8_t battery_level; // Range appears to be 0x00-0x0e
150
+
uint8_t unknown5[10];
151
+
uint8_t charging_state; // 0x00 when unplugged, 0x20 when charging
152
+
uint8_t unknown6[29];
153
+
uint8_t crc[4];
154
};
155
156
/*!
···
158
*/
159
struct pssense_input_state
160
{
161
+
uint64_t timestamp_ns;
162
+
uint32_t seq_no;
163
164
bool ps_click;
165
bool share_click;
···
182
bool thumbstick_click;
183
bool thumbstick_touch;
184
struct xrt_vec2 thumbstick;
185
+
186
+
struct xrt_vec3_i32 gyro_raw;
187
+
struct xrt_vec3_i32 accel_raw;
188
};
189
190
/*!
···
211
//! Input state parsed from most recent packet
212
struct pssense_input_state state;
213
214
+
struct m_imu_3dof fusion;
215
+
struct xrt_pose pose;
216
+
217
struct
218
{
219
bool button_states;
220
+
bool tracking;
221
} gui;
222
};
223
224
+
static uint32_t
225
+
pssense_i32_le_to_u32(const struct pssense_i32_le *from)
226
+
{
227
+
return (uint32_t)(from->lowest | from->lower << 8 | from->higher << 16 | from->highest << 24);
228
+
}
229
+
230
+
static int16_t
231
+
pssense_i16_le_to_i16(const struct pssense_i16_le *from)
232
+
{
233
+
// The cast is important, sign extend properly.
234
+
return (int16_t)(from->low | from->high << 8);
235
+
}
236
+
237
/*!
238
* Reads one packet from the device, handles time out, locking and checking if
239
* the thread has been told to shut down.
240
*/
241
static bool
242
+
pssense_read_one_packet(struct pssense_device *pssense, uint8_t *buffer, size_t size, bool check_size)
243
{
244
os_thread_helper_lock(&pssense->controller_thread);
245
···
259
PSSENSE_ERROR(pssense, "Failed to read device '%i'!", ret);
260
return false;
261
}
262
+
// Skip this check if we haven't flushed all the compat mode packets yet, since they're shorter.
263
+
if (check_size && ret != (int)size) {
264
PSSENSE_ERROR(pssense, "Unexpected HID packet size %i (expected %zu)", ret, size);
265
return false;
266
}
···
271
return false;
272
}
273
274
+
static bool
275
pssense_parse_packet(struct pssense_device *pssense,
276
struct pssense_data_packet *data,
277
struct pssense_input_state *input)
278
{
279
+
if (data->report_id != HID_PACKET_REPORT_ID) {
280
+
PSSENSE_WARN(pssense, "Unrecognized HID report id %u", data->report_id);
281
+
return false;
282
+
}
283
+
284
+
input->timestamp_ns = os_monotonic_get_ns();
285
+
286
+
uint32_t seq_no = pssense_i32_le_to_u32(&data->seq_no);
287
+
if (input->seq_no != 0 && seq_no != input->seq_no + 1) {
288
+
PSSENSE_WARN(pssense, "Missed seq no %u. Previous was %u", seq_no, input->seq_no);
289
+
}
290
+
input->seq_no = seq_no;
291
292
input->ps_click = (data->buttons[1] & 16) != 0;
293
input->squeeze_touch = (data->buttons[2] & 8) != 0;
···
318
input->trigger_click = (data->buttons[0] & 128) != 0;
319
input->thumbstick_click = (data->buttons[1] & 8) != 0;
320
}
321
+
322
+
input->gyro_raw.x = pssense_i16_le_to_i16(&data->gyro[0]);
323
+
input->gyro_raw.y = pssense_i16_le_to_i16(&data->gyro[1]);
324
+
input->gyro_raw.z = pssense_i16_le_to_i16(&data->gyro[2]);
325
+
326
+
input->accel_raw.x = pssense_i16_le_to_i16(&data->accel[0]);
327
+
input->accel_raw.y = pssense_i16_le_to_i16(&data->accel[1]);
328
+
input->accel_raw.z = pssense_i16_le_to_i16(&data->accel[2]);
329
+
330
+
return true;
331
+
}
332
+
333
+
static void
334
+
pssense_update_fusion(struct pssense_device *pssense)
335
+
{
336
+
struct xrt_vec3 gyro;
337
+
gyro.x = DEG_TO_RAD(pssense->state.gyro_raw.x * PSSENSE_GYRO_SCALE_DEG);
338
+
gyro.y = DEG_TO_RAD(pssense->state.gyro_raw.y * PSSENSE_GYRO_SCALE_DEG);
339
+
gyro.z = DEG_TO_RAD(pssense->state.gyro_raw.z * PSSENSE_GYRO_SCALE_DEG);
340
+
341
+
struct xrt_vec3 accel;
342
+
accel.x = pssense->state.accel_raw.x * PSSENSE_ACCEL_SCALE;
343
+
accel.y = pssense->state.accel_raw.y * PSSENSE_ACCEL_SCALE;
344
+
accel.z = pssense->state.accel_raw.z * PSSENSE_ACCEL_SCALE;
345
+
346
+
// TODO: Apply correction from calibration data
347
+
348
+
m_imu_3dof_update(&pssense->fusion, pssense->state.timestamp_ns, &accel, &gyro);
349
+
pssense->pose.orientation = pssense->fusion.rot;
350
}
351
352
static void *
···
358
359
union {
360
uint8_t buffer[sizeof(struct pssense_data_packet)];
361
+
struct pssense_data_packet packet;
362
} data;
363
+
struct pssense_input_state input_state = {0};
364
365
+
// The Sense controller starts in compat mode with a different HID report ID and format.
366
+
// We need to discard packets until we get a correct report.
367
+
while (pssense_read_one_packet(pssense, data.buffer, sizeof(data), false) &&
368
+
data.packet.report_id != HID_PACKET_REPORT_ID) {
369
+
PSSENSE_DEBUG(pssense, "Discarding compat mode HID report");
370
}
371
372
+
while (pssense_read_one_packet(pssense, data.buffer, sizeof(data), true)) {
373
+
if (pssense_parse_packet(pssense, &data.packet, &input_state)) {
374
+
os_mutex_lock(&pssense->lock);
375
+
pssense->state = input_state;
376
+
pssense_update_fusion(pssense);
377
+
os_mutex_unlock(&pssense->lock);
378
+
}
0
0
0
379
}
380
381
return NULL;
···
392
// Now that the thread is not running we can destroy the lock.
393
os_mutex_destroy(&pssense->lock);
394
395
+
m_imu_3dof_close(&pssense->fusion);
396
+
397
// Remove the variable tracking.
398
u_var_remove_root(pssense);
399
···
414
os_mutex_lock(&pssense->lock);
415
416
for (uint i = 0; i < (uint)sizeof(enum pssense_input_index); i++) {
417
+
pssense->base.inputs[i].timestamp = (int64_t)pssense->state.timestamp_ns;
418
}
419
pssense->base.inputs[PSSENSE_INDEX_PS_CLICK].value.boolean = pssense->state.ps_click;
420
pssense->base.inputs[PSSENSE_INDEX_SHARE_CLICK].value.boolean = pssense->state.share_click;
···
442
os_mutex_unlock(&pssense->lock);
443
}
444
445
+
static void
446
+
pssense_get_fusion_pose(struct pssense_device *pssense,
447
+
enum xrt_input_name name,
448
+
uint64_t at_timestamp_ns,
449
+
struct xrt_space_relation *out_relation)
450
+
{
451
+
out_relation->pose = pssense->pose;
452
+
out_relation->linear_velocity.x = 0.0f;
453
+
out_relation->linear_velocity.y = 0.0f;
454
+
out_relation->linear_velocity.z = 0.0f;
455
+
456
+
/*!
457
+
* @todo This is hack, fusion reports angvel relative to the device but
458
+
* it needs to be in relation to the base space. Rotating it with the
459
+
* device orientation is enough to get it into the right space, angular
460
+
* velocity is a derivative so needs a special rotation.
461
+
*/
462
+
math_quat_rotate_derivative(&pssense->pose.orientation, &pssense->fusion.last.gyro,
463
+
&out_relation->angular_velocity);
464
+
465
+
out_relation->relation_flags = (enum xrt_space_relation_flags)(
466
+
XRT_SPACE_RELATION_ORIENTATION_VALID_BIT | XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT |
467
+
XRT_SPACE_RELATION_ANGULAR_VELOCITY_VALID_BIT | XRT_SPACE_RELATION_LINEAR_VELOCITY_VALID_BIT);
468
+
}
469
+
470
+
static void
471
+
pssense_get_tracked_pose(struct xrt_device *xdev,
472
+
enum xrt_input_name name,
473
+
uint64_t at_timestamp_ns,
474
+
struct xrt_space_relation *out_relation)
475
+
{
476
+
struct pssense_device *pssense = (struct pssense_device *)xdev;
477
+
478
+
if (name != XRT_INPUT_PSSENSE_AIM_POSE && name != XRT_INPUT_PSSENSE_GRIP_POSE) {
479
+
PSSENSE_ERROR(pssense, "Unknown pose name requested %u", name);
480
+
return;
481
+
}
482
+
483
+
struct xrt_relation_chain xrc = {0};
484
+
struct xrt_pose pose_correction = {0};
485
+
486
+
// Rotate the grip/aim pose up by 60 degrees around the X axis
487
+
struct xrt_vec3 axis = {1.0, 0, 0};
488
+
math_quat_from_angle_vector(DEG_TO_RAD(60), &axis, &pose_correction.orientation);
489
+
m_relation_chain_push_pose(&xrc, &pose_correction);
490
+
491
+
struct xrt_space_relation *rel = m_relation_chain_reserve(&xrc);
492
+
493
+
os_mutex_lock(&pssense->lock);
494
+
pssense_get_fusion_pose(pssense, name, at_timestamp_ns, rel);
495
+
os_mutex_unlock(&pssense->lock);
496
+
497
+
m_relation_chain_resolve(&xrc, out_relation);
498
+
}
499
+
500
+
/**
501
+
* Retrieving the calibration data report will switch the Sense controller from compat mode into full mode.
502
+
*/
503
+
bool
504
+
pssense_get_calibration_data(struct pssense_device *pssense)
505
+
{
506
+
int ret;
507
+
uint8_t buffer[64];
508
+
uint8_t data[(sizeof(buffer) - 2) * 2];
509
+
for (int i = 0; i < 2; i++) {
510
+
ret = os_hid_get_feature(pssense->hid, CALIBRATION_DATA_FEATURE_REPORT_ID, buffer, sizeof(buffer));
511
+
if (ret < 0) {
512
+
PSSENSE_ERROR(pssense, "Failed to retrieve calibration report: %d", ret);
513
+
return false;
514
+
}
515
+
if (ret != sizeof(buffer)) {
516
+
PSSENSE_ERROR(pssense, "Invalid byte count transferred, expected %zu got %d\n", sizeof(buffer),
517
+
ret);
518
+
return false;
519
+
}
520
+
if (buffer[1] == CALIBRATION_DATA_PART_ID_1) {
521
+
memcpy(data, buffer + 2, sizeof(buffer) - 2);
522
+
} else if (buffer[1] == CALIBRATION_DATA_PART_ID_2) {
523
+
memcpy(data + sizeof(buffer) - 2, buffer + 2, sizeof(buffer) - 2);
524
+
} else {
525
+
PSSENSE_ERROR(pssense, "Unknown calibration data part ID %u", buffer[1]);
526
+
return false;
527
+
}
528
+
}
529
+
530
+
// TODO: Parse calibration data into prefiler
531
+
532
+
return true;
533
+
}
534
+
535
#define SET_INPUT(NAME) (pssense->base.inputs[PSSENSE_INDEX_##NAME].name = XRT_INPUT_PSSENSE_##NAME)
536
537
int
···
557
XRT_PROBER_STRING_PRODUCT, //
558
product_name, //
559
sizeof(product_name)); //
560
+
if (ret <= 0) {
561
U_LOG_E("Failed to get product name from Bluetooth device!");
562
return -1;
563
}
564
565
enum u_device_alloc_flags flags = U_DEVICE_ALLOC_TRACKING_NONE;
566
+
struct pssense_device *pssense = U_DEVICE_ALLOCATE(struct pssense_device, flags, 23, 0);
0
567
PSSENSE_DEBUG(pssense, "PlayStation Sense controller found");
568
+
0
569
pssense->base.name = XRT_DEVICE_PSSENSE;
570
snprintf(pssense->base.str, XRT_DEVICE_NAME_LEN, "%s", product_name);
571
+
pssense->base.update_inputs = pssense_device_update_inputs;
572
+
pssense->base.get_tracked_pose = pssense_get_tracked_pose;
573
+
pssense->base.destroy = pssense_device_destroy;
574
+
pssense->base.orientation_tracking_supported = true;
575
+
576
+
pssense->base.binding_profiles = binding_profiles_pssense;
577
+
pssense->base.binding_profile_count = ARRAY_SIZE(binding_profiles_pssense);
578
+
579
+
m_imu_3dof_init(&pssense->fusion, M_IMU_3DOF_USE_GRAVITY_DUR_20MS);
580
581
pssense->log_level = debug_get_log_option_pssense_log();
582
pssense->hid = hid;
···
614
SET_INPUT(THUMBSTICK);
615
SET_INPUT(THUMBSTICK_CLICK);
616
SET_INPUT(THUMBSTICK_TOUCH);
617
+
SET_INPUT(GRIP_POSE);
618
+
SET_INPUT(AIM_POSE);
619
620
ret = os_mutex_init(&pssense->lock);
621
if (ret != 0) {
···
638
return -1;
639
}
640
641
+
if (!pssense_get_calibration_data(pssense)) {
642
+
PSSENSE_ERROR(pssense, "Failed to retrieve calibration data");
643
+
pssense_device_destroy(&pssense->base);
644
+
return -1;
645
+
}
646
+
647
u_var_add_root(pssense, pssense->base.str, false);
648
u_var_add_log_level(pssense, &pssense->log_level, "Log level");
649
···
673
u_var_add_ro_f32(pssense, &pssense->state.thumbstick.y, "Thumbstick Y");
674
u_var_add_bool(pssense, &pssense->state.thumbstick_click, "Thumbstick Click");
675
u_var_add_bool(pssense, &pssense->state.thumbstick_touch, "Thumbstick Touch");
676
+
677
+
u_var_add_gui_header(pssense, &pssense->gui.tracking, "Tracking");
678
+
u_var_add_ro_vec3_i32(pssense, &pssense->state.gyro_raw, "Raw Gyro");
679
+
u_var_add_ro_vec3_i32(pssense, &pssense->state.accel_raw, "Raw Accel");
680
+
u_var_add_pose(pssense, &pssense->pose, "Pose");
681
682
out_xdevs[0] = &pssense->base;
683
return 1;
+1
src/xrt/drivers/pssense/pssense_interface.h
···
1
// Copyright 2023, Collabora, Ltd.
0
2
// SPDX-License-Identifier: BSL-1.0
3
/*!
4
* @file
···
1
// Copyright 2023, Collabora, Ltd.
2
+
// Copyright 2023, Jarett Millard
3
// SPDX-License-Identifier: BSL-1.0
4
/*!
5
* @file
+2
src/xrt/include/xrt/xrt_defines.h
···
946
XRT_INPUT_PSSENSE_THUMBSTICK = XRT_INPUT_NAME(0x0312, VEC2_MINUS_ONE_TO_ONE),
947
XRT_INPUT_PSSENSE_THUMBSTICK_CLICK = XRT_INPUT_NAME(0x0313, BOOLEAN),
948
XRT_INPUT_PSSENSE_THUMBSTICK_TOUCH = XRT_INPUT_NAME(0x0314, BOOLEAN),
0
0
949
// clang-format on
950
};
951
···
946
XRT_INPUT_PSSENSE_THUMBSTICK = XRT_INPUT_NAME(0x0312, VEC2_MINUS_ONE_TO_ONE),
947
XRT_INPUT_PSSENSE_THUMBSTICK_CLICK = XRT_INPUT_NAME(0x0313, BOOLEAN),
948
XRT_INPUT_PSSENSE_THUMBSTICK_TOUCH = XRT_INPUT_NAME(0x0314, BOOLEAN),
949
+
XRT_INPUT_PSSENSE_GRIP_POSE = XRT_INPUT_NAME(0x0315, POSE),
950
+
XRT_INPUT_PSSENSE_AIM_POSE = XRT_INPUT_NAME(0x0316, POSE),
951
// clang-format on
952
};
953