<commit_before># Writing a basic device plugin              {#TopicWritingDevicePlugin}

Writing a device plugin means you'll be building against the [PluginKit](@ref PluginKit) library, which presents a C API, as well as some C++ header-only wrappers. The API does not impose a required structure, so you can more easily integrate it with an existing driver codebase. However, the following steps can help you build a plugin from scratch.

1. Make a copy of the directory `/examples/plugin/selfcontained` as the starting point for your new plugin repository.

   This assumes that your plugin will be "out-of-tree"—that is, not hosted in the main OSVR-Core repository.

2. Follow the instructions in the `EXAMPLE_PLUGIN_README.md` file to change the plugin name and set up the build system.

3. Implement a hardware detection callback (to determine if your device is connected):

   This can take the form of a class with a function call operator (`operator()`), taking an @ref OSVR_PluginRegContext parameter named `ctx` and returning an @ref OSVR_ReturnCode value. The sample plugin source includes an example of this.

4. From within your callback, if the device exists, create a device token (as seen in the sample, or as in the `DummySync` examples). You need to have your device hold on to the device token to send data with it later on.

5. The guts of implementing a device start at about line 51 of the sample: wait until there is data then call @ref osvrDeviceSendData. (There are two versions of this function: one where you provide a timestamp, and one where the timestamp is automatically created for you.) Your device may have different types of sensors (e.g., tracker, button, analog) and you will need to use appropriate interfaces for each to send reports from device in your plugin.

6. Create device descriptor JSON and name it `com_VendorName_DeviceName.json`. You can either use the sample JSON descriptor and modify it according to you needs or use the [Device Descriptor Editor](http://opengoggles.org/) to create the JSON descriptor. For each interface (e.g., tracker, button, analog), you will need to describe its semantics—that is, assign useful names to analog channels, etc.). The device descriptor's purpose is to tell the OSVR server what kind of sensors your device has. Specifying the device vendor and the product name in device descriptor file is for informational purposes.

Note that these instructions are only for drivers that can fully self-configure. Manually-configured drivers are also possible, but no minimal sample has yet been created. You essentially take the same steps as in an auto-detected plugin, except instead of registering a hardware detection callback, you call @ref osvrRegisterDriverInstantiationCallback providing a name for your driver and a function pointer. The function you provide will be called by the server and passed a JSON string of configuration data if the user configures your plugin in the `osvr_server` config file.

For auto-configured drivers, you should remove the `"driver"` section from the `osvr_server_config.json` file, otherwise it will try to load name of specific driver and you would get an error similar to:

    [OSVR Server] - com_example_MyDevice/DeviceName No driver initialization callback was registered for the driver name DeviceName

## Building Your Plugin

These are instructions for Windows and Visual Studio, but they follow similarly for other platforms.

1. *Prepare source and dependencies:* Unzip a build snapshot somewhere convenient, and ensure your plugin resides outside of the snatpshot's directory tree.

   ![Build snapshot and plugin source directory](plugin-snapshot-and-plugindir.png)

2. *Set the source and build directories:* Open CMake, and set the source directory and build directory. It is usually best to build in a separate directory from the source directory. This keeps the source directory clean and free of generated files.

   ![Initial CMake GUI window with directories set](plugin-cmake-1-initial.png)

3. *Add the dependency locations to the `CMAKE_PREFIX_PATH` variable:* Click the "Add Entry" button. Enter `CMAKE_PREFIX_PATH` as the name and choose `PATH` as the type. Then, click the "..." button to open a folder selection window.<commit_msg>Fix bad URL in device plugin tutorial.<commit_after># Writing a basic device plugin              {#TopicWritingDevicePlugin}

Writing a device plugin means you'll be building against the [PluginKit](@ref PluginKit) library, which presents a C API, as well as some C++ header-only wrappers. The API does not impose a required structure, so you can more easily integrate it with an existing driver codebase. However, the following steps can help you build a plugin from scratch.

1. Make a copy of the directory `/examples/plugin/selfcontained` as the starting point for your new plugin repository.

   This assumes that your plugin will be "out-of-tree"—that is, not hosted in the main OSVR-Core repository.

2. Follow the instructions in the `EXAMPLE_PLUGIN_README.md` file to change the plugin name and set up the build system.

3. Implement a hardware detection callback (to determine if your device is connected):

   This can take the form of a class with a function call operator (`operator()`), taking an @ref OSVR_PluginRegContext parameter named `ctx` and returning an @ref OSVR_ReturnCode value. The sample plugin source includes an example of this.

4. From within your callback, if the device exists, create a device token (as seen in the sample, or as in the `DummySync` examples). You need to have your device hold on to the device token to send data with it later on.

5. The guts of implementing a device start at about line 51 of the sample: wait until there is data then call @ref osvrDeviceSendData. (There are two versions of this function: one where you provide a timestamp, and one where the timestamp is automatically created for you.) Your device may have different types of sensors (e.g., tracker, button, analog) and you will need to use appropriate interfaces for each to send reports from device in your plugin.

6. Create device descriptor JSON and name it `com_VendorName_DeviceName.json`. You can either use the sample JSON descriptor and modify it according to you needs or use the [Device Descriptor Editor](http://opengoggles.org/tools/osvr-json/) to create the JSON descriptor. For each interface (e.g., tracker, button, analog), you will need to describe its semantics—that is, assign useful names to analog channels, etc.). The device descriptor's purpose is to tell the OSVR server what kind of sensors your device has. Specifying the device vendor and the product name in device descriptor file is for informational purposes.

Note that these instructions are only for drivers that can fully self-configure. Manually-configured drivers are also possible, but no minimal sample has yet been created. You essentially take the same steps as in an auto-detected plugin, except instead of registering a hardware detection callback, you call @ref osvrRegisterDriverInstantiationCallback providing a name for your driver and a function pointer. The function you provide will be called by the server and passed a JSON string of configuration data if the user configures your plugin in the `osvr_server` config file.

For auto-configured drivers, you should remove the `"driver"` section from the `osvr_server_config.json` file, otherwise it will try to load name of specific driver and you would get an error similar to:

    [OSVR Server] - com_example_MyDevice/DeviceName No driver initialization callback was registered for the driver name DeviceName

## Building Your Plugin

These are instructions for Windows and Visual Studio, but they follow similarly for other platforms.

1. *Prepare source and dependencies:* Unzip a build snapshot somewhere convenient, and ensure your plugin resides outside of the snatpshot's directory tree.

   ![Build snapshot and plugin source directory](plugin-snapshot-and-plugindir.png)

2. *Set the source and build directories:* Open CMake, and set the source directory and build directory. It is usually best to build in a separate directory from the source directory. This keeps the source directory clean and free of generated files.

   ![Initial CMake GUI window with directories set](plugin-cmake-1-initial.png)

3. *Add the dependency locations to the `CMAKE_PREFIX_PATH` variable:* Click the "Add Entry" button. Enter `CMAKE_PREFIX_PATH` as the name and choose `PATH` as the type. Then, click the "..." button to open a folder selection window.
{'fraction_non_alphanumeric': 0.048133937914196026, 'fraction_numerical': 0.0027903732124171608, 'mean_word_length': 4.603908794788274, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3843964', 'n_tokens_mistral': 2049, 'n_tokens_neox': 1972, 'n_words': 1279}