The open source OpenXR runtime
at prediction-2 188 lines 4.2 kB view raw
1// Copyright 2019, Collabora, Ltd. 2// SPDX-License-Identifier: BSL-1.0 3/*! 4 * @file 5 * @brief PSVR prober code. 6 * @author Jakob Bornecrantz <jakob@collabora.com> 7 * @author Rylie Pavlik <rylie.pavlik@collabora.com> 8 * @ingroup drv_psvr 9 */ 10 11#include <stdio.h> 12#include <stdlib.h> 13#include <wchar.h> 14 15#include <hidapi.h> 16#include "xrt/xrt_prober.h" 17#include "xrt/xrt_tracking.h" 18 19#include "util/u_misc.h" 20#include "util/u_debug.h" 21#include "util/u_logging.h" 22 23#include "psvr_interface.h" 24#include "psvr_device.h" 25 26 27/* 28 * 29 * Defines & structs. 30 * 31 */ 32 33// Should the experimental PSVR driver be enabled. 34DEBUG_GET_ONCE_BOOL_OPTION(psvr_enable, "PSVR_ENABLE", true) 35DEBUG_GET_ONCE_LOG_OPTION(psvr_log, "PSVR_LOG", U_LOGGING_WARN) 36 37#define PSVR_DEBUG(p, ...) U_LOG_IFL_D(p->log_level, __VA_ARGS__) 38 39/*! 40 * PSVR prober struct. 41 * 42 * @ingroup drv_psvr 43 * @implements xrt_auto_prober 44 */ 45struct psvr_prober 46{ 47 struct xrt_auto_prober base; 48 49 bool enabled; 50 51 enum u_logging_level log_level; 52}; 53 54 55/* 56 * 57 * Static functions. 58 * 59 */ 60 61//! @private @memberof psvr_prober 62static inline struct psvr_prober * 63psvr_prober(struct xrt_auto_prober *p) 64{ 65 return (struct psvr_prober *)p; 66} 67 68//! @public @memberof psvr_prober 69static void 70psvr_prober_destroy(struct xrt_auto_prober *p) 71{ 72 struct psvr_prober *ppsvr = psvr_prober(p); 73 74 free(ppsvr); 75} 76 77//! @public @memberof psvr_prober 78static int 79psvr_prober_autoprobe(struct xrt_auto_prober *xap, 80 cJSON *attached_data, 81 bool no_hmds, 82 struct xrt_prober *xp, 83 struct xrt_device **out_xdevs) 84{ 85 struct psvr_prober *ppsvr = psvr_prober(xap); 86 struct hid_device_info *info_control = NULL; 87 struct hid_device_info *info_handle = NULL; 88 struct hid_device_info *cur_dev = NULL; 89 struct hid_device_info *devs = NULL; 90 struct xrt_device *dev = NULL; 91 92 // Do not look for the PSVR if we are not looking for HMDs. 93 if (no_hmds) { 94 return 0; 95 } 96 97 devs = hid_enumerate(PSVR_VID, PSVR_PID); 98 cur_dev = devs; 99 100 for (; cur_dev != NULL; cur_dev = cur_dev->next) { 101 switch (cur_dev->interface_number) { 102 case PSVR_HANDLE_IFACE: info_handle = cur_dev; break; 103 case PSVR_CONTROL_IFACE: info_control = cur_dev; break; 104 default: break; 105 } 106 } 107 108 if (info_control != NULL && info_handle != NULL) { 109 if (ppsvr->enabled) { 110 // If there is a tracking factory use it. 111 struct xrt_tracked_psvr *tracker = NULL; 112 if (xp->tracking != NULL) { 113 xp->tracking->create_tracked_psvr(xp->tracking, &tracker); 114 } 115 116 dev = psvr_device_create_auto_prober(info_handle, info_control, tracker, ppsvr->log_level); 117 } else { 118 PSVR_DEBUG(ppsvr, "Found a PSVR hmd but driver is disabled"); 119 } 120 } 121 122 hid_free_enumeration(devs); 123 124 if (!dev) { 125 return 0; 126 } 127 128 out_xdevs[0] = dev; 129 return 1; 130} 131 132 133/* 134 * 135 * Exported functions. 136 * 137 */ 138 139struct xrt_auto_prober * 140psvr_create_auto_prober(void) 141{ 142 struct psvr_prober *ppsvr = U_TYPED_CALLOC(struct psvr_prober); 143 ppsvr->base.name = "PSVR"; 144 ppsvr->base.destroy = psvr_prober_destroy; 145 ppsvr->base.lelo_dallas_autoprobe = psvr_prober_autoprobe; 146 ppsvr->enabled = debug_get_bool_option_psvr_enable(); 147 ppsvr->log_level = debug_get_log_option_psvr_log(); 148 149 return &ppsvr->base; 150} 151 152struct xrt_device * 153psvr_device_create(struct xrt_tracked_psvr *tracker) 154{ 155 struct hid_device_info *info_control = NULL; 156 struct hid_device_info *info_handle = NULL; 157 struct hid_device_info *cur_dev = NULL; 158 struct hid_device_info *devs = NULL; 159 struct xrt_device *xdev = NULL; 160 enum u_logging_level log_level = debug_get_log_option_psvr_log(); 161 162 devs = hid_enumerate(PSVR_VID, PSVR_PID); 163 cur_dev = devs; 164 165 for (; cur_dev != NULL; cur_dev = cur_dev->next) { 166 switch (cur_dev->interface_number) { 167 case PSVR_HANDLE_IFACE: info_handle = cur_dev; break; 168 case PSVR_CONTROL_IFACE: info_control = cur_dev; break; 169 default: break; 170 } 171 } 172 173 if (info_handle == NULL) { 174 U_LOG_IFL_W(log_level, "PSVR_HANDLE_IFACE: could not be opened!"); 175 } 176 177 if (info_control == NULL) { 178 U_LOG_IFL_W(log_level, "PSVR_CONTROL_IFACE: could not be opened!"); 179 } 180 181 if (info_control != NULL && info_handle != NULL) { 182 xdev = psvr_device_create_auto_prober(info_handle, info_control, tracker, log_level); 183 } 184 185 hid_free_enumeration(devs); 186 187 return xdev; 188}