Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 77 additions & 17 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,86 @@
On Windows we use msys2 and ucrt64 to compile.
You need to prefix commands with `C:\msys64\msys2_shell.cmd -defterm -here -no-start -ucrt64 -c`.
# Repository guidance

Prefix build directories with `cmake-build-`.
## Build and tests

The test executable is named `test_libvirtualhid` and will be located inside the `tests` directory within
the build directory.
On Windows, compile the normal C++ library with MSYS2/UCRT64. Prefix Windows
build and test commands with
`C:\msys64\msys2_shell.cmd -defterm -here -no-start -ucrt64 -c`.
Keep the library buildable with both MSVC and MinGW/UCRT64. The UMDF driver
package is a separate WDK/MSVC build.

The project uses gtest as a test framework. GoogleTest is vendored as a submodule under `third-party/googletest`.
Prefix build directories with `cmake-build-`. The GoogleTest executable is
`tests/test_libvirtualhid` inside the build directory (with `.exe` on
Windows). GoogleTest is vendored under
`third-party/lizardbyte-common/third-party/googletest`.

Keep the public c++ API platform-neutral. Platform-specific virtual HID details belong behind backend
implementations and should not leak into consumer code.
Add or update meaningful tests for changed behavior. Aim for full coverage of
changed code, and validate gamepad API and lifecycle changes against
`examples/gamepad_adapter.cpp` and the lifecycle tests. Run installed-device
or hardware checks when the change depends on real devices; describe any
validation that cannot run locally.

Gamepad support is the primary target. Remote streaming hosts are the first consumer class, so validate API
and behavior changes against the adapter examples and lifecycle tests.
## API and platform boundaries

Windows support must remain user-mode. Do not add a custom kernel-mode driver. The normal c++ library should
remain buildable with both MSVC and MinGW/UCRT64; any future UMDF driver package is a separate WDK/MSVC build
artifact.
Keep the public C++ API platform-neutral. Put virtual HID details behind
backend implementations, not in consumer code. Gamepads are the primary
target, with remote streaming hosts as the first consumer class.

Linux gamepad support should prefer uhid for descriptor-driven controllers. Keyboard and mouse support should
prefer uinput, with X11 XTest only as a fallback.
Windows support must remain user-mode; do not add a custom kernel-mode driver.
For Linux, prefer `uhid` for descriptor-driven gamepads and `uinput` for
keyboard and mouse, using X11/XTest only as a fallback.

Always update public documentation when changing headers, backends, or consumer-facing behavior.
## Code style and documentation

Always follow the style guidelines defined in .clang-format for c/c++ code when that file is present.
Follow `.clang-format` for C and C++ code. Do not add decorative separator
comments; use descriptive names and code structure to show grouping.

When changing headers, backends, or consumer-facing behavior, add or update
the affected Doxygen documentation blocks. Document relevant declarations and
behavior in code, including parameters and return values where applicable.
Use this style for primary documentation:

```cpp
/**
* @brief Describe the function or type.
*
* @param value Describe the parameter.
* @return Describe the result.
*/
```

Use `///< ...` for inline Doxygen comments. Keep Markdown guides focused on
installation, usage, limitations, and troubleshooting that readers need.
Update a Markdown page when one of those user-facing instructions actually
changes; routine source changes do not require Markdown edits.
Pad Markdown table cells so the `|` separators align vertically in source,
accounting for wide Unicode characters such as emoji.

## Issues and pull requests

When asked to create an issue or pull request, use the applicable templates
from LizardByte/.github, or this repository if it has a more specific template.
At the end of the body, add an attribution naming the AI agent, model, and
thinking level used to generate it.

When asked only to create an issue, investigate enough to verify and accurately
describe the observed behavior, expected behavior, and reproduction or
evidence. Keep the issue concise. Investigate or fix fully when that is the
request.

## Code reviews

Report concrete issues introduced by a change. Explain the trigger, impact,
and a practical fix; point to the relevant code or test. Keep workflow status
separate from code findings.

If GitHub Actions workflows await maintainer approval, or a dependent check
times out before its job can run, do not leave an inline comment, request
changes, or ask the contributor to run them. If missing results materially
limit the review, mention that once in the summary. Review actual failed
checks when their logs are available.

For pull request reviews, verify the current PR head and mergeability against
its target branch. If conflicts are confirmed, tell the author to rebase and
resolve them. Do not infer conflicts from unknown or pending mergeability.
When approving a pull request, the approval itself is sufficient; do not add
a comment solely to accompany it.
31 changes: 14 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@
<a href="https://sonarcloud.io/project/overview?id=LizardByte_libvirtualhid"><img src="https://img.shields.io/sonar/quality_gate/LizardByte_libvirtualhid.svg?server=https%3A%2F%2Fsonarcloud.io&style=for-the-badge&logo=sonarqubecloud&label=sonarcloud" alt="SonarCloud"></a>
</div>

