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