README: checkout from our master since our content (10-screen
docs, web-config link, multi-slot docs, Auto Haptics docs,
Acknowledgements, etc.) is the source of truth for the fork; upstream's
v0.6.0 README updates are mostly about their new web config tool which
we don't surface (we link our own fork's web config instead).
CHANGELOG: new [0.6.0-rebase] entry on top documenting (a) the
state_mgr adoption + speaker-fix hack drop, (b) the discoverable-rule
loosening for multi-slot, (c) the iSerialNumber restore that fixes
#100, and (d) verification results from the mid-rebase flash.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Build now compiles. audio.cpp on top of upstream's state_mgr-based
audio_loop adds three additive pieces:
1. VU peak meters for ch0/1 (spk_max) and ch2/3 (hap_max) tracked
per-sample in the existing loop; written back to g_peak_spk /
g_peak_hap after. Accessors decay 12.5% per read so the OLED
VU bars fall back naturally over a few frames.
2. Monotonic byte-flow counters: g_usb_frames++ after tud_audio_read
(the OLED Diagnostics screen + web emulator compute USB-aud/s
and BT-0x32/s as delta over time). g_bt_packets++ after each
0x36 bt_write.
3. Audio Auto Haptics DSP — 1-pole LP + envelope follower +
modulation + soft-clip per loteran/DS5Dongle 5d6bc2f, with our
added 4th "Fallback" mode that fires only after the game's
native haptic path has been silent for ~1 s (NATIVE_SILENT_TIMEOUT
= 100 audio_loop calls). Preserves native HD haptics (Spider-Man
Remastered) while filling in for games that send no haptic data
(Ghost of Tsushima). Modes: 0=Off, 1=Fallback (default), 2=Mix,
3=Replace.
Crucially the state_mgr-based state_set(pkt+13, 63) call is left
untouched — that's upstream's correct replacement for our prior
state_data restore hack, and it's load-bearing for speaker output.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bt.h: add OLED accessors (bt_is_connected, bt_get_addr, bt_hci_err_count)
and 6 multi-slot accessors (bt_get_slot, bt_set_slot, bt_forget_slot,
bt_wipe_all_slots, bt_slot_occupied, bt_slot_get_addr).
bt.cpp:
- #include "slots.h"; add g_current_slot + update_discoverable()
helper that gates gap_discoverable_control on slots_any_empty().
- 3 OLED accessor impls + 6 slot accessor impls.
- bt_init: slots_load() + g_current_slot from Config_body.current_slot,
then update_discoverable() instead of bare gap_discoverable_control(1).
- HCI_EVENT_INQUIRY_RESULT: slot-ownership filter (skip devices owned
by other slots; if our slot is occupied, only accept matching addr).
- L2CAP_EVENT_CHANNEL_OPENED HID_CONTROL: slot_assign on empty slot
(Phase G auto-bond pattern).
- L2CAP_EVENT_CHANNEL_OPENED HID_INTERRUPT: replace upstream's
gap_*_control(false) pair with update_discoverable() — they wanted
"non-discoverable once connected"; we want "non-discoverable once
all 4 slots are full". Strictly looser, which is correct since
empty slots need to accept new pairings.
- Inquiry-complete + disconnection-complete handlers similarly
swapped to update_discoverable().
Upstream's state_mgr hooks (state_init / state_set / state_update
calls in L2CAP_EVENT_CHANNEL_OPENED and elsewhere) are preserved
as-is — they're the upstream rumble-fix infrastructure.
Build still fails on oled.cpp references to audio_peak_* / counter
accessors that Phase E adds.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three additions on top of upstream's v0.6.0-hotfix main.cpp:
- #include "oled.h" + oled_init() after audio_init/state_init,
oled_loop() in the main while(1).
- PS + Mute hold-2-seconds combo at the top of interrupt_loop()
for headless soft-reboot via watchdog_reboot(0,0,0). Bit pattern
(interrupt_in_data[9] & 0x05) is rare in normal gameplay so the
long hold prevents accidental triggers.
Upstream's state_init() call sits right between audio_init() and our
new oled_init() — preserved as-is. The state_mgr → 0x31 output report
flow in tud_hid_set_report_cb is upstream's rumble path; not touched.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Build-system, config, usb, and CI wiring on top of upstream's
v0.6.0-hotfix tree. Build will still fail until Phase C+D land bt.h
accessors that oled.cpp references; that's expected mid-rebase.
CMakeLists.txt: add src/oled.cpp + src/slots.cpp to add_executable,
link hardware_spi, restore OUTPUT_NAME ds5-bridge-oled.
src/config.h: append the 4 OLED Edition Config_body fields
(current_slot + auto_haptics_enable/gain/lowpass). Preserves
upstream's field order for the first 8 fields.
src/config.cpp:
- speaker_volume validity default -100 dB → 0 dB (footgun fix)
- 4 new validity guards for the appended fields with sensible
defaults (Fallback / 100 % / 160 Hz / slot 0)
- config_default() impl (was declared in upstream's config.h since
v0.5.4 but never defined; the OLED Edition's "Reset to defaults"
Settings item calls it)
src/usb.cpp: drop the UAC1 SET_CUR Volume → flash-config sync that
let PipeWire/Pulse silently override the user's saved Spk Vol on
every device reconnect. Borrowed from loteran/DS5Dongle commit
03fa1e4.
src/usb_descriptors.cpp: restore iSerialNumber = STRID_SERIAL.
Upstream's commit e79c762 zeroed it to work around SpecialK (#32),
but that broke Windows device identity (#100) — users lost
per-device volume / app preferences when moving USB ports. The
OLED Edition prioritizes Windows device-identity stability for
the broader user base over SpecialK compat for a narrower one.
.github/workflows/{build,release}.yml: artifact filenames use
ds5-bridge-oled.uf2 (and -debug / -picow variants) per the
OUTPUT_NAME rebrand.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>