commit:6b0017579dde4fc596ba7dd28273f7195f55ac64
author:Chip
committer:Chip
date:Tue Feb 13 02:34:29 2024 -0600
parents:b8f84d20bb4488a76d21fdaa0df15e39a50ff46f
Basic USB keyboard working!
diff --git a/Cargo.lock b/Cargo.lock
line changes: +76/-123
index 065ae02..9a6d268
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -39,22 +39,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719"
 
 [[package]]
-name = "bitvec"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
-dependencies = [
- "funty",
- "radium",
- "tap",
- "wyz",
-]
-
-[[package]]
 name = "byteorder"
-version = "1.5.0"
+version = "1.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
 
 [[package]]
 name = "cortex-m"
@@ -122,9 +110,9 @@ dependencies = [
 
 [[package]]
 name = "either"
-version = "1.9.0"
+version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
+checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
 
 [[package]]
 name = "embedded-dma"
@@ -146,6 +134,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "encode_unicode"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
+
+[[package]]
 name = "frunk"
 version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -194,12 +188,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "funty"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
-
-[[package]]
 name = "gcd"
 version = "2.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -216,10 +204,12 @@ dependencies = [
  "embedded-hal",
  "frunk_core",
  "fugit",
- "heapless 0.7.17",
+ "heapless",
  "r0",
+ "serde",
+ "ssmarshal",
  "usb-device",
- "usbd-human-interface-device",
+ "usbd-hid",
  "usbd-serial",
 ]
 
@@ -233,38 +223,19 @@ dependencies = [
 ]
 
 [[package]]
-name = "hash32"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
-dependencies = [
- "byteorder",
-]
-
-[[package]]
 name = "heapless"
 version = "0.7.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
 dependencies = [
  "atomic-polyfill",
- "hash32 0.2.1",
+ "hash32",
  "rustc_version 0.4.0",
  "spin",
  "stable_deref_trait",
 ]
 
 [[package]]
-name = "heapless"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
-dependencies = [
- "hash32 0.3.1",
- "stable_deref_trait",
-]
-
-[[package]]
 name = "itertools"
 version = "0.10.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -304,16 +275,7 @@ version = "0.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9"
 dependencies = [
- "num_enum_derive 0.5.11",
-]
-
-[[package]]
-name = "num_enum"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845"
-dependencies = [
- "num_enum_derive 0.7.2",
+ "num_enum_derive",
 ]
 
 [[package]]
@@ -328,44 +290,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "num_enum_derive"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.48",
-]
-
-[[package]]
-name = "option-block"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0f2c5d345596a14d7c8b032a68f437955f0059f2eb9a5972371c84f7eef3227"
-
-[[package]]
-name = "packed_struct"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36b29691432cc9eff8b282278473b63df73bea49bc3ec5e67f31a3ae9c3ec190"
-dependencies = [
- "bitvec",
- "packed_struct_codegen",
-]
-
-[[package]]
-name = "packed_struct_codegen"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cd6706dfe50d53e0f6aa09e12c034c44faacd23e966ae5a209e8bdb8f179f98"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
-[[package]]
 name = "paste"
 version = "1.0.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -378,7 +302,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "76e09694b50f89f302ed531c1f2a7569f0be5867aee4ab4f8f729bbeec0078e3"
 dependencies = [
  "arrayvec",
- "num_enum 0.5.11",
+ "num_enum",
  "paste",
 ]
 
@@ -407,12 +331,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
 
 [[package]]
-name = "radium"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
-
-[[package]]
 name = "rand_core"
 version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -521,6 +439,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
 
 [[package]]
+name = "serde"
+version = "1.0.196"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.196"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.48",
+]
+
+[[package]]
 name = "spin"
 version = "0.9.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -530,6 +468,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "ssmarshal"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3e6ad23b128192ed337dfa4f1b8099ced0c2bf30d61e551b65fda5916dbb850"
+dependencies = [
+ "encode_unicode",
+ "serde",
+]
+
+[[package]]
 name = "stable_deref_trait"
 version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -558,12 +506,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "tap"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
-
-[[package]]
 name = "unicode-ident"
 version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -576,18 +518,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1f6cc3adc849b5292b4075fc0d5fdcf2f24866e88e336dd27a8943090a520508"
 
 [[package]]
