mirror of
https://github.com/safijari/openpuck.git
synced 2026-11-03 22:30:22 +00:00
[PR #216] [MERGED] Map trackpads to joysticks #241
Labels
No labels
pull-request
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
safijari/openpuck#241
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/safijari/openpuck/pull/216
Author: @Philip-Scott
Created: 8/4/2026
Status: ✅ Merged
Merged: 8/12/2026
Merged by: @safijari
Base:
main← Head:main📝 Commits (9)
ff15c23Add trackpad-to-joystick mapping configurable from the WebUI07328c3Attach test build: OpenPuck .uf2 (trackpad-to-joystick)41d72feMove trackpad->stick config fields off the per-type cfg rangeef66babAllow manual dispatch of the Build workfloweef0959Revert ci and .uf2 file5e459d3Touchpad does not override sticke2b064eCode review71222ccCorrect docs69c9b8bMerge pull request #1 from Philip-Scott/copilot/allow-mapping-trackpads-to-joysticks📊 Changes
14 files changed (+233 additions, -45 deletions)
View changed files
📝
CODE_MAP.md(+1 -0)📝
OpenPuck/config.cpp(+22 -2)📝
OpenPuck/config.h(+12 -0)📝
OpenPuck/gamepad_util.cpp(+51 -0)📝
OpenPuck/gamepad_util.h(+14 -0)📝
OpenPuck/mode_hidgyro.cpp(+16 -10)📝
OpenPuck/mode_ps3.cpp(+6 -4)📝
OpenPuck/mode_ps5.cpp(+16 -9)📝
OpenPuck/mode_switch_hori.cpp(+6 -5)📝
OpenPuck/mode_switch_pro.cpp(+4 -2)📝
OpenPuck/mode_xinput.cpp(+11 -5)📝
OpenPuck/webusb_config.cpp(+32 -3)📝
docs/PROTOCOL.md(+9 -0)📝
docs/index.html(+33 -5)📄 Description
One thing I love about the touchpads is using them for movement by emulating the sticks. On this PR I've added the ability for us to map touchpads to sticks on any of the modes such as the Switch.
https://github.com/user-attachments/assets/350a161c-5e26-4856-bb6f-0434c27880c6
AI Generated PR Description:
Adds a per-emulated-controller-type trackpad → joystick mapping, configurable from the WebUSB panel. Each type (Xbox / Switch / DS4 / DS5) gets two selects — Left trackpad → stick and Right trackpad → stick — each
Off (touchpad)/Left stick/Right stick.Semantics — a mapped pad blends with its stick, it does not replace it. While the pad is touched, each axis reports whichever of the two sources is deflected further from center (sign preserved), so the pad and the physical stick stay usable at the same time. An untouched pad contributes nothing and the physical stick passes straight through — which is also why a release can never leave a stale pad value stuck on an axis (a capacitive pad can't express a flick back to center). A mapped pad additionally stops reporting as a DS4/DS5 touchpad contact and stops driving the Xbox-mode mouse, so the host never sees the same finger twice.
Config (
config.h/config.cpp)g_padStickCfg[ET_COUNT][2]—{left pad, right pad}→PS_OFF/PS_LEFT/PS_RIGHT, off by default.Cfgtail, not insideTypeCfg, so an existingcfg.binstill loads and keeps every other setting (a short file leaves the new bytes at the0xFFprefill → compiled default, perCFG_LEN_MIN).g_padStick[2]live mirror, refreshed byapplyActiveType()and forced toPS_OFFforET_NONE, so puck/lizard modes are untouched.Input path (
gamepad_util)padStickBlend()applies the mapping;slotSticks()wraps it as "the sticks a mode should send".padStickBlend()directly against the raw0x45offsets (16/18 left pad, 22/24 right pad) becauserfXboxGamepaddecodes the report in place and never readsg_in.rfXboxMousetreats a mapped right pad as untouched so its glide velocity decays instead of stopping dead.strongerAxis()clamps the-32768magnitude to32767before comparing — negatingINT16_MINoverflows, which would make a full-deflection axis lose to anything.WebUSB (
webusb_config.cpp, protocol v20)p[187..194](2 B per type);WB_PAYLEN185 → 193, still inside the 256 B vendor TX FIFO.80..87=80 + type*2 + pad, range-checked againstPS_MAX. They must stay clear of the per-type cfg range40..75, which is claimed before the field switch runs.applyActiveType()so the change takes effect without a reboot.Panel (
docs/index.html)docs/PROTOCOL.mddocuments the new blob tail and setter fields.Cross-task note
g_padStick[]is written from the loop task (applyActiveType(), boot and the WebUSB setter) and read from the usbd task byjcInputPrefix(Switch Pro). It's a plainuint8_t[2]— byte writes, worst case one stale frame — matching howg_abSwap/g_back[]already behave.Testing
Verified on a physical puck using: Steam's Test Device Inputs section, and on a Switch 2
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.