/** * keyrelay -- build-time defaults. * * Everything here is a DEFAULT. The values stored in NVS win at runtime, so the * network and the control passphrase can be changed from the serial console * without reflashing (`wifi`, `ap`, `token` -- see README "First bring-up"). * * Nothing secret belongs in this file. The default passphrase is deliberately * weak and loudly announced as such on the serial console and in the web page, * because a keyboard that anyone on the LAN can arm is an open door. */ #pragma once #include #include namespace kr { constexpr const char kFirmwareName[] = "keyrelay"; constexpr const char kFirmwareVersion[] = "1.0.0"; // --------------------------------------------------------------------------- // Network // --------------------------------------------------------------------------- // Control plane only: the keystrokes travel WiFi -> board -> USB. The target // machine provides nothing but 5 V and a USB port, and never sees a network. constexpr uint16_t kHttpPort = 80; constexpr char kHostname[] = "keyrelay"; // http://keyrelay.local // Fallback access point, started whenever the station interface is not up, so // the board is reachable with no infrastructure at all (air-gapped target). constexpr char kApSsid[] = "keyrelay-ctl"; constexpr char kApPass[] = "keyrelay-ctl-pass"; // >= 8 chars, WPA2. CHANGE IT. constexpr char kApGw[] = "192.168.4.1"; // Build-time station credentials (optional, still only a default). Override with // pio run -e bridge -D KR_STA_SSID='"MyNet"' -D KR_STA_PASS='"hunter2"' // without ever committing them. #ifndef KR_STA_SSID #define KR_STA_SSID "" #endif #ifndef KR_STA_PASS #define KR_STA_PASS "" #endif constexpr uint32_t kStaTimeoutMs = 8000; // give the association attempt this long at boot constexpr uint32_t kStaRetryMs = 20000; // ... then retry in the background at this rate // --------------------------------------------------------------------------- // Control passphrase // --------------------------------------------------------------------------- // Checked on every WebSocket connection and on /status. The page cannot arm the // bridge without it, and nothing reaches the target until the bridge is armed. constexpr char kDefaultToken[] = "changeme"; constexpr size_t kTokenMax = 32; constexpr uint8_t kTokenMaxFails = 5; // then stop evaluating the token ... constexpr uint32_t kTokenLockMs = 30000; // ... for this long // --------------------------------------------------------------------------- // Keystroke path // --------------------------------------------------------------------------- constexpr size_t kMaxKeysPerMessage = 8; // protocol cap (HID carries 6) constexpr uint32_t kCadHoldMs = 60; // how long Ctrl+Alt+Del is held down constexpr uint32_t kChordHoldMs = 40; // ditto for the other special chords constexpr uint32_t kMinReportGapUs = 1000; // 1 kHz floor: the host polls at 1 kHz constexpr size_t kReportQueueDepth = 48; // bursts from a fast typist // --------------------------------------------------------------------------- // Pasted text // --------------------------------------------------------------------------- // `P=:` (src/text.h) types a run of characters that a human pasted and // then deliberately sent. The board owns the character map and the pacing: a // controller's clock, arriving over WiFi in whatever order the network delivers // it, is not a keyboard timing source. The controller asks for a pace; the board // keeps it. // // One controller frame is still one command, so a frame carries at most // kTextFrameMax characters and a long paste arrives as several frames. The board // holds whatever it has been given and says so in `typing` in the status frame, // which is how a controller knows it may send the next piece. constexpr size_t kTextFrameMax = 120; // characters per P= frame constexpr size_t kTextJobCap = 2048; // characters held for one paste job constexpr uint16_t kTextPeriodMsDefault = 12; // ms per character when asked for 0 constexpr uint16_t kTextPeriodMaxMs = 250; // slowest pace a controller may ask for constexpr uint16_t kTextHoldMaxMs = 6; // how long one character is held down // --------------------------------------------------------------------------- // Mouse // --------------------------------------------------------------------------- // The controller captures the pointer with the browser's own Pointer Lock and // forwards it as relative HID mouse reports. One M= frame is one report: the button // byte is restated every frame, and a movement delta is self-contained, so a frame // that never arrives moves the cursor a little less and strands nothing. See mouse.h. // // The deltas are capped at one report's worth (a signed byte) because one frame is // one command: splitting a large movement into several frames is the controller's // job, exactly like splitting a long paste. The board does not split -- it would turn // one command into a queue depth nobody asked for. constexpr int8_t kMouseDeltaMax = 127; // one signed byte, the report's range constexpr uint8_t kMouseButtonMask = 0x1F; // 5 buttons: all the report can carry constexpr size_t kMouseReportQueueDepth = 32; // movement bursts, same fail-safe // Safety: a bridge that has heard nothing from its controller for this long is // a bridge that should not be typing. Arming never survives it (laptop slept, // cable unplugged, browser killed). constexpr uint32_t kNoClientTimeoutMs = 8000; // Status heartbeat to the controller, and the interval of the held-key watchdog. constexpr uint32_t kStatusIntervalMs = 1000; // --------------------------------------------------------------------------- // Control-server buffers // --------------------------------------------------------------------------- // The status JSON, sized for every field in StatusSnapshot plus headroom. Sized in // one place because three call sites build it and a truncated status lies about state, // which is worse than no status. constexpr size_t kStatusJsonCap = 384; constexpr size_t kHttpHeaderCap = 1536; // reject a request line bigger than this constexpr size_t kWsMessageCap = 256; // one controller frame is a command, not a payload constexpr uint32_t kAuthTimeoutMs = 5000; // a new socket must authenticate this fast } // namespace kr