<div align="center">
<h2>🎮 Virtual HID Gamepad License</h2>
<p>
<strong>A license is required for Windows driver-backed devices and macOS virtual gamepads.</strong><br>
Linux and FreeBSD backends do not require a license.<br>
Yearly and lifetime options are available.
</p>
<a href="https://buy.polar.sh/polar_cl_zj6Io5NVukXfZSl97ULtFvImfI5L1jbL2cSnc0Y72Pt"><img src="https://img.shields.io/badge/Buy_a_virtual_HID_license-0078D4?style=for-the-badge" alt="Buy a virtual HID license"></a>
</div>
> [!IMPORTANT]
> **🎮 Virtual HID Gamepad License**
>
> A license is required for Windows driver-backed devices and macOS virtual
> gamepads. Linux and FreeBSD backends do not require a license. Yearly and
> lifetime options are available.
>
> [![Buy a virtual HID license](https://img.shields.io/badge/Buy_a_virtual_HID_license-0078D4?style=for-the-badge)](https://buy.polar.sh/polar_cl_zj6Io5NVukXfZSl97ULtFvImfI5L1jbL2cSnc0Y72Pt)

# Overview

Expand Down Expand Up @@ -96,14 +95,12 @@ More complete examples live in `examples/`, including the streaming-host-oriente

- [End-user gamepad guide](docs/end-user-gamepad-guide.md): Sunshine and Moonlight setup, feature caveats,
troubleshooting, and controller support references.
- [Usage and API](docs/usage.md): CMake consumption, build options, public API overview, profiles, and examples.
- [Platform support](docs/platform-support.md): backend capability model, Windows, Linux, macOS,
and Linux permission setup.
- [Windows driver package](docs/windows-driver.md): UMDF/VHF package build, installation, validation, diagnostics,
and signing notes.
- [Streaming-host integration](docs/streaming-host-integration.md): integration contract.
- [Development](docs/development.md): local build/test commands, repository layout, docs generation, and roadmap.
- [TODO](docs/todo.md): known larger compatibility gaps and proposed solution paths.
- [Usage and API](docs/usage.md): CMake consumption, profiles, and API examples.
- [Platform support](docs/platform-support.md): device availability, platform limits, and Linux permissions.
- [Windows driver package](docs/windows-driver.md): installation, licensing, diagnostics, and contributor builds.
- [macOS gamepad setup](docs/macos-gamepad.md): installation, licensing, and signed builds.
- [Streaming-host integration](docs/streaming-host-integration.md): integration pattern.
- [Development](docs/development.md): build, test, and documentation commands.

## 🎯 Scope

Expand Down
1 change: 0 additions & 1 deletion dockle.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ inputs = [
"docs/platform-support.md",
"docs/windows-driver.md",
"docs/macos-gamepad.md",
"docs/todo.md",
"docs/streaming-host-integration.md",
"docs/development.md",
"LICENSES/license-map.md",
Expand Down
113 changes: 29 additions & 84 deletions docs/development.md
Original file line number Diff line number Diff line change
@@ -1,102 +1,47 @@
# Development

This page covers project layout, local build commands, documentation generation,
and the remaining roadmap.
Build directories use the `cmake-build-` prefix. The shared GoogleTest binary
is `tests/test_libvirtualhid` in the build directory. Initialize submodules
before building.

## Repository Layout
## Windows library and tests

```text
src/include/libvirtualhid/ Public C++ headers
src/core/ Shared profile, descriptor, and report logic
src/platform/windows/ Windows client backend and UMDF control channel
src/platform/windows/driver/ Windows UMDF2 driver package sources
src/platform/linux/ Linux uhid/uinput backend
src/platform/macos/ macOS CoreGraphics and broker client backends
src/platform/macos/broker/ Licensed macOS virtual HID broker
examples/ Minimal consumers and platform smoke tests
tests/ Unit and integration tests
cmake/ Package config and helper modules
docs/ Project documentation
third-party/dockle/ LizardByte documentation toolchain submodule
third-party/googletest/ GoogleTest submodule
```

## Windows Library Build

On Windows, the normal library and tests are built with MSYS2/UCRT64 for MinGW
coverage. Build directories should use the `cmake-build-` prefix.

```bash
cmake -S . -B cmake-build-debug-mingw-ucrt64-ninja -G Ninja \
-DCMAKE_BUILD_TYPE=Debug
cmake --build cmake-build-debug-mingw-ucrt64-ninja
cmake-build-debug-mingw-ucrt64-ninja/tests/test_libvirtualhid.exe
```

The Windows UMDF driver package is a separate MSVC/WDK build. See
[Windows driver package](windows-driver.md).

## Linux Build
Run each command from the repository root through MSYS2/UCRT64:

Linux builds use the same CMake target shape. Integration tests that create real
devices require access to `/dev/uhid` and `/dev/uinput`; see
[Platform support](platform-support.md).

```bash
cmake -S . -B cmake-build-debug -G Ninja -DCMAKE_BUILD_TYPE=Debug
cmake --build cmake-build-debug
cmake-build-debug/tests/test_libvirtualhid
```powershell
& 'C:\msys64\msys2_shell.cmd' -defterm -here -no-start -ucrt64 -c 'cmake -S . -B cmake-build-debug-mingw-ucrt64-ninja -G Ninja -DCMAKE_BUILD_TYPE=Debug'
& 'C:\msys64\msys2_shell.cmd' -defterm -here -no-start -ucrt64 -c 'cmake --build cmake-build-debug-mingw-ucrt64-ninja'
& 'C:\msys64\msys2_shell.cmd' -defterm -here -no-start -ucrt64 -c './cmake-build-debug-mingw-ucrt64-ninja/tests/test_libvirtualhid.exe'
```

## macOS Build
The normal library also builds with MSVC. The Windows driver package requires
the WDK/MSVC toolchain and is built separately; see
[Windows package](windows-driver.md#build-the-driver-package).

macOS builds link the CoreGraphics keyboard/mouse backend and the broker client
against system frameworks. Top-level builds also compile the broker app. The
ordinary test suite checks translation, protocol capacity, and lifecycle paths
without creating a live virtual HID device. Live testing requires Apple's
approved virtual HID entitlement and a signed installation.
## Linux and macOS

```bash
```sh
cmake -S . -B cmake-build-debug -G Ninja -DCMAKE_BUILD_TYPE=Debug
cmake --build cmake-build-debug
cmake-build-debug/tests/test_libvirtualhid
./cmake-build-debug/tests/test_libvirtualhid
```

For the universal Apple silicon and Intel release build, profile setup, and
signing workflow, see [macOS gamepad setup](macos-gamepad.md).
Linux installed-device tests need access to `/dev/uhid` or `/dev/uinput`.
A macOS test build does not prove virtual gamepad creation; that requires a
signed broker with Apple's virtual HID entitlement. See
[macOS setup](macos-gamepad.md).

## Documentation
## Documentation and validation

Documentation is generated by Dockle. The authored inputs and project-specific
Doxygen settings are declared in `dockle.toml`; Dockle owns the generated
Doxyfile used by the CMake `docs` target.
Public declarations and changed behavior should have accurate Doxygen
comments. Markdown pages cover tasks readers perform and limits they need to
know. The documentation target uses Dockle and the sources listed in
`dockle.toml`:

```bash
cmake --build cmake-build-debug-mingw-ucrt64-ninja --target docs
```sh
cmake --build cmake-build-debug --target docs
```

Keep Markdown pages focused on decisions or workflows that consumers and
maintainers need. Avoid preserving old implementation-plan checklists once the
code and tests provide a better source of truth.

## Validation Targets

- `test_libvirtualhid`: shared GoogleTest binary under the build directory's
`tests` directory.
- `gamepad_adapter`: example executable for profile and lifecycle diagnostics.
- `run_gamepad_adapter_example`: CMake target that runs `gamepad_adapter` from
its generator-specific output path when a platform backend is available.
- Windows driver helper scripts under `scripts/windows`.
- Linux consumer tests through SDL2, libinput, `uhid`, and `uinput` where the
host environment supports real virtual devices.
- Doxygen docs target for README, Markdown pages, and public header rendering.

## Roadmap

- Validate each macOS HID gamepad profile against SDL, Steam, browsers, and
Game Controller framework consumers after Apple grants the entitlement.
- Add bindings for other languages, such as Python, Rust, and C#. Bindings will
be considered for any requested language.
- Evaluate an optional FreeBSD CUSE-backed `uhid(4)`-compatible device for
direct HID consumers. This would supplement uinput; it is not equivalent to
registering a virtual device with FreeBSD's kernel HID bus.
Validate gamepad changes against the GoogleTest lifecycle suite and
[adapter example](../examples/gamepad_adapter.cpp). Installed driver, signing,
and physical-consumer behavior require platform-specific checks.
Loading
Loading