DuckyDeck Studio (v0.1.4) is a native Linux desktop configurator, DSVM v2 bytecode compiler, KDE Plasma 6 Wayland Auto-Switcher, and host automation daemon for the duckyPad Pro (0x0483:0xd11d) and duckyPad 2020 (0x0483:0xd11c).

🏷️ Release Metadata & Official Links
Application Version: v0.1.6  β€’  Custom Firmware: v1.1.0 (DDS_FW_1.1.0_b3291568.bin)  β€’  KDE Plasma 6 Applet: v1.0.2
Website & User Guide: https://duckydeckstudio.com  β€’  Architecture Reference: https://duckydeckstudio.com/architecture.html  β€’  GitHub Repository: https://github.com/russellmilliner/duckydeck-studio
Rust 2021 Edition CXX-Qt 0.7 Bridge Qt 6 & KDE Kirigami 6 Flatpak org.kde.Platform//6.11 Two-Pass DSVM v2 Compiler zbus KWin Wayland Bridge Embedded HTTP/1.1 REST API Automated Scene-Graph UI Test Suite

πŸ›οΈ 1. System Overview & Core Design Philosophy

⚑ 1. Zero-Runtime-Wrapper Native Stack

Built directly in Rust (2021 edition) bridged to Qt 6 / KDE Frameworks 6 (Kirigami + KSyntaxHighlighting) via CXX-Qt 0.7, avoiding Electron or Python runtime overhead while delivering native KDE Breeze theming, fractional HiDPI scaling, and first-class Wayland integration.

πŸ’Ύ 2. Offline-First & Deterministic SD Sync

All profile edits, key scripts, RGB LED overrides, and rule bindings are immediately persisted to a per-device local cache (~/.local/share/duckydeck-studio/profile_cache/<serial>/) and compared against the hardware microSD state using SHA-256 content fingerprinting before writing and read-back validating .dsb bytecode.

βš™οΈ 3. Pure-Rust DSVM v2 Compiler

Compiles duckyScript 3 (keyN.txt / keyN-release.txt) directly into duckyPad virtual machine bytecode (.dsb) with live syntax diagnostics, Shunting-Yard RPN expression evaluation, control flow (IF/ELSE/WHILE), functions, OLED graphics primitives, and PGV (_GV0.._GV31) access.

πŸ”„ 4. Bidirectional Hardware-Host Automation

Combines KWin Wayland window focus events (zbus D-Bus listener) for automatic profile switching (Host β†’ duckyPad) with USB HID PGV polling (_GV31 encoded via encode_pgv31_trigger) and global F13–F24 shortcut triggers for Web API webhooks and Desktop Application Launching (duckyPad β†’ Host).

πŸ—ΊοΈ 2. High-Level System Architecture

DuckyDeck Studio is structured into four cleanly separated layers communicating across a thread-safe CXX-Qt bridge:

