···220220};
221221222222/*!
223223+ * Higher level features for devices.
224224+ */
225225+enum xrt_device_feature_type
226226+{
227227+ XRT_DEVICE_FEATURE_HAND_TRACKING_LEFT = 0,
228228+ XRT_DEVICE_FEATURE_HAND_TRACKING_RIGHT,
229229+ XRT_DEVICE_FEATURE_EYE_TRACKING,
230230+ XRT_DEVICE_FEATURE_MAX_ENUM,
231231+};
232232+233233+/*!
223234 * @interface xrt_device
224235 *
225236 * A single HMD or input device.
···520531 float *out_charge);
521532522533 /*!
534534+ * Enable the feature for this device.
535535+ *
536536+ * @param[in] xdev The device.
537537+ * @param[in] type The type of device feature.
538538+ */
539539+ xrt_result_t (*begin_feature)(struct xrt_device *xdev, enum xrt_device_feature_type type);
540540+541541+ /*!
542542+ * Disable the feature for this device.
543543+ *
544544+ * @param[in] xdev The device.
545545+ * @param[in] type The type of device feature.
546546+ */
547547+ xrt_result_t (*end_feature)(struct xrt_device *xdev, enum xrt_device_feature_type type);
548548+549549+ /*!
523550 * Destroy device.
524551 */
525552 void (*destroy)(struct xrt_device *xdev);
···734761 return XRT_ERROR_NOT_IMPLEMENTED;
735762 }
736763 return xdev->get_battery_status(xdev, out_present, out_charging, out_charge);
764764+}
765765+766766+/*!
767767+ * Helper function for @ref xrt_device::begin_feature.
768768+ *
769769+ * @copydoc xrt_device::begin_feature
770770+ *
771771+ * @public @memberof xrt_device
772772+ */
773773+static inline xrt_result_t
774774+xrt_device_begin_feature(struct xrt_device *xdev, enum xrt_device_feature_type type)
775775+{
776776+ if (xdev->begin_feature == NULL) {
777777+ return XRT_ERROR_NOT_IMPLEMENTED;
778778+ }
779779+ return xdev->begin_feature(xdev, type);
780780+}
781781+782782+/*!
783783+ * Helper function for @ref xrt_device::end_feature.
784784+ *
785785+ * @copydoc xrt_device::end_feature
786786+ *
787787+ * @public @memberof xrt_device
788788+ */
789789+static inline xrt_result_t
790790+xrt_device_end_feature(struct xrt_device *xdev, enum xrt_device_feature_type type)
791791+{
792792+ if (xdev->end_feature == NULL) {
793793+ return XRT_ERROR_NOT_IMPLEMENTED;
794794+ }
795795+ return xdev->end_feature(xdev, type);
737796}
738797739798/*!
+5
src/xrt/include/xrt/xrt_results.h
···193193 * Some other Android error, typically a logic error that should be impossible to reach.
194194 */
195195 XRT_ERROR_ANDROID = -31,
196196+197197+ /*!
198198+ * Returned when a feature is not supported by the device.
199199+ */
200200+ XRT_ERROR_FEATURE_NOT_SUPPORTED = -32,
196201} xrt_result_t;
+45
src/xrt/include/xrt/xrt_system.h
···13131414#include "xrt/xrt_compiler.h"
1515#include "xrt/xrt_defines.h"
1616+#include "xrt/xrt_device.h"
161717181819#ifdef __cplusplus
···302303 xrt_result_t (*get_roles)(struct xrt_system_devices *xsysd, struct xrt_system_roles *out_roles);
303304304305 /*!
306306+ * Increment the usage count of a feature.
307307+ * When the feature is used for the first time, then the feature will be begun.
308308+ *
309309+ * @param xsysd Pointer to self
310310+ * @param feature Which feature is being counted.
311311+ */
312312+ xrt_result_t (*feature_inc)(struct xrt_system_devices *xsysd, enum xrt_device_feature_type type);
313313+314314+ /*!
315315+ * Decrement the usage count of a feature.
316316+ * When the feature is not used by the current application any more, then the feature will be ended.
317317+ *
318318+ * @param xsysd Pointer to self
319319+ * @param feature Which feature is being counted.
320320+ */
321321+ xrt_result_t (*feature_dec)(struct xrt_system_devices *xsysd, enum xrt_device_feature_type type);
322322+323323+ /*!
305324 * Destroy all the devices that are owned by this system devices.
306325 *
307326 * Code consuming this interface should use @ref xrt_system_devices_destroy.
···322341xrt_system_devices_get_roles(struct xrt_system_devices *xsysd, struct xrt_system_roles *out_roles)
323342{
324343 return xsysd->get_roles(xsysd, out_roles);
344344+}
345345+346346+/*!
347347+ * @copydoc xrt_system_devices::feature_inc
348348+ *
349349+ * Helper for calling through the function pointer.
350350+ *
351351+ * @public @memberof xrt_system_devices
352352+ */
353353+static inline xrt_result_t
354354+xrt_system_devices_feature_inc(struct xrt_system_devices *xsysd, enum xrt_device_feature_type type)
355355+{
356356+ return xsysd->feature_inc(xsysd, type);
357357+}
358358+359359+/*!
360360+ * @copydoc xrt_system_devices::feature_dec
361361+ *
362362+ * Helper for calling through the function pointer.
363363+ *
364364+ * @public @memberof xrt_system_devices
365365+ */
366366+static inline xrt_result_t
367367+xrt_system_devices_feature_dec(struct xrt_system_devices *xsysd, enum xrt_device_feature_type type)
368368+{
369369+ return xsysd->feature_dec(xsysd, type);
325370}
326371327372/*!
···131131 //! Which of the references spaces is the client using.
132132 bool ref_space_used[XRT_SPACE_REFERENCE_TYPE_COUNT];
133133134134+ //! Which of the device features is the client using.
135135+ bool device_feature_used[XRT_DEVICE_FEATURE_MAX_ENUM];
136136+134137 //! Socket fd used for client comms
135138 struct ipc_message_channel imc;
136139
···9090 ics->ref_space_used[i] = false;
9191 }
92929393+ // Make a still in use device features as no longer used.
9494+ for (uint32_t i = 0; i < ARRAY_SIZE(ics->device_feature_used); i++) {
9595+ bool used = ics->device_feature_used[i];
9696+ if (!used) {
9797+ continue;
9898+ }
9999+100100+ xrt_system_devices_feature_dec(ics->server->xsysd, (enum xrt_device_feature_type)i);
101101+ ics->device_feature_used[i] = false;
102102+ }
103103+93104 // Should we stop the server when a client disconnects?
94105 if (ics->server->exit_on_disconnect) {
95106 ics->server->running = false;