-name = "usbd-human-interface-device"
-version = "0.4.5"
+name = "usbd-hid"
+version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d69710303c06f23a1259d086bfb241212ae1ccfb5d582ebd596bb042d662ed73"
+checksum = "975bd411f4a939986751ea09992a24fa47c4d25c6ed108d04b4c2999a4fd0132"
 dependencies = [
- "frunk",
- "fugit",
- "heapless 0.8.0",
- "num_enum 0.7.2",
- "option-block",
- "packed_struct",
+ "serde",
+ "ssmarshal",
  "usb-device",
+ "usbd-hid-macros",
+]
+
+[[package]]
+name = "usbd-hid-descriptors"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcbee8c6735e90894fba04770bc41e11fd3c5256018856e15dc4dd1e6c8a3dd1"
+dependencies = [
+ "bitfield",
+]
+
+[[package]]
+name = "usbd-hid-macros"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "261079a9ada015fa1acac7cc73c98559f3a92585e15f508034beccf6a2ab75a2"
+dependencies = [
+ "byteorder",
+ "proc-macro2",
+ "quote",
+ "serde",
+ "syn 1.0.109",
+ "usbd-hid-descriptors",
 ]
 
 [[package]]
@@ -621,12 +583,3 @@ checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc"
 dependencies = [
  "vcell",
 ]
-
-[[package]]
-name = "wyz"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
-dependencies = [
- "tap",
-]

diff --git a/Cargo.toml b/Cargo.toml
line changes: +5/-3
index 870747f..fe517a3
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,9 +14,11 @@ heapless = "0.7"
 r0 = "1.0"
 
 doa-hallonbrod = { path = "../doa-hallonbrod" }
-usb-device = "0.2.9"
-usbd-serial = "0.1.1"
-usbd-human-interface-device = "0.4.5"
+serde = { version = "1.0", default-features = false }
+ssmarshal = { version = "1.0", default-features = false }
+usb-device = "0.2"
+usbd-serial = "0.1"
+usbd-hid = "0.6.0"
 
 [target.thumbv6m-none-eabi]
 runner = "elf2uf2-rs"

diff --git a/src/apps.rs b/src/apps.rs
line changes: +1/-0
index 6e52c7b..345da52
--- a/src/apps.rs
+++ b/src/apps.rs
@@ -1 +1,2 @@
+pub mod keyboard;
 pub mod shell; 
\ No newline at end of file

