The open source OpenXR runtime
at prediction-2 156 lines 4.9 kB view raw
1// Copyright 2020-2021, N Madsen. 2// Copyright 2020-2021, Collabora, Ltd. 3// Copyright 2021-2023, Jan Schmidt 4// SPDX-License-Identifier: BSL-1.0 5// 6/*! 7 * @file 8 * @brief Common implementation for WMR controllers, handling 9 * shared behaviour such as communication, configuration reading, 10 * IMU integration. 11 * @author Jan Schmidt <jan@centricular.com> 12 * @author Nis Madsen <nima_zero_one@protonmail.com> 13 * @ingroup drv_wmr 14 */ 15#pragma once 16 17#include "os/os_threading.h" 18#include "math/m_imu_3dof.h" 19#include "util/u_logging.h" 20#include "xrt/xrt_device.h" 21 22#include "wmr_controller_protocol.h" 23#include "wmr_config.h" 24 25#ifdef __cplusplus 26extern "C" { 27#endif 28 29struct wmr_controller_base; 30 31/*! 32 * A connection for communicating with the controller. 33 * The mechanism is implementation specific, so there are 34 * two variants for either communicating directly with a 35 * controller via bluetooth, and another for talking 36 * to a controller through a headset tunnelled mapping. 37 * 38 * The controller implementation doesn't need to care how 39 * the communication is implemented. 40 * 41 * The HMD-tunnelled version of the connection is reference 42 * counted and mutex protected, as both the controller and 43 * the HMD need to hold a reference to it to clean up safely. 44 * For bluetooth controllers, destruction of the controller 45 * xrt_device calls disconnect and destroys the connection 46 * object (and bluetooth listener) immediately. 47 */ 48struct wmr_controller_connection 49{ 50 //! The controller this connection is talking to. 51 struct wmr_controller_base *wcb; 52 53 bool (*send_bytes)(struct wmr_controller_connection *wcc, const uint8_t *buffer, uint32_t buf_size); 54 void (*receive_bytes)(struct wmr_controller_connection *wcc, 55 uint64_t time_ns, 56 uint8_t *buffer, 57 uint32_t buf_size); 58 int (*read_sync)(struct wmr_controller_connection *wcc, uint8_t *buffer, uint32_t buf_size, int timeout_ms); 59 60 void (*disconnect)(struct wmr_controller_connection *wcc); 61}; 62 63static inline bool 64wmr_controller_connection_send_bytes(struct wmr_controller_connection *wcc, const uint8_t *buffer, uint32_t buf_size) 65{ 66 assert(wcc->send_bytes != NULL); 67 return wcc->send_bytes(wcc, buffer, buf_size); 68} 69 70static inline int 71wmr_controller_connection_read_sync(struct wmr_controller_connection *wcc, 72 uint8_t *buffer, 73 uint32_t buf_size, 74 int timeout_ms) 75{ 76 return wcc->read_sync(wcc, buffer, buf_size, timeout_ms); 77} 78 79static inline void 80wmr_controller_connection_disconnect(struct wmr_controller_connection *wcc) 81{ 82 wcc->disconnect(wcc); 83} 84 85/*! 86 * Common base for all WMR controllers. 87 * 88 * @ingroup drv_wmr 89 * @implements xrt_device 90 */ 91struct wmr_controller_base 92{ 93 //! Base struct. 94 struct xrt_device base; 95 96 //! Mutex protects the controller connection 97 struct os_mutex conn_lock; 98 99 //! The connection for this controller. 100 struct wmr_controller_connection *wcc; 101 102 //! Callback from the connection when a packet has been received. 103 void (*receive_bytes)(struct wmr_controller_base *wcb, uint64_t time_ns, uint8_t *buffer, uint32_t buf_size); 104 105 enum u_logging_level log_level; 106 107 //! Mutex protects shared data used from OpenXR callbacks 108 struct os_mutex data_lock; 109 110 //! Callback to parse a controller update packet and update the input / imu info. Called with the 111 // data lock held. 112 bool (*handle_input_packet)(struct wmr_controller_base *wcb, 113 uint64_t time_ns, 114 uint8_t *buffer, 115 uint32_t buf_size); 116 117 /* firmware configuration block */ 118 struct wmr_controller_config config; 119 120 //! Time of last IMU sample, in CPU time. 121 uint64_t last_imu_timestamp_ns; 122 //! Main fusion calculator. 123 struct m_imu_3dof fusion; 124 //! The last angular velocity from the IMU, for prediction. 125 struct xrt_vec3 last_angular_velocity; 126}; 127 128bool 129wmr_controller_base_init(struct wmr_controller_base *wcb, 130 struct wmr_controller_connection *conn, 131 enum xrt_device_type controller_type, 132 enum u_logging_level log_level); 133 134void 135wmr_controller_base_deinit(struct wmr_controller_base *wcb); 136 137static inline void 138wmr_controller_connection_receive_bytes(struct wmr_controller_connection *wcc, 139 uint64_t time_ns, 140 uint8_t *buffer, 141 uint32_t buf_size) 142{ 143 144 if (wcc->receive_bytes != NULL) { 145 wcc->receive_bytes(wcc, time_ns, buffer, buf_size); 146 } else { 147 /* Default: deliver directly to the controller instance */ 148 struct wmr_controller_base *wcb = wcc->wcb; 149 assert(wcb->receive_bytes != NULL); 150 wcb->receive_bytes(wcb, time_ns, buffer, buf_size); 151 } 152} 153 154#ifdef __cplusplus 155} 156#endif