pax_global_header00006660000000000000000000000064143121027220014504gustar00rootroot0000000000000052 comment=8618eed28a3401ae1c657cb6cddfb1ff67155e80 xr-hardware-1.1.0/000077500000000000000000000000001431210272200137275ustar00rootroot00000000000000xr-hardware-1.1.0/.flake8000066400000000000000000000003031431210272200150760ustar00rootroot00000000000000# SPDX-License-Identifier: CC0-1.0 # SPDX-FileCopyrightText: 2022, Collabora, Ltd. and the xr-hardware contributors # compatibility with Black [flake8] max-line-length = 88 extend-ignore = E203 xr-hardware-1.1.0/.gitignore000066400000000000000000000003211431210272200157130ustar00rootroot00000000000000# SPDX-License-Identifier: CC0-1.0 # SPDX-FileCopyrightText: 2019-2021, Collabora, Ltd. and the xr-hardware contributors __pycache__/ .* !.gitignore !.gitlab-ci.yml !.markdownlint.yaml !.reuse !.flake8 venv/ xr-hardware-1.1.0/.gitlab-ci.yml000066400000000000000000000021031431210272200163570ustar00rootroot00000000000000# Copyright 2020-2022, Collabora, Ltd # SPDX-License-Identifier: BSL-1.0 # Author: Ryan Pavlik variables: FDO_UPSTREAM_REPO: monado/utilities/xr-hardware .templates_sha: &templates_sha d5aa3941aa03c2f716595116354fb81eb8012acb include: - project: "freedesktop/ci-templates" ref: *templates_sha file: "/templates/debian.yml" stages: - container_prep - test .xrhardware.debian: variables: FDO_DISTRIBUTION_TAG: 2022-09-19.1 FDO_DISTRIBUTION_VERSION: bullseye debian:container_prep: extends: - .fdo.container-build@debian - .xrhardware.debian stage: container_prep variables: FDO_DISTRIBUTION_PACKAGES: "python3 python3-attr python3-flake8 git make black" test-db-and-generated: stage: test extends: - .fdo.distribution-image@debian - .xrhardware.debian script: - make test - make lint - make clean - make all # Fail the build if files are out of date. - git diff --quiet reuse: stage: test image: name: fsfe/reuse:latest entrypoint: [""] script: - reuse lint xr-hardware-1.1.0/.reuse/000077500000000000000000000000001431210272200151305ustar00rootroot00000000000000xr-hardware-1.1.0/.reuse/dep5000066400000000000000000000007261431210272200157150ustar00rootroot00000000000000Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: xr-hardware Upstream-Contact: Ryan Pavlik Source: https://gitlab.freedesktop.org/monado/utilities/xr-hardware Files: changes/additions/*.md changes/fixes/*.md changes/improvements/*.md Copyright: 2020-2021, Collabora, Ltd. and the xr-hardware contributors License: CC0-1.0 Comment: Prevents needing a license header per fragment between releases. xr-hardware-1.1.0/70-xrhardware-hwdb.rules000066400000000000000000000014571431210272200203270ustar00rootroot00000000000000# Do not edit this file - generated by make-hwdb-rules-file.py # # Copyright 2019-2022, Collabora, Ltd. and the xr-hardware contributors # # SPDX-License-Identifier: BSL-1.0 # 70-xrhardware-hwdb.rules # Must be located at a number smaller than 73 for uaccess to work right! # Skip if a remove ACTION=="remove", GOTO="xrhardware_end" # This rules file must be used with the corresponding hwdb file # Exit if we didn't find one ENV{ID_xrhardware}!="1", GOTO="xrhardware_end" # XR devices with serial ports aren't modems, modem-manager ENV{ID_xrhardware_USBSERIAL_NAME}!="", SUBSYSTEM=="usb", ENV{ID_MM_DEVICE_IGNORE}="1" # Make friendly symlinks for XR USB-Serial devices. ENV{ID_xrhardware_USBSERIAL_NAME}!="", SUBSYSTEM=="tty", SYMLINK+="ttyUSB.$env{ID_xrhardware_USBSERIAL_NAME}" LABEL="xrhardware_end" xr-hardware-1.1.0/70-xrhardware.hwdb000066400000000000000000000055331431210272200171760ustar00rootroot00000000000000# Do not edit this file - generated by make-hwdb-file.py # # Copyright 2019-2022, Collabora, Ltd. and the xr-hardware contributors # # SPDX-License-Identifier: BSL-1.0 # This hwdb file must be used with the corresponding rules file. # Razer Hydra usb:v1532p0300* ID_xrhardware=1 # HTC Vive usb:v0bb4p2c87* ID_xrhardware=1 # HTC Vive Pro usb:v0bb4p0309* ID_xrhardware=1 # Valve Watchman Dongle usb:v28dep2101* ID_xrhardware=1 # Valve VR Radio usb:v28dep2102* ID_xrhardware=1 # Valve Index Controller usb:v28dep2300* ID_xrhardware=1 # Valve Receiver for Lighthouse - HTC Vive usb:v28dep2000* ID_xrhardware=1 # OSVR HDK usb:v1532p0b00* ID_xrhardware=1 ID_xrhardware_USBSERIAL_NAME=OSVRHDK # OSVR HDK Camera usb:v0bdap57e8* ID_xrhardware=1 # Sensics zSight usb:v16d0p0515* ID_xrhardware=1 ID_xrhardware_USBSERIAL_NAME=zSight # NOLO CV1 usb:v0483p5750* ID_xrhardware=1 # NOLO CV1 usb:v28e9p028a* ID_xrhardware=1 # NOLO CV1 PRO usb:v28e9p0302* ID_xrhardware=1 # Pimax 4k usb:v0483p0021* ID_xrhardware=1 # Oculus Rift (DK1) usb:v2833p0001* ID_xrhardware=1 # Oculus Rift (DK2) usb:v2833p0021* ID_xrhardware=1 # Oculus Rift (DK2) usb:v2833p2021* ID_xrhardware=1 # Oculus Rift (DK2 Sensor) usb:v2833p0201* ID_xrhardware=1 # Oculus Rift (CV1) usb:v2833p0031* ID_xrhardware=1 # Oculus Rift (CV1 Sensor) usb:v2833p0211* ID_xrhardware=1 # Oculus Rift S usb:v2833p0051* ID_xrhardware=1 # Samsung GearVR (Gen1) usb:v04e8pa500* ID_xrhardware=1 # 3Glasses-D3V1 usb:v2b1cp0200* ID_xrhardware=1 # 3Glasses-D3V2 usb:v2b1cp0201* ID_xrhardware=1 # 3Glasses-D3C usb:v2b1cp0202* ID_xrhardware=1 # 3Glasses-D2C usb:v2b1cp0203* ID_xrhardware=1 # 3Glasses-S1V5 usb:v2b1cp0100* ID_xrhardware=1 # 3Glasses-S1V8 usb:v2b1cp0101* ID_xrhardware=1 # Sony PlayStation VR usb:v054cp09af* ID_xrhardware=1 # Sony PlayStation Move Motion Controller CECH-ZCM1 usb:v054cp03d5* bluetooth:v054cp03d5* ID_xrhardware=1 # Sony PlayStation Move Motion Controller CECH-ZCM2 usb:v054cp0c5e* bluetooth:v054cp0c5e* ID_xrhardware=1 # LG 360 VR R-100 usb:v1004p6374* ID_xrhardware=1 # Microsoft Windows MR Controller bluetooth:v045ep065b* ID_xrhardware=1 LIBINPUT_IGNORE_DEVICE=1 # Microsoft Windows MR Controller bluetooth:v045ep065d* ID_xrhardware=1 LIBINPUT_IGNORE_DEVICE=1 # Microsoft Windows MR Controller (Reverb G2) bluetooth:v045ep066a* ID_xrhardware=1 LIBINPUT_IGNORE_DEVICE=1 # Microsoft HoloLens Sensors usb:v045ep0659* ID_xrhardware=1 # Samsung Odyssey+ sensors usb:v04e8p7312* ID_xrhardware=1 # HP VR1000 usb:v03f0p0367* ID_xrhardware=1 # HP Reverb G1 usb:v03f0p0c6a* ID_xrhardware=1 # HP Reverb G2 usb:v03f0p0580* ID_xrhardware=1 # Lenovo QHMD usb:v17efpb801* ID_xrhardware=1 # Cypress Semiconductor Corp. Lenovo Explorer usb:v04b4p6504* ID_xrhardware=1 # Medion Erazer X1000 usb:v0408pb5d5* ID_xrhardware=1 # Vis3r NxtVR usb:v1209p9d0f* ID_xrhardware=1 xr-hardware-1.1.0/70-xrhardware.rules000066400000000000000000000144351431210272200174050ustar00rootroot00000000000000# Do not edit this file - generated by make-udev-rules.py # # Copyright 2019-2022, Collabora, Ltd. and the xr-hardware contributors # # SPDX-License-Identifier: BSL-1.0 # 70-xrhardware.rules # Must be located at a number smaller than 73 for uaccess to work right! # Skip if a remove ACTION=="remove", GOTO="xrhardware_end" # BEGIN DEVICE LIST # ##################### # Razer Hydra - USB ATTRS{idVendor}=="1532", ATTRS{idProduct}=="0300", TAG+="uaccess", ENV{ID_xrhardware}="1" # HTC Vive - USB ATTRS{idVendor}=="0bb4", ATTRS{idProduct}=="2c87", TAG+="uaccess", ENV{ID_xrhardware}="1" # HTC Vive Pro - USB ATTRS{idVendor}=="0bb4", ATTRS{idProduct}=="0309", TAG+="uaccess", ENV{ID_xrhardware}="1" # Valve Watchman Dongle - USB ATTRS{idVendor}=="28de", ATTRS{idProduct}=="2101", TAG+="uaccess", ENV{ID_xrhardware}="1" # Valve VR Radio - USB ATTRS{idVendor}=="28de", ATTRS{idProduct}=="2102", TAG+="uaccess", ENV{ID_xrhardware}="1" # Valve Index Controller - USB ATTRS{idVendor}=="28de", ATTRS{idProduct}=="2300", TAG+="uaccess", ENV{ID_xrhardware}="1" # Valve Receiver for Lighthouse - HTC Vive - USB ATTRS{idVendor}=="28de", ATTRS{idProduct}=="2000", TAG+="uaccess", ENV{ID_xrhardware}="1" # OSVR HDK - USB ATTRS{idVendor}=="1532", ATTRS{idProduct}=="0b00", TAG+="uaccess", ENV{ID_xrhardware}="1", ENV{ID_xrhardware_USBSERIAL_NAME}="OSVRHDK" # OSVR HDK Camera - USB ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="57e8", TAG+="uaccess", ENV{ID_xrhardware}="1" # Sensics zSight - USB ATTRS{idVendor}=="16d0", ATTRS{idProduct}=="0515", TAG+="uaccess", ENV{ID_xrhardware}="1", ENV{ID_xrhardware_USBSERIAL_NAME}="zSight" # NOLO CV1 - USB ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5750", TAG+="uaccess", ENV{ID_xrhardware}="1" # NOLO CV1 - USB ATTRS{idVendor}=="28e9", ATTRS{idProduct}=="028a", TAG+="uaccess", ENV{ID_xrhardware}="1" # NOLO CV1 PRO - USB ATTRS{idVendor}=="28e9", ATTRS{idProduct}=="0302", ATTRS{product}=="CV1_PRO_HEAD", TAG+="uaccess", ENV{ID_xrhardware}="1" # Pimax 4k - USB ATTRS{idVendor}=="0483", ATTRS{idProduct}=="0021", TAG+="uaccess", ENV{ID_xrhardware}="1" # Oculus Rift (DK1) - USB ATTRS{idVendor}=="2833", ATTRS{idProduct}=="0001", TAG+="uaccess", ENV{ID_xrhardware}="1" # Oculus Rift (DK2) - USB ATTRS{idVendor}=="2833", ATTRS{idProduct}=="0021", TAG+="uaccess", ENV{ID_xrhardware}="1" # Oculus Rift (DK2) - USB ATTRS{idVendor}=="2833", ATTRS{idProduct}=="2021", TAG+="uaccess", ENV{ID_xrhardware}="1" # Oculus Rift (DK2 Sensor) - USB ATTRS{idVendor}=="2833", ATTRS{idProduct}=="0201", TAG+="uaccess", ENV{ID_xrhardware}="1" # Oculus Rift (CV1) - USB ATTRS{idVendor}=="2833", ATTRS{idProduct}=="0031", TAG+="uaccess", ENV{ID_xrhardware}="1" # Oculus Rift (CV1 Sensor) - USB ATTRS{idVendor}=="2833", ATTRS{idProduct}=="0211", TAG+="uaccess", ENV{ID_xrhardware}="1" # Oculus Rift S - USB ATTRS{idVendor}=="2833", ATTRS{idProduct}=="0051", TAG+="uaccess", ENV{ID_xrhardware}="1" # Samsung GearVR (Gen1) - USB ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="a500", TAG+="uaccess", ENV{ID_xrhardware}="1" # 3Glasses-D3V1 - USB ATTRS{idVendor}=="2b1c", ATTRS{idProduct}=="0200", TAG+="uaccess", ENV{ID_xrhardware}="1" # 3Glasses-D3V2 - USB ATTRS{idVendor}=="2b1c", ATTRS{idProduct}=="0201", TAG+="uaccess", ENV{ID_xrhardware}="1" # 3Glasses-D3C - USB ATTRS{idVendor}=="2b1c", ATTRS{idProduct}=="0202", TAG+="uaccess", ENV{ID_xrhardware}="1" # 3Glasses-D2C - USB ATTRS{idVendor}=="2b1c", ATTRS{idProduct}=="0203", TAG+="uaccess", ENV{ID_xrhardware}="1" # 3Glasses-S1V5 - USB ATTRS{idVendor}=="2b1c", ATTRS{idProduct}=="0100", TAG+="uaccess", ENV{ID_xrhardware}="1" # 3Glasses-S1V8 - USB ATTRS{idVendor}=="2b1c", ATTRS{idProduct}=="0101", TAG+="uaccess", ENV{ID_xrhardware}="1" # Sony PlayStation VR - USB ATTRS{idVendor}=="054c", ATTRS{idProduct}=="09af", TAG+="uaccess", ENV{ID_xrhardware}="1" # Sony PlayStation Move Motion Controller CECH-ZCM1 - Bluetooth, USB ATTRS{idVendor}=="054c", ATTRS{idProduct}=="03d5", TAG+="uaccess", ENV{ID_xrhardware}="1" KERNELS=="0005:054C:03D5.*", TAG+="uaccess", ENV{ID_xrhardware}="1" # Sony PlayStation Move Motion Controller CECH-ZCM2 - Bluetooth, USB ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0c5e", TAG+="uaccess", ENV{ID_xrhardware}="1" KERNELS=="0005:054C:0C5E.*", TAG+="uaccess", ENV{ID_xrhardware}="1" # LG 360 VR R-100 - USB ATTRS{idVendor}=="1004", ATTRS{idProduct}=="6374", TAG+="uaccess", ENV{ID_xrhardware}="1" # Microsoft Windows MR Controller - Bluetooth KERNELS=="0005:045E:065B.*", TAG+="uaccess", ENV{ID_xrhardware}="1", ENV{LIBINPUT_IGNORE_DEVICE}="1" # Microsoft Windows MR Controller - Bluetooth KERNELS=="0005:045E:065D.*", TAG+="uaccess", ENV{ID_xrhardware}="1", ENV{LIBINPUT_IGNORE_DEVICE}="1" # Microsoft Windows MR Controller (Reverb G2) - Bluetooth KERNELS=="0005:045E:066A.*", TAG+="uaccess", ENV{ID_xrhardware}="1", ENV{LIBINPUT_IGNORE_DEVICE}="1" # Microsoft HoloLens Sensors - USB ATTRS{idVendor}=="045e", ATTRS{idProduct}=="0659", TAG+="uaccess", ENV{ID_xrhardware}="1" # Samsung Odyssey+ sensors - USB ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="7312", TAG+="uaccess", ENV{ID_xrhardware}="1" # HP VR1000 - USB ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0367", TAG+="uaccess", ENV{ID_xrhardware}="1" # HP Reverb G1 - USB ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0c6a", TAG+="uaccess", ENV{ID_xrhardware}="1" # HP Reverb G2 - USB ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0580", TAG+="uaccess", ENV{ID_xrhardware}="1" # Lenovo QHMD - USB ATTRS{idVendor}=="17ef", ATTRS{idProduct}=="b801", TAG+="uaccess", ENV{ID_xrhardware}="1" # Cypress Semiconductor Corp. Lenovo Explorer - USB ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="6504", TAG+="uaccess", ENV{ID_xrhardware}="1" # Medion Erazer X1000 - USB ATTRS{idVendor}=="0408", ATTRS{idProduct}=="b5d5", TAG+="uaccess", ENV{ID_xrhardware}="1" # Vis3r NxtVR - USB ATTRS{idVendor}=="1209", ATTRS{idProduct}=="9d0f", TAG+="uaccess", ENV{ID_xrhardware}="1" ################### # END DEVICE LIST # # Exit if we didn't find one ENV{ID_xrhardware}!="1", GOTO="xrhardware_end" # XR devices with serial ports aren't modems, modem-manager ENV{ID_xrhardware_USBSERIAL_NAME}!="", SUBSYSTEM=="usb", ENV{ID_MM_DEVICE_IGNORE}="1" # Make friendly symlinks for XR USB-Serial devices. ENV{ID_xrhardware_USBSERIAL_NAME}!="", SUBSYSTEM=="tty", SYMLINK+="ttyUSB.$env{ID_xrhardware_USBSERIAL_NAME}" LABEL="xrhardware_end" xr-hardware-1.1.0/CHANGELOG.md000066400000000000000000000111251431210272200155400ustar00rootroot00000000000000# Changelog for xr-hardware ## xr-hardware 1.1.0 (2022-09-19) - Additions - Add HP Reverb G2 WMR controller rules ([!18](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/18)) - Add Lenovo Explorer WMR headset rules ([!19](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/19)) - Add Medion Erazer X1000 WMR headset rules ([!20](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/20)) - Add Nolo CV1 Pro tracker rules ([!21](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/21), [#8](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/issues/8)) - Add HP VR1000 WinMR headset. ([!22](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/22)) - Improvements - Support specifying a product string to additionally filter on. ([!21](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/21)) - Take flake8 out of the "test" target so stricter flake8 doesn't break package tests. ([!23](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/23)) ## xr-hardware 1.0.0 (2021-10-25) Version bumped because there was no real reason to be pre-1.0 anymore, this package is widely used now. - Additions - Add USB PID for Oculus Rift CV1 sensors, needed for positional tracking support. ([!14](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/14)) - Add USB PID for Oculus Rift DK2 sensor, needed for positional tracking support. ([!15](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/15)) - Improvements - Migrate script from attrs to dataclasses (which is built-in to Python 3.7 and newer) ([!16](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/16)) - Generate copyright header into generated files, and other minor changes to meet REUSE 3.0 compliance: see . ([!17](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/17)) ## xr-hardware 0.4.0 (2021-02-10) - Additions - HP Reverb G1 & G2 ([!12](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/12)) - Improvements - Add validators to `vid`, `pid`, and `usb_serial_name` fields directly in the class, for better error detection. ([!13](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/13), [#4](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/issues/4)) ## xr-hardware 0.3.0 (2020-12-02) Note that the default branch has been renamed to "main" in the repository. - Additions - Oculus Rift S ([!5](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/5), [#3](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/issues/3)) - Windows MR controller support ([!6](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/6), [#1](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/issues/1)) - Vis3r NxtVR budget VR headset ([!7](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/7)) - Pimax 4k headset ([!10](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/10), [#5](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/issues/5)) - Improvements - Valve Index: ID for Watchman device ([!8](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/8)) - Now using [Proclamation](https://gitlab.com/ryanpavlik/proclamation) to maintain a project changelog. ([!9](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/9)) - NOLO CV1: Additional ID ([!10](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/10), [#5](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/issues/5)) - Additional IDs for HTC Vive Pro ([!11](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/merge_requests/11), [#6](https://gitlab.freedesktop.org/monado/utilities/xr-hardware/issues/6)) ## xr-hardware 0.2.1 (2020-01-22) - Fixes - Vive support ## xr-hardware 0.2 (2020-01-22) - Additions - Support for Bluetooth devices - 3Glasses devices - PS Move controllers - Improvements - Refactor generated files - Re-organize code and improve testing/quality ## xr-hardware 0.1.1 (2020-01-21) - Fixes - Fix a typo related to HTC Vive support. ## xr-hardware 0.1 (2020-01-21) Initial release. xr-hardware-1.1.0/LICENSE.txt000066400000000000000000000024721431210272200155570ustar00rootroot00000000000000Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. xr-hardware-1.1.0/LICENSES/000077500000000000000000000000001431210272200151345ustar00rootroot00000000000000xr-hardware-1.1.0/LICENSES/BSL-1.0.txt000066400000000000000000000024721431210272200166160ustar00rootroot00000000000000Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. xr-hardware-1.1.0/LICENSES/CC0-1.0.txt000066400000000000000000000156101431210272200165410ustar00rootroot00000000000000Creative Commons Legal Code CC0 1.0 Universal CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. Statement of Purpose The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. 1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; ii. moral rights retained by the original author(s) and/or performer(s); iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; v. rights protecting the extraction, dissemination, use and reuse of data in a Work; vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. 2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. 3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. 4. Limitations and Disclaimers. a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. xr-hardware-1.1.0/Makefile000066400000000000000000000023661431210272200153760ustar00rootroot00000000000000#!/usr/bin/env make -f # Copyright 2020-2022 Collabora, Ltd # SPDX-License-Identifier: BSL-1.0 # Author: Ryan Pavlik RULES_FILE := 70-xrhardware.rules HWDB_FILE := 70-xrhardware.hwdb HWDB_RULES_FILE := 70-xrhardware-hwdb.rules INSTALL ?= install PYTHON ?= python3 all: $(RULES_FILE) $(HWDB_FILE) $(HWDB_RULES_FILE) .PHONY: all test: $(PYTHON) test-db.py lint: test $(PYTHON) -m flake8 *.py xrhardware/*.py black . .PHONY: lint $(RULES_FILE): make-udev-rules.py xrhardware/db.py xrhardware/generate.py $(PYTHON) $< > $@ $(HWDB_FILE): make-hwdb-file.py xrhardware/db.py xrhardware/generate.py $(PYTHON) $< > $@ $(HWDB_RULES_FILE): make-hwdb-rules-file.py xrhardware/generate.py $(PYTHON) $< > $@ clean: -rm -f $(RULES_FILE) $(HWDB_FILE) $(HWDB_RULES_FILE) .PHONY: clean # Currently does nothing, since the generated files get committed. clean_package: .PHONY: clean_package RULES_DIR ?= /etc/udev/rules.d install: $(RULES_FILE) $(INSTALL) -d $(DESTDIR)$(RULES_DIR)/ $(INSTALL) -m 644 -D $(RULES_FILE) $(DESTDIR)$(RULES_DIR)/ .PHONY: install install_package: $(RULES_FILE) $(INSTALL) -d $(DESTDIR)$(PREFIX)/lib/udev/rules.d $(INSTALL) -m 644 -D $(RULES_FILE) $(DESTDIR)$(PREFIX)/lib/udev/rules.d/ .PHONY: install_package xr-hardware-1.1.0/README.md000066400000000000000000000120161431210272200152060ustar00rootroot00000000000000# XR Hardware Rules A simple set of scripts to generate udev rules for user access to XR (VR and AR) hardware devices. Packages are developed over at rather than this repo, in an attempt to do the Debian stuff correctly by the book. ## "Build" requirements (to re-generate files) You'll need Python 3.7 or newer. ## Quick start: "build" and use Once you have the deps installed, run: ```sh make sudo make install # to install udev rules to /etc/udev/rules.d ``` `DESTDIR` is obeyed, but packagers should really see the dedicated section for them below. You'll need to at least re-plug your devices to get this to register for now. Note that you still might see something like this in a simple `ls -l` view: ```none crw-rw----+ 1 root root 246, 2 Jan 22 12:00 /dev/hidraw2 ``` This doesn't mean it failed to work: the `+` means there's an ACL attached in addition to the normal Unix permissions. Running `getfacl` on that device node will reveal: ```none # file: dev/hidraw2 # owner: root # group: root user::rw- user:YOUR_USERNAME_HERE:rw- group::--- mask::rw- other::--- ``` and you should be able to use the device without sudo. If this is not your experience, file an issue. ## Makefile targets Right now we're generating the hwdb files as well as the shorter associated rules file, but not doing anything with it in the makefile. If Python 3.x is not named `python3` you can override the `PYTHON` variable when running `make` to tell it the correct name for your system. ### `all` or one of the generated files This generates the file(s), if out of date. ### `test` Runs some very minimal consistency checks on the database. ### `lint` Runs `flake8` and `black` on the Python code so you'll need packages `python3-flake8` and `black` or something like that. ### `clean` Removes the generated files. Since these are committed to the repo, this will "dirty" the repo. ### `install` Probably run with `sudo`. Will install by default to `/etc/udev/rules.d`: override `RULES_DIR` if you want them somewhere else. Obeys `DESTDIR` but not `PREFIX`. ### For distro packages only If you're a distro packager, use slightly different targets: - Use `clean_package` instead of `clean`. (This is currently a no-op to avoid dirtying the repo.) - Use `install_package` instead of `install` (installs to `/lib/udev/rules.d`, obeying both `DESTDIR` and `PREFIX`) ## Contributing Contributions are assumed to be under the same license license as you received with the files: the Inbound==Outbound convention. Please submit a changelog fragment with your changes: see the `changes` directory for details. The device database is in `xrhardware/db.py` so that's the most likely file to be modified. Plug your device in or connect it, and look at dmesg. ### Bluetooth You'll see something like this at the end (example is a first-generation PS Move controller): ```none [541976.201331] input: Motion Controller as /devices/pci0000:00/0000:00:01.3/0000:02:00.0/usb1/1-12/1-12:1.0/bluetooth/hci0/hci0:1/0005:054C:03D5.001A/input/input62 [541976.201426] sony 0005:054C:03D5.001A: input,hidraw6: BLUETOOTH HID v0.01 Joystick [Motion Controller] on fc:01:7c:a3:cf:06 ``` the HID "VID/PID" are in that long path, in the level that starts with `0005` (`0005:054C:03D5.001A` in our example): - 0005 means Bluetooth - 054C:03D5 are the vendor and product ID, respectively (They're also in the log "prefix" on the line starting with "sony" - the driver name.) If your device also can be used over USB, check to see if these values match between the two. If they do, you can just put `bluetooth=True` (the `usb=True` is implied by default) in the Device entry. Otherwise, be sure to add `usb=False` as well as a second device entry for the USB identity of the device. ### USB You'll see something like this at the end (example is still a first-generation PS Move controller): ```none [542674.705441] usb 3-1.2.1: USB disconnect, device number 77 [544022.781910] usb 3-1.2.1: new full-speed USB device number 78 using xhci_hcd [544022.888540] usb 3-1.2.1: New USB device found, idVendor=054c, idProduct=03d5, bcdDevice= 2.20 [544022.888541] usb 3-1.2.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0 [544022.888542] usb 3-1.2.1: Product: Motion Controller [544022.888543] usb 3-1.2.1: Manufacturer: Sony Computer Entertainment [544022.966925] input: Sony Computer Entertainment Motion Controller as /devices/pci0000:00/0000:00:07.1/0000:0b:00.3/usb3/3-1/3-1.2/3-1.2.1/3-1.2.1:1.0/0003:054C:03D5.001D/input/input65 [544022.967017] sony 0003:054C:03D5.001D: input,hidraw5: USB HID v1.10 Joystick [Sony Computer Entertainment Motion Controller] on usb-0000:0b:00.3-1.2.1/input0 ``` Here, the VID and PID are nicely called out: - `idVendor=054c` - `idProduct=03d5` Note that here, this device also can use Bluetooth, in which case it shows up with the same VID/PID but on a different bus. ## License Boost Software License 1.0 xr-hardware-1.1.0/changes/000077500000000000000000000000001431210272200153375ustar00rootroot00000000000000xr-hardware-1.1.0/changes/.markdownlint.yaml000066400000000000000000000003471431210272200210160ustar00rootroot00000000000000# SPDX-License-Identifier: CC0-1.0 # SPDX-FileCopyrightText: 2021 Collabora, Ltd. # Changelog fragments will never start with a header. MD041: false # Don't whine about line length because proclamation will wrap us. MD013: false xr-hardware-1.1.0/changes/.proclamation.json000066400000000000000000000013321431210272200207770ustar00rootroot00000000000000{ "$schema": "https://ryanpavlik.gitlab.io/proclamation/proclamation.schema.json", "#": "This is a config file for Proclamation, the changelog combiner: https://gitlab.com/ryanpavlik/proclamation", "SPDX-License-Identifier: CC0-1.0": "", "SPDX-FileCopyrightText: 2020 Collabora, Ltd. and the Proclamation contributors": "", "project_name": "xr-hardware", "base_url": "https://gitlab.freedesktop.org/monado/utilities/xr-hardware", "news_filename": "../CHANGELOG.md", "sections": { "Additions": { "directory": "additions" }, "Improvements": { "directory": "improvements" }, "Fixes": { "directory": "fixes" } } } xr-hardware-1.1.0/changes/.proclamation.json.license000066400000000000000000000001641431210272200224220ustar00rootroot00000000000000# SPDX-License-Identifier: CC0-1.0 # SPDX-FileCopyrightText: 2020 Collabora, Ltd. and the Proclamation contributors xr-hardware-1.1.0/changes/README.md000066400000000000000000000135711431210272200166250ustar00rootroot00000000000000# Usage of Proclamation to maintain changelogs This project uses the [Proclamation][] tool to maintain changelogs. Contributors to this project do not need to use Proclamation, but they are asked to write a fragment for the changelog describing their change. See below for more details. - Directory to run Proclamation in: `changes/` - Config file: default name (`.proclamation.json`) - Location of the per-changelog-section directories: `changes/` [Proclamation]: https://gitlab.com/ryanpavlik/proclamation ## Table of Contents - [Table of Contents](#table-of-contents) - [Quick Start Instructions for Contributors](#quick-start-instructions-for-contributors) - [About Proclamation and Usage Instructions](#about-proclamation-and-usage-instructions) - [Fragments](#fragments) - [References](#references) - [Sample Usage Workflow](#sample-usage-workflow) - [During Development](#during-development) - [Preparing for a Release](#preparing-for-a-release) ## Quick Start Instructions for Contributors - Get a merge request number for your change: this might involve pushing it as a WIP. - Create a file in the appropriate section's directory, named `mr.YOURNUMBER.md` - In that file, briefly describe your change as you would like it describe in the changelog for the next release. A common format is to start with a component, subsection, or type of change (bug fix, feature), then a colon, then a sentence describing the user impact of the change. - If your changes affect multiple sections, you can have a file in each section describing the section-specific changes. - If you want more than one changelog fragment per section in a single change, you can name the additional fragments `mr.YOURNUMBER.2.md`, `mr.YOURNUMBER.3.md`, etc. The additional number appended at the end will not appear in the output, but will keep the files separate and will affect the sort order of the fragments. - If your change resolves an issue or otherwise references some issue or merge request, you can add those references to the beginning of your changelog fragment. See the full instructions below regarding [References](#references). ## About Proclamation and Usage Instructions The "Proclamation" tool assembles changelogs, which incorporate fragments of changelog text added by the author of a change in a specific location and format. ### Fragments Each change should add a changelog fragment file, whose contents are Markdown-formatted text describing the change briefly. Reference metadata will be used to automatically add links to associated issues/merge requests/pull requests, so no need to add these in your fragment text. The simplest changelog fragment just contains one line of Markdown text describing the change: ```md Here the author of a change has written some text about it. ``` ### References The changelog fragment system revolves around "references" - these are issue reports or merge requests associated with a change. Each fragment must have at least one of these, which forms the main part of the filename. If applicable, additional can be added within the file - see below for details. The format of references in general is: ```txt . ``` where - `ref_type` is "issue" or "mr" - `number` is the issue or MR number Your changelog fragment filename is simply the "main" reference with the `.md` extension added. Notably, you can append an extra token, like `.2`, before the file extension to easily handle multiple fragments for a single merge request, etc. To specify additional references in a file, prefix the contents of the changelog fragment with a block delimited above and below by `---`, with one reference on each line. (This can be seen as a very minimal subset of "YAML Front Matter", if you're familiar with that concept.) For example: ```md --- - issue.35 - mr.93 --- Here the author of a change has written some text about it. ``` ## Sample Usage Workflow Note that the base `proclamation` script and all its subcommands have help, accessible through `-h` or `--help`. The guidance in this section of the README is intentionally minimal, to avoid contradicting the online help which remains up-to-date implicitly. This is also only the simplest, minimal way to perform these operations: if your project is more complex, there may already be more features to support your needs in the command line help. ### During Development As changes get submitted to your project, have each change author create a changelog fragment file. Since these are all separate files, with names made unique by your issue/repo tracker, there won't be merge conflicts no matter what order they're merged in. (This is the central benefit of Proclamation, and its inspiration, towncrier, over having each contributor edit CHANGES as part of their submission.) At any time you can run `proclamation draft` to preview the release portion that would be added to your changelog if you released at that time. ### Preparing for a Release When you're ready to perform a release, you'll want to run Proclamation to update your changelog, then remove the fragments that you've incorporated into the regular changelog. You can use a command like the following: ```sh proclamation build YOUR_NEW_VERSION ``` to preview the full file on screen. When you're ready to actually perform the update, run something like: ```sh proclamation build YOUR_NEW_VERSION --delete-fragments --overwrite ``` to overwrite your changelog file with the updated one and delete the used changelog fragments. You're welcome to manually edit the new (or old!) changelog entries as desired: as long as the `insert_point_pattern` (by default, `^## .*`) can still match, Proclamation will not be confused. Finally, make sure the deletion of the fragments and the update of the changelog has been checked in to your version control system. xr-hardware-1.1.0/changes/additions/000077500000000000000000000000001431210272200173155ustar00rootroot00000000000000xr-hardware-1.1.0/changes/additions/.gitkeep000066400000000000000000000000001431210272200207340ustar00rootroot00000000000000xr-hardware-1.1.0/changes/fixes/000077500000000000000000000000001431210272200164555ustar00rootroot00000000000000xr-hardware-1.1.0/changes/fixes/.gitkeep000066400000000000000000000000001431210272200200740ustar00rootroot00000000000000xr-hardware-1.1.0/changes/improvements/000077500000000000000000000000001431210272200200675ustar00rootroot00000000000000xr-hardware-1.1.0/changes/improvements/.gitkeep000066400000000000000000000000001431210272200215060ustar00rootroot00000000000000xr-hardware-1.1.0/make-hwdb-file.py000077500000000000000000000011441431210272200170600ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright 2019-2022 Collabora, Ltd # SPDX-License-Identifier: BSL-1.0 # Author: Ryan Pavlik """Make a hwdb file. Requires an associated .rules file.""" from xrhardware.db import get_devices from xrhardware.generate import generate_file_contents if __name__ == "__main__": all_entries = "\n\n".join(d.make_hwdb_entry() for d in get_devices()) contents = "\n".join( ( "# This hwdb file must be used with the corresponding rules file.", all_entries, ) ) print(generate_file_contents(__file__, contents)) xr-hardware-1.1.0/make-hwdb-rules-file.py000077500000000000000000000007551431210272200202170ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright 2019-2022 Collabora, Ltd # SPDX-License-Identifier: BSL-1.0 # Author: Ryan Pavlik """Make a .rules file for use with a hwdb file.""" from xrhardware.generate import generate_rules_file_contents if __name__ == "__main__": print( generate_rules_file_contents( __file__, "70-xrhardware-hwdb.rules", "# This rules file must be used with the corresponding hwdb file", ) ) xr-hardware-1.1.0/make-udev-rules.py000077500000000000000000000012571431210272200173170ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright 2019-2022 Collabora, Ltd # SPDX-License-Identifier: BSL-1.0 # Author: Ryan Pavlik """Make a standalone .rules file.""" from xrhardware.db import get_devices from xrhardware.generate import generate_rules_file_contents if __name__ == "__main__": all_rules = "\n\n".join(d.make_commented_rule() for d in get_devices()) contents = "\n".join( ( "# BEGIN DEVICE LIST #", "#####################", all_rules, "###################", "# END DEVICE LIST #", ) ) print(generate_rules_file_contents(__file__, "70-xrhardware.rules", contents)) xr-hardware-1.1.0/test-db.py000077500000000000000000000021471431210272200156520ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright 2019-2022 Collabora, Ltd # SPDX-License-Identifier: BSL-1.0 # Author: Ryan Pavlik """XR Hardware device database consistency test.""" from xrhardware.db import get_devices if __name__ == "__main__": print("Testing device database entries' consistency and uniqueness") known = set() import re hexstring = re.compile(r"[0-9a-fA-F]{4}") for dev in get_devices(): print("Checking entry for:", dev.extended_description) # Duplicate ID? for dev_id in dev.yield_hwdb_identification(): assert dev_id not in known known.add(dev_id) # Must be at least one of these assert dev.usb or dev.bluetooth # VID/PID must fit the expected format if dev.pid: assert hexstring.match(dev.pid) # prefer lowercase for compatibility assert dev.pid == dev.pid.lower() if dev.vid: assert hexstring.match(dev.vid) # prefer lowercase for compatibility assert dev.vid == dev.vid.lower() print("Success!") xr-hardware-1.1.0/xrhardware/000077500000000000000000000000001431210272200160765ustar00rootroot00000000000000xr-hardware-1.1.0/xrhardware/__init__.py000066400000000000000000000003041431210272200202040ustar00rootroot00000000000000#!/usr/bin/env python3 -i # Copyright 2020 Collabora, Ltd # SPDX-License-Identifier: BSL-1.0 # Author: Ryan Pavlik """XR hardware database and associated utilities.""" xr-hardware-1.1.0/xrhardware/db.py000066400000000000000000000102571431210272200170420ustar00rootroot00000000000000#!/usr/bin/env python3 -i # Copyright 2019-2020 Collabora, Ltd # SPDX-License-Identifier: BSL-1.0 # Author: Ryan Pavlik """XR Hardware device database.""" from .device import Device # Please make sure VID/PID are lowercase. # Black uncharacteristically makes these lists less readable. # fmt: off def get_devices(): """Return the entire device database in one really large tuple.""" return ( Device("Razer Hydra", "1532", "0300"), Device("HTC Vive", "0bb4", "2c87"), Device("HTC Vive Pro", "0bb4", "0309"), Device("Valve Watchman Dongle", "28de", "2101"), Device("Valve VR Radio", "28de", "2102"), Device("Valve Index Controller", "28de", "2300"), Device("Valve Receiver for Lighthouse - HTC Vive", "28de", "2000"), # name? # also PID 2220 (lighthouse fpga rx)? Device("OSVR HDK", "1532", "0b00", usb_serial_name="OSVRHDK"), Device("OSVR HDK Camera", "0bda", "57e8"), Device("Sensics zSight", "16d0", "0515", usb_serial_name="zSight"), # # Re-used ID from ST Micro "LED badge -- mini LED display -- 11x44" Device("NOLO CV1", "0483", "5750"), # This is a GigaDevices VID, not sure if the PID is unique so # preferably we should filter on the string too. Device("NOLO CV1", "28e9", "028a"), Device("NOLO CV1 PRO", "28e9", "0302", product_string="CV1_PRO_HEAD"), # Duplicate of NOLO CV1? # Device("Deepoon", "0483", "5750"), # # ST Micro VID, and PID not listed in usb-ids so may be uniquely # assigned (or may be just copied from PID of DK2 since the product # string is "Rift P1") Device("Pimax 4k", "0483", "0021"), # Oculus Rift Device("Oculus Rift (DK1)", "2833", "0001"), Device("Oculus Rift (DK2)", "2833", "0021"), Device("Oculus Rift (DK2)", "2833", "2021"), Device("Oculus Rift (DK2 Sensor)", "2833", "0201"), Device("Oculus Rift (CV1)", "2833", "0031"), Device("Oculus Rift (CV1 Sensor)", "2833", "0211"), Device("Oculus Rift S", "2833", "0051"), Device("Samsung GearVR (Gen1)", "04e8", "a500"), # Pretends to be a DK1... # Device("VR-Tek WVR1", "2833", "0001"), # Device("3Glasses-D3V1", "2b1c", "0200"), Device("3Glasses-D3V2", "2b1c", "0201"), Device("3Glasses-D3C", "2b1c", "0202"), Device("3Glasses-D2C", "2b1c", "0203"), Device("3Glasses-S1V5", "2b1c", "0100"), Device("3Glasses-S1V8", "2b1c", "0101"), # Device("Sony PlayStation VR", "054c", "09af"), Device("Sony PlayStation Move Motion Controller CECH-ZCM1", "054c", "03d5", bluetooth=True, usb=True), Device("Sony PlayStation Move Motion Controller CECH-ZCM2", "054c", "0c5e", bluetooth=True, usb=True), # Device("LG 360 VR R-100", "1004", "6374"), # # Windows Mixed Reality controllers # Need to be ignored by libinput to avoid spurious touchscreen events Device("Microsoft Windows MR Controller", "045e", "065b", bluetooth=True, usb=False, extra_properties={"LIBINPUT_IGNORE_DEVICE": "1"}), Device("Microsoft Windows MR Controller", "045e", "065d", bluetooth=True, usb=False, extra_properties={"LIBINPUT_IGNORE_DEVICE": "1"}), Device("Microsoft Windows MR Controller (Reverb G2)", "045e", "066a", bluetooth=True, usb=False, extra_properties={"LIBINPUT_IGNORE_DEVICE": "1"}), # # Windows Mixed Reality headsets Device("Microsoft HoloLens Sensors", "045e", "0659"), Device("Samsung Odyssey+ sensors", "04e8", "7312"), Device("HP VR1000", "03f0", "0367"), Device("HP Reverb G1", "03f0", "0c6a"), Device("HP Reverb G2", "03f0", "0580"), Device("Lenovo QHMD", "17ef", "b801"), Device("Cypress Semiconductor Corp. Lenovo Explorer", "04b4", "6504"), # Quanta QHMD == Medion Erazer X1000 Device("Medion Erazer X1000", "0408", "b5d5"), # Device("Vis3r NxtVR", "1209", "9d0f"), ) # fmt: on xr-hardware-1.1.0/xrhardware/device.py000066400000000000000000000115761431210272200177210ustar00rootroot00000000000000#!/usr/bin/env python3 -i # Copyright 2019-2021 Collabora, Ltd # SPDX-License-Identifier: BSL-1.0 # Author: Ryan Pavlik """XR Hardware device database element type.""" from typing import Dict, Optional from dataclasses import dataclass import re _VID_PID_RE = re.compile(r"^[0-9a-f]{4}$") _USBSERIALNAME_RE = re.compile(r"^[._0-9a-zA-Z]+$") def _is_four_hexits(val: Optional[str]): if val is not None and not _VID_PID_RE.match(val): raise ValueError("Must be four hexadecimal characters in lowercase") def _is_suitable_device_name(val: Optional[str]): if val is None: return if not _USBSERIALNAME_RE.match(val): raise ValueError( "Must be a reasonable thing to put in a device node name: " "a-z, A-Z, numbers, ., _" ) @dataclass class Device: """An XR hardware device that we should permit access to.""" description: str vid: Optional[str] = None pid: Optional[str] = None product_string: Optional[str] = None usb_serial_name: Optional[str] = None usb: bool = True bluetooth: bool = False extra_properties: Optional[Dict[str, str]] = None def __post_init__(self): """Validate provided values.""" _is_four_hexits(self.vid) _is_four_hexits(self.pid) _is_suitable_device_name(self.usb_serial_name) def get_properties_to_set(self): """Generate the udev properties to set for this device.""" yield ("ID_xrhardware", 1) if self.usb_serial_name: yield ("ID_xrhardware_USBSERIAL_NAME", self.usb_serial_name) if self.extra_properties: for k, v in self.extra_properties.items(): yield (k, v) def yield_hwdb_identification(self): """Compute identification for hwdb recognition of this device.""" if not self.vid: raise RuntimeError("Can't make a hwdb entry for something without a vid!") # usb: and bluetooth: prefix come later parts = [] parts.append("v%s" % self.vid) if self.pid: parts.append("p%s" % self.pid) parts.append("*") identifier_suffix = "".join(parts) if self.usb: yield "usb:" + identifier_suffix if self.bluetooth: yield "bluetooth:" + identifier_suffix def make_hwdb_entry(self): """Return a hwdb entry for this device.""" lines = ["# " + self.description] lines.extend(list(self.yield_hwdb_identification())) for k, v in self.get_properties_to_set(): lines.append(" %s=%s" % (k, v)) return "\n".join(lines) @property def extended_description(self): """Return the description augmented with the interface types.""" interfaces = [] if self.bluetooth: interfaces.append("Bluetooth") if self.usb: interfaces.append("USB") return "%s - %s" % (self.description, ", ".join(interfaces)) def make_commented_rule(self): """Return a comment and udev rule for this device.""" rule = self.make_rule() return "\n".join(("# %s" % self.extended_description, rule, "")) def yield_rule_condition_lists(self): """Yield the udev rule conditions (as lists) to select this device.""" if self.usb: parts = [] if self.vid: parts.append('ATTRS{idVendor}=="%s"' % self.vid) if self.pid: parts.append('ATTRS{idProduct}=="%s"' % self.pid) if self.product_string: parts.append('ATTRS{product}=="%s"' % self.product_string) yield parts if self.bluetooth and self.vid and self.pid: vid = self.vid.upper() pid = self.pid.upper() yield ['KERNELS=="0005:%s:%s.*"' % (vid, pid)] # Bluetooth devices don't get idVendor and idProduct, # but they do get this which is pretty similar. # However, these fail to trigger the rule properly for the PS Move # at least. # # parts = ['ATTRS{id/bustype}=="0005"'] # if self.vid: # parts.append('ATTRS{id/vendor}=="%s"' % self.vid) # if self.pid: # parts.append('ATTRS{id/product}=="%s"' % self.pid) # yield parts def yield_rule_conditions(self): """Yield the udev rule conditions to select this device.""" for conditions in self.yield_rule_condition_lists(): yield ", ".join(conditions) def make_rule(self): """Return a udev rule for this device.""" rules = [] for condition in self.yield_rule_conditions(): parts = [condition, 'TAG+="uaccess"'] parts.extend( 'ENV{%s}="%s"' % (k, v) for k, v in self.get_properties_to_set() ) rules.append(", ".join(parts)) return "\n".join(rules) xr-hardware-1.1.0/xrhardware/generate.py000066400000000000000000000033721431210272200202470ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright 2019-2022 Collabora, Ltd # SPDX-License-Identifier: BSL-1.0 # Author: Ryan Pavlik """XR Hardware generation helper code.""" # pylint: disable=E501 _SHARED_PREFIX = "\n".join( ( "# Do not edit this file - generated by {script}", "#", "# Copyright" + " 2019-2022, Collabora, Ltd. and the " + "xr-hardware contributors", "#", "# SPDX-License-" + "Identifier: BSL-1.0", "", ) ) _RULES_TEMPLATE_PREFIX = """ # Must be located at a number smaller than 73 for uaccess to work right! # Skip if a remove ACTION=="remove", GOTO="xrhardware_end" """ # Must be before 73 to have uaccess do what it should! _RULES_TEMPLATE_SUFFIX = """ # Exit if we didn't find one ENV{ID_xrhardware}!="1", GOTO="xrhardware_end" # XR devices with serial ports aren't modems, modem-manager ENV{ID_xrhardware_USBSERIAL_NAME}!="", SUBSYSTEM=="usb", ENV{ID_MM_DEVICE_IGNORE}="1" # Make friendly symlinks for XR USB-Serial devices. ENV{ID_xrhardware_USBSERIAL_NAME}!="", SUBSYSTEM=="tty", SYMLINK+="ttyUSB.$env{ID_xrhardware_USBSERIAL_NAME}" LABEL="xrhardware_end" """ # noqa: E501 # it's too long because that's what the template is. def generate_file_contents(script, body): """Return generated file contents for the given script file and body.""" from pathlib import Path script = str(Path(script).name) shared_prefix = _SHARED_PREFIX.format(script=script) return "\n".join((shared_prefix, body)) def generate_rules_file_contents(script, fn, body): """Return the body surrounded by the rules template.""" parts = ["# " + fn, _RULES_TEMPLATE_PREFIX, body, _RULES_TEMPLATE_SUFFIX] return generate_file_contents(script, "\n".join(parts))