diff --git a/src/apps/keyboard.rs b/src/apps/keyboard.rs
line changes: +171/-0
index 0000000..d42bf29
--- /dev/null
+++ b/src/apps/keyboard.rs
@@ -0,0 +1,171 @@
+use core::fmt::{self, Arguments};
+
+use crate::stdlib;
+
+const KEYCODE_MAP: [u8; 81] = [
+    // Row 1
+    53,  //Grave
+    30,  //Keyboard1
+    32,  //Keyboard3
+    34,  //Keyboard5
+    36,  //Keyboard7
+    38,  //Keyboard9
+    45,  //Minus
+    42,  //DeleteBackspace
+    120, //Stop (RUN/STOP)
+    // Row 2
+    41, //Escape
+    31, //Keyboard2
+    33, //Keyboard4
+    35, //Keyboard6
+    37, //Keyboard8
+    39, //Keyboard0
+    46, //Equal
+    73, //Insert
+    75, //PageUp
+    // Row 3
+    68, //F11, // Macro 1
+    26, //W
+    21, //R
+    28, //Y
+    12, //I
+    19, //P
+    48, //RightBrace
+    74, //Home
+    77, //End
+    // Row 4
+    43, //Tab
+    20, //Q
+    8,  //E
+    23, //T
+    24, //U
+    18, //O
+    47, //LeftBrace
+    76, //DeleteForward
+    78, //PageDown
+    // Row 5
+    69,  //F12 (Macro 2)
+    4,   //A
+    7,   //D
+    9,   //F
+    13,  //J
+    15,  //L
+    52,  //Apostrophe
+    49,  //Backslash
+    106, //F15 (Cyan)
+    // Row 6
+    224, //LeftControl
+    225, //LeftShift
+    22,  //S
+    10,  //G
+    14,  //K
+    51,  //Semicolon
+    56,  //ForwardSlash
+    40,  //ReturnEnter
+    107, //F16 (Magenta)
+    // Row 7
+    104, //F13 (Macro 3)
+    29,  //Z
+    27,  //X
+    11,  //H
+    16,  //M
+    55,  //Dot
+    229, //RightShift
+    82,  //UpArrow
+    108, //F17 (Yellow)
+    // Row 8
+    105, //F14 (Macro 4)
+    224, //LeftControl (Meta Left)
+    6,   //C
+    5,   //B
+    17,  //N
+    54,  //Comma
+    228, //RightControl (Meta Down)
+    80,  //LeftArrow
+    79,  //RightArrow
+    // Row 9
+    0,   //NoEventIndicated (Func; should never be sent)
+    227, //LeftGUI (Meta)
+    226, //LeftAlt (Meta Right)
+    25,  //V
+    44,  //Space
+    230, //RightAlt (Meta Up)
+    231, //RightGUI (Compose)
+    81,  //DownArrow
+    109, //F18 (Black)
+];
+
+fn print(buf: &mut heapless::String<80>, args: Arguments<'_>) {
+    buf.clear();
+    if fmt::write(buf, args).is_ok() {
+        stdlib::print(buf);
+    } else {
+        stdlib::print("blonk");
+    }
+}
+
+pub fn main(_base: u32, _size: u32) -> ! {
+    let mut fmt_buffer: heapless::String<80> = heapless::String::new();
+    let mut key_state = [0u32; 3];
+    let mut new_key_state = [0u32; 3];
+    let mut pressed = [0u32; 3];
+    let mut released = [0u32; 3];
+    let mut modifier = 0u8;
+    let mut keycodes = [0u8; 6];
+
+    loop {
+        stdlib::kb_read_matrix(&mut new_key_state);
+        for i in 0..3 {
+            pressed[i] = new_key_state[i] & !key_state[i];
+            released[i] = !new_key_state[i] & key_state[i];
+            key_state[i] = new_key_state[i];
+        }
+        //print(&mut fmt_buffer, format_args!("{:08x?}\r\n", key_state));
+
+        if (pressed[0] | pressed[1] | pressed[2] | released[0] | released[1] | released[2]) == 0 {
+            stdlib::sleep(1);
+            continue;
+        }
+
+        modifier = 0;
+        for i in 0..6 {
+            keycodes[i] = 0;
+        }
+        let mut c = 0;
+        for i in 0..81 {
+            let b = (key_state[i / 32] >> (i % 32) & 1) != 0;
+            if b {
+                let keycode = KEYCODE_MAP[i];
+                if keycode >= 224 && keycode <= 231 {
+                    modifier |= 1 << (keycode - 224);
+                } else {
+                    if c == 6 {
+                        keycodes[0] = 1;
+                    } else {
+                        keycodes[c] = keycode;
+                        c += 1;
+                    }
+                }
+                //print(&mut fmt_buffer, format_args!("{} ", KEYCODE_MAP[i] as u32));
+            }
+        }
+        /*
+        if keys.len() > 0 {
+            stdlib::print("\r\n");
+        }
+        */
+
+        let mut report_bytes = [0u8; 8];
+        report_bytes[0] = modifier;
+        for i in 0..6 {
+            report_bytes[i + 2] = keycodes[i];
+        }
+        if !stdlib::kb_write_hid(&report_bytes) {
+            stdlib::print("Failed to push report\r\n");
+        } else {
+            print(&mut fmt_buffer, format_args!("wrote {:?}\r\n", report_bytes));
+        }
+
+        stdlib::sleep(10);
+    }
+}

