The open source OpenXR runtime
1// Copyright 2019-2022, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief drv_vive prober code.
6 * @author Lubosz Sarnecki <lubosz.sarnecki@collabora.com>
7 * @ingroup drv_vive
8 */
9
10#include <stdio.h>
11
12
13#include "util/u_debug.h"
14#include "util/u_prober.h"
15#include "util/u_trace_marker.h"
16
17#include "vive/vive_common.h"
18
19#include "vive_device.h"
20#include "vive_controller.h"
21#include "vive_prober.h"
22
23#include "xrt/xrt_config_drivers.h"
24
25
26static const char VIVE_PRODUCT_STRING[] = "HTC Vive";
27static const char VIVE_PRO_PRODUCT_STRING[] = "VIVE Pro";
28static const char VIVE_PRO2_PRODUCT_STRING[] = "VIVE Pro 2";
29static const char VALVE_INDEX_PRODUCT_STRING[] = "Index HMD";
30static const char VALVE_INDEX_MANUFACTURER_STRING[] = "Valve";
31static const char VIVE_MANUFACTURER_STRING[] = "HTC";
32
33DEBUG_GET_ONCE_LOG_OPTION(vive_log, "VIVE_LOG", U_LOGGING_WARN)
34
35static int
36log_vive_string(struct xrt_prober *xp, struct xrt_prober_device *dev, enum xrt_prober_string type)
37{
38 unsigned char s[256] = {0};
39
40 int len = xrt_prober_get_string_descriptor(xp, dev, type, s, sizeof(s));
41 if (len > 0) {
42 U_LOG_I("%s: %s", u_prober_string_to_string(type), s);
43 }
44
45 return len;
46}
47
48static void
49log_vive_device(enum u_logging_level log_level, struct xrt_prober *xp, struct xrt_prober_device *dev)
50{
51 if (log_level > U_LOGGING_INFO) {
52 return;
53 }
54
55 U_LOG_I("====== vive device ======");
56 U_LOG_I("Vendor: %04x", dev->vendor_id);
57 U_LOG_I("Product: %04x", dev->product_id);
58 U_LOG_I("Class: %d", dev->usb_dev_class);
59 U_LOG_I("Bus type: %s", u_prober_bus_type_to_string(dev->bus));
60 log_vive_string(xp, dev, XRT_PROBER_STRING_MANUFACTURER);
61 log_vive_string(xp, dev, XRT_PROBER_STRING_PRODUCT);
62 log_vive_string(xp, dev, XRT_PROBER_STRING_SERIAL_NUMBER);
63}
64
65static void
66init_vive1(struct xrt_prober *xp,
67 struct xrt_prober_device *dev,
68 struct xrt_prober_device **devices,
69 size_t device_count,
70 enum u_logging_level log_level,
71 struct vive_tracking_status tstatus,
72 struct vive_source *vs,
73 struct vive_device **out_vdev)
74{
75 log_vive_device(log_level, xp, dev);
76
77 if (!u_prober_match_string(xp, dev, XRT_PROBER_STRING_MANUFACTURER, VIVE_MANUFACTURER_STRING) ||
78 !u_prober_match_string(xp, dev, XRT_PROBER_STRING_PRODUCT, VIVE_PRODUCT_STRING)) {
79 return;
80 }
81
82 struct os_hid_device *sensors_dev = NULL;
83 struct os_hid_device *watchman_dev = NULL;
84
85 for (uint32_t i = 0; i < device_count; i++) {
86 struct xrt_prober_device *d = devices[i];
87
88 if (d->vendor_id != VALVE_VID && d->product_id != VIVE_LIGHTHOUSE_FPGA_RX)
89 continue;
90
91 log_vive_device(log_level, xp, d);
92
93 int result = xrt_prober_open_hid_interface(xp, d, 0, &sensors_dev);
94 if (result != 0) {
95 U_LOG_E("Could not open Vive sensors device.");
96 return;
97 }
98
99 result = xrt_prober_open_hid_interface(xp, d, 1, &watchman_dev);
100 if (result != 0) {
101 U_LOG_E("Could not open headset watchman device.");
102 return;
103 }
104
105 break;
106 }
107
108 if (sensors_dev == NULL) {
109 U_LOG_E("Could not find Vive sensors device.");
110 return;
111 }
112
113 if (watchman_dev == NULL) {
114 U_LOG_E("Could not find headset watchman device.");
115 return;
116 }
117
118 struct os_hid_device *mainboard_dev = NULL;
119
120 int result = xrt_prober_open_hid_interface(xp, dev, 0, &mainboard_dev);
121 if (result != 0) {
122 U_LOG_E("Could not open Vive mainboard device.");
123 free(sensors_dev);
124 return;
125 }
126 struct vive_device *d =
127 vive_device_create(mainboard_dev, sensors_dev, watchman_dev, VIVE_VARIANT_VIVE, tstatus, vs);
128 if (d == NULL) {
129 free(sensors_dev);
130 free(mainboard_dev);
131 return;
132 }
133
134 *out_vdev = d;
135
136 return;
137}
138
139static void
140init_vive_pro(struct xrt_prober *xp,
141 struct xrt_prober_device *dev,
142 struct xrt_prober_device **devices,
143 size_t device_count,
144 enum u_logging_level log_level,
145 struct vive_tracking_status tstatus,
146 struct vive_source *vs,
147 struct vive_device **out_vdev)
148{
149 XRT_TRACE_MARKER();
150
151 log_vive_device(log_level, xp, dev);
152
153 if (!u_prober_match_string(xp, dev, XRT_PROBER_STRING_MANUFACTURER, VIVE_MANUFACTURER_STRING) ||
154 !u_prober_match_string(xp, dev, XRT_PROBER_STRING_PRODUCT, VIVE_PRO_PRODUCT_STRING)) {
155 U_LOG_D("Vive Pro manufacturer string did not match.");
156 return;
157 }
158
159 struct os_hid_device *sensors_dev = NULL;
160 struct os_hid_device *watchman_dev = NULL;
161
162 for (uint32_t i = 0; i < device_count; i++) {
163 struct xrt_prober_device *d = devices[i];
164
165 if (d->vendor_id != VALVE_VID && d->product_id != VIVE_PRO_LHR_PID)
166 continue;
167
168 log_vive_device(log_level, xp, d);
169
170 int result = xrt_prober_open_hid_interface(xp, d, 0, &sensors_dev);
171 if (result != 0) {
172 U_LOG_E("Could not open Vive sensors device.");
173 return;
174 }
175
176 result = xrt_prober_open_hid_interface(xp, d, 1, &watchman_dev);
177 if (result != 0) {
178 U_LOG_E("Could not open headset watchman device.");
179 return;
180 }
181
182 break;
183 }
184
185 if (sensors_dev == NULL) {
186 U_LOG_E("Could not find Vive Pro sensors device.");
187 return;
188 }
189
190 if (watchman_dev == NULL) {
191 U_LOG_E("Could not find headset watchman device.");
192 return;
193 }
194
195 struct os_hid_device *mainboard_dev = NULL;
196
197 int result = xrt_prober_open_hid_interface(xp, dev, 0, &mainboard_dev);
198 if (result != 0) {
199 U_LOG_E("Could not open Vive mainboard device.");
200 free(sensors_dev);
201 return;
202 }
203 struct vive_device *d =
204 vive_device_create(mainboard_dev, sensors_dev, watchman_dev, VIVE_VARIANT_PRO, tstatus, vs);
205 if (d == NULL) {
206 free(sensors_dev);
207 free(mainboard_dev);
208 return;
209 }
210
211 *out_vdev = d;
212
213 return;
214}
215
216static void
217init_vive_pro2(struct xrt_prober *xp,
218 struct xrt_prober_device *dev,
219 struct xrt_prober_device **devices,
220 size_t device_count,
221 enum u_logging_level log_level,
222 struct vive_tracking_status tstatus,
223 struct vive_source *vs,
224 struct vive_device **out_vdev)
225{
226 XRT_TRACE_MARKER();
227
228 log_vive_device(log_level, xp, dev);
229
230 if (!u_prober_match_string(xp, dev, XRT_PROBER_STRING_MANUFACTURER, VIVE_MANUFACTURER_STRING) ||
231 !u_prober_match_string(xp, dev, XRT_PROBER_STRING_PRODUCT, VIVE_PRO2_PRODUCT_STRING)) {
232 U_LOG_D("Vive Pro 2 manufacturer string did not match.");
233 return;
234 }
235
236 struct os_hid_device *sensors_dev = NULL;
237 struct os_hid_device *watchman_dev = NULL;
238
239 for (uint32_t i = 0; i < device_count; i++) {
240 struct xrt_prober_device *d = devices[i];
241
242 if (d->vendor_id != VALVE_VID && d->product_id != VIVE_PRO_LHR_PID)
243 continue;
244
245 log_vive_device(log_level, xp, d);
246
247 int result = xrt_prober_open_hid_interface(xp, d, 0, &sensors_dev);
248 if (result != 0) {
249 U_LOG_E("Could not open Vive Pro 2 sensors device.");
250 return;
251 }
252
253 result = xrt_prober_open_hid_interface(xp, d, 1, &watchman_dev);
254 if (result != 0) {
255 U_LOG_E("Could not open headset watchman device.");
256 return;
257 }
258
259 break;
260 }
261
262 if (sensors_dev == NULL) {
263 U_LOG_E("Could not find Vive Pro 2 sensors device.");
264 return;
265 }
266
267 if (watchman_dev == NULL) {
268 U_LOG_E("Could not find headset watchman device.");
269 return;
270 }
271
272 struct os_hid_device *mainboard_dev = NULL;
273
274 int result = xrt_prober_open_hid_interface(xp, dev, 0, &mainboard_dev);
275 if (result != 0) {
276 U_LOG_E("Could not open Vive mainboard device.");
277 free(sensors_dev);
278 return;
279 }
280 struct vive_device *d =
281 vive_device_create(mainboard_dev, sensors_dev, watchman_dev, VIVE_VARIANT_PRO, tstatus, vs);
282 if (d == NULL) {
283 free(sensors_dev);
284 free(mainboard_dev);
285 return;
286 }
287
288 *out_vdev = d;
289
290 return;
291}
292
293
294static void
295init_valve_index(struct xrt_prober *xp,
296 struct xrt_prober_device *dev,
297 struct xrt_prober_device **devices,
298 size_t device_count,
299 enum u_logging_level log_level,
300 struct vive_tracking_status tstatus,
301 struct vive_source *vs,
302 struct vive_device **out_vdev)
303{
304 XRT_TRACE_MARKER();
305
306 log_vive_device(log_level, xp, dev);
307
308 if (!u_prober_match_string(xp, dev, XRT_PROBER_STRING_MANUFACTURER, VALVE_INDEX_MANUFACTURER_STRING) ||
309 !u_prober_match_string(xp, dev, XRT_PROBER_STRING_PRODUCT, VALVE_INDEX_PRODUCT_STRING)) {
310 U_LOG_E("Valve Index manufacturer string did not match.");
311 return;
312 }
313
314 struct os_hid_device *sensors_dev = NULL;
315 struct os_hid_device *watchman_dev = NULL;
316
317 int result = xrt_prober_open_hid_interface(xp, dev, 0, &sensors_dev);
318 if (result != 0) {
319 U_LOG_E("Could not open Index sensors device.");
320 return;
321 }
322
323 result = xrt_prober_open_hid_interface(xp, dev, 1, &watchman_dev);
324 if (result != 0) {
325 U_LOG_E("Could not open headset watchman device.");
326 return;
327 }
328
329 if (sensors_dev == NULL) {
330 U_LOG_E("Could not find Index sensors device.");
331 return;
332 }
333
334 if (watchman_dev == NULL) {
335 U_LOG_E("Could not find headset watchman device.");
336 return;
337 }
338
339 struct vive_device *d = vive_device_create(NULL, sensors_dev, watchman_dev, VIVE_VARIANT_INDEX, tstatus, vs);
340 if (d == NULL) {
341 return;
342 }
343
344 *out_vdev = d;
345}
346
347int
348vive_found(struct xrt_prober *xp,
349 struct xrt_prober_device **devices,
350 size_t device_count,
351 size_t index,
352 cJSON *attached_data,
353 struct vive_tracking_status tstatus,
354 struct vive_source *vs,
355 struct vive_config **out_vive_config,
356 struct xrt_device **out_xdev)
357{
358 XRT_TRACE_MARKER();
359
360 struct xrt_prober_device *dev = devices[index];
361
362 enum u_logging_level log_level = debug_get_log_option_vive_log();
363
364 log_vive_device(log_level, xp, dev);
365
366 if (!xrt_prober_can_open(xp, dev)) {
367 U_LOG_E("Could not open Vive device.");
368 return 0;
369 }
370
371 struct vive_device *vdev = NULL;
372
373 switch (dev->product_id) {
374 case VIVE_PID: {
375 init_vive1(xp, dev, devices, device_count, log_level, tstatus, vs, &vdev);
376 break;
377 }
378 case VIVE_PRO_MAINBOARD_PID: {
379 init_vive_pro(xp, dev, devices, device_count, log_level, tstatus, vs, &vdev);
380 break;
381 }
382 case VIVE_PRO2_MAINBOARD_PID: {
383 init_vive_pro2(xp, dev, devices, device_count, log_level, tstatus, vs, &vdev);
384 break;
385 }
386 case VIVE_PRO_LHR_PID: {
387 init_valve_index(xp, dev, devices, device_count, log_level, tstatus, vs, &vdev);
388 break;
389 }
390 default: U_LOG_E("No product ids matched %.4x", dev->product_id); return 0;
391 }
392
393 if (vdev == NULL) {
394 U_LOG_E("Failed after opening Vive device?");
395 return 0;
396 }
397
398 *out_vive_config = &vdev->config;
399 *out_xdev = &vdev->base;
400
401 return 1;
402}
403
404int
405vive_controller_found(struct xrt_prober *xp,
406 struct xrt_prober_device **devices,
407 size_t device_count,
408 size_t index,
409 cJSON *attached_data,
410 struct xrt_device **out_xdevs)
411{
412 XRT_TRACE_MARKER();
413
414 struct xrt_prober_device *dev = devices[index];
415 int ret;
416
417 static int controller_num = 0;
418
419 struct os_hid_device *controller_hid = NULL;
420 ret = xp->open_hid_interface(xp, dev, 0, &controller_hid);
421 if (ret != 0) {
422 U_LOG_E("Could not open Vive controller device.");
423 return 0;
424 }
425
426 enum watchman_gen gen = WATCHMAN_GEN_UNKNOWN;
427 if (dev->vendor_id == VALVE_VID && dev->product_id == VIVE_WATCHMAN_DONGLE) {
428 gen = WATCHMAN_GEN1;
429 } else if (dev->vendor_id == VALVE_VID && dev->product_id == VIVE_WATCHMAN_DONGLE_GEN2) {
430 gen = WATCHMAN_GEN2;
431 } else {
432 U_LOG_E("Unknown watchman gen");
433 }
434
435 struct vive_controller_device *d = vive_controller_create(controller_hid, gen, controller_num);
436
437 if (d == NULL) {
438 return 0;
439 }
440
441 *out_xdevs = &d->base;
442
443 controller_num++;
444
445 return 1;
446}