fix: VirtIO keyboard input latency and direction accuracy

- Driver now drains SYN/repeat/unknown events in a loop instead of
  returning None on the first non-key event
- Snake drains all pending input events per tick, applies only the
  latest direction change (prevents stale event accumulation)
This commit is contained in:
2026-10-19 00:34:13 +02:00
parent 0a47b5489a
commit 2792387348
2 changed files with 30 additions and 26 deletions

View File

@@ -65,16 +65,19 @@ extern "C" fn main() {
} }
fn handle_input(snake: &mut Snake) { fn handle_input(snake: &mut Snake) {
let _ = syscall::send(INPUT_EP, 0, 0, 0, 0); // Drain all pending events, apply the latest direction
let (tag, kind, _, _) = syscall::receive(INPUT_EP); loop {
let _ = syscall::send(INPUT_EP, 0, 0, 0, 0);
if tag == 1 { let (tag, kind, _, _) = syscall::receive(INPUT_EP);
match kind { if tag == 0 { break; } // NoEvent — queue drained
0 => snake.set_direction(Direction::Up), if tag == 1 {
1 => snake.set_direction(Direction::Down), match kind {
2 => snake.set_direction(Direction::Left), 0 => snake.set_direction(Direction::Up),
3 => snake.set_direction(Direction::Right), 1 => snake.set_direction(Direction::Down),
_ => {} 2 => snake.set_direction(Direction::Left),
3 => snake.set_direction(Direction::Right),
_ => {}
}
} }
} }
} }

View File

@@ -129,28 +129,29 @@ fn linux_keycode_to_key(code: u16) -> Option<Key> {
impl InputDevice for VirtioInputDevice { impl InputDevice for VirtioInputDevice {
fn poll(&mut self) -> Option<InputEvent> { fn poll(&mut self) -> Option<InputEvent> {
let current_used = self.used_idx(); loop {
if current_used == self.last_used { let current_used = self.used_idx();
return None; if current_used == self.last_used {
} return None;
}
let desc_idx = self.used_entry_id(self.last_used); let desc_idx = self.used_entry_id(self.last_used);
self.last_used = self.last_used.wrapping_add(1); self.last_used = self.last_used.wrapping_add(1);
let (ev_type, ev_code, ev_value) = self.read_event(desc_idx); let (ev_type, ev_code, ev_value) = self.read_event(desc_idx);
self.resubmit(desc_idx); self.resubmit(desc_idx);
if ev_type == EV_KEY { if ev_type == EV_KEY {
if let Some(key) = linux_keycode_to_key(ev_code) { if let Some(key) = linux_keycode_to_key(ev_code) {
if ev_value == KEY_PRESS { if ev_value == KEY_PRESS {
return Some(InputEvent::KeyDown(key)); return Some(InputEvent::KeyDown(key));
} else if ev_value == 0 { } else if ev_value == 0 {
return Some(InputEvent::KeyUp(key)); return Some(InputEvent::KeyUp(key));
}
} }
} }
// Skip SYN events, repeats, and unknown keys — keep draining
} }
None
} }
fn has_event(&self) -> bool { fn has_event(&self) -> bool {