• v0.2.0 d0d9c451aa

    chore: cut 0.2.0 — README, LICENSE, publish metadata, runtime tune, USB identity, F13

    swaits released this 2026-05-02 04:32:17 +00:00 | 6 commits to main since this release

    Release-prep work for a publish-worthy 0.2.0:

    • LICENSE: MIT, © 2026 Stephen Waits.
    • README.md: tagline, what-it-does, hardware, build/flash recipes,
      ASCII statechart overview, "Why four hours…" runtime-tuning rationale,
      USB identity section.
    • Cargo.toml: 0.1.0 → 0.2.0; description, license, repository, readme,
      keywords, categories; publish = false (firmware, not a library);
      release profile tightened (lto = "fat", opt-level = "z", panic =
      "abort"). Flashed binary stays 47 KB; the size knobs are explicit
      rather than relying on defaults.
    • CHANGELOG.md: collapse Unreleased → [0.2.0] - 2026-05-01.
    • scripts/tune_runtime.py: 4-D Monte Carlo over (RUN_DURATION, YELLOW_AT,
      RED_AT, FAST_RED_AT). PEP 723 inline deps so uv run just works.

    Runtime + LED thresholds re-derived from a typical office workday
    distribution with a per-minute press-on-warning user model. Joint
    optimum:

    RUN_DURATION: 4h00m
    YELLOW_AT / RED_AT / FAST_RED_AT (min remaining): 30 / 25 / 20

    USB identity:

    VID/PID: 046d:c07d (G502) → 1209:b0b0 (pid.codes)
    manufacturer: "Logitech" → "swaits.com"
    product: "G502 Mouse" → "jiggly"
    bcdDevice: default 0x0010 → 0x0200 (matches firmware version)
    serial: (none) → RP2040 chip ID as 16 hex chars

    Bug fix in the descriptor change: an interim version spoofed the
    Logitech Unifying Receiver (046d:c52b). On Linux, hid-logitech-dj
    matches that exact PID and tries to talk Logitech's HID++ protocol to
    enumerate paired wireless devices. The firmware doesn't speak HID++,
    so the driver waits through ~10–20 s of control-transfer timeouts on
    every plug before unbinding and letting hid-generic actually start
    polling. macOS has no such driver and was always fast. Moving to a
    pid.codes VID routes the device straight to hid-generic.

    Wake key: tapped Left Shift in early versions to wake the host. In
    practice that turned out to be exactly the nightmare scenario it
    sounds like — if the deadline preempted the loop between a Shift-down
    report and its Shift-up, the host would silently capitalise every
    keystroke from the user's real keyboard until the device was unplugged.
    Switched to F13: still wakes any modern OS, but no mainstream OS maps
    F13 by default, so a stuck F13 has zero visible effect. Also added an
    unconditional all-keys-released cleanup report at the end of the wake
    action, bounded by KBD_RELEASE_DEADLINE = 100 ms, so even a deadline
    that fires mid-press can't leave anything held.

    Wake refactor: WakingWithKeyboard and WakingWithMouse use oneshot
    entry: actions that race their work against an internal deadline via
    embassy_futures::select; the chart timer (on(after KBD_PHASE_DURATION)
    / on(after MOUSE_PHASE_DURATION)) advances. Removes a class of "slow
    USB ⇒ chart stalls" failure modes from the wake path.

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    Downloads