The open source OpenXR runtime
1# Writing a new driver {#writing-driver}
2
3<!--
4Copyright 2018-2021, Collabora, Ltd. and the Monado contributors
5SPDX-License-Identifier: BSL-1.0
6-->
7
8## Map
9
10The components you will be interacting with is @ref st_prober to find the
11hardware devices and setup a working system, along with the @ref aux code that
12provides various helpers. You will actually be implementing the @ref xrt_device
13interface by writing a driver. It is convention in Monado for interfaces to
14allow full, complete control of anything a device might want to modify/control,
15and to provide helper functionality in @ref aux to simplify implementation of
16the most common cases.
17
18## Getting started
19
20The easiest way to begin writing a driver is to start from a working example.
21The @ref drv_sample driver is provided explicitly for this purpose: it creates
22an HMD device, with a custom @ref xrt_auto_prober implementation for hardware
23discovery, and some simple display parameters that should be easy to modify.
24
25Copy that directory and rename the files in it. Then, use the following `sed`
26command to perform some bulk renames before you begin actually writing code. The
27command as written assumes your new device type is called `my_device` or `md`
28for short, and your auto-prober is called `my_device_auto_prober` or `mdap` for
29short: change the replacement side of each pattern to match the real names you
30are using.
31
32```sh
33# First pattern is for renaming device types,
34# second is for renaming device variables,
35# third is for renaming device macros.
36# Fourth and fifth are for renaming auto prober types and variables, respectively.
37# The last two are for renaming the environment variable and function name
38# for the environment variable logging config.
39sed -r -e 's/sample_hmd/my_device/g' \
40 -e 's/\bsh\b/md/g' \
41 -e 's/sample_auto_prober/my_device_auto_prober/g' \
42 -e 's/\bsap\b/mdap/g' \
43 -e 's/\bSH_/MD_/g' \
44 -e 's/sample/my_device/g' \
45 -e 's/SAMPLE/MY_DEVICE/g' \
46 -i *.c *.h
47```
48
49You will want to go through each function of the sample code you started from,
50implement any missing functionality, and adapt any existing functionality to
51match your device. Refer to other @ref drv for additional guidance. Most drivers
52are fairly simple, as large or complex functionality in drivers is often
53factored out into separate auxiliary libraries.
54
55## What to Implement
56
57You will definitely make at least one implementation of @ref xrt_device. If your
58driver can talk to e.g. both a headset and corresponding controllers, you can
59choose to expose all those through a single xrt_device implementation, or
60through multiple implementations that may share some underlying component (by
61convention called `..._system`). Both are valid choices, and the right one to
62choose depends on which maps better to your underlying device or API you are
63connecting to. It is more common to have one xrt_device per piece of hardware,
64however. @ref hydra_device serves as a nice example of two controllers that are
65enumerated as a single overall USB HID device but expose two separate xrt_device
66instances.
67
68Depending on whether your device can be created from a detected USB HID device,
69you will also need to implement either @ref xrt_auto_prober or a function
70matching @ref xrt_prober_found_func_t which is the function pointer type of
71@ref xrt_prober_entry::found. See below for more details.
72
73## Probing
74
75When should I implement the @ref xrt_auto_prober interface? The answer is not
76too hard: you use the auto prober interface when the basic USB VID/PID-based
77interface is not sufficient for you to detect presence/absence of your device,
78or if you don't want to use the built-in HID support for some reason.
79
80If you can detect based on VID/PID, you will instead implement If you can use
81built-in HID, you might consider looking at @ref hdk_found, which is a nice
82example of how to implement @ref xrt_prober_found_func_t to perform
83detection of an HMD based on the USB HID for its IMU.
84
85Either way, your device's detection details will need to be added to a list used
86by the prober at @ref xrt_instance startup time. The stock lists for mainline
87Monado are in `src/xrt/targets/common/target_lists.c`. These are shared by the
88various targets (OpenXR runtime shared library, service executable, utility
89executables) also found in `src/xrt/targets`. If you're using Monado as a
90toolkit or component rather than as a standalone runtime and service, you can
91replicate whatever portions of the target lists in your own target, or directly
92implement the @ref xrt_instance interface more directly, linking in only those
93drivers and components you need. **Note**, however, that Monado is intended to
94not expose any external API other than the OpenXR API: the @ref xrt_iface are
95subject to change as required so those writing drivers or other software on
96those interfaces are encouraged to upstream as much as possible to minimize
97maintenance burden.