summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-11-01 16:05:09 +0100
committersalmonik <salmonik@tuta.io>2026-11-01 16:05:09 +0100
commit561354b69c5ae5e73b036b382988fda02bc9fb01 (patch)
treee030b0c493637502f24e0f6e60ae2ca4418e0c03
parentscripts: rebuild the dev loop around build.sh/run.sh (diff)
downloadrs-dos-561354b69c5ae5e73b036b382988fda02bc9fb01.tar.gz
rs-dos-561354b69c5ae5e73b036b382988fda02bc9fb01.zip
usb: re-enable EHCI, share HID keyboard decoding, fix boot protocol
- ehci: DEBUG_MATRIX was left true in be868a4, so every boot replaced enumeration with the one-shot diagnostic transfer matrix and returned false -- the EHCI driver never brought a device up. Default it off; flip it back on only when bisecting a controller fault. - new rsnix/src/hid.rs: boot-keyboard HID usage -> scancode-set-1 tables, the shared scancode FIFO, and a per-device report differ. UHCI now uses it instead of its own copy, so EHCI/xHCI keyboards can feed the same PS/2 decoder (`ps2::feed_scancode`). - uhci: SET_PROTOCOL now asks for the boot protocol (wValue 0) instead of report protocol (wValue 1). In report protocol the report layout is device-defined, but every driver parses boot reports.
-rw-r--r--rsnix/src/ehci.rs7
-rw-r--r--rsnix/src/hid.rs232
-rw-r--r--rsnix/src/lib.rs1
-rw-r--r--rsnix/src/uhci.rs228
4 files changed, 253 insertions, 215 deletions
diff --git a/rsnix/src/ehci.rs b/rsnix/src/ehci.rs
index 6209155..8baa0ad 100644
--- a/rsnix/src/ehci.rs
+++ b/rsnix/src/ehci.rs
@@ -89,7 +89,12 @@ static QR_SHOWN: AtomicBool = AtomicBool::new(false);
89// DEBUG: run the one-boot transfer variant matrix (real-hardware bisection 89// DEBUG: run the one-boot transfer variant matrix (real-hardware bisection
90// of the EHCI System Error trigger). MATRIX_DONE gates it to one pass; 90// of the EHCI System Error trigger). MATRIX_DONE gates it to one pass;
91// XFER_TWEAK flips construction variables inside ctl_xfer. 91// XFER_TWEAK flips construction variables inside ctl_xfer.
92static DEBUG_MATRIX: bool = true; 92//
93// OFF in normal builds: with it on, `enumerate()` is replaced by the
94// diagnostic matrix and returns false, i.e. the EHCI driver never brings a
95// device up. Flip to true only when bisecting a hardware fault, and expect
96// no USB input in that build.
97static DEBUG_MATRIX: bool = false;
93static MATRIX_DONE: AtomicBool = AtomicBool::new(false); 98static MATRIX_DONE: AtomicBool = AtomicBool::new(false);
94static XFER_TWEAK: AtomicU32 = AtomicU32::new(0); 99static XFER_TWEAK: AtomicU32 = AtomicU32::new(0);
95// Low-region (<1 MB) control QH for the matrix's low-region variant. 100// Low-region (<1 MB) control QH for the matrix's low-region variant.
diff --git a/rsnix/src/hid.rs b/rsnix/src/hid.rs
new file mode 100644
index 0000000..42c7602
--- /dev/null
+++ b/rsnix/src/hid.rs
@@ -0,0 +1,232 @@
1// ---------------------------------------------------------------------------
2// Shared USB HID helpers: boot-keyboard report decoding into scancode-set-1
3// bytes, plus the FIFO the drivers hand to the PS/2 decoder.
4//
5// Every HID keyboard (UHCI, EHCI, xHCI) feeds the same `ps2::feed_scancode`
6// state machine, so a USB keyboard behaves exactly like the PS/2 one. The
7// per-report diff state lives in `Keyboard` (one instance per device); the
8// byte FIFO is shared because the consumer is a single scancode stream.
9// ---------------------------------------------------------------------------
10
11use core::sync::atomic::Ordering;
12
13/// HID usage -> scancode set 1 (make code). High byte 0xE0 = E0-prefixed.
14/// 0 = unmapped. Table covers the common keyboard usages (0x04..0x63).
15static HID_TO_SCAN: [u16; 0x64] = {
16 let mut t = [0u16; 0x64];
17 let mut i = 0;
18 while i < 0x64 {
19 t[i] = 0;
20 i += 1;
21 }
22 // Letters a-z
23 t[0x04] = 0x1E;
24 t[0x05] = 0x30;
25 t[0x06] = 0x2E;
26 t[0x07] = 0x20;
27 t[0x08] = 0x12;
28 t[0x09] = 0x21;
29 t[0x0A] = 0x22;
30 t[0x0B] = 0x23;
31 t[0x0C] = 0x17;
32 t[0x0D] = 0x24;
33 t[0x0E] = 0x25;
34 t[0x0F] = 0x26;
35 t[0x10] = 0x32;
36 t[0x11] = 0x31;
37 t[0x12] = 0x18;
38 t[0x13] = 0x19;
39 t[0x14] = 0x10;
40 t[0x15] = 0x13;
41 t[0x16] = 0x1F;
42 t[0x17] = 0x14;
43 t[0x18] = 0x16;
44 t[0x19] = 0x2F;
45 t[0x1A] = 0x11;
46 t[0x1B] = 0x2D;
47 t[0x1C] = 0x15;
48 t[0x1D] = 0x2C;
49 // Digits + punctuation
50 t[0x1E] = 0x02;
51 t[0x1F] = 0x03;
52 t[0x20] = 0x04;
53 t[0x21] = 0x05;
54 t[0x22] = 0x06;
55 t[0x23] = 0x07;
56 t[0x24] = 0x08;
57 t[0x25] = 0x09;
58 t[0x26] = 0x0A;
59 t[0x27] = 0x0B;
60 t[0x28] = 0x1C; // Enter
61 t[0x29] = 0x01; // Esc
62 t[0x2A] = 0x0E; // Backspace
63 t[0x2B] = 0x0F; // Tab
64 t[0x2C] = 0x39; // Space
65 t[0x2D] = 0x0C; // -
66 t[0x2E] = 0x0D; // =
67 t[0x2F] = 0x1A; // [
68 t[0x30] = 0x1B; // ]
69 t[0x31] = 0x2B; // backslash
70 t[0x33] = 0x27; // ;
71 t[0x34] = 0x28; // '
72 t[0x35] = 0x29; // `
73 t[0x36] = 0x33; // ,
74 t[0x37] = 0x34; // .
75 t[0x38] = 0x35; // /
76 t[0x39] = 0x3A; // CapsLock
77 // F-keys
78 t[0x3A] = 0x3B; // F1
79 t[0x3B] = 0x3C;
80 t[0x3C] = 0x3D;
81 t[0x3D] = 0x3E;
82 t[0x3E] = 0x3F;
83 t[0x3F] = 0x40;
84 t[0x40] = 0x41;
85 t[0x41] = 0x42;
86 t[0x42] = 0x43;
87 t[0x43] = 0x44; // F10
88 t[0x44] = 0xE057; // F11
89 t[0x45] = 0xE058; // F12
90 // Nav cluster
91 t[0x49] = 0xE052; // Insert
92 t[0x4A] = 0xE047; // Home
93 t[0x4B] = 0xE049; // PageUp
94 t[0x4C] = 0xE053; // Delete
95 t[0x4D] = 0xE04F; // End
96 t[0x4E] = 0xE051; // PageDown
97 t[0x4F] = 0xE04D; // Right
98 t[0x50] = 0xE04B; // Left
99 t[0x51] = 0xE050; // Down
100 t[0x52] = 0xE048; // Up
101 // Keypad
102 t[0x53] = 0x45; // NumLock
103 t[0x54] = 0xE035; // /
104 t[0x55] = 0x37; // *
105 t[0x56] = 0x4A; // -
106 t[0x57] = 0x4E; // +
107 t[0x58] = 0xE01C; // Enter
108 t[0x59] = 0x4F; // 1
109 t[0x5A] = 0x50; // 2
110 t[0x5B] = 0x51; // 3
111 t[0x5C] = 0x4B; // 4
112 t[0x5D] = 0x4C; // 5
113 t[0x5E] = 0x4D; // 6
114 t[0x5F] = 0x47; // 7
115 t[0x60] = 0x48; // 8
116 t[0x61] = 0x49; // 9
117 t[0x62] = 0x52; // 0
118 t[0x63] = 0x53; // .
119 t
120};
121
122/// Modifier bit -> scancode (set 1, high byte 0xE0 = E0-prefixed).
123static MOD_TO_SCAN: [u16; 8] = [
124 0x1D, // 0 LCtrl
125 0x2A, // 1 LShift
126 0x38, // 2 LAlt
127 0xE05B, // 3 LGui
128 0xE01D, // 4 RCtrl
129 0x36, // 5 RShift
130 0xE038, // 6 RAlt
131 0xE05C, // 7 RGui
132];
133
134// ---- scancode FIFO (shared: one PS/2 decoder consumer) ----
135const Q_SIZE: usize = 128;
136static mut Q: [u8; Q_SIZE] = [0; Q_SIZE];
137static Q_HEAD: core::sync::atomic::AtomicU32 = core::sync::atomic::AtomicU32::new(0);
138static Q_LEN: core::sync::atomic::AtomicU32 = core::sync::atomic::AtomicU32::new(0);
139
140/// Queue one scancode-set-1 byte (drops when the FIFO is full).
141pub fn push_byte(b: u8) {
142 unsafe {
143 let h = Q_HEAD.load(Ordering::Relaxed) as usize;
144 let l = Q_LEN.load(Ordering::Relaxed) as usize;
145 if l >= Q_SIZE {
146 return;
147 }
148 Q[(h + l) % Q_SIZE] = b;
149 Q_LEN.store((l + 1) as u32, Ordering::Relaxed);
150 }
151}
152
153/// Pop one queued scancode byte (callers feed it to `ps2::feed_scancode`).
154pub fn pop_byte() -> Option<u8> {
155 unsafe {
156 let l = Q_LEN.load(Ordering::Relaxed) as usize;
157 if l == 0 {
158 return None;
159 }
160 let h = Q_HEAD.load(Ordering::Relaxed) as usize;
161 let b = Q[h];
162 Q_HEAD.store(((h + 1) % Q_SIZE) as u32, Ordering::Relaxed);
163 Q_LEN.store((l - 1) as u32, Ordering::Relaxed);
164 Some(b)
165 }
166}
167
168/// Push the make (press) or break (release) scancode sequence for a
169/// scancode-map entry (0 = unmapped, 0x00XX = plain, 0xE0XX = E0-prefixed).
170pub fn push_scancode(scan: u16, press: bool) {
171 if scan == 0 {
172 return;
173 }
174 if scan & 0xFF00 == 0xE000 {
175 push_byte(0xE0);
176 let code = (scan & 0xFF) as u8;
177 push_byte(if press { code } else { code | 0x80 });
178 } else {
179 let code = scan as u8;
180 push_byte(if press { code } else { code | 0x80 });
181 }
182}
183
184/// Per-device boot-keyboard report differ. Boot protocol reports are
185/// 8 bytes: modifiers, reserved, 6 usage codes.
186pub struct Keyboard {
187 prev: [u8; 8],
188}
189
190impl Keyboard {
191 pub const fn new() -> Self {
192 Self { prev: [0; 8] }
193 }
194
195 /// Diff `report` against the previous one and queue make/break bytes.
196 pub fn diff(&mut self, report: &[u8]) {
197 let mut rep = [0u8; 8];
198 for (i, b) in rep.iter_mut().enumerate() {
199 *b = report.get(i).copied().unwrap_or(0);
200 }
201 let new_mods = rep[0];
202 let old_mods = self.prev[0];
203 for bit in 0..8 {
204 let new_set = new_mods & (1 << bit) != 0;
205 let old_set = old_mods & (1 << bit) != 0;
206 if new_set != old_set {
207 push_scancode(MOD_TO_SCAN[bit], new_set);
208 }
209 }
210 let new_keys = &rep[2..8];
211 let old_keys = &self.prev[2..8];
212 // Releases first (old keys not in the new set).
213 for &k in old_keys {
214 if k == 0 || new_keys.contains(&k) {
215 continue;
216 }
217 if (k as usize) < HID_TO_SCAN.len() {
218 push_scancode(HID_TO_SCAN[k as usize], false);
219 }
220 }
221 // Then presses (new keys not in the old set).
222 for &k in new_keys {
223 if k == 0 || old_keys.contains(&k) {
224 continue;
225 }
226 if (k as usize) < HID_TO_SCAN.len() {
227 push_scancode(HID_TO_SCAN[k as usize], true);
228 }
229 }
230 self.prev = rep;
231 }
232}
diff --git a/rsnix/src/lib.rs b/rsnix/src/lib.rs
index 325932a..b4307a3 100644
--- a/rsnix/src/lib.rs
+++ b/rsnix/src/lib.rs
@@ -11,6 +11,7 @@ pub mod font;
11pub mod fs; 11pub mod fs;
12pub mod gdt; 12pub mod gdt;
13pub mod gop; 13pub mod gop;
14pub mod hid;
14pub mod interrupts; 15pub mod interrupts;
15pub mod klog; 16pub mod klog;
16pub mod load; 17pub mod load;
diff --git a/rsnix/src/uhci.rs b/rsnix/src/uhci.rs
index 87ec9c6..988db72 100644
--- a/rsnix/src/uhci.rs
+++ b/rsnix/src/uhci.rs
@@ -133,12 +133,9 @@ const OFF_CFG: usize = 0x300; // config descriptor (256 B)
133const OFF_KBD_REPORT: usize = 0x500; // 8 B 133const OFF_KBD_REPORT: usize = 0x500; // 8 B
134const OFF_MOUSE_REPORT: usize = 0x520; // 8 B 134const OFF_MOUSE_REPORT: usize = 0x520; // 8 B
135 135
136// Keyboard: previous report + pending scancode FIFO (fed to ps2 decoder). 136// Keyboard: per-device HID report diff state. Scancode bytes go to the
137static mut KBD_PREV: [u8; 8] = [0; 8]; 137// shared FIFO in `hid.rs` (drained by the single PS/2 decoder).
138const KBDQ_SIZE: usize = 64; 138static mut KBD: crate::hid::Keyboard = crate::hid::Keyboard::new();
139static mut KBDQ: [u8; KBDQ_SIZE] = [0; KBDQ_SIZE];
140static KBDQ_HEAD: AtomicU32 = AtomicU32::new(0);
141static KBDQ_LEN: AtomicU32 = AtomicU32::new(0);
142 139
143// ---- port I/O ---- 140// ---- port I/O ----
144#[inline] 141#[inline]
@@ -495,7 +492,10 @@ unsafe fn enumerate_port(p: usize, want: u8) -> bool {
495 } 492 }
496 493
497 // 6. Boot protocol + no idle. Some devices stall these; tolerate. 494 // 6. Boot protocol + no idle. Some devices stall these; tolerate.
498 let req = ctrl_req(RT_CLASS_IFACE, REQ_SET_PROTOCOL, 1, ep.iface as u16, 0); 495 // wValue 0 = boot protocol: guarantees the 3-byte mouse / 8-byte
496 // keyboard report layout the drivers parse. (wValue 1 would be
497 // report protocol, where the layout is device-defined.)
498 let req = ctrl_req(RT_CLASS_IFACE, REQ_SET_PROTOCOL, 0, ep.iface as u16, 0);
499 if ctl_xfer(dev, mps0, low_speed, &req, false, core::ptr::null_mut(), 0) < 0 { 499 if ctl_xfer(dev, mps0, low_speed, &req, false, core::ptr::null_mut(), 0) < 0 {
500 crate::serial_println!("uhci: set-protocol stalled on port {}", p); 500 crate::serial_println!("uhci: set-protocol stalled on port {}", p);
501 } 501 }
@@ -618,211 +618,10 @@ unsafe fn arm_device(want: u8) -> bool {
618} 618}
619 619
620// --------------------------------------------------------------------------- 620// ---------------------------------------------------------------------------
621// Keyboard: HID report -> scancode-set-1 make/break bytes -> ps2 decoder 621// Keyboard: HID reports feed the shared scancode FIFO (`hid.rs`), drained by
622// try_poll_key through the PS/2 decoder.
622// --------------------------------------------------------------------------- 623// ---------------------------------------------------------------------------
623 624
624/// HID usage -> scancode set 1 (make code). High byte 0xE0 = E0-prefixed.
625/// 0 = unmapped. Table covers the common keyboard usages (0x04..0x63).
626static HID_TO_SCAN: [u16; 0x64] = {
627 let mut t = [0u16; 0x64];
628 let mut i = 0;
629 while i < 0x64 {
630 t[i] = 0;
631 i += 1;
632 }
633 // Letters a-z
634 t[0x04] = 0x1E;
635 t[0x05] = 0x30;
636 t[0x06] = 0x2E;
637 t[0x07] = 0x20;
638 t[0x08] = 0x12;
639 t[0x09] = 0x21;
640 t[0x0A] = 0x22;
641 t[0x0B] = 0x23;
642 t[0x0C] = 0x17;
643 t[0x0D] = 0x24;
644 t[0x0E] = 0x25;
645 t[0x0F] = 0x26;
646 t[0x10] = 0x32;
647 t[0x11] = 0x31;
648 t[0x12] = 0x18;
649 t[0x13] = 0x19;
650 t[0x14] = 0x10;
651 t[0x15] = 0x13;
652 t[0x16] = 0x1F;
653 t[0x17] = 0x14;
654 t[0x18] = 0x16;
655 t[0x19] = 0x2F;
656 t[0x1A] = 0x11;
657 t[0x1B] = 0x2D;
658 t[0x1C] = 0x15;
659 t[0x1D] = 0x2C;
660 // Digits + punctuation
661 t[0x1E] = 0x02;
662 t[0x1F] = 0x03;
663 t[0x20] = 0x04;
664 t[0x21] = 0x05;
665 t[0x22] = 0x06;
666 t[0x23] = 0x07;
667 t[0x24] = 0x08;
668 t[0x25] = 0x09;
669 t[0x26] = 0x0A;
670 t[0x27] = 0x0B;
671 t[0x28] = 0x1C; // Enter
672 t[0x29] = 0x01; // Esc
673 t[0x2A] = 0x0E; // Backspace
674 t[0x2B] = 0x0F; // Tab
675 t[0x2C] = 0x39; // Space
676 t[0x2D] = 0x0C; // -
677 t[0x2E] = 0x0D; // =
678 t[0x2F] = 0x1A; // [
679 t[0x30] = 0x1B; // ]
680 t[0x31] = 0x2B; // backslash
681 t[0x33] = 0x27; // ;
682 t[0x34] = 0x28; // '
683 t[0x35] = 0x29; // `
684 t[0x36] = 0x33; // ,
685 t[0x37] = 0x34; // .
686 t[0x38] = 0x35; // /
687 t[0x39] = 0x3A; // CapsLock
688 // F-keys
689 t[0x3A] = 0x3B; // F1
690 t[0x3B] = 0x3C;
691 t[0x3C] = 0x3D;
692 t[0x3D] = 0x3E;
693 t[0x3E] = 0x3F;
694 t[0x3F] = 0x40;
695 t[0x40] = 0x41;
696 t[0x41] = 0x42;
697 t[0x42] = 0x43;
698 t[0x43] = 0x44; // F10
699 t[0x44] = 0xE057; // F11
700 t[0x45] = 0xE058; // F12
701 // Nav cluster
702 t[0x49] = 0xE052; // Insert
703 t[0x4A] = 0xE047; // Home
704 t[0x4B] = 0xE049; // PageUp
705 t[0x4C] = 0xE053; // Delete
706 t[0x4D] = 0xE04F; // End
707 t[0x4E] = 0xE051; // PageDown
708 t[0x4F] = 0xE04D; // Right
709 t[0x50] = 0xE04B; // Left
710 t[0x51] = 0xE050; // Down
711 t[0x52] = 0xE048; // Up
712 // Keypad
713 t[0x53] = 0x45; // NumLock
714 t[0x54] = 0xE035; // /
715 t[0x55] = 0x37; // *
716 t[0x56] = 0x4A; // -
717 t[0x57] = 0x4E; // +
718 t[0x58] = 0xE01C; // Enter
719 t[0x59] = 0x4F; // 1
720 t[0x5A] = 0x50; // 2
721 t[0x5B] = 0x51; // 3
722 t[0x5C] = 0x4B; // 4
723 t[0x5D] = 0x4C; // 5
724 t[0x5E] = 0x4D; // 6
725 t[0x5F] = 0x47; // 7
726 t[0x60] = 0x48; // 8
727 t[0x61] = 0x49; // 9
728 t[0x62] = 0x52; // 0
729 t[0x63] = 0x53; // .
730 t
731};
732
733/// Modifier bit -> scancode (set 1, high byte 0xE0 = E0-prefixed).
734static MOD_TO_SCAN: [u16; 8] = [
735 0x1D, // 0 LCtrl
736 0x2A, // 1 LShift
737 0x38, // 2 LAlt
738 0xE05B, // 3 LGui
739 0xE01D, // 4 RCtrl
740 0x36, // 5 RShift
741 0xE038, // 6 RAlt
742 0xE05C, // 7 RGui
743];
744
745fn kbdq_push(b: u8) {
746 unsafe {
747 let h = KBDQ_HEAD.load(Ordering::Relaxed) as usize;
748 let l = KBDQ_LEN.load(Ordering::Relaxed) as usize;
749 if l >= KBDQ_SIZE {
750 return;
751 }
752 KBDQ[(h + l) % KBDQ_SIZE] = b;
753 KBDQ_LEN.store((l + 1) as u32, Ordering::Relaxed);
754 }
755}
756fn kbdq_pop() -> Option<u8> {
757 unsafe {
758 let l = KBDQ_LEN.load(Ordering::Relaxed) as usize;
759 if l == 0 {
760 return None;
761 }
762 let h = KBDQ_HEAD.load(Ordering::Relaxed) as usize;
763 let b = KBDQ[h];
764 KBDQ_HEAD.store(((h + 1) % KBDQ_SIZE) as u32, Ordering::Relaxed);
765 KBDQ_LEN.store((l - 1) as u32, Ordering::Relaxed);
766 Some(b)
767 }
768}
769
770/// Push the make (press) or break (release) scancode sequence for a
771/// scancode-map entry (0 = unmapped, 0x00XX = plain, 0xE0XX = E0-prefixed).
772fn push_scancode(scan: u16, press: bool) {
773 if scan == 0 {
774 return;
775 }
776 if scan & 0xFF00 == 0xE000 {
777 kbdq_push(0xE0);
778 let code = (scan & 0xFF) as u8;
779 kbdq_push(if press { code } else { code | 0x80 });
780 } else {
781 let code = scan as u8;
782 kbdq_push(if press { code } else { code | 0x80 });
783 }
784}
785
786/// Diff the completed HID report against the previous one and queue the
787/// scancode transitions (make/break) for the shared PS/2 decoder.
788unsafe fn diff_report(report: &[u8]) {
789 unsafe {
790 let prev = &mut *core::ptr::addr_of_mut!(KBD_PREV);
791 let new_mods = report[0];
792 let old_mods = prev[0];
793 for bit in 0..8 {
794 let new_set = new_mods & (1 << bit) != 0;
795 let old_set = old_mods & (1 << bit) != 0;
796 if new_set != old_set {
797 push_scancode(MOD_TO_SCAN[bit], new_set);
798 }
799 }
800 let new_keys = &report[2..8];
801 let old_keys = &prev[2..8];
802 // Releases first (old keys not in new set).
803 for &k in old_keys {
804 if k == 0 || new_keys.contains(&k) {
805 continue;
806 }
807 if k as usize >= HID_TO_SCAN.len() {
808 continue;
809 }
810 push_scancode(HID_TO_SCAN[k as usize], false);
811 }
812 // Then presses (new keys not in the old set).
813 for &k in new_keys {
814 if k == 0 || old_keys.contains(&k) {
815 continue;
816 }
817 if k as usize >= HID_TO_SCAN.len() {
818 continue;
819 }
820 push_scancode(HID_TO_SCAN[k as usize], true);
821 }
822 prev.copy_from_slice(report);
823 }
824}
825
826/// Re-arm a completed interrupt-IN TD (one-outstanding report pattern). 625/// Re-arm a completed interrupt-IN TD (one-outstanding report pattern).
827unsafe fn rearm_td(qho: usize, tdo: usize, toggle: u32, ls: bool, mps: usize, explen: u32) { 626unsafe fn rearm_td(qho: usize, tdo: usize, toggle: u32, ls: bool, mps: usize, explen: u32) {
828 unsafe { 627 unsafe {
@@ -998,7 +797,7 @@ pub fn init() -> bool {
998pub fn try_poll_key() -> Option<crate::ps2::KeyEvent> { 797pub fn try_poll_key() -> Option<crate::ps2::KeyEvent> {
999 unsafe { 798 unsafe {
1000 // Fast path: pending scancodes first. 799 // Fast path: pending scancodes first.
1001 if let Some(b) = kbdq_pop() { 800 if let Some(b) = crate::hid::pop_byte() {
1002 return crate::ps2::feed_scancode(b); 801 return crate::ps2::feed_scancode(b);
1003 } 802 }
1004 if KBD_ARMED.load(Ordering::Relaxed) { 803 if KBD_ARMED.load(Ordering::Relaxed) {
@@ -1016,7 +815,8 @@ pub fn try_poll_key() -> Option<crate::ps2::KeyEvent> {
1016 for (i, b) in report.iter_mut().enumerate() { 815 for (i, b) in report.iter_mut().enumerate() {
1017 *b = core::ptr::read_volatile(rep.add(i)); 816 *b = core::ptr::read_volatile(rep.add(i));
1018 } 817 }
1019 diff_report(&report); 818 let kbd = &mut *core::ptr::addr_of_mut!(KBD);
819 kbd.diff(&report);
1020 let tog = KBD_TOGGLE.load(Ordering::Relaxed) ^ 1; 820 let tog = KBD_TOGGLE.load(Ordering::Relaxed) ^ 1;
1021 KBD_TOGGLE.store(tog, Ordering::Relaxed); 821 KBD_TOGGLE.store(tog, Ordering::Relaxed);
1022 rearm_td( 822 rearm_td(
@@ -1027,7 +827,7 @@ pub fn try_poll_key() -> Option<crate::ps2::KeyEvent> {
1027 KBD_MPS.load(Ordering::Relaxed) as usize, 827 KBD_MPS.load(Ordering::Relaxed) as usize,
1028 8, 828 8,
1029 ); 829 );
1030 return kbdq_pop().and_then(crate::ps2::feed_scancode); 830 return crate::hid::pop_byte().and_then(crate::ps2::feed_scancode);
1031 } 831 }
1032 return None; 832 return None;
1033 } 833 }
@@ -1039,7 +839,7 @@ pub fn try_poll_key() -> Option<crate::ps2::KeyEvent> {
1039 let _ = arm_device(1); 839 let _ = arm_device(1);
1040 } 840 }
1041 } 841 }
1042 kbdq_pop().and_then(crate::ps2::feed_scancode) 842 crate::hid::pop_byte().and_then(crate::ps2::feed_scancode)
1043 } 843 }
1044} 844}
1045 845