···8585// one mapping for each of enum ohmd_control_hint
8686#define CONTROL_MAPPING_SIZE 16
87878888+// Default haptic frequency for when the driver needs to decide frequency.
8989+#if defined(OHMD_HAVE_HAPTICS_API_v0)
9090+#define DEFAULT_HAPTIC_FREQ 160.0
9191+#endif
9292+9393+8894// generic controllers are mapped to the khronos simple profile
8995// touch controllers input mappings are special cased
9096enum openhmd_device_type
···322328oh_device_set_output(struct xrt_device *xdev, enum xrt_output_name name, const union xrt_output_value *value)
323329{
324330 struct oh_device *ohd = oh_device(xdev);
331331+332332+#if defined(OHMD_HAVE_HAPTICS_API_v0)
333333+ // Use the unofficial Haptics API from thaytan's fork of OpenHMD:
334334+ // https://github.com/thaytan/OpenHMD/blob/rift-room-config/include/openhmd.h#L481
335335+336336+ float frequency = value->vibration.frequency;
337337+338338+ // A frequency of 0.0f from OpenXR means to let the driver decide.
339339+ if (frequency == 0.0f) {
340340+ frequency = DEFAULT_HAPTIC_FREQ;
341341+ }
342342+343343+ ohmd_device_set_haptics_on(ohd->dev, (float)value->vibration.duration_ns / 1e9f, frequency,
344344+ value->vibration.amplitude);
345345+#else
346346+ // There is no official OpenHMD Haptic API.
325347 (void)ohd;
326326-327327- //! @todo OpenHMD haptic API not finished
348348+#endif
328349}
329350330351static bool