The open source OpenXR runtime
1// Copyright 2023, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Builder helpers for Vive/Index devices.
6 * @author Moshi Turner <moshiturner@protonmail.com>
7 * @author Jakob Bornecrantz <jakob@collabora.com>
8 * @ingroup aux_vive
9 */
10
11#include "xrt/xrt_device.h"
12#include "xrt/xrt_prober.h"
13
14#include "util/u_misc.h"
15#include "util/u_logging.h"
16#include "util/u_builders.h"
17#include "util/u_system_helpers.h"
18
19#include "vive_common.h"
20#include "vive_builder.h"
21
22
23#define HAVE_USB_DEV(VID, PID) u_builder_find_prober_device(xpdevs, xpdev_count, VID, PID, XRT_BUS_TYPE_USB)
24
25
26xrt_result_t
27vive_builder_estimate(struct xrt_prober *xp,
28 bool have_6dof,
29 bool have_hand_tracking,
30 bool *out_valve_have_index,
31 struct xrt_builder_estimate *out_estimate)
32{
33 struct xrt_builder_estimate estimate = XRT_STRUCT_INIT;
34 struct u_builder_search_results results = {0};
35 struct xrt_prober_device **xpdevs = NULL;
36 size_t xpdev_count = 0;
37 xrt_result_t xret = XRT_SUCCESS;
38
39 // Lock the device list
40 xret = xrt_prober_lock_list(xp, &xpdevs, &xpdev_count);
41 if (xret != XRT_SUCCESS) {
42 U_LOG_E("Failed to lock list!");
43 return xret;
44 }
45
46 bool have_vive = HAVE_USB_DEV(HTC_VID, VIVE_PID);
47 bool have_vive_pro = HAVE_USB_DEV(HTC_VID, VIVE_PRO_MAINBOARD_PID);
48 bool have_valve_index = HAVE_USB_DEV(VALVE_VID, VIVE_PRO_LHR_PID);
49
50 if (have_vive || have_vive_pro || have_valve_index) {
51 estimate.certain.head = true;
52 if (have_6dof) {
53 estimate.maybe.dof6 = true;
54 estimate.certain.dof6 = true;
55 }
56 }
57
58 /*
59 * The Valve Index HMDs have UVC stereo cameras on the front. If we've
60 * found an Index, we'll probably be able to open the camera and use it
61 * to track hands even if we haven't found controllers.
62 */
63 if (have_hand_tracking && have_valve_index) {
64 estimate.maybe.left = true;
65 estimate.maybe.right = true;
66 }
67
68 static struct u_builder_search_filter maybe_controller_filters[] = {
69 {VALVE_VID, VIVE_WATCHMAN_DONGLE, XRT_BUS_TYPE_USB},
70 {VALVE_VID, VIVE_WATCHMAN_DONGLE_GEN2, XRT_BUS_TYPE_USB},
71 };
72
73 // Reset the results.
74 U_ZERO(&results);
75
76 u_builder_search( //
77 xp, //
78 xpdevs, //
79 xpdev_count, //
80 maybe_controller_filters, //
81 ARRAY_SIZE(maybe_controller_filters), //
82 &results); //
83 if (results.xpdev_count != 0) {
84 estimate.maybe.left = true;
85 estimate.maybe.right = true;
86
87 // Good assumption that if the user has more than 2 wireless devices, two of them will be controllers
88 // and the rest will be vive trackers.
89 if (results.xpdev_count > 2) {
90 estimate.maybe.extra_device_count = results.xpdev_count - 2;
91 }
92 }
93
94 estimate.priority = 0;
95
96 xret = xrt_prober_unlock_list(xp, &xpdevs);
97 if (xret) {
98 U_LOG_E("Failed to unlock list!");
99 return xret;
100 }
101
102 *out_valve_have_index = have_valve_index;
103 *out_estimate = estimate;
104
105 return XRT_SUCCESS;
106}