a87b279c2b68674a58a401dfc59be6c583072bd3
1216 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
a87b279c2b |
test(host): Windows on-hardware NVENC reconfigure smoke — 20→60→10 Mbps in place, zero IDRs
ci / web (push) Successful in 1m16s
ci / docs-site (push) Successful in 1m37s
arch / build-publish (push) Successful in 10m16s
decky / build-publish (push) Successful in 36s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
ci / bench (push) Successful in 5m11s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 10s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m2s
android / android (push) Successful in 15m11s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 6m51s
docker / deploy-docs (push) Successful in 16s
deb / build-publish (push) Successful in 12m48s
ci / rust (push) Successful in 16m56s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 12m32s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m47s
apple / swift (push) Successful in 4m30s
windows-host / package (push) Successful in 14m43s
apple / screenshots (push) Successful in 21m55s
The Windows twin of nvenc_cuda_reconfigure_no_idr, green on the .173 RTX box (release profile — the dev-profile test binary trips a pre-existing LNK2019 on the sdk crate's unused safe EncodeAPI statics, which release LTO strips). Chasing this also uncovered why the live A/B kept rebuilding: the PunktfunkHost service runs C:\Users\Public\punktfunk-native's exe, not the Developer clone deploy-host.ps1 had been rebuilding. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
9bf72cdfb5 |
fix(host): forward reconfigure_bitrate through TrackedEncoder + probe --rebitrate validator
ci / web (push) Successful in 56s
ci / docs-site (push) Successful in 1m5s
decky / build-publish (push) Successful in 21s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 8s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 6s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 9s
arch / build-publish (push) Successful in 13m33s
android / android (push) Successful in 14m55s
ci / bench (push) Successful in 5m19s
ci / rust (push) Successful in 16m59s
flatpak / build-publish (push) Failing after 8m7s
apple / swift (push) Successful in 4m30s
deb / build-publish (push) Successful in 11m24s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 16m31s
docker / deploy-docs (push) Successful in 25s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 17m8s
windows-host / package (push) Successful in 8m14s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 4m3s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m46s
release / apple (push) Successful in 24m38s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m12s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 5m56s
apple / screenshots (push) Successful in 21m24s
The gpu-session TrackedEncoder wrapper delegates every Encoder method by hand, so the new reconfigure_bitrate fell through to the trait's false default and EVERY bitrate change silently took the rebuild+IDR path — the live .21 A/B caught it (host log said 'rebuilt', never 'in place'). Also: - punktfunk-probe --rebitrate KBPS:SECS — headless mid-stream SetBitrate validator (cursor-wiggles so a damage-driven idle desktop keeps publishing frames through the switch). Live-verified on .21: one NVENC session open, then 'encoder bitrate reconfigured in place (adaptive bitrate — no IDR)' at 20→60 Mbps. - on-hardware nvenc_cuda reconfigure smoke test (20→60→10 Mbps in place, zero IDRs — green on the RTX 5070 Ti). - BitrateChanged doc no longer claims the switch costs an IDR. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a1af916e38 |
feat(host): in-place encoder rate reconfigure — ABR steps no longer cost an IDR
ci / web (push) Successful in 56s
ci / docs-site (push) Successful in 1m8s
ci / bench (push) Successful in 5m25s
decky / build-publish (push) Successful in 21s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 9s
arch / build-publish (push) Successful in 11m11s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 8s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 41s
android / android (push) Successful in 14m53s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 6m24s
deb / build-publish (push) Successful in 11m50s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m5s
ci / rust (push) Successful in 23m4s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 16m54s
docker / deploy-docs (push) Successful in 22s
apple / swift (push) Successful in 4m31s
windows-host / package (push) Successful in 14m46s
apple / screenshots (push) Successful in 18m26s
Every adaptive-bitrate step used to tear the encoder down and rebuild it, opening on a full IDR (a 20-40x frame-size spike, in-flight AU forfeit and an IDR-cooldown anchor) — exactly when the Automatic controller is climbing. Encoder::reconfigure_bitrate(bps) retargets the LIVE encoder instead (default false, so libavcodec/software paths keep the rebuild fallback, which also still owns the bitrate clamping): - Linux + Windows direct NVENC: nvEncReconfigureEncoder (added to the hand-rolled runtime EncodeApi tables) with resetEncoder=0 / forceIDR=0; the same init/config is re-authored via the new shared build_config/ build_init_params with only avg/max bitrate + VBV (PUNKTFUNK_VBV_FRAMES) moved. On-hardware test: 20→60→10 Mbps in place, zero IDRs (RTX 5070 Ti). - Native AMF: TargetBitrate/PeakBitrate/VBVBufferSize are dynamic properties — SetProperty on the live component, no Terminate/re-Init. - Vulkan Video (HEVC + AV1): stage the rate and emit an ENCODE_RATE_CONTROL control command on the next recorded frame (begin keeps declaring the session's current state, as the spec requires). The session glue tries the in-place retarget first and skips the rebuild/ inflight-clear/IDR-cooldown bookkeeping when it succeeds — the reference chain and the wire-index prediction survive, so RFI keeps working across rate steps. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
46b7ffc001 |
fix(client): Linux auto decoder tries VAAPI before FFmpeg-Vulkan on desktop Mesa
ci / web (push) Successful in 48s
ci / docs-site (push) Successful in 56s
decky / build-publish (push) Successful in 16s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 9s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m1s
arch / build-publish (push) Successful in 11m4s
ci / bench (push) Successful in 6m7s
android / android (push) Successful in 15m32s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 7m29s
flatpak / build-publish (push) Failing after 8m12s
deb / build-publish (push) Successful in 11m17s
ci / rust (push) Successful in 22m25s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 14m11s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m41s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 16m36s
docker / deploy-docs (push) Successful in 26s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 4m30s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m8s
apple / swift (push) Successful in 4m47s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 5m56s
apple / screenshots (push) Successful in 19m45s
Mesa now exposes Vulkan Video decode queues by default (and the session binary opts RADV in for the Deck's sake), which silently moved every desktop AMD/Intel box onto FFmpeg-Vulkan-on-Mesa under `auto` — user-reported (CachyOS/KDE) to judder or error-streak into the software demotion while an explicit VAAPI pick streams perfectly. Auto's hardware order is now device-aware (`VulkanDecodeDevice::prefer_vulkan_over_vaapi`, fed vendor id + device name by the presenter): Vulkan-first stays only where it is the established right answer — NVIDIA (no usable VAAPI) and the Deck's VanGogh (VAAPI dmabuf import chroma-fringes) — and everything else gets the battle-tested zero-copy VAAPI first, with Vulkan as its fallback. A mid-session Vulkan failure streak now also demotes to VAAPI before software, so a broken Mesa Vulkan path can never strand a box with a perfectly good VAAPI driver on CPU decode. The GTK shell's decoder setting gains the missing "Vulkan Video" option (values now mirror the console UI's auto/vulkan/vaapi/software) and drops its pre-Vulkan "Automatic (VAAPI → software)" label. Verified on the RTX 5070 Ti box (loopback session, auto → "Vulkan Video hardware decode active", 60 fps); policy locked by unit test; clippy -D warnings + pf-client-core/pf-presenter tests green on Linux. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
9b7fc127ef |
feat(core): Automatic bitrate scales to measured link capacity — probe ceiling + slow start
ci / web (push) Successful in 49s
ci / docs-site (push) Successful in 52s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
decky / build-publish (push) Successful in 15s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 7s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 10s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 45s
apple / swift (push) Successful in 4m34s
ci / bench (push) Successful in 6m1s
flatpak / build-publish (push) Failing after 8m11s
docker / deploy-docs (push) Successful in 27s
deb / build-publish (push) Successful in 12m30s
windows-host / package (push) Successful in 14m50s
arch / build-publish (push) Successful in 15m1s
android / android (push) Successful in 15m47s
ci / rust (push) Successful in 17m55s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 4m0s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 17m4s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m17s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 4m54s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m4s
release / apple (push) Successful in 25m7s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 6m4s
apple / screenshots (push) Successful in 18m44s
The ABR ceiling was the negotiated start rate, so an 'Automatic' session was permanently boxed at the 20 Mbps default no matter the link — the most user-visible cap left after the transport work lifted the client receive ceiling to ~4.8 Gbps wire. - Startup link-capacity probe: ~2 s into an Automatic session the pump fires one speed-test burst (2 Gbps target, 800 ms) over the existing ProbeRequest machinery; delivered wire throughput x0.7 (FEC + variance headroom) becomes the controller's climb ceiling via set_ceiling(). Old hosts decline (all-zero reply) or never answer (a 6 s timeout clears the stuck probe state so LossReports resume) — the ceiling then stays negotiated, exactly the old behavior. PUNKTFUNK_ABR_PROBE=0 opts out. - Slow start: until the first congestion signal, every cooled clean window DOUBLES the rate toward the ceiling (20 Mbps -> 640 Mbps in ~10 s) instead of +6% per ~10 s (which would have taken ~10 minutes). Any congestion signal ends it for good; classic AIMD takes over. - Faster, severity-aware AIMD: a SEVERE window (unrecoverable frame, jump-to-live flush, or >=6% loss) backs off x0.7 immediately instead of waiting two windows; ordinary congestion (2-6% loss, OWD rise) keeps the two-window fuse. Additive climbs need 6 clean windows (~4.5 s, was ~10 s); the change cooldown drops 3 s -> 1.5 s. - PUNKTFUNK_VBV_FRAMES now also scales the direct-NVENC VBV (Windows + Linux, previously hardwired to 1 frame) — parity with AMF/VAAPI/QSV. Each accepted step still costs an encoder rebuild + IDR on the host; in-place rate reconfigure (NvEncReconfigureEncoder / AMF dynamic properties / Vulkan per-frame RC) is the planned follow-up that makes stepping free. Controller tests rewritten to the new policy (severity classes, slow-start climb, ceiling semantics; 144 green). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
1a559e8d5e |
feat(core): scale the receive path to the new multi-Gbps ceiling
- REPLAY_WINDOW 32768 -> 131072: the anti-replay bitmap covered the 120 ms loss window only to ~2 Gbps; the client now delivers ~4.8 Gbps wire, where a late-but-valid Wi-Fi-retried datagram would have been dropped as 'older than the window' — false loss. 16 KiB/session covers ~12 Gbps. - RECV_BATCH 32 -> 128: syscall rate stays ~3.4k/s at 430k pkt/s and each pump iteration drains the kernel buffer deeper (ring 64->256 KB, client sessions only). flush_backlog's iteration cap rescaled to keep its ~190 MB guard equivalent. - PUNKTFUNK_GSO gate is now value-aware: '=0' used to ENABLE GSO on Linux (presence check) while disabling Windows USO. GSO stays OPT-IN, deliberately: A/B'd twice today — it cuts send-thread CPU ~30% but its 16-packet line-rate trains cost delivered throughput on a constrained fabric (2.5GbE-hop pair: peak 2453 -> 1908 Mbps and 0.4% loss at a rate sendmmsg carries clean). Flipping the default belongs with pace-aware chunk spacing (plan Phase 1.2/1.3). docs-site row corrected to match. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
160914c48b |
perf(build): enable ARMv8 hardware AES-GCM — every aarch64 client ran software crypto
RustCrypto aes 0.8.x and polyval 0.6.x gate their ARMv8 AES / PMULL paths behind --cfg aes_armv8 / --cfg polyval_armv8 on aarch64 (x86_64 runtime-detects AES-NI with no flag, which is why hosts never showed it). Without the cfgs every Apple and Android client decrypted the media plane in SOFTWARE: 240 MiB/s/core measured on an M3 Ultra — 7 µs per 1.4 KB datagram, single-handedly capping receive throughput at ~1.57 Gbps wire on both host pairs. Workspace .cargo/config.toml sets both cfgs for cfg(target_arch = "aarch64"); detection stays runtime (cpufeatures) with a safe soft fallback. open_in_place: 240 MiB/s -> 2.42 GiB/s (10.3x). Live sweep .173 -> M3 Ultra over 10GbE: ceiling 1572 -> 4830 Mbps wire, zero loss through a 3.5 Gbps target; the .21 pair now saturates its physical 2.4 Gbps fabric exactly. No in-tree build path sets RUSTFLAGS (xcframework + gradle checked), so the config reaches all client builds; a lane that sets RUSTFLAGS overrides config rustflags entirely and must carry the cfgs itself (noted in the file). Shipping Apple/Android binaries stay on software crypto until rebuilt. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
ed0ce5dc6d |
feat(core): zero-copy pooled reassembly — shards land at their final AU offset
Rewrite the client Reassembler around one whole-frame buffer per frame: frame_bytes rides in every header and packetize geometry is deterministic (every non-final block is exactly max_data_per_block data shards), so a data shard's final AU offset is computable on arrival — copy it there once, straight from the decrypt ring. New ErasureCoder::reconstruct_into decodes ONLY the missing shards directly into the frame buffer's holes (gf16 native; gf8 legacy shim); received recovery shards ride pooled shard-sized buffers. The completed buffer IS Frame::data. Deletes the per-shard to_vec + per-block concat + final AU concat (~178k allocs and a double copy of every byte per second at 2 Gbps — the pump wall the 2026-07-14 sweeps measured at 98.9% of an M3 Ultra core). Reassembly now costs ~0.4 µs/packet in-stream. The eager buffer changes the hostile-header exposure, so two new firewalls: derived-geometry validation (a header lying about its data_shards/block_count vs its own frame_bytes is dropped before it can scribble across another shard's range) and an in-flight allocation budget (IN_FLIGHT_BUF_FACTOR × max_frame_bytes) so a window of tiny first-shards can't commit gigabytes. Behavior parity pinned by the existing suite (all green unchanged) plus new end-to-end roundtrips through the real Packetizer (multi-block + partial tail, loss within budget, reversed delivery, duplicates, empty frame, unrecoverable block ages out, budget enforcement). loss-harness recovery curve identical; pipeline bench: gf8/1MB +42%, gf16 neutral (host-encode dominated). Known pre-existing quirk kept as-is: reversed delivery reconstructs early (data+recovery ≥ k) and counts late-not-lost shards into fec_recovered_shards. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
f2fa7828d6 |
fix(probe,scripts): make speed-test sweeps work headless and tell the truth
Three bugs found running the owed throughput sweeps (all three conspired to make yesterday's 'transport does 1G+' numbers fabrications): - the probe never advertised VIDEO_CAP_PROBE_SEQ, so every host DECLINED its speed tests; the zeroed decline reply divided a settle-window sliver by 1 ms and printed plausible-looking garbage. Advertise the cap (the shared-core reassembler windows probe-space frames) and detect the all-zero decline explicitly. - an idle virtual desktop publishes no frames on damage-driven capture (Windows IDD-push), so the pipeline build timed out before the burst could run. The probe now injects a ±2 px cursor wiggle over the wire during --speed-test warmup — injected host-side into the right session, works headless everywhere. - throughput-sweep.py: tracing emits ANSI color into pipes, which broke the key=value parser (crash on the first point); strip it, guard half-parsed lines, and surface host declines as a flag. Also logs the whole-run receive stage split (PUNKTFUNK_PERF) at stream end — the probe is the measurement tool for the client-pump wall. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
85513d1697 |
fix(host/linux): headless gamescope must not inherit a desktop DISPLAY/WAYLAND_DISPLAY
A host (re)started after a desktop login inherits the user manager's
compositor env; a stale WAYLAND_DISPLAY makes headless gamescope 3.16
exit at startup ('Failed to connect to wayland socket') before its
PipeWire node appears. Unset both on the systemd-run transient unit
(UnsetEnvironment=) and the direct spawn (env_remove) — gamescope
exports its own DISPLAY/GAMESCOPE_WAYLAND_DISPLAY to the nested app.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
0058f624a2 |
feat(core): receive-path stage timing + frame-jitter observability (PUNKTFUNK_PERF)
Session::poll_frame accumulates per-stage ns (recv_batch syscall, AES-GCM open, Reassembler::push incl. FEC) into a PumpPerf drained via take_pump_perf(); the client pump logs the split plus completed-AU inter-arrival jitter (p50/p95/max + late count) every report window. Gated on PUNKTFUNK_PERF — one branch per stage when off. Smoothness previously had no metric at all (jump-to-live counters fire seconds late), and the receive core had no attribution. First live use pinned the 1.57 Gbps client wall on software AES-GCM (7 µs/pkt) vs 0.4 µs reassembly — see punktfunk-planning/design/throughput-beyond-1gbps.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a7a1e871e8 |
chore(tools): add throughput-sweep diagnostic script
windows-drivers / probe-and-proto (push) Successful in 38s
ci / web (push) Successful in 47s
ci / docs-site (push) Successful in 1m0s
decky / build-publish (push) Successful in 27s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 12s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 13s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 12s
windows-drivers / driver-build (push) Successful in 1m44s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 47s
apple / swift (push) Successful in 4m25s
ci / bench (push) Successful in 5m57s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8m46s
flatpak / build-publish (push) Failing after 8m10s
windows-host / package (push) Successful in 9m0s
docker / deploy-docs (push) Successful in 29s
deb / build-publish (push) Successful in 13m5s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 2m44s
arch / build-publish (push) Successful in 15m16s
android / android (push) Successful in 16m2s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 2m35s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 12m51s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m24s
ci / rust (push) Successful in 22m20s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m22s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 1m25s
release / apple (push) Successful in 24m23s
apple / screenshots (push) Successful in 19m17s
Standalone sweep to probe the ~500 Mbps throughput wall (transport vs encoder CBR undershoot); built and validated, no runtime coupling. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
840e5d590e |
fix(host/linux): free a desktop-session Steam before a dedicated gamescope launch
B1b: a Steam running in a plain GNOME/KDE desktop session holds Steam's single instance, so a dedicated gamescope launch's own Steam exits at birth — the game-library launch goes to a black screen. Release the desktop instance (free_desktop_steam) on Steam launches before creating the managed session. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
d58524c899 |
feat(client): opt-in "Rumble on this phone" mirrors pad-0 rumble onto the device
iOS + Android: a new opt-in setting mirrors controller 1's rumble onto the device's own actuator (Apple RumbleRenderer Actuator.device / CoreHaptics, Android deviceBodyVibrator), so a motor-less clip-on pad still gives haptic feedback through the phone/tablet it's clamped to. Default off; wired through the gamepad settings on both platforms. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
6db91cbf40 |
feat(client): 3-finger swipe toggles the on-screen keyboard mid-stream
iOS + Android: a three-finger vertical swipe up/down summons/dismisses the device soft keyboard while streaming (trackpad + pointer modes). Mobile scroll is now exactly two fingers so it never collides with the 3+-finger gesture (3+ only fell into the old `>= 2` scroll path by accident). Android: a TYPE_NULL KeyCaptureView plus IME meta-shift wrapping feeds key events through. iOS: UIKeyInput plus a SoftKeyMap char->VK table with a GCKeyboard dup gate so a hardware keyboard and the soft keyboard don't double-emit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
60d4653083 |
feat(decky): native-touch controller layout + restructured shortcuts + artwork
Ship a Steam Input controller layout (controller_config/punktfunk.vdf) whose always-on `ts_n` command enables native touchscreen delivery on the Deck, and have the backend auto-install it (apply_controller_config: copy to controller_base/templates + upsert the per-account configset entry, chown to the user, back up first). This is what makes the Deck touchscreen reach the client as native touch under gamescope without disabling Steam Input (impossible on the Deck) — no manual controller setup. Two shortcuts sharing the "Punktfunk" name (so one config key covers both): a hidden stateful stream entry and a visible stateless entry that launches straight into the gamepad UI. Both get full artwork (grid/gridwide/hero/logo/icon, replaced with exported PNGs). Drop the art-generation script. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
927a571414 |
feat(console): touch-mode setting + request-access pairing + polish
Extend the gamepad/console shell (pf-console-ui) to parity with the other clients: - Settings gain a Touchscreen → Touch mode row (Trackpad / Direct pointer / Touch passthrough), the one couch-relevant Settings field the screen lacked. - The pair screen adds the no-PIN delegated-approval path: a "Request access" action (only when the host advertises a fingerprint to pin) opens a connect the host PARKS until the operator approves this device, then persists it as paired. A role-based row model keeps the cursor off stale indices; manual hosts stay PIN-only, matching the desktop shells. - Threads request_access through OverlayAction::Launch and ConnectIntent; the shell shows a "Waiting for approval…" takeover, and the session binary parks on a 185 s budget (PendingApproval → persist-as-paired via on_connected). Auto-wake (WoL) was already implemented end-to-end and is left as-is. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
f3b6ccaa7f |
fix(gamepad/windows): Steam-accepted Deck unit serial un-mangles the controller name
Steam validates the Deck unit serial's format before accepting it. Our
"PFDK..." serial was REJECTED ("Invalid or missing unit serial number"), so
Steam substituted a hash identity and mangled the displayed name to
"Steam Deck Controllerggg" on every host tested. An 'F'-leading serial passes,
so switch to "FVPF..." — keeps the PunktFunk marker one slot in, still distinct
from a real Deck's "FVZZ..." for the Linux self-detection in
physical_steam_controller_present(). The name now shows a clean "Steam Deck
Controller" with a serial-derived handle (verified on .173).
Also fix the UMDF driver's 0xAE GET_STRING_ATTRIBUTE handler to echo the
requested attribute id faithfully instead of collapsing board-serial (0x00)
requests to unit-serial (0x01). Steam still logs a benign "Deck Controller PCB
Serial# invalid" for the board serial — it validates that against a
Valve-internal format for ANY value, including an empty one (verified) — but
that line does not mangle the name, change the handle, or block promotion.
Applied to both transports: host inject/proto/steam_proto.rs::deck_serial
(Linux gadget/usbip) and the pf-dualsense UMDF driver (Windows), which mirror
each other's serial format.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
d8e8529cd7 |
feat(gamepad): Windows Steam Deck backend — Steam-Input-promoted UMDF virtual Deck
windows-drivers / probe-and-proto (push) Successful in 18s
windows / build (aarch64-pc-windows-msvc) (push) Has been cancelled
windows / build (x86_64-pc-windows-msvc) (push) Has been cancelled
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Has been cancelled
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Has been cancelled
windows-host / package (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
release / apple (push) Has been cancelled
flatpak / build-publish (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
decky / build-publish (push) Has been cancelled
deb / build-publish (push) Has been cancelled
ci / web (push) Successful in 51s
windows-drivers / driver-build (push) Successful in 1m51s
ci / docs-site (push) Successful in 54s
ci / bench (push) Successful in 5m20s
arch / build-publish (push) Successful in 13m32s
android / android (push) Successful in 15m7s
ci / rust (push) Successful in 21m11s
apple / swift (push) Successful in 4m59s
apple / screenshots (push) Successful in 20m53s
The N4 GO verdict, productized. GamepadPref::SteamDeck on a Windows host now builds a real virtual Deck instead of folding to DualSense: games get native Deck glyphs + both trackpads + gyro + all four back grips through Steam Input's own remapping. - steam_deck_windows.rs: DeckWinPad/DeckWinProto/SteamDeckWindowsManager over the sealed shm channel, sharing the whole Linux Deck codec (steam_proto now compiles on Windows too — it was already pure). The SwDevice identity carries usb_mi: Some(2): the &MI_02 hardware-id token hidclass mirrors into the HID child and Steam parses as the wired controller interface — the promotion gate. - Driver: DEVTYPE_STEAMDECK (3) graduates from the spike — SET_FEATURE 0xEB rumble / 0x8F haptic pulses are republished to the host through the output slot (report-id-0 prefixed, so parse_steam_output sees the Linux wire shape), and the 0xAE/GET_STRING serial + 0x83 unit id are per-pad (read from the section's pad_index; PFDK<unit-id> matches steam_proto::deck_serial). - Router: SteamDeck arms in the Windows Pads paths; pick_gamepad flips SteamDeck-if-windows -> SteamDeck (the DualSense fold retires); dualsense-windows-test grows --deck. ON-GLASS VALIDATED on .173 (rebuilt signed driver 9.9.0714.12xx installed, Steam live): the manager-created pad (index 1) enumerates with per-pad serial PFDK50460001, Steam logs Interface: 2 -> '!! Steam controller device opened' -> 'Steam Controller reserving XInput slot 0' -> PollState 2 (actively polling our cycling input frames) -> mapping activated; clean teardown on exit. Rumble round-trip through a real game remains an on-glass debt (nothing sent 0xEB during the idle hold). Known gap vs Linux: no physical-Steam-controller conflict degrade on Windows yet (degrade_steam_on_conflict is Linux-only — /sys scan); a Windows equivalent needs SetupDi enumeration and is deferred. Verified: .21 clippy -D warnings + 304/0 tests + fmt --all; .133 clippy -D warnings + the WDK driver-workspace check. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
4201851c7f |
fix(fmt) + feat(gamepad): CI-matching rustfmt everywhere, enforced by repo git hooks; N4 spike flips to GO via MI_02
windows / build (aarch64-pc-windows-msvc) (push) Has been cancelled
windows / build (x86_64-pc-windows-msvc) (push) Has been cancelled
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Has been cancelled
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Has been cancelled
windows-host / package (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
flatpak / build-publish (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
decky / build-publish (push) Has been cancelled
deb / build-publish (push) Has been cancelled
ci / rust (push) Has been cancelled
ci / web (push) Has been cancelled
ci / docs-site (push) Has been cancelled
ci / bench (push) Has been cancelled
arch / build-publish (push) Has been cancelled
apple / swift (push) Has been cancelled
apple / screenshots (push) Has been cancelled
android / android (push) Has been cancelled
Three things that belong together:
1. rustfmt the gamepad-new-types host files ci.yml's `cargo fmt --all
--check` gate flags (the .21/.133 verify recipes ran clippy+tests
but never fmt — the same class of miss as
|
||
|
|
eb4bca11c5 |
feat(android): Switch 2 Pro Controller + Joy-Con 2 pair declare SwitchPro
ci / rust (push) Failing after 42s
ci / web (push) Successful in 53s
apple / swift (push) Successful in 4m31s
ci / docs-site (push) Successful in 59s
decky / build-publish (push) Successful in 19s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 9s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7s
ci / bench (push) Successful in 5m19s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 6m40s
docker / deploy-docs (push) Successful in 10s
android / android (push) Successful in 15m28s
arch / build-publish (push) Successful in 13m31s
deb / build-publish (push) Successful in 13m55s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 13m52s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m38s
apple / screenshots (push) Successful in 19m37s
057E:2069 (Pro Controller 2) and 057E:2068 (Joy-Con 2 pair) are the same full pad surface as the OG Pro and ride the same virtual hid-nintendo pad. Mirrors SDL, which folds both to its public NINTENDO_SWITCH_PRO type (the SDL clients bundle 3.4.10, whose switch2 hidapi driver already covers them end to end incl. gyro + GL/GR paddles-as-paddle-buttons). :kit Kotlin compile green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
69f30f30b6 |
style(pf-dualsense): rustfmt the N4-spike additions (CI fmt gate)
windows-drivers / probe-and-proto (push) Successful in 18s
windows-drivers / driver-build (push) Successful in 1m37s
windows-host / package (push) Successful in 9m1s
ci / rust (push) Failing after 40s
ci / web (push) Successful in 55s
ci / docs-site (push) Successful in 1m7s
decky / build-publish (push) Successful in 24s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10s
arch / build-publish (push) Successful in 10m21s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 9s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 7s
ci / bench (push) Successful in 5m20s
android / android (push) Successful in 16m58s
apple / swift (push) Successful in 4m31s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7m19s
deb / build-publish (push) Successful in 11m39s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m8s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 16m27s
docker / deploy-docs (push) Successful in 10s
apple / screenshots (push) Successful in 20m45s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
f7356d0820 |
Merge branch 'fix/android-tv-implied-features': Play TV compatibility
deb / build-publish (push) Has been cancelled
ci / rust (push) Failing after 42s
decky / build-publish (push) Successful in 27s
ci / web (push) Successful in 1m0s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 9s
ci / docs-site (push) Successful in 1m2s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 16s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 17s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 13s
ci / bench (push) Successful in 5m24s
arch / build-publish (push) Successful in 11m39s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 11m25s
apple / swift (push) Successful in 4m34s
android / android (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 19m55s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 19m58s
docker / deploy-docs (push) Successful in 25s
apple / screenshots (push) Successful in 18m6s
RECORD_AUDIO / Wi-Fi-state permissions implied hard microphone + wifi requirements, filtering mic-less TVs (reported: Philips OLED707) and ethernet-only boxes as "not compatible" on Play; both are optional at runtime and now declared required=false (aapt2-verified). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
51cdaea3f3 |
Merge branch 'feat/gamepad-new-types': DualSense Edge + Switch Pro + classic SC virtual pads
windows-drivers / probe-and-proto (push) Successful in 41s
ci / rust (push) Failing after 1m2s
ci / docs-site (push) Successful in 1m0s
ci / web (push) Successful in 1m8s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 9s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 14s
decky / build-publish (push) Successful in 29s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 44s
windows-drivers / driver-build (push) Failing after 1m31s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 48s
apple / swift (push) Successful in 4m29s
ci / bench (push) Successful in 6m29s
docker / deploy-docs (push) Successful in 27s
arch / build-publish (push) Has been cancelled
deb / build-publish (push) Has been cancelled
flatpak / build-publish (push) Has been cancelled
release / apple (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
android / android (push) Has been cancelled
apple / screenshots (push) Has been cancelled
windows-host / package (push) Has been cancelled
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Has been cancelled
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Has been cancelled
windows / build (aarch64-pc-windows-msvc) (push) Has been cancelled
windows / build (x86_64-pc-windows-msvc) (push) Has been cancelled
gamepad-new-types plan, all phases (7 commits, hashes preserved): Phase 0 wire bytes 7/8; N1 DualSense Edge (Linux UHID + Windows UMDF device_type 2 — all four wire paddles on native back/Fn slots); N2 Switch Pro (Linux UHID, full hid-nintendo probe conversation canned); N3 classic Steam Controller (reserved slot 5 live, UHID); N4 Windows-Deck spike -> NO-GO documented (Steam wants interface 2, a software devnode reads as 0); SDL/Apple/Android kind pickers. Verified per commit: .21 clippy -D warnings + 304/0 host tests + headless bind/probe/evdev smokes for all three new backends; .133 clippy -D warnings + WDK driver-workspace check. On-glass on .173: Windows Edge identity confirmed live by Steam (HIDAPI claim as 054c:0df2) with the rebuilt signed driver (9.9.0714.1141) staged. Remaining physical-pad debts tracked in the plan doc. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
ea2e3578e2 |
feat(gamepad): dualsense-windows-test grows --edge (drives device_type 2, cycles R4/L4)
Used for the .173 on-glass verify: the Edge devnode enumerates (SWD\PUNKTFUNK\PF_EDGE_1, driver pf_dualsenseedge attaches, proto 2), and Steam's live controller.txt confirms the identity end to end — 'type: 054c 0df2', 'Product: DualSense Edge Wireless Controller', 'Controller using HIDAPI driver, vid=0x054c, pid=0x0df2' — with probe lightbar/player-LED feedback flowing back on the 0xCD plane. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
8d8168b0e0 |
feat(gamepad): N4 spike kit — software-devnode Steam Deck probe for Windows
The gamepad-new-types §6 go/no-go rig, ready to run the moment .173 is back (the box is currently down, so the observation itself is still owed): does Steam Input on Windows promote a software-devnode HID Deck (28DE:1205), or does it need a real USB bus identity (the documented GameInput instance-path gap — the Linux 'Interface: -1' lesson)? - Driver: scratch device_type=3 serves the Deck identity — the captured 38-byte controller-interface descriptor, 28DE:1205 attributes, Valve strings, the Deck neutral frame, and the Steam 0x83/0xAE feature contract (SET_FEATURE latches the command, GET_FEATURE answers it — attribute blob + unit serial mirroring steam_proto::feature_reply). Never stamped by a session. INF gains pf_steamdeck. - Host: deck_spike_hold() + the `deck-windows-spike` subcommand — stamps devtype 3, spawns the devnode under VID_28DE&PID_1205, streams the neutral frame, prints what to observe (Steam logs/controller.txt, controller settings) and logs any output reports Steam writes. Run recipe (on .173, once the updated signed driver is staged): install driver, start Steam, `punktfunk-host.exe deck-windows-spike`, watch controller.txt. GO -> plan a proper N4 phase (the Deck codec is already shared); NO-GO -> document next to the Linux Interface:-1 note and keep the SteamDeck->DualSense Windows fold. Verified: .133 clippy -D warnings + the driver workspace cargo check (WDK) both green; .21 clippy + 304/0 tests unaffected. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
61c752e91e |
feat(gamepad): Apple + Android pickers declare DualSense Edge / Switch Pro
Plan 0.4 for the N1/N2 backends (SDL landed with them): - Apple: GamepadType grows dualSenseEdge=7 / switchPro=8 (wire-byte parity + name parsing). padKind splits the Edge out of the shared GCDualSenseGamepad subclass by product category, and resolves Switch Pro / a paired Joy-Con set by category (GameController has no Nintendo subclass; single Joy-Cons stay on the Xbox 360 fallback — half a pad). The DualSense-only gates (adaptive-trigger feedback, player LEDs, the touchpad+motion rich capture) now include the Edge — same surfaces. Paddle CAPTURE stays gated on G22 (needs a real pad to pin the paddleButton1..4 correspondence); the declared identity is right meanwhile. swift build + 124 tests green. - Android: PREF_DUALSENSEEDGE/PREF_SWITCHPRO wire bytes; the Sony PID table splits 0x0DF2 (Edge) out of DualSense; Nintendo 057E:2009 declares Switch Pro; ControllersScreen labels the new kinds. :kit/:app Kotlin compile green (-PskipRustBuild). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
8c854e0a19 |
feat(gamepad): classic Steam Controller backend — Linux UHID via hid-steam (N3)
The reserved GamepadPref::SteamController = 5 slot goes live: the same hid-steam driver under the wired-SC identity (28DE:1102, ID_CONTROLLER_STATE), UHID-only in v1 (no captured SC USB interface layout, so no Steam-Input promotion — the pre-usbip Deck state; acceptable for discontinued hardware). Layout pinned against the kernel's ID_CONTROLLER_STATE table: 24-bit buttons at 8..11 (low bits shared with the Deck; grips at 9.7/10.0 = the Deck's L5/R5 positions; right-pad click 10.2; joystick click 10.6), u8 triggers at 11/12, the joystick/left-pad MULTIPLEX at 16..20 (a left-pad contact shadows the stick, like real hardware's lpad_touched flag), right pad at 20..24. Mapping: wire left stick -> SC stick; wire right stick -> right-pad coords + touched bit (the SC's camera surface — the second-stick loss is inherent); PADDLE1/2 -> the two grips (natively, masked out of the fold input); PADDLE3/4 + MISC1 -> the remap policy. The SC parser has NO gamepad_mode gate, so no mode-entry pulse. SteamDeckPad grew a SteamModel (open_model); ScProto/SteamCtrlManager; pick_gamepad flips SteamController -> itself on Linux (replacing the Xbox360 fold); SDL picker splits Valve PIDs (Deck 1205 stays SteamDeck, SC 1102/1142 now declare SteamController). Verified: .21 clippy -D warnings + 304/0 tests + on-box UHID smoke (hid-steam binds 1102, BTN_A + right-pad ABS_RX land on evdev, no mode pulse); .133 clippy -D warnings green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
70a74b0d7c |
feat(gamepad): Switch Pro backend — Linux UHID via hid-nintendo (N2)
A virtual Pro Controller (057E:2009, BUS_USB, verbatim 203-byte USB
descriptor triple-cross-checked from real-device captures) bound by
hid-nintendo (>= 5.16): Nintendo-family client pads get correct glyphs +
POSITIONAL layout (wire south/east/west/north -> Switch B/A/Y/X, so the
physical-position <-> glyph relationship survives), live gyro/accel, and
HD-rumble feedback — instead of folding to Xbox360 (mirrored A/B + X/Y,
no motion).
- switch_proto: report-0x30/0x21/0x81 codec + the entire canned probe
conversation, pinned line-by-line against hid-nintendo.c: 0x80-family
USB acks, device info (type 0x03 + per-pad MAC), SPI-flash calibration
blobs (user magics ABSENT -> factory path; sticks 2048 +/- 1400 with
the left/right byte-order difference; IMU offsets 0 + the driver's own
default scales so raw units pass 1:1), rumble amplitude decode through
the driver's inverted joycon_rumble_amplitudes table, player lights ->
0xCD PlayerLeds. 11 new pin tests.
- switch_pro: UHID backend answering the probe from the manager's
service pass; SwitchProManager = UhidManager<SwitchProProto> (the 8 ms
heartbeat doubles as the steady 0x30 stream the driver's post-probe
rate limiter wants). switchpro-test CLI smoke.
- Router/fold: SwitchPro arms; pick_gamepad SwitchPro -> itself on Linux;
degrade_if_no_uhid covers it. SDL picker: NintendoSwitchPro + JoyconPair
declare SwitchPro.
Headless-validated on .21 (hid-nintendo 7.1): probe completes ('using
factory cal' for sticks + IMU, player-1 LED round-trips to the 0xCD
plane), gamepad + IMU input devices created, and an evdev capture pins
the positional swap (wire A/B -> BTN_SOUTH/BTN_EAST) + full-range stick
scaling. .21 clippy -D warnings + 303/0 tests; .133 clippy -D warnings.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
41be73fbc6 |
fix(android): declare microphone + wifi features optional for Play TV filtering
RECORD_AUDIO implies android.hardware.microphone required=true and the Wi-Fi state permissions imply android.hardware.wifi required=true unless declared otherwise, so Google Play filtered the app as "not compatible" on TVs that declare no microphone (reported on a Philips 65OLED707/12, Android TV 11, closed-testing track) and would do the same on ethernet-only boxes. Both capabilities are optional at runtime: the mic uplink is runtime-requested and the Wi-Fi locks are best-effort hedges. Verified via aapt2 dump badging: microphone + wifi now report uses-feature-not-required and no implied hard requirements remain. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
1830e095f8 |
feat(gamepad): DualSense Edge backend — Linux UHID + Windows UMDF (N1)
The plain-DualSense transport + report codec under the Edge USB identity (054C:0DF2, verbatim 389-byte real-device descriptor cross-checked against the raw usbmon capture + hhd's production virtual Edge), so the wire back grips (BTN_PADDLE1..4: Deck L4/L5/R4/R5, Elite P1-P4) land on the Edge's NATIVE buttons[2] bits instead of the fold/drop policy: PADDLE1/2 -> the right/left back buttons, PADDLE3/4 -> the right/left Fn buttons (kernel BTN_TRIGGER_HAPPY1..4 on >= 7.2; SDL/Steam read hidraw on any kernel). - proto: Edge descriptor + btn2 bits + edge_paddle_bits(), pinned against hid-playstation DS_EDGE_BUTTONS_* and SDL_hidapi_ps5 (tests). - Linux: DsUhidIdentity parameterizes the UHID create; DsEdgeLinuxProto / DualSenseEdgeManager. Headless-validated on .21 (7.1): driver=playstation binds 0DF2, all 4 input devices created, probe lightbar/player-LED feedback round-trips; dualsense-test grew --edge (cycles all 4 paddles). - Windows: UMDF driver serves device_type=2 (Edge descriptor/attrs/strings, DS feature blobs); WinDsIdentity parameterizes the SwDevice profile + devtype stamp; DsEdgeWinProto / DualSenseEdgeWindowsManager; INF gains pf_dualsenseedge. Driver change => resign + reinstall before on-glass. - Router: DualSenseEdge arms in route_handle/apply_rich/pump/heartbeat; pick_gamepad folds Edge -> itself on linux||windows; degrade_if_no_uhid covers it. - Client (SDL): 054C:0DF2 declares DualSenseEdge (no distinct SDL type); Edge physical pads take the raw DS5 effects path; console-UI glyphs = Shapes. Apple/Android pickers follow separately. Verified: .21 clippy -D warnings + 292/0 host tests + on-box UHID bind smoke; .133 clippy pending in this push. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
45bde370e2 |
feat(gamepad): GamepadPref wire bytes for DualSense Edge (7) + Switch Pro (8)
Phase 0 of gamepad-new-types: the two new kinds exist on the wire (enum, to_u8/from_u8/from_name/as_str, C-ABI constants + header), and pick_gamepad folds them to the closest EXISTING backend until their own backends land — DualSenseEdge -> DualSense (keeps the rich planes; only the paddles go through the fold policy), SwitchPro -> Xbox360. Wire round-trip pinned 0..=8 + unknown->Auto; fold table extended. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
57d89217fb |
Merge branch 'gamepad-g12-skeleton': G12/3.3 UhidManager skeleton extraction
ci / web (push) Successful in 43s
ci / docs-site (push) Successful in 1m19s
apple / swift (push) Successful in 4m28s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 12s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 9s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 12s
decky / build-publish (push) Successful in 38s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 14s
ci / bench (push) Successful in 6m20s
arch / build-publish (push) Successful in 11m25s
deb / build-publish (push) Successful in 13m3s
windows-host / package (push) Successful in 14m33s
android / android (push) Successful in 15m23s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m14s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 15m39s
ci / rust (push) Successful in 22m7s
apple / screenshots (push) Successful in 19m33s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 8s
docker / deploy-docs (push) Successful in 23s
The deferred Phase 3.3 of the gamepad review (gamepad-review-cleanup.md §3a): the seven virtual-pad managers' copy-pasted lifecycle (slot table, active_mask unplug sweep, gate-checked create, rumble/hidout dedup, heartbeat) extracted into shared PadSlots<P> + PadProto/UhidManager<B>; each backend now supplies only its protocol half via a type alias, with zero Pads-router edits. Includes the 3.3.0 pre-step fixing the drifted Linux DS4 backend (rich-plane pad clicks + the Steam left pad were dead on the DS4 kind). 10 commits, each verified as it landed: Linux .21 clippy -D warnings + full host suite 290 pass / 0 fail + fmt; Windows CI VM .133 clippy --all-targets -D warnings EXITCODE 0. On-glass kind-cycling smoke (one real pad per platform) still owed post-merge. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
650acda334 |
chore(inject): post-extraction sweep (3.3)
Drop the vestigial Ds4Feedback.hidout field (parse_ds4_output never filled it and neither DS4 manager read it — the lightbar rides the led field, now converted to a HidOutput::Led by the protos) and its now-unused HidOutput import; refresh the pad_gate module doc (managers now drive it via pad_slots). Verified: .21 clippy --all-targets -D warnings + full suite 290 pass / 0 fail + cargo fmt --check clean; .133 clippy --all-targets -D warnings EXITCODE 0. Part of G12/3.3 (§3a.4 commit 10) — extraction complete. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
89aa52bc58 |
refactor(inject): uinput + XUSB managers onto PadSlots (3.3)
The two stateless backends keep their structs and special pumps (uinput
FF-effect mixing via pump_ff/last_mix; the XUSB stale-residual
RUMBLE_IDLE_TIMEOUT force-off) but delegate slot lifecycle — table,
unplug sweep, gate-checked create — to the shared PadSlots. XUSB resets
last_rumble/last_active on the swept indices and on fresh create exactly
as before (the G10/G16-adjacent semantics untouched).
Two accepted deltas, both flagged in the plan (§3a): the uinput
arrival/unplug log lines gain the pad-identity label every other backend
already has ("controller arrival (X-Box 360 pad)"), and XUSB's
f.index.max(0) clamp is replaced by the bounds check every other manager
uses — a negative wire index is now dropped instead of being treated as
pad 0.
Verified: .21 clippy --all-targets -D warnings clean + full suite 290
pass / 0 fail (uinput); .133 clippy --all-targets -D warnings EXITCODE 0
(XUSB).
Part of G12/3.3 (§3a.4 commit 9) — all seven managers now share the
PadSlots lifecycle.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
384fc30833 |
refactor(inject/linux/steam_controller): convert to UhidManager<SteamProto> (3.3)
The most hook-laden conversion: SteamControllerManager becomes a pub type alias of UhidManager<SteamProto>. The Steam-specific pieces map cleanly onto the trait — open() delegates to open_transport (usbip → gadget → UHID fallback, which keeps its own per-transport logging, so no extra success line, matching the old ensure), merge_frame preserves the trackpad coords/touch-bits/clicks + motion across button-only frames (the G2 fix, verbatim), and the gamepad-mode-entry pulse rides the force_heartbeat hook. DeckTransport goes pub (type Pad in a public-trait impl). Also un-fuses a doc-comment glitch where the manager's doc had been merged onto the DeckTransport enum. Verified on .21: clippy --all-targets -D warnings clean; full suite 290 pass / 0 fail. Part of G12/3.3 (§3a.4 commit 8) — all five stateful managers now share one skeleton. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
365d4bb8f1 |
refactor(inject/linux/dualshock4): convert to UhidManager<Ds4LinuxProto> (3.3)
DualShock4Manager becomes a pub type alias of UhidManager<Ds4LinuxProto> (the same shape as the other three DS-family conversions); the bespoke last_led lightbar dedup folds into the shared HidoutDedup exactly as the Windows DS4 conversion did. With 3.3.0 already applied, the proto half is byte-identical to Ds4WinProto except the transport open — the codec, the mappers, and now the manager all shared. Verified on .21: clippy --all-targets -D warnings clean; full suite 290 pass / 0 fail. Part of G12/3.3 (§3a.4 commit 7). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
f1efd3091e |
refactor(inject/windows/dualshock4): convert to UhidManager<Ds4WinProto> (3.3)
DualShock4WindowsManager becomes a pub type alias of UhidManager<Ds4WinProto>. The bespoke last_led lightbar dedup folds into the shared HidoutDedup: the proto's service() converts Ds4Feedback.led into a HidOutput::Led, and HidoutDedup compares it against the last-forwarded value with the same reset-on-create/unplug semantics the Option<(u8,u8,u8)> vec had. Everything else mirrors the DualSense conversion (same DsState mappers as linux/dualshock4.rs). Ds4WinPad goes pub (type Pad in a public-trait impl, E0446 otherwise). Verified on the Windows CI VM .133: cargo clippy -p punktfunk-host --all-targets -- -D warnings EXITCODE 0 at this tip. Part of G12/3.3 (§3a.4 commit 6). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
446818eea6 |
refactor(inject/windows/dualsense): convert to UhidManager<DsWinProto> (3.3)
DualSenseWindowsManager becomes a pub type alias of UhidManager<DsWinProto>; the proto supplies the UMDF sealed-channel open (+ success log), the DsState mappers (identical to linux/dualsense.rs, paddle fold included), and the section feedback poll. Lifecycle, dedup, and heartbeat come from the shared skeleton — behavior-identical, same log lines (LABEL DualSense/Windows + the driver-install hint). DsWinPad goes pub (it appears as type Pad in the impl of the public PadProto trait — E0446 otherwise; the Linux pads were already pub). Verified on the Windows CI VM .133 (same pinned 1.96.0 MSVC toolchain + Public-path FFmpeg/LLVM the runner uses): cargo clippy -p punktfunk-host --all-targets -- -D warnings EXITCODE 0 at the DS4-conversion tip (.173 was down; .133 carries the identical toolchain). Part of G12/3.3 (§3a.4 commit 5). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
4d6c2394dc |
refactor(inject/linux/dualsense): convert to UhidManager<DsLinuxProto> (3.3)
The first backend onto the shared skeleton: DualSenseManager becomes pub type DualSenseManager = UhidManager<DsLinuxProto>, where DsLinuxProto supplies only the protocol half (UHID open + success log, DsState neutral/merge/apply_rich with the paddle fold, best-effort write, the GET_REPORT-answering service pass). handle/apply_rich/heartbeat/pump and the unplug sweep now come from uhid_manager — behavior-identical (same log lines, same dedup + reset semantics), zero Pads-router edits. Verified on .21: clippy --all-targets -D warnings clean; full suite 290 pass / 0 fail. Part of G12/3.3 (§3a.4 commit 4). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
2bea02b0ea |
feat(inject): generic PadProto + UhidManager<B> stateful manager (3.3 layer 2)
The shared skeleton of the five stateful UHID/UMDF managers (Linux DualSense / DualShock 4 / Steam Deck, Windows DualSense / DualShock 4), written once over PadSlots: event routing with the unplug sweep and was-the-unplug early return, the merge-preserving frame fold, rich-input application, the silence heartbeat (with a backend force hook for the Steam mode-entry pulse), and the feedback pump with rumble dedup + HidoutDedup. A backend supplies only its per-controller half via PadProto: open / neutral / merge_frame / apply_rich / write_state / service — exactly where the real protocol differences live. Method surface (new/handle/apply_rich/pump/heartbeat) matches what the punktfunk1.rs Pads router already drives, so each backend will convert as a pub type alias with zero router edits. Additive only — no backend converted yet. 8 mock-backend tests make the manager lifecycle unit-testable for the first time; G2 (rich fields survive a button-only frame) and G10 (Arrival eager-creates) are now generic regression tests, plus removal-frame no-recreate, absent-pad rich drop, create-backoff state tracking, rumble/hidout dedup + re-arm on recreate, and heartbeat gap/force semantics. Verified on .21: clippy --all-targets -D warnings clean; suite 293 pass / 0 fail (285 prior + 8 new). Part of G12/3.3 (gamepad-review-cleanup.md §3a.3, commit 3 of the §3a.4 sequence). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
528a51d75c |
feat(inject): shared PadSlots<P> slot table + lifecycle (3.3 layer 1)
The Vec<Option<Pad>> slot table, active_mask unplug sweep, and PadGate- checked create that all seven backend managers copy-paste, extracted into one unit-tested inject/pad_slots.rs (cfg any(linux,windows), like pad_gate). sweep() returns the swept indices as a bitmask and ensure() returns fresh-create, so managers reset their per-index sibling state (state / last_rumble / dedup / clocks) without closure gymnastics. Lifecycle log lines are label/device/hint-parameterized to stay byte-identical per backend; open() keeps the success line (it knows the transport detail). Additive only — no manager converted yet; first unit coverage for the sweep/create lifecycle (5 tests: freshness, sweep-once semantics, gate integration, recreate, pump iteration). Verified on .21: clippy --all-targets -D warnings clean; suite 285 pass / 0 fail (280 prior + 5 new). Part of G12/3.3 (gamepad-review-cleanup.md §3a.3, commit 2 of the §3a.4 sequence). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
b597bb74bd |
fix(inject/linux/ds4): fold the Linux DS4 backend onto the shared proto codec (3.3.0)
The Linux DualShock 4 backend missed the G2-era shared-mapping work and drifted from dualshock4_proto three ways, leaving two user-visible gaps on the DS4 kind (Windows, written later against the proto, is correct): - its serialize_state duplicated the proto's byte-for-byte EXCEPT byte 7: raw st.buttons[2] instead of buttons2_with_click(), so a rich-plane pad click never reached the report; - its inline apply_rich never set touch_click and dropped the Steam LEFT pad entirely (surface 1 skipped), where the shared dualsense_proto::DsState::apply_rich splits the one touchpad left/right; - handle() didn't preserve touch_click across button-only frames. Net effect: Deck client -> Linux host on the DS4 kind = pad clicks and the left pad dead. Delete the local serialize_state/parse_ds4_output/Ds4Feedback/pack_touch and touch-dim consts in favor of dualshock4_proto (dropping the proto's keep-in-sync FIXME), route rich events through the shared DsState::apply_rich, and preserve touch_click in the frame merge exactly like the other three DS-family managers. The proto's serialize_offsets test gains a touch_click case pinning byte 7 bit 1. Verified on .21: cargo clippy -p punktfunk-host --all-targets -D warnings clean; full suite 277 pass / 0 fail. Pre-step 3.3.0 of the G12 skeleton extraction (gamepad-review-cleanup.md §3a.2) — the behavior fix lands before the mechanical dedup. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
49533ff90a |
style(touch): rustfmt the presenter finger dispatch + gesture engine
ci / web (push) Successful in 52s
ci / docs-site (push) Successful in 1m5s
apple / swift (push) Successful in 4m33s
ci / bench (push) Successful in 5m22s
android-screenshots / screenshots (push) Successful in 3m30s
ci / rust (push) Successful in 23m9s
decky / build-publish (push) Successful in 1m23s
android / android (push) Successful in 12m54s
arch / build-publish (push) Successful in 13m16s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 55s
web-screenshots / screenshots (push) Successful in 2m51s
docker / deploy-docs (push) Successful in 9s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 28s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 23s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 24s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 30s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 30s
flatpak / build-publish (push) Successful in 7m4s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 1m19s
linux-client-screenshots / screenshots (push) Successful in 7m45s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 14m47s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m47s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m51s
deb / build-publish (push) Successful in 12m5s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 4m2s
apple / screenshots (push) Successful in 19m24s
windows-host / package (push) Successful in 9m19s
release / apple (push) Successful in 27m34s
Wrap the long dispatch_finger call args, Abs struct literals, and Act::Button/ Scroll/MoveRel pushes per rustfmt (the CI fmt check on pf-presenter). No behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>v0.10.1 |
||
|
|
1b890ae919 |
chore(release): bump workspace version to 0.10.1
android-screenshots / screenshots (push) Has been cancelled
apple / swift (push) Has been cancelled
apple / screenshots (push) Has been cancelled
audit / bun-audit (push) Successful in 10s
audit / cargo-audit (push) Has been cancelled
ci / rust (push) Failing after 40s
ci / docs-site (push) Successful in 48s
ci / web (push) Successful in 51s
decky / build-publish (push) Successful in 16s
ci / bench (push) Successful in 5m12s
linux-client-screenshots / screenshots (push) Successful in 8m48s
flatpak / build-publish (push) Successful in 6m17s
arch / build-publish (push) Successful in 12m42s
release / apple (push) Has been cancelled
deb / build-publish (push) Has been cancelled
web-screenshots / screenshots (push) Successful in 2m51s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m58s
windows-host / package (push) Successful in 13m48s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m54s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 17m33s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 2m16s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 4m50s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 5m41s
android / android (push) Failing after 15m19s
docker / deploy-docs (push) Successful in 25s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 10s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 6m6s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 9s
Bumps [workspace.package] version 0.10.0 -> 0.10.1 (14 workspace crates) and syncs Cargo.lock (versions-only). Apple MARKETING_VERSION / Android versionName are set from the release tag by CI, so no client manifest changes; the nested Windows-driver workspace keeps its independent 0.0.1 version. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
f88d0ae4dc |
feat(touch): cross-client touch-input modes on Linux + Windows
ci / web (push) Successful in 43s
ci / rust (push) Failing after 53s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
decky / build-publish (push) Successful in 16s
ci / docs-site (push) Successful in 1m5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 7s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 6s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 8s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m41s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m53s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 52s
apple / swift (push) Successful in 4m41s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 54s
ci / bench (push) Successful in 6m30s
docker / deploy-docs (push) Successful in 23s
flatpak / build-publish (push) Failing after 8m9s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
android / android (push) Has been cancelled
apple / screenshots (push) Has been cancelled
arch / build-publish (push) Has been cancelled
deb / build-publish (push) Has been cancelled
Bring the SDL presenter (Linux/Deck + Windows) to parity with the Android and
Apple clients: a persisted TouchMode selects how a touchscreen drives the host —
* Trackpad (default): relative cursor with pointer ballistics + the shared
gesture vocabulary (tap = left click, two-finger tap = right click,
two-finger drag = scroll, tap-then-drag = held left drag, three-finger tap =
cycle the stats overlay).
* Direct pointer: the cursor jumps to and follows the finger (absolute).
* Touch passthrough: every finger is a real host touchscreen contact.
Previously the presenter had no finger handling, so SDL synthesized mouse events
from touch and — under the stream's relative-mouse lock — walked the host cursor
into the corner (the reported Deck bug). SDL touch->mouse synthesis is now off;
DIRECT touchscreens route through a new incremental gesture engine (a port of
Android TouchInput.kt / Apple TouchMouse.swift), while INDIRECT trackpads keep
driving the mouse. Fingers map through the aspect-fit letterbox onto the content
rect.
TouchMode lives in the shared trust::Settings (default trackpad, so passthrough
is opt-in like the other clients); the GTK and WinUI settings screens both gained
a "Touch input" picker. Gesture engine, letterbox mapping, and settings
back-compat are unit-tested (28 tests green); clippy -D warnings clean; full
Linux client + session build verified on-host.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
94802795e7 |
Merge branch 'gamepad-apple-cleanup': cross-client + host gamepad review cleanup (G1–G25)
audit / bun-audit (push) Successful in 13s
ci / docs-site (push) Successful in 49s
ci / web (push) Successful in 53s
decky / build-publish (push) Successful in 21s
audit / cargo-audit (push) Successful in 2m27s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 41s
apple / swift (push) Successful in 4m22s
ci / bench (push) Successful in 5m54s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m1s
windows-host / package (push) Successful in 9m55s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 2m5s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 11m12s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9m58s
flatpak / build-publish (push) Successful in 6m18s
docker / deploy-docs (push) Successful in 27s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 2m14s
arch / build-publish (push) Successful in 16m1s
android / android (push) Successful in 16m36s
deb / build-publish (push) Successful in 16m58s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 4m46s
ci / rust (push) Successful in 22m42s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 5m19s
release / apple (push) Successful in 20m57s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 13m8s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m49s
apple / screenshots (push) Successful in 18m55s
48-finding cross-client + host gamepad audit (2026-07-13). Apple/Android/SDL-core capture + feedback and the Linux/Windows host injectors: held-guide release, the permanent broken-latch cliff (PadGate), Steam Deck trackpad clicks, DualSense mute, Windows DS/DS4 paddle fold, uinput button re-sync, gamestream BTN_* dedup, the dead Windows shell fork, legacy-Deck rumble ceiling, XUSB arrival, ARM64 fences, the truncate-everywhere value convention, and more. See punktfunk-planning/design/gamepad-review-cleanup.md. |
||
|
|
764b5d938b |
fix(gamepad): resolve the menu diagonal tie-break horizontally on all clients (G25)
The gamepad-UI navigation resolvers disagreed on which way a perfect 45-degree stick push (|x| == |y|) resolves: the SDL core picked horizontal (`ax >= ay`) while Apple (`abs(x) > abs(y)`) and Android (`abs(Y) >= abs(X)`) picked vertical. Align Apple (`>` -> `>=`) and Android (`>=` -> `>`) to the SDL core so an exact diagonal moves focus the same way on every client (horizontal wins). This is client-local menu navigation only and never reaches the wire. Completes the last deferred G25 sub-part. Verified: Apple `swift build` + full suite (124 pass); Android `:app:compileDebugKotlin`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
1af11cc64d |
fix(inject/host/windows): order the pad change-detect fields with Release/Acquire (G21)
The XUSB `packet` publish and the XUSB `rumble_seq` / DualSense `out_seq` reads used plain unaligned accesses with no fence, so a driver could observe a bumped change-detect field over a torn body on a weakly-ordered core (ARM64). Publish `packet` via a Release AtomicU32 store behind a Release fence, and Acquire-load the seq fields, mirroring the gamepad_raii PadChannel seq-fence precedent. The DualSense input report embeds its seq mid-report with no driver-gated change-detect field, so it gets a Release fence after the copy and a documented residual (a per-frame input generation is deferred). No-op on x86-TSO. Verified: Windows .173 `cargo clippy -p punktfunk-host --all-targets -- -D warnings` (green). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
2f214532d9 |
fix(inject/host/windows): eager-create the XUSB pad on Arrival + refresh last_active (G10)
The XUSB manager's `handle` dropped `GamepadEvent::Arrival` via a `let else`, so the GameStream path never created the pad until the first `State` and missed the first XInput poll. Match on the event and `ensure` eagerly on Arrival, mirroring the DualSense backend. Also refresh `last_active` on create and unplug so a freshly-created pad's residual-rumble idle clock starts fresh rather than inheriting a stale Instant (which could force off a legitimate rumble at once). Verified: Windows .173 `cargo clippy -p punktfunk-host --all-targets -- -D warnings` (green). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |