fix: complete the docs/→design/ and openapi→api/ rename references
The file moves (docs/ → design/, docs/api/openapi.json → api/openapi.json) landed
in 8897286, but the matching reference updates did not — so mgmt.rs's drift-test
`include_str!("../../../docs/api/openapi.json")` pointed at a path that no longer
exists and the host failed to build. This restores it and updates every reference:
- mgmt.rs include_str! → ../../../api/openapi.json (fixes the build)
- web/orval.config.ts codegen target, web/Dockerfile, .dockerignore
- deb/rpm/Arch packaging install paths
- CLAUDE.md, the .gitea CI workflows, code doc-comments, design-doc cross-links
docs-site route URLs (/docs/...) untouched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+2
-2
@@ -1,9 +1,9 @@
|
|||||||
# Root build context is used only by web/Dockerfile, which needs web/ and
|
# Root build context is used only by web/Dockerfile, which needs web/ and
|
||||||
# docs/api/openapi.json. Allowlist those; keep everything else (target/, .git, crates)
|
# api/openapi.json. Allowlist those; keep everything else (target/, .git, crates)
|
||||||
# out of the context upload.
|
# out of the context upload.
|
||||||
*
|
*
|
||||||
!web
|
!web
|
||||||
!docs/api/openapi.json
|
!api/openapi.json
|
||||||
web/node_modules
|
web/node_modules
|
||||||
web/.output
|
web/.output
|
||||||
web/dist
|
web/dist
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
# The flatpak is the CLIENT — only rebuild when the client/core/manifest change, not on every
|
# The flatpak is the CLIENT — only rebuild when the client/core/manifest change, not on every
|
||||||
# docs/host push (this is a heavy flatpak-builder run). Tags (v*, the client release) build too.
|
# design/host push (this is a heavy flatpak-builder run). Tags (v*, the client release) build too.
|
||||||
paths:
|
paths:
|
||||||
- 'clients/linux/**'
|
- 'clients/linux/**'
|
||||||
- 'crates/punktfunk-core/**'
|
- 'crates/punktfunk-core/**'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# One-shot provisioning of the WDK + cargo-wdk onto the persistent self-hosted windows-amd64 runner, so
|
# One-shot provisioning of the WDK + cargo-wdk onto the persistent self-hosted windows-amd64 runner, so
|
||||||
# the all-Rust UMDF drivers can build there (docs/windows-host-rewrite.md, M0). The runner has the base
|
# the all-Rust UMDF drivers can build there (design/windows-host-rewrite.md, M0). The runner has the base
|
||||||
# Windows SDK + MSVC + LLVM + Rust but NOT the WDK (no km/wdf/iddcx headers) or cargo-wdk.
|
# Windows SDK + MSVC + LLVM + Rust but NOT the WDK (no km/wdf/iddcx headers) or cargo-wdk.
|
||||||
#
|
#
|
||||||
# Dispatch manually (workflow_dispatch). Idempotent: re-running is a near no-op once provisioned. The
|
# Dispatch manually (workflow_dispatch). Idempotent: re-running is a near no-op once provisioned. The
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Windows driver workspace CI — runs on the self-hosted Windows runner (home-windows-1, host mode;
|
# Windows driver workspace CI — runs on the self-hosted Windows runner (home-windows-1, host mode;
|
||||||
# label windows-amd64). Part of the Windows-host rewrite (docs/windows-host-rewrite.md, M0).
|
# label windows-amd64). Part of the Windows-host rewrite (design/windows-host-rewrite.md, M0).
|
||||||
#
|
#
|
||||||
# Stage 1 (this file): PROBE the runner's driver toolchain (WDK / EWDK / cargo-make / LLVM / the
|
# Stage 1 (this file): PROBE the runner's driver toolchain (WDK / EWDK / cargo-make / LLVM / the
|
||||||
# inf2cat/stampinf/devgen/signtool tools) so we know what's provisioned BEFORE writing driver code,
|
# inf2cat/stampinf/devgen/signtool tools) so we know what's provisioned BEFORE writing driver code,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Low-latency desktop/game streaming stack, Linux-first, with a shared Rust protocol core
|
Low-latency desktop/game streaming stack, Linux-first, with a shared Rust protocol core
|
||||||
(`punktfunk-core`) exposed over a C ABI and native clients per platform. Full design:
|
(`punktfunk-core`) exposed over a C ABI and native clients per platform. Full design:
|
||||||
[`docs/implementation-plan.md`](docs/implementation-plan.md). Status table: `README.md`.
|
[`design/implementation-plan.md`](design/implementation-plan.md). Status table: `README.md`.
|
||||||
|
|
||||||
## Where the work stands
|
## Where the work stands
|
||||||
|
|
||||||
@@ -104,9 +104,16 @@ Low-latency desktop/game streaming stack, Linux-first, with a shared Rust protoc
|
|||||||
captures the HDR desktop as FP16/Rgb10a2 (DDA FP16 for the secure desktop), the encoder forces HEVC
|
captures the HDR desktop as FP16/Rgb10a2 (DDA FP16 for the secure desktop), the encoder forces HEVC
|
||||||
Main10 + BT.2020 PQ (NVENC ABGR10/P010; AMF/QSV P010 + a swscale Rgb10a2→P010 fallback), the client
|
Main10 + BT.2020 PQ (NVENC ABGR10/P010; AMF/QSV P010 + a swscale Rgb10a2→P010 fallback), the client
|
||||||
auto-detects PQ from the HEVC VUI — gated by `PUNKTFUNK_10BIT` + client `VIDEO_CAP_10BIT`; **Windows
|
auto-detects PQ from the HEVC VUI — gated by `PUNKTFUNK_10BIT` + client `VIDEO_CAP_10BIT`; **Windows
|
||||||
host only** (the Linux host stays 8-bit, blocked upstream). **AMF/QSV is CI-green but not yet
|
host only** (the Linux host stays 8-bit, blocked upstream). **Vulkan-game HDR over the virtual
|
||||||
on-glass validated** (no AMD/Intel Windows box in the lab); NVENC is live-validated. Newer/less
|
display**: NVIDIA/AMD Vulkan ICDs refuse to *advertise* an HDR color space for a surface on an IddCx
|
||||||
battle-tested than the Linux host. Packaging: `packaging/windows/`.
|
indirect display (so Vulkan games — Doom: The Dark Ages, id Tech, etc. — say "device does not support
|
||||||
|
HDR"), even though the ICD happily *accepts + presents* a forced HDR swapchain there. A tiny always-on
|
||||||
|
Vulkan **implicit layer** (`packaging/windows/pf-vkhdr-layer/`, `VK_LAYER_PUNKTFUNK_hdr_inject`)
|
||||||
|
injects the `HDR10_ST2084`/scRGB surface formats into `vkGetPhysicalDeviceSurfaceFormats[2]KHR`,
|
||||||
|
self-gated on the display's actual advanced-color state (no-op on SDR / real monitors); bundled +
|
||||||
|
HKLM-registered by the installer. **Live-validated: Doom: The Dark Ages enables HDR over the virtual
|
||||||
|
display.** **AMF/QSV is CI-green but not yet on-glass validated** (no AMD/Intel Windows box in the
|
||||||
|
lab); NVENC is live-validated. Newer/less battle-tested than the Linux host. Packaging: `packaging/windows/`.
|
||||||
|
|
||||||
## What's left
|
## What's left
|
||||||
|
|
||||||
@@ -245,8 +252,8 @@ bash crates/punktfunk-core/tests/c/run.sh # standalone C-ABI link + round-trip
|
|||||||
```
|
```
|
||||||
|
|
||||||
Generated artifacts are **checked in** and CI fails on drift: `include/punktfunk_core.h`
|
Generated artifacts are **checked in** and CI fails on drift: `include/punktfunk_core.h`
|
||||||
(cbindgen from `punktfunk-core/src/abi.rs`) and `docs/api/openapi.json` (regenerate with
|
(cbindgen from `punktfunk-core/src/abi.rs`) and `api/openapi.json` (regenerate with
|
||||||
`cargo run -p punktfunk-host -- openapi > docs/api/openapi.json`; spec lives in `mgmt.rs`).
|
`cargo run -p punktfunk-host -- openapi > api/openapi.json`; spec lives in `mgmt.rs`).
|
||||||
|
|
||||||
CI is Gitea Actions (`.gitea/workflows/`, guide: docs-site `ci.md`): `ci.yml` runs the
|
CI is Gitea Actions (`.gitea/workflows/`, guide: docs-site `ci.md`): `ci.yml` runs the
|
||||||
workspace checks inside the `git.unom.io/unom/punktfunk-rust-ci` image plus web/docs-site
|
workspace checks inside the `git.unom.io/unom/punktfunk-rust-ci` image plus web/docs-site
|
||||||
|
|||||||
@@ -361,4 +361,4 @@ ever switched to a logged-in GUI session, re-adding macOS to the job's capture s
|
|||||||
- Mid-stream renegotiation (resolution change without reconnect) is designed-for but not
|
- Mid-stream renegotiation (resolution change without reconnect) is designed-for but not
|
||||||
implemented (the Welcome is one-shot today).
|
implemented (the Welcome is one-shot today).
|
||||||
- Host-side gamepad injection needs `/dev/uinput` access on the box (udev rule from
|
- Host-side gamepad injection needs `/dev/uinput` access on the box (udev rule from
|
||||||
`docs/linux-setup.md`).
|
`design/linux-setup.md`).
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ pub mod frame {
|
|||||||
/// These were hand-duplicated as `OFF_*`/`SHM_*` constants in `inject/{gamepad,dualsense}_windows.rs`
|
/// These were hand-duplicated as `OFF_*`/`SHM_*` constants in `inject/{gamepad,dualsense}_windows.rs`
|
||||||
/// and (as bare literals — `*view.add(140)`) in the standalone `xusb-driver`/`dualsense-driver`
|
/// and (as bare literals — `*view.add(140)`) in the standalone `xusb-driver`/`dualsense-driver`
|
||||||
/// workspaces, guarded only by "must match" comments — the top ABI-drift hazard the audit flagged
|
/// workspaces, guarded only by "must match" comments — the top ABI-drift hazard the audit flagged
|
||||||
/// (`docs/windows-host-rewrite.md` §2.7). Owning them here with `Pod` derives + `offset_of!`
|
/// (`design/windows-host-rewrite.md` §2.7). Owning them here with `Pod` derives + `offset_of!`
|
||||||
/// asserts makes a one-sided edit a compile error.
|
/// asserts makes a one-sided edit a compile error.
|
||||||
///
|
///
|
||||||
/// The host creates the section (privileged, permissive DACL so the restricted WUDFHost token can
|
/// The host creates the section (privileged, permissive DACL so the restricted WUDFHost token can
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//! Input-desktop watcher (Windows) — the authoritative "normal vs secure desktop" signal for the
|
//! Input-desktop watcher (Windows) — the authoritative "normal vs secure desktop" signal for the
|
||||||
//! two-process secure-desktop design (docs/windows-secure-desktop.md).
|
//! two-process secure-desktop design (design/windows-secure-desktop.md).
|
||||||
//!
|
//!
|
||||||
//! Windows switches the *input desktop* to "Winlogon" (the secure desktop) for UAC elevation, the
|
//! Windows switches the *input desktop* to "Winlogon" (the secure desktop) for UAC elevation, the
|
||||||
//! lock screen and the login screen, and back to "Default" for the normal session. WGC captures only
|
//! lock screen and the login screen, and back to "Default" for the normal session. WGC captures only
|
||||||
|
|||||||
@@ -562,7 +562,7 @@ impl IddPushCapturer {
|
|||||||
|
|
||||||
/// Block (bounded) until the driver has ATTACHED to the host ring (`DRV_STATUS_OPENED`) **and published
|
/// Block (bounded) until the driver has ATTACHED to the host ring (`DRV_STATUS_OPENED`) **and published
|
||||||
/// a first frame**, else fail so the caller can fall back to DDA (audit §5.1 +
|
/// a first frame**, else fail so the caller can fall back to DDA (audit §5.1 +
|
||||||
/// `docs/windows-host-rewrite.md` §2.5 — the GB1 game-capture fix).
|
/// `design/windows-host-rewrite.md` §2.5 — the GB1 game-capture fix).
|
||||||
///
|
///
|
||||||
/// Requiring the first frame — not just the attach — catches the *reconnect-into-a-broken-state* case:
|
/// Requiring the first frame — not just the attach — catches the *reconnect-into-a-broken-state* case:
|
||||||
/// a fullscreen game can leave the virtual display in a format/size that the driver's `publish()` guard
|
/// a fullscreen game can leave the virtual display in a format/size that the driver's `publish()` guard
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//! Host-side WGC helper relay (Windows two-process secure-desktop design,
|
//! Host-side WGC helper relay (Windows two-process secure-desktop design,
|
||||||
//! docs/windows-secure-desktop.md — step 4).
|
//! design/windows-secure-desktop.md — step 4).
|
||||||
//!
|
//!
|
||||||
//! WGC won't activate under the SYSTEM account, so the SYSTEM host can't capture the normal desktop
|
//! WGC won't activate under the SYSTEM account, so the SYSTEM host can't capture the normal desktop
|
||||||
//! itself. Instead it spawns `punktfunk-host wgc-helper` in the **interactive user session** (so WGC works)
|
//! itself. Instead it spawns `punktfunk-host wgc-helper` in the **interactive user session** (so WGC works)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
//! environment before the host starts, and **for the knobs captured here the environment is constant for the
|
//! environment before the host starts, and **for the knobs captured here the environment is constant for the
|
||||||
//! process lifetime**, so a lazily-parsed global is equivalent to "parsed once at startup".
|
//! process lifetime**, so a lazily-parsed global is equivalent to "parsed once at startup".
|
||||||
//!
|
//!
|
||||||
//! **Goal-1 stages 1–2** (`docs/windows-host-rewrite.md` §2.2): stage 1 stood this up; stage 2 migrated the
|
//! **Goal-1 stages 1–2** (`design/windows-host-rewrite.md` §2.2): stage 1 stood this up; stage 2 migrated the
|
||||||
//! genuinely-constant operator/dispatch knobs onto it (the dispatch-disagreement bug class: `idd_push`,
|
//! genuinely-constant operator/dispatch knobs onto it (the dispatch-disagreement bug class: `idd_push`,
|
||||||
//! `capture_backend`, `encoder_pref`, `render_adapter`, `no_wgc`, the vdisplay backend select — plus the
|
//! `capture_backend`, `encoder_pref`, `render_adapter`, `no_wgc`, the vdisplay backend select — plus the
|
||||||
//! plan-named `secure_dda`/`idd_depth`/`zerocopy`/`ten_bit` and the multi-site `perf`/`compositor`/
|
//! plan-named `secure_dda`/`idd_depth`/`zerocopy`/`ten_bit` and the multi-site `perf`/`compositor`/
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//! Pairing crypto primitives (control plane only — distinct from `punktfunk_core`'s AES-GCM
|
//! Pairing crypto primitives (control plane only — distinct from `punktfunk_core`'s AES-GCM
|
||||||
//! data-plane sealing). GameStream pairing uses: AES-128-**ECB** with **no padding**,
|
//! data-plane sealing). GameStream pairing uses: AES-128-**ECB** with **no padding**,
|
||||||
//! SHA-256 (host appversion major ≥ 7), and RSA-PKCS1v15-SHA256 signatures. See the
|
//! SHA-256 (host appversion major ≥ 7), and RSA-PKCS1v15-SHA256 signatures. See the
|
||||||
//! `serverinfo + pairing` section of `docs/research/gamestream-protocol-research.json`.
|
//! `serverinfo + pairing` section of `design/research/gamestream-protocol-research.json`.
|
||||||
|
|
||||||
use aes::cipher::generic_array::GenericArray;
|
use aes::cipher::generic_array::GenericArray;
|
||||||
use aes::cipher::{BlockDecrypt, BlockEncrypt, KeyInit};
|
use aes::cipher::{BlockDecrypt, BlockEncrypt, KeyInit};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//! GameStream (P1) control plane — what a stock Moonlight/Artemis client talks to around
|
//! GameStream (P1) control plane — what a stock Moonlight/Artemis client talks to around
|
||||||
//! the media streams: mDNS discovery, the nvhttp serverinfo + pairing HTTP(S) API, RTSP,
|
//! the media streams: mDNS discovery, the nvhttp serverinfo + pairing HTTP(S) API, RTSP,
|
||||||
//! and the ENet control stream. `tokio`/`axum` live here (control plane, I/O-bound — never
|
//! and the ENet control stream. `tokio`/`axum` live here (control plane, I/O-bound — never
|
||||||
//! the per-frame hot path; that is `punktfunk_core`'s P1 wire codec). See `docs/gamestream-host-plan.md`.
|
//! the per-frame hot path; that is `punktfunk_core`'s P1 wire codec). See `design/gamestream-host-plan.md`.
|
||||||
//!
|
//!
|
||||||
//! Status: P1.1 — mDNS `_nvstream._tcp` advertisement + `/serverinfo`. Pairing, RTSP, and
|
//! Status: P1.1 — mDNS `_nvstream._tcp` advertisement + `/serverinfo`. Pairing, RTSP, and
|
||||||
//! the media streams follow (see the GameStream host task list / plan).
|
//! the media streams follow (see the GameStream host task list / plan).
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//! The 4-phase GameStream pairing state machine (over HTTP), keyed by `uniqueid`. Proves
|
//! The 4-phase GameStream pairing state machine (over HTTP), keyed by `uniqueid`. Proves
|
||||||
//! both sides know the PIN (via the SHA-256(salt||pin) AES-ECB key) and own their certs
|
//! both sides know the PIN (via the SHA-256(salt||pin) AES-ECB key) and own their certs
|
||||||
//! (RSA signatures), then pins the client cert. The final `pairchallenge` happens over
|
//! (RSA signatures), then pins the client cert. The final `pairchallenge` happens over
|
||||||
//! HTTPS (handled in `nvhttp`). Byte-exact spec: `docs/research/…-research.json`.
|
//! HTTPS (handled in `nvhttp`). Byte-exact spec: `design/research/…-research.json`.
|
||||||
|
|
||||||
use super::cert::ServerIdentity;
|
use super::cert::ServerIdentity;
|
||||||
use super::crypto;
|
use super::crypto;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//! `RTP_PACKET(12, big-endian) + reserved[4] + NV_VIDEO_PACKET(16, little-endian) + payload`
|
//! `RTP_PACKET(12, big-endian) + reserved[4] + NV_VIDEO_PACKET(16, little-endian) + payload`
|
||||||
//! and the frame's bitstream is prefixed with an 8-byte `video_short_frame_header_t`, then
|
//! and the frame's bitstream is prefixed with an 8-byte `video_short_frame_header_t`, then
|
||||||
//! striped into ≤4 FEC blocks of ≤255 shards. Byte-exact spec:
|
//! striped into ≤4 FEC blocks of ≤255 shards. Byte-exact spec:
|
||||||
//! `docs/research/gamestream-protocol-research.json` (video plane).
|
//! `design/research/gamestream-protocol-research.json` (video plane).
|
||||||
//!
|
//!
|
||||||
//! FEC (P1.5): each block carries `m = ⌈k·pct/100⌉` Reed–Solomon parity shards generated by
|
//! FEC (P1.5): each block carries `m = ⌈k·pct/100⌉` Reed–Solomon parity shards generated by
|
||||||
//! `punktfunk_core::fec::Gf8Coder` (the nanors-compatible Cauchy GF(2⁸) coder). Crucially, RS runs
|
//! `punktfunk_core::fec::Gf8Coder` (the nanors-compatible Cauchy GF(2⁸) coder). Crucially, RS runs
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ pub(super) struct SwDeviceProfile<'a> {
|
|||||||
/// `profile.instance`). The returned `HSWDEVICE` owns it — `SwDeviceClose` removes it on drop, so the
|
/// `profile.instance`). The returned `HSWDEVICE` owns it — `SwDeviceClose` removes it on drop, so the
|
||||||
/// pad appears/disappears with the session and nothing persists.
|
/// pad appears/disappears with the session and nothing persists.
|
||||||
///
|
///
|
||||||
/// **Game-detection identity** (see `docs/windows-dualsense-game-detection.md`). `HIDD_ATTRIBUTES`
|
/// **Game-detection identity** (see `design/windows-dualsense-game-detection.md`). `HIDD_ATTRIBUTES`
|
||||||
/// alone (VID/PID via the IOCTL) satisfies SDL/HIDAPI/RawInput, but a native PS5 path (libScePad-
|
/// alone (VID/PID via the IOCTL) satisfies SDL/HIDAPI/RawInput, but a native PS5 path (libScePad-
|
||||||
/// style raw HID) classifies the *connection type* by walking from the HID child to its parent
|
/// style raw HID) classifies the *connection type* by walking from the HID child to its parent
|
||||||
/// (`CM_Get_Parent`) and string-matching `"USB"`/`"BTHENUM"` in that parent's
|
/// (`CM_Get_Parent`) and string-matching `"USB"`/`"BTHENUM"` in that parent's
|
||||||
|
|||||||
@@ -389,7 +389,7 @@ fn real_main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
// USER-session WGC helper (Windows two-process secure-desktop design): capture the EXISTING
|
// USER-session WGC helper (Windows two-process secure-desktop design): capture the EXISTING
|
||||||
// SudoVDA via WGC + NVENC, stream AUs on stdout to the SYSTEM host. Spawned by the host
|
// SudoVDA via WGC + NVENC, stream AUs on stdout to the SYSTEM host. Spawned by the host
|
||||||
// (CreateProcessAsUser), not run by hand. See docs/windows-secure-desktop.md.
|
// (CreateProcessAsUser), not run by hand. See design/windows-secure-desktop.md.
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
Some("wgc-helper") => {
|
Some("wgc-helper") => {
|
||||||
let get = |flag: &str| {
|
let get = |flag: &str| {
|
||||||
@@ -704,7 +704,7 @@ SPIKE OPTIONS:
|
|||||||
|
|
||||||
NOTES:
|
NOTES:
|
||||||
'portal' needs headless Sway + xdg-desktop-portal-wlr running in this session
|
'portal' needs headless Sway + xdg-desktop-portal-wlr running in this session
|
||||||
(see docs/linux-setup.md). 'synthetic' needs no capture session and always runs.
|
(see design/linux-setup.md). 'synthetic' needs no capture session and always runs.
|
||||||
Encoded AUs are written to a playable file AND (unless --no-loopback) fed through a
|
Encoded AUs are written to a playable file AND (unless --no-loopback) fed through a
|
||||||
punktfunk_core host→client loopback that reassembles and byte-verifies each one.
|
punktfunk_core host→client loopback that reassembles and byte-verifies each one.
|
||||||
Both 'serve' and 'punktfunk1-host' advertise the native service over mDNS
|
Both 'serve' and 'punktfunk1-host' advertise the native service over mDNS
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
//! The API is versioned under `/api/v1` and described by an OpenAPI 3.1 document generated
|
//! The API is versioned under `/api/v1` and described by an OpenAPI 3.1 document generated
|
||||||
//! at compile time with `utoipa` — `punktfunk-host openapi` prints it for client codegen, the
|
//! at compile time with `utoipa` — `punktfunk-host openapi` prints it for client codegen, the
|
||||||
//! running server serves it at `/api/v1/openapi.json` plus interactive docs at `/api/docs`,
|
//! running server serves it at `/api/v1/openapi.json` plus interactive docs at `/api/docs`,
|
||||||
//! and a copy is checked in at `docs/api/openapi.json` (a test fails if it drifts, like the
|
//! and a copy is checked in at `api/openapi.json` (a test fails if it drifts, like the
|
||||||
//! cbindgen header).
|
//! cbindgen header).
|
||||||
//!
|
//!
|
||||||
//! Security: binds loopback by default, serves HTTPS with the host's identity cert, and requires
|
//! Security: binds loopback by default, serves HTTPS with the host's identity cert, and requires
|
||||||
@@ -164,7 +164,7 @@ fn api_router_parts() -> (Router<Arc<MgmtState>>, utoipa::openapi::OpenApi) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The OpenAPI document as pretty JSON — what `punktfunk-host openapi` prints and what is
|
/// The OpenAPI document as pretty JSON — what `punktfunk-host openapi` prints and what is
|
||||||
/// checked in at `docs/api/openapi.json` for client codegen.
|
/// checked in at `api/openapi.json` for client codegen.
|
||||||
pub fn openapi_json() -> String {
|
pub fn openapi_json() -> String {
|
||||||
let (_, api) = api_router_parts();
|
let (_, api) = api_router_parts();
|
||||||
let mut json = api.to_pretty_json().expect("serialize OpenAPI document");
|
let mut json = api.to_pretty_json().expect("serialize OpenAPI document");
|
||||||
@@ -1663,14 +1663,14 @@ mod tests {
|
|||||||
serde_json::json!([{}])
|
serde_json::json!([{}])
|
||||||
);
|
);
|
||||||
|
|
||||||
let checked_in = include_str!("../../../docs/api/openapi.json");
|
let checked_in = include_str!("../../../api/openapi.json");
|
||||||
// Compare content, not line-ending style: the generated `json` is LF (serde_json), but git
|
// Compare content, not line-ending style: the generated `json` is LF (serde_json), but git
|
||||||
// may check the file out CRLF on Windows.
|
// may check the file out CRLF on Windows.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
json.trim().replace('\r', ""),
|
json.trim().replace('\r', ""),
|
||||||
checked_in.trim().replace('\r', ""),
|
checked_in.trim().replace('\r', ""),
|
||||||
"docs/api/openapi.json is stale — regenerate with: \
|
"api/openapi.json is stale — regenerate with: \
|
||||||
cargo run -p punktfunk-host -- openapi > docs/api/openapi.json"
|
cargo run -p punktfunk-host -- openapi > api/openapi.json"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2221,7 +2221,7 @@ fn virtual_stream(ctx: SessionContext) -> Result<()> {
|
|||||||
// Windows two-process secure-desktop path: when the host runs as SYSTEM (required for the secure
|
// Windows two-process secure-desktop path: when the host runs as SYSTEM (required for the secure
|
||||||
// desktop + SendInput), WGC can't activate in-process, so we capture the normal desktop via a
|
// desktop + SendInput), WGC can't activate in-process, so we capture the normal desktop via a
|
||||||
// helper spawned in the user session and relay its AUs. (Single-process WGC/DDA is used as the
|
// helper spawned in the user session and relay its AUs. (Single-process WGC/DDA is used as the
|
||||||
// user, and stays the path on Linux.) See docs/windows-secure-desktop.md.
|
// user, and stays the path on Linux.) See design/windows-secure-desktop.md.
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
if plan.topology == crate::session_plan::SessionTopology::TwoProcessRelay {
|
if plan.topology == crate::session_plan::SessionTopology::TwoProcessRelay {
|
||||||
return virtual_stream_relay(ctx);
|
return virtual_stream_relay(ctx);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//! `SessionPlan` — the per-session capture / topology / encoder decision, resolved **once** from
|
//! `SessionPlan` — the per-session capture / topology / encoder decision, resolved **once** from
|
||||||
//! [`HostConfig`](crate::config) (+ the handshake-negotiated bit depth) into a typed, logged value.
|
//! [`HostConfig`](crate::config) (+ the handshake-negotiated bit depth) into a typed, logged value.
|
||||||
//!
|
//!
|
||||||
//! **Goal-1 stage 3** (`docs/windows-host-rewrite.md` §2.2): before this, the Windows session decision was
|
//! **Goal-1 stage 3** (`design/windows-host-rewrite.md` §2.2): before this, the Windows session decision was
|
||||||
//! re-derived at three call sites — the capture backend inside `capture::capture_virtual_output`, the
|
//! re-derived at three call sites — the capture backend inside `capture::capture_virtual_output`, the
|
||||||
//! process topology in `punktfunk1::should_use_helper`, and the encode backend in
|
//! process topology in `punktfunk1::should_use_helper`, and the encode backend in
|
||||||
//! `encode::windows_resolved_backend` — each reading [`config`](crate::config) independently, with no
|
//! `encode::windows_resolved_backend` — each reading [`config`](crate::config) independently, with no
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
//! Raw C-ABI FFI (winmm/kernel32/dwmapi/avrt) rather than the `windows` crate so it builds without
|
//! Raw C-ABI FFI (winmm/kernel32/dwmapi/avrt) rather than the `windows` crate so it builds without
|
||||||
//! pulling new windows-rs features. No-op on non-Windows. Per-thread effects (MMCSS, execution
|
//! pulling new windows-rs features. No-op on non-Windows. Per-thread effects (MMCSS, execution
|
||||||
//! state) auto-revert at thread exit (= session end); the process-wide bits revert at process exit.
|
//! state) auto-revert at thread exit (= session end); the process-wide bits revert at process exit.
|
||||||
//! See `docs/host-latency-plan.md` Tier 3A.
|
//! See `design/host-latency-plan.md` Tier 3A.
|
||||||
|
|
||||||
// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program).
|
// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program).
|
||||||
#![deny(clippy::undocumented_unsafe_blocks)]
|
#![deny(clippy::undocumented_unsafe_blocks)]
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
//!
|
//!
|
||||||
//! Control surface: a device-interface-GUID + `CreateFileW` + `DeviceIoControl` IOCTL protocol, with
|
//! Control surface: a device-interface-GUID + `CreateFileW` + `DeviceIoControl` IOCTL protocol, with
|
||||||
//! the wire contract OWNED by [`pf_driver_proto::control`] (versioned + `#[repr(C)] Pod` structs,
|
//! the wire contract OWNED by [`pf_driver_proto::control`] (versioned + `#[repr(C)] Pod` structs,
|
||||||
//! NOT the SudoVDA ABI). No DLL, no named pipe. See `docs/windows-host-rewrite.md`.
|
//! NOT the SudoVDA ABI). No DLL, no named pipe. See `design/windows-host-rewrite.md`.
|
||||||
//!
|
//!
|
||||||
//! This is a faithful clone of [`super::sudovda`] (the shipping fallback) repointed at the new driver:
|
//! This is a faithful clone of [`super::sudovda`] (the shipping fallback) repointed at the new driver:
|
||||||
//! same reference-counted/lingering monitor lifecycle, same CCD isolation + active-mode forcing — those
|
//! same reference-counted/lingering monitor lifecycle, same CCD isolation + active-mode forcing — those
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//! USER-session WGC helper (Windows) — part of the two-process secure-desktop design
|
//! USER-session WGC helper (Windows) — part of the two-process secure-desktop design
|
||||||
//! (docs/windows-secure-desktop.md).
|
//! (design/windows-secure-desktop.md).
|
||||||
//!
|
//!
|
||||||
//! WGC won't activate under the SYSTEM account, but the host must run as SYSTEM for the secure
|
//! WGC won't activate under the SYSTEM account, but the host must run as SYSTEM for the secure
|
||||||
//! desktop. So the SYSTEM host spawns THIS helper in the interactive user session
|
//! desktop. So the SYSTEM host spawns THIS helper in the interactive user session
|
||||||
|
|||||||
+2
-2
@@ -16,8 +16,8 @@ sidebar, and the landing page). It reads [`public/openapi.json`](public/openapi.
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
# from the repo root — regenerate the spec, then copy the snapshot in:
|
# from the repo root — regenerate the spec, then copy the snapshot in:
|
||||||
cargo run -p punktfunk-host -- openapi > docs/api/openapi.json
|
cargo run -p punktfunk-host -- openapi > api/openapi.json
|
||||||
cp docs/api/openapi.json docs-site/public/openapi.json
|
cp api/openapi.json docs-site/public/openapi.json
|
||||||
```
|
```
|
||||||
|
|
||||||
## Develop
|
## Develop
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ package_punktfunk-host() {
|
|||||||
install -Dm0644 "$R/scripts/host.env.example" "$pkgdir/usr/share/punktfunk/host.env.example"
|
install -Dm0644 "$R/scripts/host.env.example" "$pkgdir/usr/share/punktfunk/host.env.example"
|
||||||
install -Dm0644 "$R/packaging/bazzite/host.env" "$pkgdir/usr/share/punktfunk/host.env.bazzite"
|
install -Dm0644 "$R/packaging/bazzite/host.env" "$pkgdir/usr/share/punktfunk/host.env.bazzite"
|
||||||
install -Dm0644 "$R/packaging/kde/host.env" "$pkgdir/usr/share/punktfunk/host.env.kde"
|
install -Dm0644 "$R/packaging/kde/host.env" "$pkgdir/usr/share/punktfunk/host.env.kde"
|
||||||
install -Dm0644 "$R/docs/api/openapi.json" "$pkgdir/usr/share/punktfunk/openapi.json"
|
install -Dm0644 "$R/api/openapi.json" "$pkgdir/usr/share/punktfunk/openapi.json"
|
||||||
install -Dm0644 "$R/LICENSE-MIT" "$pkgdir/usr/share/licenses/punktfunk-host/LICENSE-MIT"
|
install -Dm0644 "$R/LICENSE-MIT" "$pkgdir/usr/share/licenses/punktfunk-host/LICENSE-MIT"
|
||||||
install -Dm0644 "$R/LICENSE-APACHE" "$pkgdir/usr/share/licenses/punktfunk-host/LICENSE-APACHE"
|
install -Dm0644 "$R/LICENSE-APACHE" "$pkgdir/usr/share/licenses/punktfunk-host/LICENSE-APACHE"
|
||||||
install -Dm0644 "$R/README.md" "$pkgdir/usr/share/doc/punktfunk-host/README.md"
|
install -Dm0644 "$R/README.md" "$pkgdir/usr/share/doc/punktfunk-host/README.md"
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ journalctl --user -u punktfunk-host -f
|
|||||||
|
|
||||||
> ⚠️ **There is no firewall script or firewall doc in the repo.** The ports below are derived
|
> ⚠️ **There is no firewall script or firewall doc in the repo.** The ports below are derived
|
||||||
> directly from the code constants (`crates/punktfunk-host/src/gamestream/mod.rs`, `mgmt.rs`) and
|
> directly from the code constants (`crates/punktfunk-host/src/gamestream/mod.rs`, `mgmt.rs`) and
|
||||||
> the GameStream-host port-map (`docs/gamestream-host-plan.md`). Treat the `firewall-cmd` lines as recommended-but-verified,
|
> the GameStream-host port-map (`design/gamestream-host-plan.md`). Treat the `firewall-cmd` lines as recommended-but-verified,
|
||||||
> not a checked-in script.
|
> not a checked-in script.
|
||||||
|
|
||||||
**GameStream / Moonlight ports** (fixed; Moonlight derives them from the HTTP base). These only apply
|
**GameStream / Moonlight ports** (fixed; Moonlight derives them from the HTTP base). These only apply
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ install -Dm0644 scripts/headless/punktfunk-sink.conf "$SHAREDIR/headless/punkt
|
|||||||
install -Dm0644 scripts/host.env.example "$SHAREDIR/host.env.example"
|
install -Dm0644 scripts/host.env.example "$SHAREDIR/host.env.example"
|
||||||
install -Dm0644 packaging/bazzite/host.env "$SHAREDIR/host.env.bazzite"
|
install -Dm0644 packaging/bazzite/host.env "$SHAREDIR/host.env.bazzite"
|
||||||
install -Dm0644 packaging/kde/host.env "$SHAREDIR/host.env.kde"
|
install -Dm0644 packaging/kde/host.env "$SHAREDIR/host.env.kde"
|
||||||
install -Dm0644 docs/api/openapi.json "$SHAREDIR/openapi.json"
|
install -Dm0644 api/openapi.json "$SHAREDIR/openapi.json"
|
||||||
install -Dm0644 LICENSE-MIT "$DOCDIR/LICENSE-MIT"
|
install -Dm0644 LICENSE-MIT "$DOCDIR/LICENSE-MIT"
|
||||||
install -Dm0644 LICENSE-APACHE "$DOCDIR/LICENSE-APACHE"
|
install -Dm0644 LICENSE-APACHE "$DOCDIR/LICENSE-APACHE"
|
||||||
install -Dm0644 README.md "$DOCDIR/README.md"
|
install -Dm0644 README.md "$DOCDIR/README.md"
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ install -Dm0644 packaging/kde/host.env %{buildroot}%{_datadir}/%
|
|||||||
# Bazzite KDE Desktop-mode one-shot setup (KWIN_WAYLAND_NO_PERMISSION_CHECKS + RemoteDesktop grant).
|
# Bazzite KDE Desktop-mode one-shot setup (KWIN_WAYLAND_NO_PERMISSION_CHECKS + RemoteDesktop grant).
|
||||||
install -d %{buildroot}%{_datadir}/%{name}/bazzite
|
install -d %{buildroot}%{_datadir}/%{name}/bazzite
|
||||||
install -Dm0755 packaging/bazzite/kde-desktop-setup.sh %{buildroot}%{_datadir}/%{name}/bazzite/kde-desktop-setup.sh
|
install -Dm0755 packaging/bazzite/kde-desktop-setup.sh %{buildroot}%{_datadir}/%{name}/bazzite/kde-desktop-setup.sh
|
||||||
install -Dm0644 docs/api/openapi.json %{buildroot}%{_datadir}/%{name}/openapi.json
|
install -Dm0644 api/openapi.json %{buildroot}%{_datadir}/%{name}/openapi.json
|
||||||
|
|
||||||
%if %{with web}
|
%if %{with web}
|
||||||
# --- web console subpackage (punktfunk-web) ---
|
# --- web console subpackage (punktfunk-web) ---
|
||||||
@@ -246,7 +246,7 @@ install -Dm0644 web/web.env.example %{buildroot}%{_datadir}/punkt
|
|||||||
|
|
||||||
%files
|
%files
|
||||||
%license LICENSE-MIT LICENSE-APACHE
|
%license LICENSE-MIT LICENSE-APACHE
|
||||||
%doc README.md docs/implementation-plan.md packaging/README.md
|
%doc README.md design/implementation-plan.md packaging/README.md
|
||||||
%{_bindir}/punktfunk-host
|
%{_bindir}/punktfunk-host
|
||||||
%{_udevrulesdir}/60-punktfunk.rules
|
%{_udevrulesdir}/60-punktfunk.rules
|
||||||
%{_prefix}/lib/sysctl.d/99-punktfunk-net.conf
|
%{_prefix}/lib/sysctl.d/99-punktfunk-net.conf
|
||||||
|
|||||||
@@ -76,10 +76,11 @@ read it from `%ProgramData%\punktfunk\web-password`.
|
|||||||
| `reset-pf-vdisplay.ps1` | **Dev:** recover a wedged driver — stop host → reap ghost monitor nodes → reload the adapter → start host (no reboot). See *Dev iteration* below. |
|
| `reset-pf-vdisplay.ps1` | **Dev:** recover a wedged driver — stop host → reap ghost monitor nodes → reload the adapter → start host (no reboot). See *Dev iteration* below. |
|
||||||
| `redeploy-pf-vdisplay.ps1` | **Dev:** one-shot redeploy — (optional) build → stop host → `deploy-dev.ps1 -Install` → reload adapter → start host. |
|
| `redeploy-pf-vdisplay.ps1` | **Dev:** one-shot redeploy — (optional) build → stop host → `deploy-dev.ps1 -Install` → reload adapter → start host. |
|
||||||
| `nvenc/nvenc.def`, `nvenc/gen-nvenc-importlib.ps1` | Synthesise `nvencodeapi.lib` for the `--features nvenc` link (llvm-dlltool / lib.exe). |
|
| `nvenc/nvenc.def`, `nvenc/gen-nvenc-importlib.ps1` | Synthesise `nvencodeapi.lib` for the `--features nvenc` link (llvm-dlltool / lib.exe). |
|
||||||
|
| `pf-vkhdr-layer/` | **HDR Vulkan layer** (standalone `cdylib`): lets Vulkan games (Doom: The Dark Ages, etc.) enable HDR over the virtual display by advertising the HDR surface formats the NVIDIA/AMD ICDs hide on an indirect display. Built by the packer, laid into `{app}\vklayer`, registered under `HKLM64\…\Khronos\Vulkan\ImplicitLayers` (opt-out *Install the HDR Vulkan layer* task). Self-gated on the display's HDR state. See its README. |
|
||||||
|
|
||||||
> **Vendored driver:** pf-vdisplay is our **all-Rust IddCx** virtual display (UMDF2), built from
|
> **Vendored driver:** pf-vdisplay is our **all-Rust IddCx** virtual display (UMDF2), built from
|
||||||
> `packaging/windows/drivers/`. It replaced the vendored SudoVDA C++ driver — full story in
|
> `packaging/windows/drivers/`. It replaced the vendored SudoVDA C++ driver — full story in
|
||||||
> [`docs/windows-virtual-display-rust-port.md`](../../docs/windows-virtual-display-rust-port.md). The
|
> [`design/windows-virtual-display-rust-port.md`](../../design/windows-virtual-display-rust-port.md). The
|
||||||
> **signed** output (`pf_vdisplay.dll`/`.inf`/`.cat` + `punktfunk-driver.cer`; signer
|
> **signed** output (`pf_vdisplay.dll`/`.inf`/`.cat` + `punktfunk-driver.cer`; signer
|
||||||
> `punktfunk-ds-test` — the same cert the gamepad drivers ship, Class=Display, HWID `root\pf_vdisplay`)
|
> `punktfunk-ds-test` — the same cert the gamepad drivers ship, Class=Display, HWID `root\pf_vdisplay`)
|
||||||
> is checked in under `pf-vdisplay/`. To refresh it after a driver-source change, rebuild + re-sign with
|
> is checked in under `pf-vdisplay/`. To refresh it after a driver-source change, rebuild + re-sign with
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Unified in-tree workspace for punktfunk's all-Rust UMDF drivers, on microsoft/windows-drivers-rs
|
# Unified in-tree workspace for punktfunk's all-Rust UMDF drivers, on microsoft/windows-drivers-rs
|
||||||
# (crates.io wdk/wdk-sys/wdk-build — NOT the dev-box ../../crates/wdk* path-deps). Part of the
|
# (crates.io wdk/wdk-sys/wdk-build — NOT the dev-box ../../crates/wdk* path-deps). Part of the
|
||||||
# Windows-host rewrite (docs/windows-host-rewrite.md, M1). pf-vdisplay + the gamepad drivers move here.
|
# Windows-host rewrite (design/windows-host-rewrite.md, M1). pf-vdisplay + the gamepad drivers move here.
|
||||||
#
|
#
|
||||||
# Separate from the main cargo workspace (own [workspace] root) because driver crates are cdylibs built
|
# Separate from the main cargo workspace (own [workspace] root) because driver crates are cdylibs built
|
||||||
# with the WDK toolchain (cargo-wdk / wdk-build) on Windows only. Path-deps the shared ABI crate
|
# with the WDK toolchain (cargo-wdk / wdk-build) on Windows only. Path-deps the shared ABI crate
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# pf-vdisplay — the all-Rust UMDF IddCx virtual-display driver (M1 step-2 rewrite onto wdk-sys + the
|
# pf-vdisplay — the all-Rust UMDF IddCx virtual-display driver (M1 step-2 rewrite onto wdk-sys + the
|
||||||
# owned pf-driver-proto ABI). Replaces the vendored-binding oracle at packaging/windows/vdisplay-driver/
|
# owned pf-driver-proto ABI). Replaces the vendored-binding oracle at packaging/windows/vdisplay-driver/
|
||||||
# (deleted once on-glass parity is reached, per docs/windows-host-rewrite.md §14 STEP 8).
|
# (deleted once on-glass parity is reached, per design/windows-host-rewrite.md §14 STEP 8).
|
||||||
[package]
|
[package]
|
||||||
name = "pf-vdisplay"
|
name = "pf-vdisplay"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ pub(crate) fn adapter() -> Option<iddcx::IDDCX_ADAPTER> {
|
|||||||
/// iGPU+dGPU box the OS may otherwise pick the iGPU to render the virtual monitor, so the host's shared
|
/// iGPU+dGPU box the OS may otherwise pick the iGPU to render the virtual monitor, so the host's shared
|
||||||
/// ring textures (created on the NVENC dGPU) can't be opened → `DRV_STATUS_TEX_FAIL` → the host's 20 s
|
/// ring textures (created on the NVENC dGPU) can't be opened → `DRV_STATUS_TEX_FAIL` → the host's 20 s
|
||||||
/// black bail. Pinning the render adapter to the encode GPU fixes that. Unconditional — NOT the
|
/// black bail. Pinning the render adapter to the encode GPU fixes that. Unconditional — NOT the
|
||||||
/// SudoVDA-parity default-off branch (`docs/windows-host-rewrite.md` §2.8). Returns
|
/// SudoVDA-parity default-off branch (`design/windows-host-rewrite.md` §2.8). Returns
|
||||||
/// `STATUS_NOT_FOUND` if called before the adapter exists.
|
/// `STATUS_NOT_FOUND` if called before the adapter exists.
|
||||||
pub fn set_render_adapter(luid_low: u32, luid_high: i32) -> NTSTATUS {
|
pub fn set_render_adapter(luid_low: u32, luid_high: i32) -> NTSTATUS {
|
||||||
let Some(adapter) = adapter() else {
|
let Some(adapter) = adapter() else {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ static WATCHDOG_STARTED: AtomicBool = AtomicBool::new(false);
|
|||||||
/// without a cooperative REMOVE (crash / `TerminateProcess`) left its virtual monitor + swap-chain
|
/// without a cooperative REMOVE (crash / `TerminateProcess`) left its virtual monitor + swap-chain
|
||||||
/// worker + pooled D3D device wedged in WUDFHost until the next host start's CLEAR_ALL, and a
|
/// worker + pooled D3D device wedged in WUDFHost until the next host start's CLEAR_ALL, and a
|
||||||
/// not-restarted host left the orphan monitor in the desktop topology indefinitely
|
/// not-restarted host left the orphan monitor in the desktop topology indefinitely
|
||||||
/// (`docs/windows-host-rewrite.md` §2.8). This thread closes that: if no IOCTL arrives for
|
/// (`design/windows-host-rewrite.md` §2.8). This thread closes that: if no IOCTL arrives for
|
||||||
/// `WATCHDOG_TIMEOUT_S` while monitors exist, it departs them all.
|
/// `WATCHDOG_TIMEOUT_S` while monitors exist, it departs them all.
|
||||||
///
|
///
|
||||||
/// (A WDF `EvtFileClose` on the control handle would be more immediate — the plan's preferred §3.4
|
/// (A WDF `EvtFileClose` on the control handle would be more immediate — the plan's preferred §3.4
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//! pf-vdisplay — the all-Rust UMDF IddCx virtual-display driver (M1 step-2 rewrite, on wdk-sys + the
|
//! pf-vdisplay — the all-Rust UMDF IddCx virtual-display driver (M1 step-2 rewrite, on wdk-sys + the
|
||||||
//! owned pf-driver-proto ABI). See docs/windows-host-rewrite.md §14 for the full port plan.
|
//! owned pf-driver-proto ABI). See design/windows-host-rewrite.md §14 for the full port plan.
|
||||||
//!
|
//!
|
||||||
//! STEP 2: the IddCx driver SKELETON — DriverEntry → driver_add builds the full `IDD_CX_CLIENT_CONFIG`
|
//! STEP 2: the IddCx driver SKELETON — DriverEntry → driver_add builds the full `IDD_CX_CLIENT_CONFIG`
|
||||||
//! (14 IddCx callbacks + the PnP `EvtDeviceD0Entry`, all stubs) sized via the versioned
|
//! (14 IddCx callbacks + the PnP `EvtDeviceD0Entry`, all stubs) sized via the versioned
|
||||||
|
|||||||
@@ -205,5 +205,5 @@ cat <<'NEXT'
|
|||||||
export XDG_RUNTIME_DIR=/run/user/$(id -u) WAYLAND_DISPLAY=wayland-1
|
export XDG_RUNTIME_DIR=/run/user/$(id -u) WAYLAND_DISPLAY=wayland-1
|
||||||
swaymsg -t get_outputs # confirm HEADLESS-1
|
swaymsg -t get_outputs # confirm HEADLESS-1
|
||||||
bash scripts/headless/capture-smoke-test.sh # wf-recorder -> hevc_nvenc -> /tmp/*.mkv
|
bash scripts/headless/capture-smoke-test.sh # wf-recorder -> hevc_nvenc -> /tmp/*.mkv
|
||||||
5. Then start M0 proper: see docs/linux-setup.md.
|
5. Then start M0 proper: see design/linux-setup.md.
|
||||||
NEXT
|
NEXT
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Provision the Windows Driver Kit (WDK) + cargo-wdk on the self-hosted windows-amd64 runner, so the
|
# Provision the Windows Driver Kit (WDK) + cargo-wdk on the self-hosted windows-amd64 runner, so the
|
||||||
# all-Rust UMDF drivers (pf-vdisplay + the gamepad drivers, unified on microsoft/windows-drivers-rs)
|
# all-Rust UMDF drivers (pf-vdisplay + the gamepad drivers, unified on microsoft/windows-drivers-rs)
|
||||||
# can build there. See docs/windows-host-rewrite.md (M0).
|
# can build there. See design/windows-host-rewrite.md (M0).
|
||||||
#
|
#
|
||||||
# The runner already has the base Windows SDK 10.0.26100 (um/ headers) + MSVC + LLVM + Rust, but NOT the
|
# The runner already has the base Windows SDK 10.0.26100 (um/ headers) + MSVC + LLVM + Rust, but NOT the
|
||||||
# WDK — no km/ + wdf/ + um/iddcx headers, no inf2cat/stampinf/devgen. wdk-sys's bindgen needs those.
|
# WDK — no km/ + wdf/ + um/iddcx headers, no inf2cat/stampinf/devgen. wdk-sys's bindgen needs those.
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
# ScreenCast portal (xdg-desktop-portal-wlr) and the punktfunk host share one bus. After this
|
# ScreenCast portal (xdg-desktop-portal-wlr) and the punktfunk host share one bus. After this
|
||||||
# is up, run `prepare-session.sh` from a second shell to set the mode + portal env.
|
# is up, run `prepare-session.sh` from a second shell to set the mode + portal env.
|
||||||
#
|
#
|
||||||
# Prereqs (see docs/linux-setup.md / scripts/bootstrap-ubuntu.sh):
|
# Prereqs (see design/linux-setup.md / scripts/bootstrap-ubuntu.sh):
|
||||||
# - nvidia-drm.modeset=Y
|
# - nvidia-drm.modeset=Y
|
||||||
# - the NVIDIA GL/EGL userspace (libnvidia-gl-NNN) — provides libEGL_nvidia + the GLVND
|
# - the NVIDIA GL/EGL userspace (libnvidia-gl-NNN) — provides libEGL_nvidia + the GLVND
|
||||||
# vendor JSON; without it wlroots can't init EGL on the GPU and falls back to pixman,
|
# vendor JSON; without it wlroots can't init EGL on the GPU and falls back to pixman,
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
# punktfunk management console — TanStack Start built with Bun, served by the Nitro `bun`
|
# punktfunk management console — TanStack Start built with Bun, served by the Nitro `bun`
|
||||||
# preset bundle. Build context is the REPO ROOT (orval generates the API client from
|
# preset bundle. Build context is the REPO ROOT (orval generates the API client from
|
||||||
# docs/api/openapi.json, referenced as ../docs/api/openapi.json from web/):
|
# api/openapi.json, referenced as ../api/openapi.json from web/):
|
||||||
#
|
#
|
||||||
# docker build -f web/Dockerfile -t punktfunk-web .
|
# docker build -f web/Dockerfile -t punktfunk-web .
|
||||||
#
|
#
|
||||||
@@ -15,7 +15,7 @@ WORKDIR /repo/web
|
|||||||
COPY web/package.json web/bun.lock ./
|
COPY web/package.json web/bun.lock ./
|
||||||
RUN bun install --frozen-lockfile --ignore-scripts
|
RUN bun install --frozen-lockfile --ignore-scripts
|
||||||
|
|
||||||
COPY docs/api/openapi.json /repo/docs/api/openapi.json
|
COPY api/openapi.json /repo/api/openapi.json
|
||||||
COPY web/ ./
|
COPY web/ ./
|
||||||
# prebuild runs orval (openapi → src/api/gen); the paraglide vite plugin compiles i18n.
|
# prebuild runs orval (openapi → src/api/gen); the paraglide vite plugin compiles i18n.
|
||||||
RUN bun run build
|
RUN bun run build
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
# punktfunk web — management console
|
# punktfunk web — management console
|
||||||
|
|
||||||
The browser UI for the punktfunk host's **management REST API** (`crates/punktfunk-host/src/mgmt.rs`,
|
The browser UI for the punktfunk host's **management REST API** (`crates/punktfunk-host/src/mgmt.rs`,
|
||||||
OpenAPI at `docs/api/openapi.json`). It shows live status, host capabilities, paired
|
OpenAPI at `api/openapi.json`). It shows live status, host capabilities, paired
|
||||||
clients, the pairing-PIN flow, and session controls.
|
clients, the pairing-PIN flow, and session controls.
|
||||||
|
|
||||||
Stack: **TanStack Start** (full SSR) on **Bun** via **Nitro v2** (`bun` preset) · **React
|
Stack: **TanStack Start** (full SSR) on **Bun** via **Nitro v2** (`bun` preset) · **React
|
||||||
@@ -88,7 +88,7 @@ Generated code is **not committed** (gitignored) — reproduced from sources:
|
|||||||
`bun install` (`prepare`) and before `dev`/`build` (`pre*` for orval; the Vite plugin
|
`bun install` (`prepare`) and before `dev`/`build` (`pre*` for orval; the Vite plugin
|
||||||
compiles paraglide on dev/build).
|
compiles paraglide on dev/build).
|
||||||
- After a management-API change, regenerate the spec on the Rust side first:
|
- After a management-API change, regenerate the spec on the Rust side first:
|
||||||
`cargo run -p punktfunk-host -- openapi > docs/api/openapi.json`, then `bun run api:gen`.
|
`cargo run -p punktfunk-host -- openapi > api/openapi.json`, then `bun run api:gen`.
|
||||||
|
|
||||||
## Layout
|
## Layout
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -2,11 +2,11 @@ import { defineConfig } from "orval";
|
|||||||
|
|
||||||
// Generates a typed React Query client from the host's checked-in OpenAPI document.
|
// Generates a typed React Query client from the host's checked-in OpenAPI document.
|
||||||
// Regenerate after any management-API change: `pnpm api:gen` (the Rust side regenerates
|
// Regenerate after any management-API change: `pnpm api:gen` (the Rust side regenerates
|
||||||
// docs/api/openapi.json via `cargo run -p punktfunk-host -- openapi`).
|
// api/openapi.json via `cargo run -p punktfunk-host -- openapi`).
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
punktfunk: {
|
punktfunk: {
|
||||||
input: {
|
input: {
|
||||||
target: "../docs/api/openapi.json",
|
target: "../api/openapi.json",
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
mode: "tags-split",
|
mode: "tags-split",
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
/* ── punktfunk brand · violet product chrome ────────────────────────────────
|
/* ── punktfunk brand · violet product chrome ────────────────────────────────
|
||||||
Two themes on one violet identity: LIGHT (lavender docs surface — the same
|
Two themes on one violet identity: LIGHT (lavender docs surface — the same
|
||||||
palette the docs/Scalar reference uses: white bg, faint-violet cards/borders,
|
palette the design/Scalar reference uses: white bg, faint-violet cards/borders,
|
||||||
#6c5bf3 brand) is the :root default; DARK (the violet-tinted app-icon chrome
|
#6c5bf3 brand) is the :root default; DARK (the violet-tinted app-icon chrome
|
||||||
#141019 / #1c1530, #a79ff8 brand) is the `.dark` override. The live console
|
#141019 / #1c1530, #a79ff8 brand) is the `.dark` override. The live console
|
||||||
pins `<html class="dark">` so it stays dark by default — removing or toggling
|
pins `<html class="dark">` so it stays dark by default — removing or toggling
|
||||||
|
|||||||
Reference in New Issue
Block a user