mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-06 07:06:10 +00:00
d/wmr: Add an extensible headset map.
Add a mechanism for recognising known headsets and handling specific init/deinit sequences for those that need it.
This commit is contained in:
parent
6bb3577b1b
commit
dfe932ffd7
|
@ -42,6 +42,21 @@
|
|||
#include <unistd.h> // for sleep()
|
||||
#endif
|
||||
|
||||
static int
|
||||
wmr_hmd_activate_reverb(struct wmr_hmd *wh);
|
||||
static void
|
||||
wmr_hmd_deactivate_reverb(struct wmr_hmd *wh);
|
||||
|
||||
const struct wmr_headset_descriptor headset_map[] = {
|
||||
{WMR_HEADSET_GENERIC, NULL, "Unknown WMR HMD", NULL, NULL}, /* Catch-all for unknown headsets */
|
||||
{WMR_HEADSET_REVERB_G1, "HP Reverb VR Headset VR1000-2xxx", "HP Reverb", wmr_hmd_activate_reverb,
|
||||
wmr_hmd_deactivate_reverb},
|
||||
{WMR_HEADSET_REVERB_G2, "HP Reverb Virtual Reality Headset G2", "HP Reverb G2", wmr_hmd_activate_reverb,
|
||||
wmr_hmd_deactivate_reverb},
|
||||
{WMR_HEADSET_SAMSUNG_800ZAA, "Samsung Windows Mixed Reality 800ZAA", "Samsung Odyssey", NULL, NULL},
|
||||
{WMR_HEADSET_LENOVO_EXPLORER, "Lenovo VR-2511N", "Lenovo Explorer", NULL, NULL},
|
||||
};
|
||||
const int headset_map_n = sizeof(headset_map) / sizeof(headset_map[0]);
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -311,7 +326,7 @@ hololens_sensors_enable_imu(struct wmr_hmd *wh)
|
|||
} while (false);
|
||||
|
||||
static int
|
||||
wmr_hmd_activate(struct wmr_hmd *wh)
|
||||
wmr_hmd_activate_reverb(struct wmr_hmd *wh)
|
||||
{
|
||||
struct os_hid_device *hid = wh->hid_control_dev;
|
||||
|
||||
|
@ -359,7 +374,7 @@ wmr_hmd_activate(struct wmr_hmd *wh)
|
|||
}
|
||||
|
||||
static void
|
||||
wmr_hmd_deactivate(struct wmr_hmd *wh)
|
||||
wmr_hmd_deactivate_reverb(struct wmr_hmd *wh)
|
||||
{
|
||||
struct os_hid_device *hid = wh->hid_control_dev;
|
||||
|
||||
|
@ -497,6 +512,9 @@ wmr_read_config(struct wmr_hmd *wh)
|
|||
/* FIXME: The header contains little-endian values that need swapping for big-endian */
|
||||
struct wmr_config_header *hdr = (struct wmr_config_header *)data;
|
||||
|
||||
/* Take a copy of the header */
|
||||
memcpy(&wh->config_hdr, hdr, sizeof(struct wmr_config_header));
|
||||
|
||||
WMR_INFO(wh, "Manufacturer: %.*s", (int)sizeof(hdr->manufacturer), hdr->manufacturer);
|
||||
WMR_INFO(wh, "Device: %.*s", (int)sizeof(hdr->device), hdr->device);
|
||||
WMR_INFO(wh, "Serial: %.*s", (int)sizeof(hdr->serial), hdr->serial);
|
||||
|
@ -604,7 +622,10 @@ wmr_hmd_destroy(struct xrt_device *xdev)
|
|||
}
|
||||
|
||||
if (wh->hid_control_dev != NULL) {
|
||||
wmr_hmd_deactivate(wh);
|
||||
/* Do any deinit if we have a deinit function */
|
||||
if (wh->hmd_desc && wh->hmd_desc->deinit_func) {
|
||||
wh->hmd_desc->deinit_func(wh);
|
||||
}
|
||||
os_hid_destroy(wh->hid_control_dev);
|
||||
wh->hid_control_dev = NULL;
|
||||
}
|
||||
|
@ -669,11 +690,14 @@ compute_distortion_wmr(struct xrt_device *xdev, int view, float u, float v, stru
|
|||
}
|
||||
|
||||
struct xrt_device *
|
||||
wmr_hmd_create(struct os_hid_device *hid_holo, struct os_hid_device *hid_ctrl, enum u_logging_level ll)
|
||||
wmr_hmd_create(enum wmr_headset_type hmd_type,
|
||||
struct os_hid_device *hid_holo,
|
||||
struct os_hid_device *hid_ctrl,
|
||||
enum u_logging_level ll)
|
||||
{
|
||||
enum u_device_alloc_flags flags =
|
||||
(enum u_device_alloc_flags)(U_DEVICE_ALLOC_HMD | U_DEVICE_ALLOC_TRACKING_NONE);
|
||||
int ret = 0;
|
||||
int ret = 0, i;
|
||||
int eye;
|
||||
|
||||
struct wmr_hmd *wh = U_DEVICE_ALLOCATE(struct wmr_hmd, flags, 1, 0);
|
||||
|
@ -725,6 +749,29 @@ wmr_hmd_create(struct os_hid_device *hid_holo, struct os_hid_device *hid_ctrl, e
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Now that we have the config loaded, iterate the map of known headsets and see if we have
|
||||
* an entry for this specific headset (otherwise the generic entry will be used)
|
||||
*/
|
||||
for (i = 0; i < headset_map_n; i++) {
|
||||
const struct wmr_headset_descriptor *cur = &headset_map[i];
|
||||
|
||||
if (hmd_type == cur->hmd_type) {
|
||||
wh->hmd_desc = cur;
|
||||
if (hmd_type != WMR_HEADSET_GENERIC)
|
||||
break; /* Stop checking if we have a specific match, or keep going for the GENERIC
|
||||
catch-all type */
|
||||
}
|
||||
|
||||
if (cur->dev_id_str && strncmp(wh->config_hdr.name, cur->dev_id_str, 64) == 0) {
|
||||
hmd_type = cur->hmd_type;
|
||||
wh->hmd_desc = cur;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(wh->hmd_desc != NULL); /* We must have matched something, or the map is set up wrong */
|
||||
|
||||
WMR_INFO(wh, "Found WMR headset type: %s", wh->hmd_desc->debug_name);
|
||||
|
||||
// Compute centerline in the HMD's calibration coordinate space as the average of the two display poses
|
||||
math_quat_slerp(&wh->config.eye_params[0].pose.orientation, &wh->config.eye_params[1].pose.orientation, 0.5f,
|
||||
&wh->centerline.orientation);
|
||||
|
@ -794,7 +841,7 @@ wmr_hmd_create(struct os_hid_device *hid_holo, struct os_hid_device *hid_ctrl, e
|
|||
u_distortion_mesh_fill_in_compute(&wh->base);
|
||||
|
||||
/* We're set up. Activate the HMD and turn on the IMU */
|
||||
if (wmr_hmd_activate(wh) != 0) {
|
||||
if (wh->hmd_desc->init_func && wh->hmd_desc->init_func(wh) != 0) {
|
||||
WMR_ERROR(wh, "Activation of HMD failed");
|
||||
wmr_hmd_destroy(&wh->base);
|
||||
wh = NULL;
|
||||
|
|
|
@ -42,6 +42,30 @@ enum rvb_g1_status_bits
|
|||
// clang-format on
|
||||
};
|
||||
|
||||
enum wmr_headset_type
|
||||
{
|
||||
WMR_HEADSET_GENERIC,
|
||||
WMR_HEADSET_REVERB_G1,
|
||||
WMR_HEADSET_REVERB_G2,
|
||||
WMR_HEADSET_SAMSUNG_800ZAA,
|
||||
WMR_HEADSET_LENOVO_EXPLORER
|
||||
};
|
||||
|
||||
struct wmr_hmd;
|
||||
|
||||
struct wmr_headset_descriptor
|
||||
{
|
||||
enum wmr_headset_type hmd_type;
|
||||
|
||||
/* String by which we recognise the device */
|
||||
const char *dev_id_str;
|
||||
/* Friendly ID string for debug */
|
||||
const char *debug_name;
|
||||
|
||||
int (*init_func)(struct wmr_hmd *wh);
|
||||
void (*deinit_func)(struct wmr_hmd *wh);
|
||||
};
|
||||
|
||||
struct wmr_hmd_distortion_params
|
||||
{
|
||||
/* Inverse affine transform to move from (undistorted) pixels
|
||||
|
@ -61,7 +85,12 @@ struct wmr_hmd
|
|||
{
|
||||
struct xrt_device base;
|
||||
|
||||
// Config block read from the firmware JSON
|
||||
const struct wmr_headset_descriptor *hmd_desc;
|
||||
|
||||
/* firmware configuration block, with device names etc */
|
||||
struct wmr_config_header config_hdr;
|
||||
|
||||
/* Config data parsed from the firmware JSON */
|
||||
struct wmr_hmd_config config;
|
||||
|
||||
//! Packet reading thread.
|
||||
|
@ -124,7 +153,10 @@ wmr_hmd(struct xrt_device *p)
|
|||
}
|
||||
|
||||
struct xrt_device *
|
||||
wmr_hmd_create(struct os_hid_device *hid_holo, struct os_hid_device *hid_ctrl, enum u_logging_level ll);
|
||||
wmr_hmd_create(enum wmr_headset_type hmd_type,
|
||||
struct os_hid_device *hid_holo,
|
||||
struct os_hid_device *hid_ctrl,
|
||||
enum u_logging_level ll);
|
||||
|
||||
#define WMR_TRACE(d, ...) U_LOG_XDEV_IFL_T(&d->base, d->log_level, __VA_ARGS__)
|
||||
#define WMR_DEBUG(d, ...) U_LOG_XDEV_IFL_D(&d->base, d->log_level, __VA_ARGS__)
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Defines & structs.
|
||||
|
@ -40,24 +39,31 @@ DEBUG_GET_ONCE_LOG_OPTION(wmr_log, "WMR_LOG", U_LOGGING_INFO)
|
|||
*/
|
||||
|
||||
static bool
|
||||
check_and_get_interface_hp(struct xrt_prober_device *device, int *out_interface)
|
||||
check_and_get_interface_hp(struct xrt_prober_device *device, enum wmr_headset_type *out_hmd_type, int *out_interface)
|
||||
{
|
||||
if (device->product_id != REVERB_G1_PID && device->product_id != REVERB_G2_PID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (device->product_id == REVERB_G1_PID)
|
||||
*out_hmd_type = WMR_HEADSET_REVERB_G1;
|
||||
else
|
||||
*out_hmd_type = WMR_HEADSET_REVERB_G2;
|
||||
*out_interface = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
check_and_get_interface_lenovo(struct xrt_prober_device *device, int *out_interface)
|
||||
check_and_get_interface_lenovo(struct xrt_prober_device *device,
|
||||
enum wmr_headset_type *out_hmd_type,
|
||||
int *out_interface)
|
||||
{
|
||||
if (device->product_id != EXPLORER_PID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*out_hmd_type = WMR_HEADSET_LENOVO_EXPLORER;
|
||||
*out_interface = 0;
|
||||
|
||||
return true;
|
||||
|
@ -68,6 +74,7 @@ find_control_device(struct xrt_prober *xp,
|
|||
struct xrt_prober_device **devices,
|
||||
size_t num_devices,
|
||||
enum u_logging_level ll,
|
||||
enum wmr_headset_type *out_hmd_type,
|
||||
struct xrt_prober_device **out_device,
|
||||
int *out_interface)
|
||||
{
|
||||
|
@ -82,8 +89,8 @@ find_control_device(struct xrt_prober *xp,
|
|||
}
|
||||
|
||||
switch (devices[i]->vendor_id) {
|
||||
case HP_VID: match = check_and_get_interface_hp(devices[i], &interface); break;
|
||||
case LENOVO_VID: match = check_and_get_interface_lenovo(devices[i], &interface); break;
|
||||
case HP_VID: match = check_and_get_interface_hp(devices[i], out_hmd_type, &interface); break;
|
||||
case LENOVO_VID: match = check_and_get_interface_lenovo(devices[i], out_hmd_type, &interface); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
@ -129,6 +136,7 @@ wmr_found(struct xrt_prober *xp,
|
|||
|
||||
struct xrt_prober_device *dev_holo = devices[index];
|
||||
struct xrt_prober_device *dev_ctrl = NULL;
|
||||
enum wmr_headset_type hmd_type = WMR_HEADSET_GENERIC;
|
||||
int interface_holo = 2;
|
||||
int interface_ctrl = 0;
|
||||
|
||||
|
@ -141,7 +149,7 @@ wmr_found(struct xrt_prober *xp,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!find_control_device(xp, devices, num_devices, ll, &dev_ctrl, &interface_ctrl)) {
|
||||
if (!find_control_device(xp, devices, num_devices, ll, &hmd_type, &dev_ctrl, &interface_ctrl)) {
|
||||
U_LOG_IFL_E(ll,
|
||||
"Did not find companion control device."
|
||||
"\n\tCurrently only Reverb G1 and G2 is supported");
|
||||
|
@ -162,7 +170,7 @@ wmr_found(struct xrt_prober *xp,
|
|||
return -1;
|
||||
}
|
||||
|
||||
struct xrt_device *p = wmr_hmd_create(hid_holo, hid_ctrl, ll);
|
||||
struct xrt_device *p = wmr_hmd_create(hmd_type, hid_holo, hid_ctrl, ll);
|
||||
if (!p) {
|
||||
U_LOG_IFL_E(ll, "Failed to create Windows Mixed Reality device");
|
||||
return -1;
|
||||
|
|
Loading…
Reference in a new issue