feat(usb): track keyboard connection state

Add a persistent KBD_PRESENT atomic (set on setup, cleared on unplug)
and a keyboard_present() accessor. DEV_GONE is a one-shot detach event
the client loop consumes, not a state the panel can read.
This commit is contained in:
Julien Calixte
2026-07-08 21:33:32 +02:00
parent d6b9e46ec1
commit ddd9c387d3

View File

@@ -71,6 +71,10 @@ const SET_IDLE_INFINITE: [u8; 8] = [0x21, 0x0a, 0x00, 0x00, KBD_INTERFACE, 0x00,
static NEW_DEV_ADDR: AtomicU8 = AtomicU8::new(0);
/// Set when the open device is unplugged.
static DEV_GONE: AtomicBool = AtomicBool::new(false);
/// Whether a keyboard is currently open (attached + set up). Unlike `DEV_GONE`
/// (a one-shot detach event the client loop consumes), this is the persistent
/// connection state the side-panel disconnect flag reads via `keyboard_present`.
static KBD_PRESENT: AtomicBool = AtomicBool::new(false);
/// Control-transfer completion, published by `ctrl_cb` to the setup routine.
static CTRL_DONE: AtomicBool = AtomicBool::new(false);
static CTRL_STATUS: AtomicU32 = AtomicU32::new(0);
@@ -92,6 +96,12 @@ pub fn next_key() -> Option<Key> {
KEY_QUEUE.get()?.lock().unwrap().pop_front()
}
/// Whether a USB keyboard is currently attached and set up. Read by the main
/// loop to drive the side-panel disconnect flag.
pub fn keyboard_present() -> bool {
KBD_PRESENT.load(Ordering::SeqCst)
}
/// Install the USB Host Library and spawn the daemon + client event pumps.
/// Returns once the stack is up; key events then arrive via `next_key()`.
pub fn start() -> Result<(), EspError> {
@@ -154,6 +164,7 @@ fn client_loop() {
Ok((dev, xfer)) => {
open_dev = dev;
report_xfer = xfer;
KBD_PRESENT.store(true, Ordering::SeqCst);
}
Err(e) => log::error!("keyboard setup failed: {e:?}"),
}
@@ -170,6 +181,7 @@ fn client_loop() {
unsafe { usb_host_device_close(client, open_dev) };
open_dev = ptr::null_mut();
*PREV_KEYS.lock().unwrap() = [0; 6];
KBD_PRESENT.store(false, Ordering::SeqCst);
}
}
}