[RFC] HID: battery support design for Fractal Scape USB dongle (36bc:0001)
From: Andreas Kotiagin <hidden>
Date: 2026-09-15 17:08:50
Hello, I am investigating battery reporting for the Fractal Scape wireless headset through its USB dongle, with the intention of exposing a peripheral battery through power_supply. Before building a substantial driver, I would appreciate feedback on the integration and coexistence approach below. Descriptor observations from an attached 36bc:0001 dongle (bcdDevice 3.21): - Interfaces 0-2 are USB audio. Interface 3 is the only HID interface. - That HID interface contains consumer controls, telephony, and vendor collections. The final collection is usage page 0xff00, usage 1, with report ID 2 and 63 payload bytes for both input and output. - It has an interrupt IN endpoint 0x84, max packet 64, and no interrupt OUT endpoint. The complete HID report descriptor is 177 bytes. - There is no advertised standard battery usage. The whole HID interface currently binds to hid-generic. Source inspection of ScapeCtl at commit b5ec62ccbbb090dec24c614c5580fd1b2bf6fdbb indicates a status output request consisting of report ID 02 followed by f1 21 and 61 zero bytes. Its parser uses payload byte 14 for percentage and payload byte 18 == 1 for connection (raw report offsets 15 and 19, respectively). Replies echo f1 21. It uses a 500 ms response deadline, a default 1.5 second polling interval, and also sends a separate keepalive. Its README reports unsolicited 11 21 messages but warns that their presence byte is unreliable. These response semantics are source-derived, not yet confirmed on the attached headset. Captures across power-off, range loss, docking and cable charging, comparison with Fractal Adjust, and the need for keepalive at slower polling rates are still pending. No charging field has been established. ScapeCtl's root license is GPLv3; the planned kernel implementation will be independently written from protocol facts and hardware measurements, without copying or translating its code. Proposed design: - A small dedicated hid-scape driver matching only USB 36bc:0001, interface 3, with input/output report-size and vendor-usage checks. No hub or unverified wired-headset IDs. - Normal hid_parse / hid_hw_start(HID_CONNECT_DEFAULT) / hid_hw_open, with raw_event returning 0 so media controls and hidraw continue to receive reports. Audio interfaces remain with snd-usb-audio. - Cached power_supply data parented to the HID device, SCOPE_DEVICE, CAPACITY 0-100 after validated input, STATUS_UNKNOWN until charging is established, and no invented voltage, current or energy properties. Connection and stale-data semantics must be settled by measurements; a timeout must not be exposed as zero percent. - Initial 60 second polling from scheduled work using an output SET_REPORT, with a bounded response deadline, conservative backoff, and synchronous work cancellation on removal/suspend. No USB I/O in property callbacks. - A way to pause polling and drain outstanding driver requests before Adjust/ScapeCtl configuration sessions. There is no known transaction ID; separate hidraw readers and ScapeCtl's process-local mutex do not establish safe simultaneous device access. Passive reception can still cache valid status while preserving all incoming reports. The v6.18 SteelSeries headset driver is a useful integration reference, but the opaque vendor protocol appears to need more than a generic HID battery quirk. Does a dedicated HID driver fit here? Is there an existing preferred mechanism for coordinating such polling with hidraw configuration clients, or a recommended precedent for a per-device polling pause control? I will provide raw captures, lifecycle/coexistence results and a tested patch once those outstanding hardware questions are resolved. This is a design inquiry, not a request to merge unverified protocol support. ScapeCtl source inspected: https://github.com/charlietran/scapectl/tree/b5ec62ccbbb090dec24c614c5580fd1b2bf6fdbb Thanks, Andreas Kotiagin