Development
July 30, 2026 ยท View on GitHub
This page covers local builds for the Pico 2 W firmware and the Windows companion app.
Prerequisites
Install these tools before building:
- Git with submodule support.
- CMake and Ninja.
- Arm GNU Toolchain
15.2.Rel1(arm-none-eabi-gcc15.2.1). - Raspberry Pi Pico SDK
2.3.0. - Node.js
22. - .NET SDK
9.0. - Windows, for building and running the companion app.
The firmware CI currently builds with Pico SDK 2.3.0 and TinyUSB commit
2d56dc533e45e4e91b15e93fdab5e22e964f328d.
For the closest local match, use the same versions.
For debug presets and runtime diagnostic flags, see docs/diagnostics.md.
Clone
Initialize the bundled third-party source submodules:
git submodule update --init --recursive
Firmware
Build the companion firmware with the Pico SDK toolchain:
cmake -S . -B build/companion -G Ninja `
-DCMAKE_BUILD_TYPE=Release `
-DPICO_SDK_PATH=/path/to/pico-sdk `
-DENABLE_COMPANION=ON
cmake --build build/companion --target ds5-bridge
The resulting firmware is:
build/companion/ds5-bridge.uf2
Waveshare RP2350B-Plus-W
The Waveshare RP2350B-Plus-W (USB-C, 16MB flash, RM2 wireless) wires the
CYW43/RM2 module to different RP2350 GPIOs than the Pico 2 W, so it needs its
own build. Add -DWAVESHARE_RP2350B_PLUS_W_BUILD=ON to the cmake configure
above, or use the convenience script:
PICO_SDK_PATH=/path/to/pico-sdk ./boards/build_waveshare_rp2350b_plus_w.sh
The board header lives in boards/headers/waveshare_rp2350b_plus_w.h; it is
not part of upstream pico-sdk.
Companion App
Install dependencies from the lockfile and run the checks:
cd companion
npm ci
npm run typecheck
npm test
The companion app also keeps a repo-local .npmrc that blocks git dependencies
and avoids newly published packages younger than three days.
For a stricter supply-chain check, install without lifecycle scripts and then explicitly rebuild the packages that are expected to need native or tool binary setup:
npm ci --ignore-scripts
npm rebuild electron esbuild node-hid electron-winstaller --ignore-scripts=false
npm run build:audio-helper
npm run typecheck
npm test
Build the companion app:
npm run build
npm run build publishes the audio helper from:
companion/native/AudioHelper
The helper output is written to:
companion/native/AudioHelper/bin/publish/win-x64
Packaging also builds the repo-owned Pico Universal Flash Nuke utility from
tools/pico-universal-flash-nuke, then writes the bundled UF2 and manifest used
by the Bridge Settings nuke action to:
companion/firmware/pico-universal-flash-nuke.uf2
companion/firmware/pico-universal-flash-nuke.uf2.sha256
For local development:
npm run dev
Packaging
Build an unpacked Windows package:
npm run package:win
Build the Windows installer:
npm run installer:win
The installer build includes the published audio helper and Pico Universal Flash Nuke UF2/manifest as Electron extra resources.
Installer Upgrades
The Windows installer is an NSIS installer generated by electron-builder. A
newer DS5-Bridge-Companion-Setup-*.exe upgrades an existing install in place
when the installer identity matches:
build.appIdmust remainio.github.sundaymoments.ds5bridge.build.nsis.guidmust remain40464839-1bb3-5f24-b04b-13b55106e88b.build.nsis.perMachinemust remain compatible with the existing per-user install path unless the release explicitly migrates users.
On upgrade, electron-builder reads the existing install registry key, skips the
fresh-install directory page, closes the running companion if needed, runs the
old uninstaller with the --updated flag so user data is preserved, writes the
new app files, refreshes shortcuts, and records the new version in Windows'
Apps & features entry. Users should be able to run the new installer directly
without uninstalling first.
Do not change the NSIS GUID to a newly generated value. That would make Windows and the installer treat the build as a different app, which can leave users with side-by-side installs instead of an upgrade.
Release Candidate Bundle
Create a timestamped release candidate folder in Documents with the firmware UF2, Windows installer, portable companion folder, portable ZIP, and a manifest:
.\tools\create-release-candidate.ps1
Useful options:
.\tools\create-release-candidate.ps1 -Label rc1
.\tools\create-release-candidate.ps1 -OutputRoot "$env:USERPROFILE\Desktop"
.\tools\create-release-candidate.ps1 -SkipBuild
.\tools\create-release-candidate.ps1 -NoZip
Beta Releases
Run the Publish beta release workflow manually and enter the next positive
beta number. The workflow always tags the current port-dev head and derives
the version from firmware-version.txt; for example, base version 1.7.0 and
beta number 2 produce v1.7.0-beta.2.
The workflow creates a draft GitHub prerelease, calls the shared release build
for both firmware targets plus the Windows installer and portable app, and only
publishes the prerelease after every artifact and the release metadata upload
succeeds. A failed build remains a draft for inspection. Beta tags are
immutable inputs: rerunning the same beta is allowed only while its tag still
points at the same port-dev commit and its release remains a draft.
The workflow definition must be present on the repository's default branch for
GitHub's Run workflow button to expose it, but all beta source and submodules
are checked out from port-dev.
Audio Helper Runtime
The audio helper is published as a self-contained Windows x64 build so end users do not need to install a separate .NET runtime. Developer machines still need the .NET SDK to build or publish the helper locally. The helper is used for audio session discovery, audio-reactive haptics mirroring, default endpoint setup, speaker test playback, mic keepalive, media metadata, game discovery, and icon extraction.
Enable helper diagnostics while developing companion-side audio integrations:
$env:DS5_BRIDGE_AUDIO_HELPER_DIAGNOSTICS="1"
cd companion
npm run dev
Project Layout
| Path | Purpose |
|---|---|
src/main.cpp | Pico startup, watchdog handling, USB task loop, and HID report bridge. |
src/bt.cpp | Bluetooth inquiry, pairing, L2CAP HID channels, and report queueing. |
src/audio.cpp | USB audio ingestion, haptic resampling, Opus speaker encoding, and audio packet assembly. |
src/companion.cpp | Vendor HID companion protocol, status reports, command ACKs, and runtime setting dispatch. |
src/usb.cpp | TinyUSB audio control callbacks and runtime settings fallback. |
src/usb_descriptors.c | USB device, configuration, HID report, audio, and string descriptors. |
companion/ | Electron companion app source, protocol parser, HID service, assets, and UI. |
companion/native/AudioHelper/ | Native audio helper source. |
.github/workflows | CI and release builds. |