Overlay #106: gesture-free serials via node-hid enumeration in main#107
Overlay #106: gesture-free serials via node-hid enumeration in main#107petegordon wants to merge 3 commits into
Conversation
The renderer's WebHID serial scan needs a user gesture (Blink), so the #104 auto-opened list showed no serials. node-hid enumerates in MAIN — per-device path + serialNumber, read-only (no open, no contention with WebHID handles), and NO gesture. Populates the existing hidControllers inventory at launch + polls for hot-plug; broadcasts only on change. - Guarded require: if the native module isn't built for this Electron ABI it stays null and we fall back to the Electron HID-event inventory (no regression). - hidKey now prefers vid:pid:serial so a multi-interface device collapses to one entry (the Steam Puck exposes ~11 interfaces sharing one serial). - Skips productId-0 / nameless vendor-shared junk (e.g. Microsoft 045e HID). - forge: @electron-forge/plugin-auto-unpack-natives so the .node binary is loadable from the packaged asar; `npm run rebuild` helper for local dev. FEASIBILITY VERIFIED under Node on this Windows machine: node-hid installed from a prebuilt (2s, no compiler) and enumerated the real pads gesture-free with matching serials — Steam FXB9960202571, Switch 98e255badd18, DS4 (none) — and the dedup collapsed the Puck's 11 interfaces to 1. NEEDS verify under Electron 33 runtime + packaged build. This delivers win #1 (gesture-free serials); per-unit same-transport auto-select (win #2) still needs the handle->path bridge — noted.
🔎 PR #107 preview — test it in isolation🌐 Web overlay: https://lab.usersfirst.games/pr-preview/pr-107/overlay/ 💻 Desktop installers (prerelease): https://github.com/UsersFirst/tandemonium-controller-lab/releases/tag/pr-107
Updated for 8560fda. Web preview and prerelease are torn down when this PR closes. |
… pads (USB DS4) The USB DualShock 4 leaves iSerialNumber empty (WebHID + node-hid both saw serial=(none)), but it exposes its Bluetooth MAC via HID feature report 0x12 — a report Chromium blocklists in WebHID (why the renderer can't read it) but node-hid in main can. On enumeration, when a pad has no serialNumber, probe the MAC (per-controller report id; DS4 0x12, bytes 1..6 little-endian), format it as 12 hex chars to match node-hid's serial format, and use it as the unit's id. Probe once per device path and cache (no re-open on the 2s poll). HARDWARE-VERIFIED on this Windows machine (probe succeeded while the overlay had the pad open over WebHID — shared feature-report reads work): the DS4 now shows serial 90fba6ba591c; Steam FXB9960202571 / Switch 98e255badd18 unchanged; dedup intact. Gives each physical unit an id in the inventory, incl. the serial-less DS4. NOTE: full two-identical-same-transport AUTO-SELECT still needs the renderer WebHID-handle -> unit bridge (grant-time correlation) — remaining #106 follow-up.
|
Win #2 (feature-report MAC) added — commit 8560fda. Pads with no iSerialNumber now get their MAC from a HID feature report (DS4 report 0x12) via node-hid in main. Hardware-verified on Windows (probe succeeded even with the overlay holding the pad open over WebHID — shared feature-report reads work): Every physical unit now has an id in the inventory, including the serial-less USB DS4. Remaining for full two-identical-same-transport auto-select: the renderer WebHID-handle -> unit bridge (grant-time correlation) — the last #106 follow-up. |
Implements win #1 of #106: enumerate HID in the Electron main process via
node-hid, so serials populate at launch with no user gesture — fixing the #104 auto-opened list showing blank serials (the renderer's WebHIDrequestDevicescan needs transient activation, which the auto-open lacks).What it does
require('node-hid')in main. If it fails to load for this Electron ABI it staysnulland we degrade to the existing Electron HID-event inventory — no regression.enumerateHidViaNodeHid()readsHID.devices()(metadata only — no open, so no contention with the renderer's WebHID handles), filters to controller VIDs, and rebuilds the existinghidControllersinventory. Runs at launch + polls every 2s for hot-plug; broadcasts only on change.hidKeynow prefersvid:pid:serialso a multi-interface device collapses to one row — the Steam Puck exposes ~11 HID interfaces sharing one serial.productId === 0/ nameless vendor-shared junk (e.g. Microsoft045ekeyboards/mice).forge.config.js: adds@electron-forge/plugin-auto-unpack-natives(so the.nodebinary loads from the packaged asar);npm run rebuildhelper +@electron/rebuilddev dep for local dev.Feasibility — verified under Node on this Windows machine
node-hidinstalled from a prebuilt in 2s (no compiler) and enumerated the real pads gesture-free with matching serials:(the Puck's 11 interfaces collapsed to 1; serials match the earlier gesture-scan values).
Verify (Electron runtime + package) — draft until confirmed
node-hid loaded — gesture-free serial enumeration activeandnode-hid enumeration: N controller(s).npm run makeand confirm the packaged app still loads node-hid (auto-unpack-natives).Scope
Delivers gesture-free serials (win #1). Per-unit same-transport auto-select (win #2) still needs the renderer WebHID-handle → node-hid-
pathbridge (or moving report I/O to main) — left as the follow-up noted in #106.Refs #106, #104, #105.