Layer 1 β€” Qt 6 / KDE Kirigami QML Frontend (src/qml/*.qml)
Main.qml ApplicationWindow Shell, Profiles Sidebar, Inline Filter & duckyScript 3 Editor
HardwareCanvas.qml 4Γ—5 RGB Matrix, Option C Header-Footer Keycaps, Dual Encoders, 128Γ—128 OLED Simulator
OledDesktopWidget.qml Floating Companion Widget with 0Β°/90Β°/180Β°/270Β° Grid & In-Key Label Rotation
Builders & Dialogs WebApiBuilder, AppLaunchBuilder, AutoSwitchDrawer, ColorPickerWindow, SdSyncDialog, SettingsPage, EventLogDialog
β‡… QProperty Bindings & QInvokable Calls (Single-Thread Qt Affinity)
Layer 2 β€” CXX-Qt 0.7 QObject Bridge & Native KF6 Helpers
DeviceController (src/bridge/device_controller.rs) Central QObject, CxxQtThread Queue, Profile/Rule Invariants & State Synchronization
Bridge Submodules (src/bridge/*.rs) rest_routes.rs, serialize.rs, event_log.rs, showcase.rs
KF6 C++ Helper (src/cpp/app_helper.h) QSystemTrayIcon (Dynamic Profile Badge + About Action), KColorScheme, KSyntaxHighlighting
β‡… Thread-Safe Rust APIs, Arc<Mutex<...>> Registries & CxxQtThread Queues
Layer 3 β€” Pure-Rust Core Subsystems
Hardware & Storage (src/hardware/*.rs) storage.rs (HID), profile.rs (SD/Cache), msc.rs (udisksctl / Flatpak Host Spawn), firmware.rs, permissions.rs
DSVM v2 Compiler (src/vm/compiler.rs) Two-Pass duckyScript 3 β†’ .dsb Bytecode Compiler, RPN Evaluator & Syntax Verifier
Host Actions (src/actions/*.rs) web_api.rs (HTTP/HA + Keyring), app_launch.rs (Desktop Spawner), desktop_apps.rs (.desktop Scanner)
Wayland & REST API auto_switcher.rs (KWin 6 D-Bus + Rule Remapper), api_server.rs (HTTP/1.1 /api/v1/*), shortcut_scraper.rs
β‡… USB HID (0x0483:0xd11d / 0xd11c), Session D-Bus & Flatpak Host Portal
Layer 4 β€” Background Worker Threads & External Interfaces
USB Hotplug & _GV31 Poller Polls HID 0x00 & 0x18, decodes _GV31 triggers (0x5741xxxx), re-arms _GV31=0 via 0x19
Tokio zbus D-Bus Service io.github.duckydeck.Studio at /KWinBridge for KWin Active-Window Hooks & CLI IPC
Async REST Job Worker Executes non-blocking 202 Accepted SD Sync, Mount, Unmount & Reboot jobs

πŸ“‚ 3. Repository & Module Structure

Path Responsibility
Cargo.toml Crate manifest (version = "0.1.4", cxx-qt 0.7, hidapi, zbus, tokio, reqwest, keyring, serde, serde_json, sha2).
build.rs CxxQtBuilder configuration registering QML module io.github.duckydeck and compiling src/bridge/device_controller.rs.
src/main.rs Application entrypoint: CLI & D-Bus single-instance IPC client, QApplication initialization, KSyntaxHighlighting registration, QML startup, and automated Native + Flatpak UI test suites.
src/paths.rs XDG directory helpers (XDG_CONFIG_HOME, XDG_DATA_HOME, XDG_CACHE_HOME, XDG_RUNTIME_DIR) and environment sanitization.
src/api_server.rs Embedded HTTP/1.1 REST API Server (/api/v1/*) with constant-time Bearer auth, 8-slot connection cap, 2 MB payload guard, and async job worker.
src/bridge/device_controller.rs Central #[cxx_qt::bridge] DeviceController QObject, profile fallback & Auto-Switcher synchronization invariants, background thread orchestration, and QInvokable wrappers.
src/bridge/event_log.rs Thread-safe ring buffer (SYSTEM_EVENT_LOG), log file appender, and JSON serializer for system diagnostics.
src/bridge/rest_routes.rs REST API route table and request handlers executed via the DeviceController bridge.
src/bridge/serialize.rs JSON serializers for profiles, slots, unsynced diffs, and templates exposed to QML and the REST API.
src/bridge/showcase.rs Built-in profile templates, SVG icon helpers (known_site_svg), and optional --features demo showcase generator.
src/hardware/storage.rs USB HID transport (hidapi), device discovery, RTC sync, PGV burst read/write (0x18/0x19), and submodule re-exports.
src/hardware/profile.rs DuckyProfile and DuckyKeySlot parser/writer (config.txt, profile_info.txt), SHA-256 diffing, and local cache management.
src/hardware/msc.rs USB Mass Storage (0x14) mounting/unmounting via udisksctl (bridged via flatpak-spawn --host inside Flatpak) and microSD capacity inspection.
src/hardware/firmware.rs Embedded DuckyDeck Studio custom firmware (DDS_FW_1.1.0_b3291568.bin), official dekuNukem release catalog downloader, and IEEE CRC32 integrity verification.
src/hardware/permissions.rs Inspects /sys/class/hidraw device nodes for PermissionDenied and invokes pkexec (or flatpak-spawn --host pkexec) to install 70-duckypad.rules.
src/actions/web_api.rs Web API / Webhook & Home Assistant client, OS keyring secret storage, and _GV31 trigger encoding (encode_pgv31_trigger).
src/actions/app_launch.rs Desktop Application Launcher metadata parser/generator (// @DUCKYDECK_APPLAUNCH), host-aware process spawner, and _GV31 / F13–F24 registries.
src/actions/desktop_apps.rs XDG .desktop entry scanner across system, user, and Flatpak directories.
src/vm/compiler.rs Pure-Rust duckyScript 3 β†’ DSVM v2 (.dsb) two-pass bytecode compiler and syntax verifier.
src/kwin/auto_switcher.rs KWin Wayland script injector, zbus D-Bus service (io.github.duckydeck.Studio at /KWinBridge), window picker, profile reorder/deletion rule remapper, and persisted rules (kwin_rules.json).
src/ai/shortcut_scraper.rs Parses ~/.config/kglobalshortcutsrc and converts KDE shortcuts into duckyScript 3 syntax (kde_shortcut_to_duckyscript).
src/cpp/app_helper.h C++ helper bridging QSystemTrayIcon (dynamic profile badge, SD status, Auto-Switcher/Autostart toggles, and "About DuckyDeck Studio" dialog trigger), KColorScheme, KIconLoader, and KSyntaxHighlighting into QML.
src/qml/*.qml 14 QML components: Main.qml, HardwareCanvas.qml, OledDesktopWidget.qml, AutoSwitchDrawer.qml, ColorPickerWindow.qml, WebApiBuilder.qml, AppLaunchBuilder.qml, SettingsPage.qml, RestApiSettings.qml, SdSyncDialog.qml, EventLogDialog.qml, PgvInspectorDrawer.qml, AiArchitectModal.qml, and UdevBanner.qml.

πŸ”— 4. CXX-Qt Concurrency Model & _GV31 Trigger Encoding

Because Qt GUI objects (QObject) have strict single-thread affinity on the Qt main event loop thread, src/bridge/device_controller.rs separates state into Qt-thread-owned fields and thread-safe shared registries:

Unified _GV31 Hardware-to-Host Trigger Word

Both Web API (// @DUCKYDECK_WEBAPI) and Desktop Application Launch (// @DUCKYDECK_APPLAUNCH) scripts in pgv trigger mode write a 32-bit magic word into Persistent Global Variable _GV31 (PGV_TRIGGER_INDEX = 31):

// 32-bit _GV31 Trigger Word Layout:
// Bits 16..31 : 0x5741 ("WA" magic header)
// Bit  15     : is_release (0 = On Press, 1 = On Release)
// Bits 8..14  : profile_num (1..64)
// Bits 0..7   : slot_num (1..58)
pub fn encode_pgv31_trigger(profile_num: u8, slot_num: u8, is_release: bool) -> u32 {
    let rel_bit = if is_release { 0x8000 } else { 0 };
    0x5741_0000 | rel_bit | ((profile_num as u32 & 0x7F) << 8) | (slot_num as u32)
}

When the background USB HID poller reads _GV0.._GV31 via command 0x18 (HID_CMD_DUMP_PGV) and detects a non-zero _GV31 matching decode_pgv31_trigger, it immediately writes _GV31 = 0 via command 0x19 (HID_CMD_WRITE_PGV) to re-arm the trigger and dispatches the matching WEB_API_PGV_REGISTRY or APP_LAUNCH_PGV_REGISTRY action on the Linux host.

πŸ”Œ 5. USB HID Protocol, USB Mass Storage & Flatpak Host Bridge

5.1 64-Byte USB HID Report Protocol (src/hardware/storage.rs)

The duckyPad Pro (0x0483:0xd11d) and duckyPad 2020 (0x0483:0xd11c) communicate over a 64-byte vendor-defined USB HID interface (HID_REPORT_ID_OUT = 0x05):

Command Byte (tx[2]) Constant Name Description
0x00 HID_CMD_QUERY_INFO Returns firmware version, hardware model, serial number, active profile, and 'D','D','S' custom firmware capability signature.
0x01 HID_CMD_GOTO_PROFILE_BY_NUM Switches the active hardware profile by number (1..=64).
0x04 HID_CMD_SET_LED_SINGLE Sets key RGB LED overrides in real time.
0x14 HID_CMD_SOFTWARE_RESET Reboots the duckyPad firmware (tx[3] = 0 normal HID mode, tx[3] = 1 USB Mass Storage mode).
0x17 HID_CMD_GOTO_PROFILE_BY_NAME Switches the active hardware profile by folder name.
0x18 HID_CMD_DUMP_PGV Reads all 32 32-bit Persistent Global Variables (_GV0.._GV31, 128 bytes) across 3 burst packets (start_idx = 0, 15, 30).
0x19 HID_CMD_WRITE_PGV Writes up to 12 (pgv_index | 0x80, i32_le) entries per packet into _GV0.._GV31.

5.2 USB Mass Storage (MSC) Mounting & Flatpak Host Command Bridging (src/hardware/msc.rs)

When reading or writing profiles or staging firmware on a duckyPad Pro, DuckyDeck Studio sends HID command 0x14 (tx[3] = 1) to enumerate the microSD card as a TinyUSB Mass Storage block device (/dev/disk/by-label/DP24_* or /dev/disk/by-id/*TinyUSB_Flash_Storage*), mounts the FAT32 partition via udisksctl mount --no-user-interaction -b /dev/sdX1, performs SHA-256 read-back verification, flushes buffers via sync, unmounts cleanly via udisksctl unmount, and reboots back into HID mode (0x14, tx[3] = 0).

πŸ“¦ Flatpak Host Storage Bridge (run_storage_cmd)
Inside the Flatpak sandbox (org.kde.Platform//6.11), host utilities like udisksctl and umount are not installed inside the container's /usr/bin. src/hardware/msc.rs automatically detects /.flatpak-info and routes udisksctl, umount, sync, and host /proc/mounts queries through flatpak-spawn --host while accessing the mounted filesystem directly via --filesystem=/run/media:rw and --filesystem=/media:rw.

βš™οΈ 6. DSVM v2 Bytecode Compiler (src/vm/compiler.rs)

The duckyPad Pro executes compiled DSVM v2 (.dsb) stack-machine bytecode binaries rather than interpreting raw text on-device. src/vm/compiler.rs implements a complete two-pass compiler in pure Rust:

1️⃣ Preprocessor & Directive Preservation

Strips comments while preserving structured visual-builder metadata directives (// @DUCKYDECK_WEBAPI {...} and // @DUCKYDECK_APPLAUNCH {...}), expands DEFINE macros safely (with recursion/expansion caps), and injects $_ALLOW_ABORT / $_DONT_REPEAT header flags.

2️⃣ Block & Control-Flow Parser

Resolves nested IF / ELSE_IF / ELSE / END_IF, WHILE / END_WHILE, LOOP0..LOOP9 state machines, and FUNCTION / RETURN call frames into structured intermediate labels.

3️⃣ Shunting-Yard RPN Expression Engine

Converts infix arithmetic, bitwise, comparison, and boolean expressions into stack-based RPN instructions (OP_PUSH_CONST, OP_PUSH_VAR, OP_ADD, OP_EQ, OP_BITWISE_AND) and maps user variables alongside hardware globals (_GV0.._GV31).

4️⃣ Two-Pass Linker & Bytecode Emitter

Resolves 16-bit jump target offsets and null-terminated UTF-8 string pool addresses across two passes, emitting little-endian .dsb binaries verified for parity against official DSVM v2 semantics.

πŸͺŸ 7. Wayland Auto-Switcher, Session D-Bus IPC & Rule Invariants

On KDE Plasma 6 Wayland, DuckyDeck Studio registers the session D-Bus service io.github.duckydeck.Studio at object path /KWinBridge (interface io.github.duckydeck.KWinBridge) via zbus:

Profile Fallback & Auto-Switcher Synchronization Invariants

First-Run Deck Setup, Legacy Migration & Conflict Resolution

🎨 8. Keycap Layout, OLED Desktop Widget & Automated UI Verification

🎹 Option C Header-Footer Split Keycap Layout

Each mechanical keycap cell in src/qml/HardwareCanvas.qml uses a non-overlapping 3-zone vertical structure: a 15px top header strip (key number + pill-shaped RGB LED bar), a centered 2-line OLED preview area, and a 15px bottom footer strip (APP/API host badges + ↻/⏹ execution flags).

πŸ–₯️ 4-Way Rotated Desktop OLED Widget

src/qml/OledDesktopWidget.qml and the KDE Plasma 6 Applet (plasmoid/io.github.duckydeck.oled) support per-profile orientation (0Β°, 90Β°, 180Β°, 270Β°, or Follow Hardware OLED), applying both 4Γ—5 grid coordinate remapping and in-key text rotation.

Automated Scene-Graph UI Test Suite (Native & Flatpak)

src/qml/EventLogDialog.qml and src/main.rs include a comprehensive automated UI verification harness (--ui-test-suite) that walks every window, drawer, and modal across both Dark Mode and Light Mode at 100% and 115% zoom levels, auditing:

πŸ’Ύ 9. Persistence, Credentials & Hardware Portability

Path (Host / XDG) Flatpak Sandbox Equivalent Contents
~/.config/duckydeck-studio/kwin_rules.json ~/.var/app/io.github.duckydeck.Studio/config/duckydeck-studio/kwin_rules.json Auto-Switcher rules, fallback profile, UI text scale, tray settings, REST API config, Global Profile Webhook, and Saved Colors palette.
~/.config/duckydeck-studio/first_run_onboarding_state.json ~/.var/app/io.github.duckydeck.Studio/config/duckydeck-studio/first_run_onboarding_state.json Onboarding setup completion flag and application version metadata.
<microSD>/duckydeck_rules.json <microSD>/duckydeck_rules.json Portable KWin Wayland auto-switcher rules bundle (SdPersistedRulesBundle) stored on deck microSD.
~/.config/duckydeck-studio/oled_widget_geometry.json ~/.var/app/io.github.duckydeck.Studio/config/duckydeck-studio/oled_widget_geometry.json Desktop OLED Widget monitor, position, size, transparency, always-on-top, and frameless settings.
~/.local/share/duckydeck-studio/profile_cache/<serial>/ ~/.var/app/io.github.duckydeck.Studio/data/duckydeck-studio/profile_cache/<serial>/ Offline mirror of all hardware profiles and .sd_synced_snapshot.json baseline for SHA-256 diffing.
~/.local/share/duckydeck-studio/firmware/DDS_FW_1.1.0_b3291568.bin /app/share/duckydeck-studio/firmware/DDS_FW_1.1.0_b3291568.bin Bundled DuckyDeck Studio custom firmware v1.1.0 (also embedded in the binary for automatic extraction).

🌐 9.7 Embedded HTTP REST API Server (src/api_server.rs)

DuckyDeck Studio embeds a bounded, stoppable/restartable HTTP/1.1 REST API server (src/api_server.rs and src/bridge/rest_routes.rs):

πŸ“¦ 10. Flatpak Sandbox Architecture & Packaging

DuckyDeck Studio is packaged as a self-contained Flatpak bundle (io.github.duckydeck.Studio) built against org.kde.Platform//6.11 and org.kde.Sdk//6.11 (configured in io.github.duckydeck.Studio.yml and scripts/build-flatpak.sh).

Sandbox Permission Purpose
--device=all, --filesystem=/run/udev:ro Direct USB HID access to /dev/hidraw* and block device symlink discovery in /dev/disk/by-label and /dev/disk/by-id.
--filesystem=/run/media:rw, --filesystem=/media:rw, --filesystem=xdg-run/gvfs:ro Read/write access to mounted duckyPad microSD volumes for profile sync and firmware staging.
--talk-name=org.freedesktop.Flatpak, --system-talk-name=org.freedesktop.UDisks2 Allows invoking flatpak-spawn --host udisksctl / umount / pkexec / xdg-open and launching host desktop applications.
--talk-name=org.kde.KWin, --filesystem=xdg-run/duckydeck-studio:create Allows loading the KWin 6 Wayland active-window tracking script and receiving focus callbacks over session D-Bus.
--talk-name=org.kde.StatusNotifierWatcher, --talk-name=org.freedesktop.secrets System tray icon integration and OS keyring credential storage.

Download, Install & Run the Flatpak

# Download & install the latest Flatpak bundle directly:
curl -LO https://duckydeckstudio.com/releases/duckydeck-studio-v0.1.4-x86_64.flatpak
flatpak install --user -y duckydeck-studio-v0.1.4-x86_64.flatpak

# Launch GUI:
flatpak run io.github.duckydeck.Studio

# Run CLI commands inside Flatpak:
flatpak run io.github.duckydeck.Studio --status

πŸ› οΈ 11. Building, Testing & Extending

# 1. Run formatting, clippy (-D warnings), unit tests, and architecture path checks:
bash scripts/check.sh

# 2. Run the Native QML UI Overflow, Contrast & Behavioral Test Suite:
cargo test ui_test_suite::test_full_qml_ui_overflow_and_contrast_suite -- --ignored --nocapture

# 3. Build & install the Flatpak bundle from source:
bash scripts/build-flatpak.sh
flatpak install --user -y --reinstall target/release/duckydeck-studio-v0.1.4-x86_64.flatpak

# 4. Run the Flatpak QML UI Test Suite inside the Flatpak sandbox:
bash scripts/test-flatpak-ui.sh