The open source OpenXR runtime
at prediction-2 857 lines 25 kB view raw
1// Copyright 2019, Collabora, Ltd. 2// Copyright 2011, Iowa State University 3// SPDX-License-Identifier: BSL-1.0 4/*! 5 * @file 6 * @brief Razer Hydra prober and driver code 7 * @author Rylie Pavlik <rylie.pavlik@collabora.com> 8 * @author Jakob Bornecrantz <jakob@collabora.com> 9 * 10 * Portions based on the VRPN Razer Hydra driver, 11 * originally written by Rylie Pavlik and available under the BSL-1.0. 12 */ 13 14 15#include <assert.h> 16#include <stdio.h> 17#include <stdlib.h> 18#include <string.h> 19 20#include "xrt/xrt_prober.h" 21 22#include "os/os_hid.h" 23#include "os/os_time.h" 24#include "os/os_threading.h" 25#include "xrt/xrt_byte_order.h" 26 27#include "math/m_api.h" 28#include "math/m_filter_one_euro.h" 29#include "math/m_relation_history.h" 30#include "math/m_space.h" 31 32#include "util/u_debug.h" 33#include "util/u_device.h" 34#include "util/u_misc.h" 35#include "util/u_time.h" 36#include "util/u_logging.h" 37#include "util/u_linux.h" 38#include "util/u_trace_marker.h" 39#include "util/u_var.h" 40 41#include "hydra_interface.h" 42 43 44 45/* 46 * 47 * Defines & structs. 48 * 49 */ 50 51#define HD_TRACE(d, ...) U_LOG_XDEV_IFL_T(&d->base, d->sys->log_level, __VA_ARGS__) 52#define HD_DEBUG(d, ...) U_LOG_XDEV_IFL_D(&d->base, d->sys->log_level, __VA_ARGS__) 53#define HD_INFO(d, ...) U_LOG_XDEV_IFL_I(&d->base, d->sys->log_level, __VA_ARGS__) 54#define HD_WARN(d, ...) U_LOG_XDEV_IFL_W(&d->base, d->sys->log_level, __VA_ARGS__) 55#define HD_ERROR(d, ...) U_LOG_XDEV_IFL_E(&d->base, d->sys->log_level, __VA_ARGS__) 56 57#define HS_TRACE(d, ...) U_LOG_IFL_T(d->log_level, __VA_ARGS__) 58#define HS_DEBUG(d, ...) U_LOG_IFL_D(d->log_level, __VA_ARGS__) 59#define HS_INFO(d, ...) U_LOG_IFL_I(d->log_level, __VA_ARGS__) 60#define HS_WARN(d, ...) U_LOG_IFL_W(d->log_level, __VA_ARGS__) 61#define HS_ERROR(d, ...) U_LOG_IFL_E(d->log_level, __VA_ARGS__) 62 63DEBUG_GET_ONCE_LOG_OPTION(hydra_log, "HYDRA_LOG", U_LOGGING_WARN) 64 65enum hydra_input_index 66{ 67 HYDRA_INDEX_1_CLICK, 68 HYDRA_INDEX_2_CLICK, 69 HYDRA_INDEX_3_CLICK, 70 HYDRA_INDEX_4_CLICK, 71 HYDRA_INDEX_MIDDLE_CLICK, 72 HYDRA_INDEX_BUMPER_CLICK, 73 HYDRA_INDEX_JOYSTICK_CLICK, 74 HYDRA_INDEX_JOYSTICK_VALUE, 75 HYDRA_INDEX_TRIGGER_VALUE, 76 HYDRA_INDEX_GRIP_POSE, 77 HYDRA_INDEX_AIM_POSE, 78 HYDRA_MAX_CONTROLLER_INDEX 79}; 80 81/* Yes this is a bizarre bit mask. Mysteries of the Hydra. */ 82enum hydra_button_bit 83{ 84 HYDRA_BUTTON_BIT_BUMPER = (1 << 0), 85 86 HYDRA_BUTTON_BIT_3 = (1 << 1), 87 HYDRA_BUTTON_BIT_1 = (1 << 2), 88 HYDRA_BUTTON_BIT_2 = (1 << 3), 89 HYDRA_BUTTON_BIT_4 = (1 << 4), 90 91 HYDRA_BUTTON_BIT_MIDDLE = (1 << 5), 92 HYDRA_BUTTON_BIT_JOYSTICK = (1 << 6), 93}; 94 95static const uint8_t HYDRA_REPORT_START_MOTION[] = { 96 97 0x00, // first byte must be report type 98 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00}; 103 104static const uint8_t HYDRA_REPORT_START_GAMEPAD[] = { 105 0x00, // first byte must be report type 106 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00}; 111 112struct hydra_controller_state 113{ 114 struct m_relation_history *relation_history; 115 struct 116 { 117 struct m_filter_euro_vec3 position; 118 struct m_filter_euro_quat orientation; 119 } motion_vector_filters; 120 121 struct xrt_vec2 js; 122 float trigger; 123 uint8_t buttons; 124}; 125/*! 126 * The states of the finite-state machine controlling the Hydra. 127 */ 128enum hydra_sm_state 129{ 130 HYDRA_SM_LISTENING_AFTER_CONNECT = 0, 131 HYDRA_SM_LISTENING_AFTER_SET_FEATURE, 132 HYDRA_SM_REPORTING 133}; 134 135/*! 136 * The details of the Hydra state machine in a convenient package. 137 */ 138struct hydra_state_machine 139{ 140 enum hydra_sm_state current_state; 141 142 //! Time of the last (non-trivial) state transition 143 timepoint_ns transition_time; 144}; 145 146struct hydra_device; 147 148/*! 149 * A Razer Hydra system containing two controllers. 150 * 151 * @ingroup drv_hydra 152 * @extends xrt_tracking_origin 153 */ 154struct hydra_system 155{ 156 struct xrt_tracking_origin base; 157 struct os_hid_device *data_hid; 158 struct os_hid_device *command_hid; 159 160 struct os_thread_helper usb_thread; 161 162 struct os_mutex data_mutex; 163 164 struct hydra_state_machine sm; 165 struct hydra_device *devs[2]; 166 167 int16_t report_counter; 168 169 //! Last time that we received a report 170 timepoint_ns report_time; 171 172 /*! 173 * Reference count of the number of devices still alive using this 174 * system 175 */ 176 uint8_t refs; 177 178 /*! 179 * Was the hydra in gamepad mode at start? 180 * 181 * If it was, we set it back to gamepad on destruction. 182 */ 183 bool was_in_gamepad_mode; 184 int motion_attempt_number; 185 186 enum u_logging_level log_level; 187}; 188 189/*! 190 * A Razer Hydra device, representing just a single controller. 191 * 192 * @ingroup drv_hydra 193 * @implements xrt_device 194 */ 195struct hydra_device 196{ 197 struct xrt_device base; 198 struct hydra_system *sys; 199 200 //! Last time that we updated inputs 201 timepoint_ns input_time; 202 203 // bool calibration_done; 204 // int mirror; 205 // int sign_x; 206 207 struct hydra_controller_state state; 208 209 //! Which hydra controller in the system are we? 210 size_t index; 211}; 212 213/* 214 * 215 * Internal functions. 216 * 217 */ 218 219static void 220hydra_device_parse_controller(struct hydra_device *hd, uint8_t *buf, int64_t now); 221 222static inline struct hydra_device * 223hydra_device(struct xrt_device *xdev) 224{ 225 assert(xdev); 226 struct hydra_device *ret = (struct hydra_device *)xdev; 227 assert(ret->sys != NULL); 228 return ret; 229} 230 231static inline struct hydra_system * 232hydra_system(struct xrt_tracking_origin *xtrack) 233{ 234 assert(xtrack); 235 struct hydra_system *ret = (struct hydra_system *)xtrack; 236 return ret; 237} 238 239/*! 240 * Reports the number of seconds since the most recent change of state. 241 * 242 * @relates hydra_sm 243 */ 244static float 245hydra_sm_seconds_since_transition(struct hydra_state_machine *hsm, timepoint_ns now) 246{ 247 248 if (hsm->transition_time == 0) { 249 hsm->transition_time = now; 250 return 0.f; 251 } 252 253 float state_duration_s = time_ns_to_s(now - hsm->transition_time); 254 return state_duration_s; 255} 256/*! 257 * Performs a state transition, updating the transition time if the state 258 * actually changed. 259 * 260 * @relates hydra_sm 261 */ 262static void 263hydra_sm_transition(struct hydra_state_machine *hsm, enum hydra_sm_state new_state, timepoint_ns now) 264{ 265 if (hsm->transition_time == 0) { 266 hsm->transition_time = now; 267 } 268 if (new_state != hsm->current_state) { 269 hsm->current_state = new_state; 270 hsm->transition_time = now; 271 } 272} 273static inline uint8_t 274hydra_read_uint8(uint8_t **bufptr) 275{ 276 uint8_t ret = **bufptr; 277 (*bufptr)++; 278 return ret; 279} 280static inline int16_t 281hydra_read_int16_le(uint8_t **bufptr) 282{ 283 uint8_t *buf = *bufptr; 284#ifdef XRT_BIG_ENDIAN 285 uint8_t bytes[2] = {buf[1], buf[0]}; 286#else 287 uint8_t bytes[2] = {buf[0], buf[1]}; 288#endif // XRT_BIG_ENDIAN 289 (*bufptr) += 2; 290 int16_t ret; 291 memcpy(&ret, bytes, sizeof(ret)); 292 return ret; 293} 294 295/*! 296 * Parse the controller-specific part of a buffer into a hydra device. 297 */ 298static void 299hydra_device_parse_controller(struct hydra_device *hd, uint8_t *buf, int64_t now) 300{ 301 struct hydra_controller_state *state = &hd->state; 302 303 static const float SCALE_MM_TO_METER = 0.001f; 304 static const float SCALE_INT16_TO_FLOAT_PLUSMINUS_1 = 1.0f / 32768.0f; 305 static const float SCALE_UINT8_TO_FLOAT_0_TO_1 = 1.0f / 255.0f; 306 307 struct xrt_pose pose; 308 309 pose.position.x = hydra_read_int16_le(&buf) * SCALE_MM_TO_METER; 310 pose.position.z = hydra_read_int16_le(&buf) * SCALE_MM_TO_METER; 311 pose.position.y = -hydra_read_int16_le(&buf) * SCALE_MM_TO_METER; 312 313 // the negatives are to fix handedness 314 pose.orientation.w = hydra_read_int16_le(&buf) * SCALE_INT16_TO_FLOAT_PLUSMINUS_1; 315 pose.orientation.x = hydra_read_int16_le(&buf) * SCALE_INT16_TO_FLOAT_PLUSMINUS_1; 316 pose.orientation.y = hydra_read_int16_le(&buf) * SCALE_INT16_TO_FLOAT_PLUSMINUS_1; 317 pose.orientation.z = hydra_read_int16_le(&buf) * SCALE_INT16_TO_FLOAT_PLUSMINUS_1; 318 319 //! @todo the presence of this suggest we're not decoding the 320 //! orientation right. 321 math_quat_normalize(&pose.orientation); 322 323 struct xrt_quat fixed = { 324 .x = pose.orientation.x, 325 .y = -pose.orientation.z, 326 .z = pose.orientation.y, 327 .w = pose.orientation.w, 328 }; 329 330 struct xrt_quat adjustment = {.x = 0, .y = 1, .z = 0, .w = 0}; 331 math_quat_rotate(&fixed, &adjustment, &fixed); 332 333 adjustment = (struct xrt_quat){.x = 0, .y = 0, .z = 1, .w = 0}; 334 math_quat_rotate(&fixed, &adjustment, &fixed); 335 336 pose.orientation = fixed; 337 338 struct xrt_space_relation space_relation = {0}; 339 m_filter_euro_vec3_run(&state->motion_vector_filters.position, now, &pose.position, 340 &space_relation.pose.position); 341 m_filter_euro_quat_run(&state->motion_vector_filters.orientation, now, &pose.orientation, 342 &space_relation.pose.orientation); 343 344 space_relation.relation_flags = 345 (XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT | XRT_SPACE_RELATION_ORIENTATION_VALID_BIT) | 346 (XRT_SPACE_RELATION_POSITION_TRACKED_BIT | XRT_SPACE_RELATION_POSITION_VALID_BIT); 347 348 m_relation_history_estimate_motion(state->relation_history, &space_relation, now, &space_relation); 349 350 m_relation_history_push(state->relation_history, &space_relation, now); 351 352 state->buttons = hydra_read_uint8(&buf); 353 354 state->js.x = hydra_read_int16_le(&buf) * SCALE_INT16_TO_FLOAT_PLUSMINUS_1; 355 state->js.y = hydra_read_int16_le(&buf) * SCALE_INT16_TO_FLOAT_PLUSMINUS_1; 356 357 state->trigger = hydra_read_uint8(&buf) * SCALE_UINT8_TO_FLOAT_0_TO_1; 358 359 HD_TRACE(hd, 360 "\n\t" 361 "controller: %i\n\t" 362 "position: (%-1.2f, %-1.2f, %-1.2f)\n\t" 363 "orientation: (%-1.2f, %-1.2f, %-1.2f, %-1.2f)\n\t" 364 "buttons: %08x\n\t" 365 "joystick: (%-1.2f, %-1.2f)\n\t" 366 "trigger: %01.2f\n", 367 (int)hd->index, pose.position.x, pose.position.y, pose.position.z, pose.orientation.x, 368 pose.orientation.y, pose.orientation.z, pose.orientation.w, state->buttons, state->js.x, state->js.y, 369 state->trigger); 370} 371 372static int 373hydra_system_read_data_hid(struct hydra_system *hs) 374{ 375 assert(hs); 376 uint8_t buffer[128]; 377 378 int ret = os_hid_read(hs->data_hid, buffer, sizeof(buffer), 379 20); // 20ms is a generous number above the 16.66ms we expect to receive reports at (60hz) 380 381 timepoint_ns now = os_monotonic_get_ns(); 382 383 // we dont care if we get no data 384 if (ret <= 0) { 385 return ret; 386 } 387 388 if (ret != 52) { 389 HS_ERROR(hs, "Unexpected data report of size %d", ret); 390 return -1; 391 } 392 393 os_mutex_lock(&hs->data_mutex); 394 395 uint8_t new_counter = buffer[7]; 396 bool missed = false; 397 if (hs->report_counter != -1) { 398 uint8_t expected_counter = ((hs->report_counter + 1) & 0xff); 399 missed = new_counter != expected_counter; 400 } 401 hs->report_counter = new_counter; 402 403 404 if (hs->devs[0] != NULL) { 405 hydra_device_parse_controller(hs->devs[0], buffer + 8, now); 406 } 407 if (hs->devs[1] != NULL) { 408 hydra_device_parse_controller(hs->devs[1], buffer + 30, now); 409 } 410 411 hs->report_time = now; 412 413 os_mutex_unlock(&hs->data_mutex); 414 415 HS_TRACE(hs, 416 "\n\t" 417 "missed: %s\n\t" 418 "seq_no: %x\n", 419 missed ? "yes" : "no", new_counter); 420 421 return ret; 422} 423 424 425/*! 426 * Switch to motion controller mode. 427 */ 428static void 429hydra_system_enter_motion_control(struct hydra_system *hs, timepoint_ns now) 430{ 431 assert(hs); 432 433 hs->was_in_gamepad_mode = true; 434 hs->motion_attempt_number++; 435 HS_DEBUG(hs, 436 "Setting feature report to start motion-controller mode, " 437 "attempt %d", 438 hs->motion_attempt_number); 439 440 os_hid_set_feature(hs->command_hid, HYDRA_REPORT_START_MOTION, sizeof(HYDRA_REPORT_START_MOTION)); 441 442 // Doing a throwaway get-feature now. 443 uint8_t buf[91] = {0}; 444 os_hid_get_feature(hs->command_hid, 0, buf, sizeof(buf)); 445 446 hydra_sm_transition(&hs->sm, HYDRA_SM_LISTENING_AFTER_SET_FEATURE, now); 447} 448/*! 449 * Update the internal state of the Hydra driver. 450 * 451 * Reads devices, checks the state machine and timeouts, etc. 452 * 453 */ 454static int 455hydra_system_update(struct hydra_system *hs) 456{ 457 assert(hs); 458 459 // In all states of the state machine: 460 // Try reading a report: will only return >0 if we get a full motion 461 // report. 462 int received = hydra_system_read_data_hid(hs); 463 464 // we got an error 465 if (received < 0) { 466 return received; 467 } 468 469 os_mutex_lock(&hs->data_mutex); 470 471 timepoint_ns now = os_monotonic_get_ns(); 472 473 // if we got data, transition to "reporting" mode 474 if (received > 0) { 475 hydra_sm_transition(&hs->sm, HYDRA_SM_REPORTING, now); 476 } 477 478 switch (hs->sm.current_state) { 479 case HYDRA_SM_LISTENING_AFTER_CONNECT: { 480 float state_duration_s = hydra_sm_seconds_since_transition(&hs->sm, now); 481 if (state_duration_s > 1.0f) { 482 // only waiting 1 second for the initial report after 483 // connect 484 hydra_system_enter_motion_control(hs, now); 485 } 486 } break; 487 case HYDRA_SM_LISTENING_AFTER_SET_FEATURE: { 488 float state_duration_s = hydra_sm_seconds_since_transition(&hs->sm, now); 489 if (state_duration_s > 5.0f) { 490 // giving each motion control attempt 5 seconds to work. 491 hydra_system_enter_motion_control(hs, now); 492 } 493 } break; 494 default: break; 495 } 496 497 os_mutex_unlock(&hs->data_mutex); 498 499 return 0; 500} 501 502static void 503hydra_device_update_input_click(struct hydra_device *hd, timepoint_ns now, int index, uint32_t bit) 504{ 505 assert(hd); 506 hd->base.inputs[index].timestamp = now; 507 hd->base.inputs[index].value.boolean = (hd->state.buttons & bit) != 0; 508} 509 510static void * 511hydra_usb_thread_run(void *user_data) 512{ 513 struct hydra_system *hs = (struct hydra_system *)user_data; 514 515 const char *thread_name = "Hydra USB"; 516 517 U_TRACE_SET_THREAD_NAME(thread_name); 518 os_thread_helper_name(&hs->usb_thread, thread_name); 519 520#ifdef XRT_OS_LINUX 521 // Try to raise priority of this thread. 522 u_linux_try_to_set_realtime_priority_on_thread(hs->log_level, thread_name); 523#endif 524 525 os_thread_helper_lock(&hs->usb_thread); 526 527 int result = 0; 528#if 0 529 int ticks = 0; 530#endif 531 532 while (os_thread_helper_is_running_locked(&hs->usb_thread) && result >= 0) { 533 os_thread_helper_unlock(&hs->usb_thread); 534 535 result = hydra_system_update(hs); 536 537 os_thread_helper_lock(&hs->usb_thread); 538#if 0 539 ticks += 1; 540#endif 541 } 542 543 os_thread_helper_unlock(&hs->usb_thread); 544 545 return NULL; 546} 547 548/* 549 * 550 * Device functions. 551 * 552 */ 553 554static xrt_result_t 555hydra_device_update_inputs(struct xrt_device *xdev) 556{ 557 struct hydra_device *hd = hydra_device(xdev); 558 struct hydra_system *hs = hydra_system(xdev->tracking_origin); 559 560 os_mutex_lock(&hs->data_mutex); 561 562 if (hd->input_time != hs->report_time) { 563 timepoint_ns now = hs->report_time; 564 hd->input_time = now; 565 566 hydra_device_update_input_click(hd, now, HYDRA_INDEX_1_CLICK, HYDRA_BUTTON_BIT_1); 567 hydra_device_update_input_click(hd, now, HYDRA_INDEX_2_CLICK, HYDRA_BUTTON_BIT_2); 568 hydra_device_update_input_click(hd, now, HYDRA_INDEX_3_CLICK, HYDRA_BUTTON_BIT_3); 569 hydra_device_update_input_click(hd, now, HYDRA_INDEX_4_CLICK, HYDRA_BUTTON_BIT_4); 570 571 hydra_device_update_input_click(hd, now, HYDRA_INDEX_MIDDLE_CLICK, HYDRA_BUTTON_BIT_MIDDLE); 572 hydra_device_update_input_click(hd, now, HYDRA_INDEX_BUMPER_CLICK, HYDRA_BUTTON_BIT_BUMPER); 573 hydra_device_update_input_click(hd, now, HYDRA_INDEX_JOYSTICK_CLICK, HYDRA_INDEX_JOYSTICK_CLICK); 574 575 struct xrt_input *inputs = hd->base.inputs; 576 struct hydra_controller_state *state = &(hd->state); 577 578 inputs[HYDRA_INDEX_JOYSTICK_VALUE].timestamp = now; 579 inputs[HYDRA_INDEX_JOYSTICK_VALUE].value.vec2 = state->js; 580 581 inputs[HYDRA_INDEX_TRIGGER_VALUE].timestamp = now; 582 inputs[HYDRA_INDEX_TRIGGER_VALUE].value.vec1.x = state->trigger; 583 } 584 585 os_mutex_unlock(&hs->data_mutex); 586 587 return XRT_SUCCESS; 588} 589 590static xrt_result_t 591hydra_device_get_tracked_pose(struct xrt_device *xdev, 592 enum xrt_input_name name, 593 int64_t at_timestamp_ns, 594 struct xrt_space_relation *out_relation) 595{ 596 struct hydra_device *hd = hydra_device(xdev); 597 598 struct xrt_relation_chain xrc = {0}; 599 600 switch (name) { 601 case XRT_INPUT_HYDRA_AIM_POSE: { 602 const struct xrt_pose aim_offset = { 603 .position = {0, 0.045, -0.08}, 604 .orientation = {-0.258819, 0, 0, 0.9659258}, 605 }; 606 m_relation_chain_push_pose(&xrc, &aim_offset); 607 break; 608 } 609 case XRT_INPUT_HYDRA_GRIP_POSE: 610 default: break; 611 } 612 613 struct xrt_space_relation device_relation = {0}; 614 m_relation_history_get(hd->state.relation_history, at_timestamp_ns, &device_relation); 615 616 m_relation_chain_push_relation(&xrc, &device_relation); 617 618 m_relation_chain_resolve(&xrc, out_relation); 619 620 return XRT_SUCCESS; 621} 622 623static void 624hydra_system_remove_child(struct hydra_system *hs, struct hydra_device *hd) 625{ 626 assert(hydra_system(hd->base.tracking_origin) == hs); 627 assert(hd->index == 0 || hd->index == 1); 628 629 // Make the device not point to the system 630 hd->sys = NULL; 631 632 // Make the system not point to the device 633 assert(hs->devs[hd->index] == hd); 634 hs->devs[hd->index] = NULL; 635 636 // Decrease ref count of system 637 hs->refs--; 638 639 if (hs->refs == 0) { 640 os_thread_helper_destroy(&hs->usb_thread); 641 642 os_mutex_destroy(&hs->data_mutex); 643 644 // No more children, destroy system. 645 if (hs->data_hid != NULL && hs->command_hid != NULL && hs->sm.current_state == HYDRA_SM_REPORTING && 646 hs->was_in_gamepad_mode) { 647 648 HS_DEBUG(hs, 649 "Sending command to re-enter gamepad mode " 650 "and pausing while it takes effect."); 651 652 os_hid_set_feature(hs->command_hid, HYDRA_REPORT_START_GAMEPAD, 653 sizeof(HYDRA_REPORT_START_GAMEPAD)); 654 os_nanosleep(2 * 1000 * 1000 * 1000); 655 } 656 if (hs->data_hid != NULL) { 657 os_hid_destroy(hs->data_hid); 658 hs->data_hid = NULL; 659 } 660 if (hs->command_hid != NULL) { 661 os_hid_destroy(hs->command_hid); 662 hs->command_hid = NULL; 663 } 664 free(hs); 665 } 666} 667 668static void 669hydra_device_destroy(struct xrt_device *xdev) 670{ 671 struct hydra_device *hd = hydra_device(xdev); 672 struct hydra_system *hs = hydra_system(xdev->tracking_origin); 673 674 m_relation_history_destroy(&hd->state.relation_history); 675 676 hydra_system_remove_child(hs, hd); 677 678 free(hd); 679} 680 681/* 682 * 683 * Prober functions. 684 * 685 */ 686#define SET_INPUT(NAME) \ 687 do { \ 688 (hd->base.inputs[HYDRA_INDEX_##NAME].name = XRT_INPUT_HYDRA_##NAME); \ 689 } while (0) 690 691static struct xrt_binding_input_pair touch_inputs[19] = { 692 {XRT_INPUT_TOUCH_X_CLICK, XRT_INPUT_HYDRA_2_CLICK}, 693 {XRT_INPUT_TOUCH_X_TOUCH, XRT_INPUT_HYDRA_2_CLICK}, 694 {XRT_INPUT_TOUCH_Y_CLICK, XRT_INPUT_HYDRA_4_CLICK}, 695 {XRT_INPUT_TOUCH_Y_TOUCH, XRT_INPUT_HYDRA_4_CLICK}, 696 {XRT_INPUT_TOUCH_MENU_CLICK, XRT_INPUT_HYDRA_MIDDLE_CLICK}, 697 {XRT_INPUT_TOUCH_A_CLICK, XRT_INPUT_HYDRA_1_CLICK}, 698 {XRT_INPUT_TOUCH_A_TOUCH, XRT_INPUT_HYDRA_1_CLICK}, 699 {XRT_INPUT_TOUCH_B_CLICK, XRT_INPUT_HYDRA_3_CLICK}, 700 {XRT_INPUT_TOUCH_B_TOUCH, XRT_INPUT_HYDRA_3_CLICK}, 701 {XRT_INPUT_TOUCH_SYSTEM_CLICK, XRT_INPUT_HYDRA_MIDDLE_CLICK}, 702 {XRT_INPUT_TOUCH_SQUEEZE_VALUE, XRT_INPUT_HYDRA_BUMPER_CLICK}, 703 {XRT_INPUT_TOUCH_TRIGGER_TOUCH, XRT_INPUT_HYDRA_TRIGGER_VALUE}, 704 {XRT_INPUT_TOUCH_TRIGGER_VALUE, XRT_INPUT_HYDRA_TRIGGER_VALUE}, 705 {XRT_INPUT_TOUCH_THUMBSTICK_CLICK, XRT_INPUT_HYDRA_JOYSTICK_CLICK}, 706 {XRT_INPUT_TOUCH_THUMBSTICK, XRT_INPUT_HYDRA_JOYSTICK_VALUE}, 707 {XRT_INPUT_TOUCH_GRIP_POSE, XRT_INPUT_HYDRA_GRIP_POSE}, 708 {XRT_INPUT_TOUCH_AIM_POSE, XRT_INPUT_HYDRA_AIM_POSE}, 709}; 710 711static struct xrt_binding_input_pair simple_inputs[4] = { 712 {XRT_INPUT_SIMPLE_SELECT_CLICK, XRT_INPUT_HYDRA_TRIGGER_VALUE}, 713 {XRT_INPUT_SIMPLE_MENU_CLICK, XRT_INPUT_HYDRA_MIDDLE_CLICK}, 714 {XRT_INPUT_SIMPLE_GRIP_POSE, XRT_INPUT_HYDRA_GRIP_POSE}, 715 {XRT_INPUT_SIMPLE_AIM_POSE, XRT_INPUT_HYDRA_AIM_POSE}, 716}; 717 718static struct xrt_binding_profile binding_profiles[2] = { 719 { 720 .name = XRT_DEVICE_TOUCH_CONTROLLER, 721 .inputs = touch_inputs, 722 .input_count = ARRAY_SIZE(touch_inputs), 723 }, 724 { 725 .name = XRT_DEVICE_SIMPLE_CONTROLLER, 726 .inputs = simple_inputs, 727 .input_count = ARRAY_SIZE(simple_inputs), 728 }, 729}; 730 731int 732hydra_found(struct xrt_prober *xp, 733 struct xrt_prober_device **devices, 734 size_t device_count, 735 size_t index, 736 cJSON *attached_data, 737 struct xrt_device **out_xdevs) 738{ 739 struct xrt_prober_device *dev = devices[index]; 740 int ret; 741 742 struct os_hid_device *data_hid = NULL; 743 ret = xrt_prober_open_hid_interface(xp, dev, 0, &data_hid); 744 if (ret != 0) { 745 return -1; 746 } 747 struct os_hid_device *command_hid = NULL; 748 ret = xrt_prober_open_hid_interface(xp, dev, 1, &command_hid); 749 if (ret != 0) { 750 os_hid_destroy(data_hid); 751 return -1; 752 } 753 754 // Create the system 755 struct hydra_system *hs = U_TYPED_CALLOC(struct hydra_system); 756 hs->base.type = XRT_TRACKING_TYPE_MAGNETIC; 757 snprintf(hs->base.name, XRT_TRACKING_NAME_LEN, "%s", "Sixense Magnetic Tracking"); 758 // Arbitrary static transform from local space to base. 759 hs->base.initial_offset.position.y = 1.0f; 760 hs->base.initial_offset.position.z = -0.25f; 761 hs->base.initial_offset.orientation.w = 1.0f; 762 763 ret = os_thread_helper_init(&hs->usb_thread); 764 if (ret < 0) { 765 HS_ERROR(hs, "Failed to init USB thread."); 766 after_system_err: 767 free(hs); 768 os_hid_destroy(command_hid); 769 os_hid_destroy(data_hid); 770 return -1; 771 } 772 773 ret = os_mutex_init(&hs->data_mutex); 774 if (ret < 0) { 775 HS_ERROR(hs, "Failed to init data mutex."); 776 os_thread_helper_destroy(&hs->usb_thread); 777 goto after_system_err; 778 } 779 780 hs->data_hid = data_hid; 781 hs->command_hid = command_hid; 782 783 enum u_device_alloc_flags flags = (enum u_device_alloc_flags)0; 784 hs->devs[0] = U_DEVICE_ALLOCATE(struct hydra_device, flags, HYDRA_MAX_CONTROLLER_INDEX, 0); 785 hs->devs[1] = U_DEVICE_ALLOCATE(struct hydra_device, flags, HYDRA_MAX_CONTROLLER_INDEX, 0); 786 787 hs->report_counter = -1; 788 hs->refs = 2; 789 790 hs->log_level = debug_get_log_option_hydra_log(); 791 792 u_var_add_root(hs, "Razer Hydra System", false); 793 u_var_add_log_level(hs, &hs->log_level, "Log Level"); 794 u_var_add_bool(hs, &hs->was_in_gamepad_mode, "Was In Gamepad Mode"); 795 u_var_add_i32(hs, &hs->motion_attempt_number, "Motion Attempt Number"); 796 u_var_add_ro_i16(hs, &hs->report_counter, "Report Counter"); 797 798 // Populate the individual devices 799 for (size_t i = 0; i < 2; ++i) { 800 struct hydra_device *hd = hs->devs[i]; 801 802 hd->base.destroy = hydra_device_destroy; 803 hd->base.update_inputs = hydra_device_update_inputs; 804 hd->base.get_tracked_pose = hydra_device_get_tracked_pose; 805 hd->base.set_output = u_device_ni_set_output; 806 hd->base.name = XRT_DEVICE_HYDRA; 807 snprintf(hd->base.str, XRT_DEVICE_NAME_LEN, "%s %i", "Razer Hydra Controller", (int)(i + 1)); 808 snprintf(hd->base.serial, XRT_DEVICE_NAME_LEN, "%s%i", "RZRHDRC", (int)(i + 1)); 809 SET_INPUT(1_CLICK); 810 SET_INPUT(2_CLICK); 811 SET_INPUT(3_CLICK); 812 SET_INPUT(4_CLICK); 813 SET_INPUT(MIDDLE_CLICK); 814 SET_INPUT(BUMPER_CLICK); 815 SET_INPUT(JOYSTICK_CLICK); 816 SET_INPUT(JOYSTICK_VALUE); 817 SET_INPUT(TRIGGER_VALUE); 818 SET_INPUT(GRIP_POSE); 819 SET_INPUT(AIM_POSE); 820 hd->index = i; 821 hd->sys = hs; 822 823 const float fc_min = 9.f; 824 const float fc_min_d = 9.f; 825 const float beta = 0.1f; 826 827 m_filter_euro_vec3_init(&hd->state.motion_vector_filters.position, fc_min, fc_min_d, beta); 828 m_filter_euro_quat_init(&hd->state.motion_vector_filters.orientation, fc_min, fc_min_d, beta); 829 830 m_relation_history_create(&hd->state.relation_history); 831 832 hd->base.binding_profiles = binding_profiles; 833 hd->base.binding_profile_count = ARRAY_SIZE(binding_profiles); 834 835 hd->base.tracking_origin = &hs->base; 836 837 hd->base.supported.position_tracking = true; 838 hd->base.supported.orientation_tracking = true; 839 hd->base.device_type = XRT_DEVICE_TYPE_ANY_HAND_CONTROLLER; 840 841 out_xdevs[i] = &(hd->base); 842 } 843 844 ret = os_thread_helper_start(&hs->usb_thread, hydra_usb_thread_run, hs); 845 if (ret < 0) { 846 HS_ERROR(hs, "Failed to start USB thread."); 847 848 // doing this will destroy the system as well 849 xrt_device_destroy((struct xrt_device **)&hs->devs[0]); 850 xrt_device_destroy((struct xrt_device **)&hs->devs[1]); 851 852 return ret; 853 } 854 855 HS_INFO(hs, "Opened Razer Hydra!"); 856 return 2; 857}