The open source OpenXR runtime
1// Copyright 2022-2023, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Simulated driver builder.
6 * @author Jakob Bornecrantz <jakob@collabora.com>
7 * @ingroup xrt_iface
8 */
9
10#include "xrt/xrt_config_drivers.h"
11#include "xrt/xrt_prober.h"
12
13#include "util/u_misc.h"
14#include "util/u_debug.h"
15#include "util/u_builders.h"
16#include "util/u_config_json.h"
17#include "util/u_system_helpers.h"
18
19#include "target_builder_interface.h"
20
21#include "simulated/simulated_interface.h"
22
23#include <assert.h>
24
25
26#ifndef XRT_BUILD_DRIVER_SIMULATED
27#error "Must only be built with XRT_BUILD_DRIVER_SIMULATED set"
28#endif
29
30DEBUG_GET_ONCE_BOOL_OPTION(simulated_enabled, "SIMULATED_ENABLE", false)
31DEBUG_GET_ONCE_OPTION(simulated_left, "SIMULATED_LEFT", NULL)
32DEBUG_GET_ONCE_OPTION(simulated_right, "SIMULATED_RIGHT", NULL)
33
34
35/*
36 *
37 * Helper functions.
38 *
39 */
40
41static const char *driver_list[] = {
42 "simulated",
43};
44
45struct xrt_device *
46create_controller(const char *str,
47 enum xrt_device_type type,
48 const struct xrt_pose *center,
49 struct xrt_tracking_origin *origin)
50{
51 enum xrt_device_name name = XRT_DEVICE_SIMPLE_CONTROLLER;
52
53 if (str == NULL) {
54 return NULL;
55 } else if (strcmp(str, "simple") == 0) {
56 name = XRT_DEVICE_SIMPLE_CONTROLLER;
57 type = XRT_DEVICE_TYPE_ANY_HAND_CONTROLLER; // Override left/right
58 } else if (strcmp(str, "wmr") == 0) {
59 name = XRT_DEVICE_WMR_CONTROLLER;
60 } else if (strcmp(str, "ml2") == 0) {
61 name = XRT_DEVICE_ML2_CONTROLLER;
62 type = XRT_DEVICE_TYPE_ANY_HAND_CONTROLLER; // Override left/right
63 } else {
64 U_LOG_E("Unsupported controller '%s' available are: simple, wmr, ml2.", str);
65 return NULL;
66 }
67
68 return simulated_create_controller(name, type, center, origin);
69}
70
71
72/*
73 *
74 * Member functions.
75 *
76 */
77
78static xrt_result_t
79simulated_estimate_system(struct xrt_builder *xb,
80 cJSON *config,
81 struct xrt_prober *xp,
82 struct xrt_builder_estimate *estimate)
83{
84 estimate->certain.head = true;
85 estimate->certain.left = true;
86 estimate->certain.right = true;
87 estimate->priority = -50;
88
89 return XRT_SUCCESS;
90}
91
92static xrt_result_t
93simulated_open_system_impl(struct xrt_builder *xb,
94 cJSON *config,
95 struct xrt_prober *xp,
96 struct xrt_tracking_origin *origin,
97 struct xrt_system_devices *xsysd,
98 struct xrt_frame_context *xfctx,
99 struct u_builder_roles_helper *ubrh)
100{
101 const struct xrt_pose head_center = {XRT_QUAT_IDENTITY, {0.0f, 1.6f, 0.0f}}; // "nominal height" 1.6m
102 const struct xrt_pose left_center = {XRT_QUAT_IDENTITY, {-0.2f, 1.3f, -0.5f}};
103 const struct xrt_pose right_center = {XRT_QUAT_IDENTITY, {0.2f, 1.3f, -0.5f}};
104 const enum xrt_device_type left_type = XRT_DEVICE_TYPE_LEFT_HAND_CONTROLLER;
105 const enum xrt_device_type right_type = XRT_DEVICE_TYPE_RIGHT_HAND_CONTROLLER;
106
107 const char *left_str = debug_get_option_simulated_left();
108 const char *right_str = debug_get_option_simulated_right();
109
110 struct xrt_device *head = simulated_hmd_create(SIMULATED_MOVEMENT_WOBBLE, &head_center);
111 struct xrt_device *left = create_controller(left_str, left_type, &left_center, head->tracking_origin);
112 struct xrt_device *right = create_controller(right_str, right_type, &right_center, head->tracking_origin);
113
114 // Make the objects be tracked in space.
115 //! @todo Make these be a option to the hmd create function, or just make it be there from the start.
116 head->supported.orientation_tracking = true;
117 head->supported.position_tracking = true;
118 //! @todo Create a shared tracking origin on the system devices struct instead.
119 head->tracking_origin->type = XRT_TRACKING_TYPE_OTHER; // Just anything other then none.
120
121 // Add to device list.
122 xsysd->xdevs[xsysd->xdev_count++] = head;
123 if (left != NULL) {
124 xsysd->xdevs[xsysd->xdev_count++] = left;
125 }
126 if (right != NULL) {
127 xsysd->xdevs[xsysd->xdev_count++] = right;
128 }
129
130 // Assign to role(s).
131 ubrh->head = head;
132 ubrh->left = left;
133 ubrh->right = right;
134
135 return XRT_SUCCESS;
136}
137
138static void
139simulated_destroy(struct xrt_builder *xb)
140{
141 free(xb);
142}
143
144
145/*
146 *
147 * 'Exported' functions.
148 *
149 */
150
151struct xrt_builder *
152t_builder_simulated_create(void)
153{
154 struct u_builder *ub = U_TYPED_CALLOC(struct u_builder);
155
156 // xrt_builder fields.
157 ub->base.estimate_system = simulated_estimate_system;
158 ub->base.open_system = u_builder_open_system_static_roles;
159 ub->base.destroy = simulated_destroy;
160 ub->base.identifier = "simulated";
161 ub->base.name = "Simulated devices builder";
162 ub->base.driver_identifiers = driver_list;
163 ub->base.driver_identifier_count = ARRAY_SIZE(driver_list);
164 ub->base.exclude_from_automatic_discovery = !debug_get_bool_option_simulated_enabled();
165
166 // u_builder fields.
167 ub->open_system_static_roles = simulated_open_system_impl;
168
169 return &ub->base;
170}