Repository navigation
Add support for Sony PULSE 3D (CFI-ZWH1) - #610
Ashraf-Obay wants to merge 2 commits into
Conversation
Battery status for the PULSE 3D wireless headset via its USB dongle (054c:0d5e). The dongle never answers queries; it sends an 8-byte status report (ID 0xB0) on the vendor collection (usage page 0xFF01, usage 0x20) only when something changes: byte[3] battery 0-100 in steps of 10, or 0x80 while charging byte[4] bit 0x08 set while the headset is connected getBattery() drains the reports queued on the cached connection, keeps the newest status per handle, and otherwise waits up to the device timeout for the next report. Nothing is written to the device. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Good protocol write-up, and the passive approach is the right call - the mock asserting I broke each behaviour to see what the tests hold. Three of four fail as they should: clearing state on close, the The report-ID filter isn't covered. Drop // Same length as a status report but another collection's report ID
const std::vector<uint8_t> OTHER_COLLECTION_8B { 0x01, 0x05, 0x00, 0x64, 0xef, 0x15, 0x11, 0x64 };queued after The collection comment is out of date. Lines 70-71 and the PR body say the usage lookup is Windows-only with an interface-3 fallback elsewhere. #596 is in your history and it made the Keep Not yours to fix: Those two and I'll merge. |
Changes made
Adds battery status for the Sony PULSE 3D wireless headset (CFI-ZWH1, the PS5 headset) through its USB dongle
054c:0d5e.Protocol (found by passive listening; nothing is written to the device)
HID is on interface 3, which has four top-level collections. The headset status is on the vendor collection (usage page
0xFF01, usage0x0020) as an 8-byte input report:0xB00x80while charging0x08set while the headset is connected, cleared on power-offThe other bytes (a 0–100 level and some button flags) aren't decoded.
Evidence: a 6-hour log on real hardware showed byte 3 stepping 80 → 70 → 60 → 50 → 40 → 30 about once an hour. Power-off/on, plugging the charge cable in and out, and button presses were each checked separately.
The catch: the dongle never answers queries
It only sends the status report when something changes (power on/off, a button press, the charge cable, or a battery step, about hourly). Feature reports on the vendor collections read back as zeros. The collection also declares a 1-bit output report
0xB1, but the dongle rejects writes to it (ERROR_GEN_FAILUREon both interrupt OUT and SET_REPORT), so I couldn't find a way to request a report.So
getBattery():hsc_device_timeoutfor the next one, and otherwise returns a timeout telling the user to press a headset button;onConnectionClosed(), aslogitech_astro_a50_gen4.hppdoes.Mapping: powered off →
BATTERY_UNAVAILABLE(-1). Charging →BATTERY_CHARGINGwith the last level seen before plugging in, or -1 if none was seen.Tests:
tests/test_sony_pulse_3d.cppcovers newest-report-wins with other collections' reports in between, state kept across calls and per handle, charging, power-off, and error propagation, using the real captured reports. It also asserts that nothing is written to the device.Tested on hardware: Windows 11 with the CI-built
headsetcontrol.exefrom this branch:Sony PULSE 3D [0x054c:0x0d5e];-bwith no headset event times out after the configured--timeout(checked at 2 s, 5 s and 10 s) with the "press a button" error andBATTERY_UNAVAILABLE;-b --timeout 30000with one volume press during the wait →BATTERY_AVAILABLE, level 20.I verified the charging and power-off flags on the hardware with a standalone listener; in this branch they're covered by unit tests. Linux and macOS are untested (no hardware/OS access). The device only uses the usage-page lookup with an interface-3 fallback and filters by report ID, so reports from the other collections on that interface are ignored.
The one-shot CLI is the worst case for this device (a press is needed during the wait). Long-running library users that keep the
Headsetalive get the queued reports and stay current.Checklist
(Not a new feature, just a new device using the existing battery capability.)
🤖 Generated with Claude Code