diff --git a/src/apps/shell.rs b/src/apps/shell.rs
line changes: +1/-1
index ff5384f..602a533
--- a/src/apps/shell.rs
+++ b/src/apps/shell.rs
@@ -154,7 +154,7 @@ fn parse_cmdline(cmdline: &str) -> Result<(), CommandError> {
         "k" => {
             let mut keybits = [0u32; 3];
             let mut db = [0u8; 1];
-            stdlib::read_keys(&mut keybits);
+            stdlib::kb_read_matrix(&mut keybits);
             stdlib::print("   c1 c2 c3 c4 c5 c6 c7 c8 c9\r\n");
             for r in 0..9 {
                 stdlib::print("r");

diff --git a/src/main.rs b/src/main.rs
line changes: +2/-1
index 34d6e2b..3bdc8ca
--- a/src/main.rs
+++ b/src/main.rs
@@ -36,7 +36,8 @@ fn main() -> ! {
     kprintf!("Kernel started: {} ticks\r\n", ticks);
 
     with_task_manager(|tm| {
-        tm.add_task("shell", apps::shell::shell, &[CapType::ConsoleRead, CapType::ConsoleWrite], 0).expect("launch task one");
+        tm.add_task("shell", apps::shell::shell, &[CapType::ConsoleRead, CapType::ConsoleWrite], 1).expect("shell task");
+        tm.add_task("keyboard", apps::keyboard::main, &[CapType::Keyboard], 0).expect("keyboard task");
     });
 
     unsafe {

diff --git a/src/peripherals/keyboard.rs b/src/peripherals/keyboard.rs
line changes: +0/-2
index 58d7a26..d478439
--- a/src/peripherals/keyboard.rs
+++ b/src/peripherals/keyboard.rs
@@ -1,5 +1,3 @@
-use core::arch::asm;
-
 use doa_hallonbrod::hal::gpio::{DynPinId, FunctionSioInput, FunctionSioOutput, Pin, PullNone, PullUp};
 use embedded_hal::digital::v2::{InputPin, OutputPin};
 

diff --git a/src/peripherals/usbdev.rs b/src/peripherals/usbdev.rs
line changes: +46/-28
index 77fd3c2..d5ff244
--- a/src/peripherals/usbdev.rs
+++ b/src/peripherals/usbdev.rs
@@ -6,39 +6,53 @@ use bsp::hal::clocks::UsbClock;
 use bsp::hal::usb::UsbBus;
 use bsp::pac::{interrupt, RESETS, USBCTRL_DPRAM, USBCTRL_REGS};
 use critical_section::Mutex;
-use frunk_core::hlist::{HCons, HNil};
+use serde::{ser::SerializeTuple, Serialize, Serializer};
 use usb_device::{class_prelude::*, prelude::*};
-use usbd_human_interface_device::device::keyboard::NKROBootKeyboard;
-use usbd_human_interface_device::prelude::*;
+use usbd_hid::descriptor::{gen_hid_descriptor, AsInputReport, SerializedDescriptor};
+use usbd_hid::hid_class::{
+    HIDClass, HidClassSettings, HidCountryCode, HidProtocol, HidSubClass, ProtocolModeConfig,
+};
 use usbd_serial::SerialPort;
 
+#[gen_hid_descriptor(
+    (collection = APPLICATION, usage_page = GENERIC_DESKTOP, usage = KEYBOARD) = {
+        (usage_page = KEYBOARD, usage_min = 0xE0, usage_max = 0xE7) = {
+            #[packed_bits 8]
+            #[item_settings data, variable, absolute]
+            modifier = input;
+        };
+        #[item_settings constant, array, absolute]
+        reserved = input;
+        (usage_page = LEDS, usage_min = 0x01, usage_max = 0x03) = {
+            #[packed_bits 3]
+            #[item_settings data, variable, absolute]
+            leds = output;
+        };
+        (usage_page = KEYBOARD, usage_min = 0x00, usage_max = 0xFF) = {
+            #[item_settings data, array, absolute]
+            keycodes = input;
+        };
+    }
+)]
+struct KeyboardReport {
+    pub modifier: u8,
+    pub reserved: u8,
+    pub leds: u8,
+    pub keycodes: [u8; 6],
+}
+
 static mut USB_ALLOCATOR: Option<UsbBusAllocator<UsbBus>> = None;
 static USB_MANAGER: Mutex<RefCell<Option<UsbManager>>> = Mutex::new(RefCell::new(None));
 
 pub struct UsbManager<'a> {
-    dev: usb_device::device::UsbDevice<'a, UsbBus>,
-    keyboard: UsbHidClass<'a, UsbBus, HCons<NKROBootKeyboard<'a, UsbBus>, HNil>>,
+    dev: UsbDevice<'a, UsbBus>,
+    keyboard: HIDClass<'a, UsbBus>,
     serial: SerialPort<'a, UsbBus>,
 }
 
 impl<'a> UsbManager<'a> {
     pub fn update(&mut self) {
-        match self.keyboard.tick() {
-            Err(UsbHidError::WouldBlock) => {}
-            Ok(_) => {}
-            Err(e) => {
-                core::panic!("Failed to process keyboard tick: {:?}", e)
-            }
-        }
-
         if self.dev.poll(&mut [&mut self.keyboard, &mut self.serial]) {
-            match self.keyboard.device().read_report() {
-                Err(UsbError::WouldBlock) => {}
-                Err(e) => {
-                    core::panic!("Failed to read keyboard report: {:?}", e)
-                }
-                Ok(_leds) => {}
-            }
             let mut buf = [0u8; 64];
             match self.serial.read(&mut buf) {
                 Ok(n) => {
@@ -58,9 +72,7 @@ impl<'a> UsbManager<'a> {
         }
     }
 
-    pub fn keyboard(
-        &mut self,
-    ) -> &mut UsbHidClass<'a, UsbBus, HCons<NKROBootKeyboard<'a, UsbBus>, HNil>> {
+    pub fn keyboard(&mut self) -> &mut HIDClass<'a, UsbBus> {
         &mut self.keyboard
     }
 
@@ -85,11 +97,17 @@ pub fn init_usb(
         USB_ALLOCATOR.as_ref().unwrap()
     };
 
-    let keyboard = UsbHidClassBuilder::new()
-        .add_device(
-            usbd_human_interface_device::device::keyboard::NKROBootKeyboardConfig::default(),
-        )
-        .build(usballoc);
+    let keyboard = HIDClass::new_ep_in_with_settings(
+        usballoc,
+        KeyboardReport::desc(),
+        1,
+        HidClassSettings {
+            subclass: HidSubClass::NoSubClass,
+            protocol: HidProtocol::Keyboard,
+            config: ProtocolModeConfig::DefaultBehavior,
+            locale: HidCountryCode::NotSupported,
+        },
+    );
 
     let serial = SerialPort::new(usballoc);
 

diff --git a/src/stdlib.rs b/src/stdlib.rs
line changes: +7/-1
index b541c45..7c5d0bc
--- a/src/stdlib.rs
+++ b/src/stdlib.rs
@@ -62,7 +62,13 @@ pub fn kernel_panic() {
     unsafe { _svc_call(200, 0, 0, 0); }
 }
 
-pub fn read_keys(buf: &mut [u32; 3]) {
+pub fn kb_read_matrix(buf: &mut [u32; 3]) {
     let ptr = buf.as_ptr() as u32;
     unsafe { _svc_call(1000, ptr, 0, 0); }
+}
+
+pub fn kb_write_hid(buf: &[u8]) -> bool {
+    let ptr = buf.as_ptr() as u32;
+    let len = buf.len() as u32;
+    unsafe { _svc_call(1001, ptr, len, 0) == 1 }
 } 
\ No newline at end of file

diff --git a/src/svc.rs b/src/svc.rs
line changes: +35/-1
index 13e2e27..af9e786
--- a/src/svc.rs
+++ b/src/svc.rs
@@ -1,11 +1,13 @@
 use core::arch::global_asm;
 
 use embedded_hal::digital::v2::OutputPin;
+use usbd_hid::descriptor::KeyboardReport;
 
 use crate::bsp::pac::SCB;
 use crate::capabilities::CapType;
 use crate::console::{self, ConsoleError};
-use crate::peripherals::with_peripherals;
+use crate::kprintf;
+use crate::peripherals::{with_peripherals, with_usb};
 use crate::task::{current_task_has_capability, with_task_manager, TaskRegisters};
 use crate::timer::ticks;
 
@@ -98,10 +100,42 @@ unsafe fn svcall_handler(regs: Option<&mut TaskRegisters>) {
             regs.r0 = b as u32;
         }
         1000 => {
+            // kb_read_matrix(bits: *mut u32)
+            if !current_task_has_capability(CapType::Keyboard) {
+                return;
+            }
+
             let keys = core::slice::from_raw_parts_mut(regs.r1 as *mut u32, 3);
             let keybits = with_peripherals(|p| p.keyboard().scan());
             keys.copy_from_slice(&keybits);
         }
+        1001 => {
+            // kb_write_hid(arr: *const u8, len: usize) -> bool
+            if !current_task_has_capability(CapType::Keyboard) {
+                return;
+            }
+
+            if regs.r2 > 8 {
+                return;
+            }
+
+            let raw_report = core::slice::from_raw_parts(regs.r1 as *const u8, regs.r2 as usize);
+            let report = KeyboardReport {
+                modifier: raw_report[0],
+                reserved: 0,
+                leds: 0,
+                keycodes: raw_report[2..].try_into().unwrap(),
+            };
+
+            let r = with_usb(|u| u.keyboard().push_input(&report));
+            regs.r0 = match r {
+                Ok(_) => 1,
+                Err(e) => {
+                    kprintf!("{:?}\r\n", e);
+                    0
+                }
+            };
+        }
         _ => panic!("Unknown SVCall"),
     }
 }

diff --git a/src/task.rs b/src/task.rs
line changes: +1/-1
index 258d682..78547ff
--- a/src/task.rs
+++ b/src/task.rs
@@ -114,7 +114,7 @@ impl TaskManager {
             panic!("Scheduling with no tasks!");
         }
 
-        if self.tasks.len() == 1 && self.tasks[0].id == 1 {
+        if self.tasks.len() == 1 && self.tasks[0].name == "idle" {
             kprint!("Only idle task remains - relaunching shell\r\n");
             self.add_task(
                 "shell",