From 394dc8f060c40e632f963df537b3aee7381b021c Mon Sep 17 00:00:00 2001 From: ergXned <126957013+ergXned@users.noreply.github.com> Date: Mon, 26 Aug 2024 14:50:28 +0200 Subject: [PATCH] Added: ble, keymaps --- Cargo.toml | 5 +- sdkconfig.defaults | 12 ++ src/ble_keyboard.rs | 317 ++++++++++++++++++++++++++++++++++++++++++++ src/enums.rs | 202 ++++++++++++++++++++++++++++ src/lib.rs | 221 +++++++++++++++--------------- src/main.rs | 173 +++++++++++++----------- 6 files changed, 737 insertions(+), 193 deletions(-) create mode 100644 src/ble_keyboard.rs create mode 100644 src/enums.rs diff --git a/Cargo.toml b/Cargo.toml index a60f69f..c4c83ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,9 +29,12 @@ embassy = ["esp-idf-svc/embassy-sync", "esp-idf-svc/critical-section", "esp-idf- [dependencies] log = { version = "0.4", default-features = false } -esp-idf-svc = { version = "0.49", default-features = false } +esp-idf-svc = { version = "0.49", default-features = false, features = ["alloc", "embassy-sync"] } esp-idf-hal = "0.44.1" chrono = "0.4.38" +esp32-nimble = "0.7.0" +anyhow = "1" [build-dependencies] +anyhow = "1" embuild = "0.32.0" diff --git a/sdkconfig.defaults b/sdkconfig.defaults index c25b89d..2df93a0 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -8,3 +8,15 @@ CONFIG_ESP_MAIN_TASK_STACK_SIZE=8000 # Workaround for https://github.com/espressif/esp-idf/issues/7631 #CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=n #CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=n +CONFIG_LOG_DEFAULT_LEVEL=5 + +CONFIG_BT_ENABLED=y +CONFIG_BT_BLE_ENABLED=y +CONFIG_BT_BLUEDROID_ENABLED=n +CONFIG_BT_NIMBLE_ENABLED=y +CONFIG_BT_NIMBLE_NVS_PERSIST=y +# CONFIG_BT_NIMBLE_EXT_ADV=y + +CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y +CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n +CONFIG_BTDM_CTRL_MODE_BTDM=n \ No newline at end of file diff --git a/src/ble_keyboard.rs b/src/ble_keyboard.rs new file mode 100644 index 0000000..ca71628 --- /dev/null +++ b/src/ble_keyboard.rs @@ -0,0 +1,317 @@ +// originally: https://github.com/T-vK/ESP32-BLE-Keyboard +#![allow(dead_code)] + +use esp32_nimble::{ + enums::*, hid::*, utilities::mutex::Mutex, BLEAdvertisementData, BLECharacteristic, BLEDevice, + BLEHIDDevice, BLEServer, +}; +use std::sync::Arc; + +const KEYBOARD_ID: u8 = 0x01; +const MEDIA_KEYS_ID: u8 = 0x02; + +const HID_REPORT_DISCRIPTOR: &[u8] = hid!( + (USAGE_PAGE, 0x01), // USAGE_PAGE (Generic Desktop Ctrls) + (USAGE, 0x06), // USAGE (Keyboard) + (COLLECTION, 0x01), // COLLECTION (Application) + // ------------------------------------------------- Keyboard + (REPORT_ID, KEYBOARD_ID), // REPORT_ID (1) + (USAGE_PAGE, 0x07), // USAGE_PAGE (Kbrd/Keypad) + (USAGE_MINIMUM, 0xE0), // USAGE_MINIMUM (0xE0) + (USAGE_MAXIMUM, 0xE7), // USAGE_MAXIMUM (0xE7) + (LOGICAL_MINIMUM, 0x00), // LOGICAL_MINIMUM (0) + (LOGICAL_MAXIMUM, 0x01), // Logical Maximum (1) + (REPORT_SIZE, 0x01), // REPORT_SIZE (1) + (REPORT_COUNT, 0x08), // REPORT_COUNT (8) + (HIDINPUT, 0x02), // INPUT (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + (REPORT_COUNT, 0x01), // REPORT_COUNT (1) ; 1 byte (Reserved) + (REPORT_SIZE, 0x08), // REPORT_SIZE (8) + (HIDINPUT, 0x01), // INPUT (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + (REPORT_COUNT, 0x05), // REPORT_COUNT (5) ; 5 bits (Num lock, Caps lock, Scroll lock, Compose, Kana) + (REPORT_SIZE, 0x01), // REPORT_SIZE (1) + (USAGE_PAGE, 0x08), // USAGE_PAGE (LEDs) + (USAGE_MINIMUM, 0x01), // USAGE_MINIMUM (0x01) ; Num Lock + (USAGE_MAXIMUM, 0x05), // USAGE_MAXIMUM (0x05) ; Kana + (HIDOUTPUT, 0x02), // OUTPUT (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + (REPORT_COUNT, 0x01), // REPORT_COUNT (1) ; 3 bits (Padding) + (REPORT_SIZE, 0x03), // REPORT_SIZE (3) + (HIDOUTPUT, 0x01), // OUTPUT (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + (REPORT_COUNT, 0x06), // REPORT_COUNT (6) ; 6 bytes (Keys) + (REPORT_SIZE, 0x08), // REPORT_SIZE(8) + (LOGICAL_MINIMUM, 0x00), // LOGICAL_MINIMUM(0) + (LOGICAL_MAXIMUM, 0x65), // LOGICAL_MAXIMUM(0x65) ; 101 keys + (USAGE_PAGE, 0x07), // USAGE_PAGE (Kbrd/Keypad) + (USAGE_MINIMUM, 0x00), // USAGE_MINIMUM (0) + (USAGE_MAXIMUM, 0x65), // USAGE_MAXIMUM (0x65) + (HIDINPUT, 0x00), // INPUT (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + (END_COLLECTION), // END_COLLECTION + // ------------------------------------------------- Media Keys + (USAGE_PAGE, 0x0C), // USAGE_PAGE (Consumer) + (USAGE, 0x01), // USAGE (Consumer Control) + (COLLECTION, 0x01), // COLLECTION (Application) + (REPORT_ID, MEDIA_KEYS_ID), // REPORT_ID (3) + (USAGE_PAGE, 0x0C), // USAGE_PAGE (Consumer) + (LOGICAL_MINIMUM, 0x00), // LOGICAL_MINIMUM (0) + (LOGICAL_MAXIMUM, 0x01), // LOGICAL_MAXIMUM (1) + (REPORT_SIZE, 0x01), // REPORT_SIZE (1) + (REPORT_COUNT, 0x10), // REPORT_COUNT (16) + (USAGE, 0xB5), // USAGE (Scan Next Track) ; bit 0: 1 + (USAGE, 0xB6), // USAGE (Scan Previous Track) ; bit 1: 2 + (USAGE, 0xB7), // USAGE (Stop) ; bit 2: 4 + (USAGE, 0xCD), // USAGE (Play/Pause) ; bit 3: 8 + (USAGE, 0xE2), // USAGE (Mute) ; bit 4: 16 + (USAGE, 0xE9), // USAGE (Volume Increment) ; bit 5: 32 + (USAGE, 0xEA), // USAGE (Volume Decrement) ; bit 6: 64 + (USAGE, 0x23, 0x02), // Usage (WWW Home) ; bit 7: 128 + (USAGE, 0x94, 0x01), // Usage (My Computer) ; bit 0: 1 + (USAGE, 0x92, 0x01), // Usage (Calculator) ; bit 1: 2 + (USAGE, 0x2A, 0x02), // Usage (WWW fav) ; bit 2: 4 + (USAGE, 0x21, 0x02), // Usage (WWW search) ; bit 3: 8 + (USAGE, 0x26, 0x02), // Usage (WWW stop) ; bit 4: 16 + (USAGE, 0x24, 0x02), // Usage (WWW back) ; bit 5: 32 + (USAGE, 0x83, 0x01), // Usage (Media sel) ; bit 6: 64 + (USAGE, 0x8A, 0x01), // Usage (Mail) ; bit 7: 128 + (HIDINPUT, 0x02), // INPUT (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + (END_COLLECTION), // END_COLLECTION +); + +pub const SHIFT: u8 = 0x80; +pub const ASCII_MAP: &[u8] = &[ + 0x00, // NUL + 0x00, // SOH + 0x00, // STX + 0x00, // ETX + 0x00, // EOT + 0x00, // ENQ + 0x00, // ACK + 0x00, // BEL + 0x2a, // BS Backspace + 0x2b, // TAB Tab + 0x28, // LF Enter + 0x00, // VT + 0x00, // FF + 0x00, // CR + 0x00, // SO + 0x00, // SI + 0x00, // DEL + 0x00, // DC1 + 0x00, // DC2 + 0x00, // DC3 + 0x00, // DC4 + 0x00, // NAK + 0x00, // SYN + 0x00, // ETB + 0x00, // CAN + 0x00, // EM + 0x00, // SUB + 0x00, // ESC + 0x00, // FS + 0x00, // GS + 0x00, // RS + 0x00, // US + 0x2c, // ' ' + 0x1e | SHIFT, // ! + 0x34 | SHIFT, // " + 0x20 | SHIFT, // # + 0x21 | SHIFT, // $ + 0x22 | SHIFT, // % + 0x24 | SHIFT, // & + 0x34, // ' + 0x26 | SHIFT, // ( + 0x27 | SHIFT, // ) + 0x25 | SHIFT, // * + 0x2e | SHIFT, // + + 0x36, // , + 0x2d, // - + 0x37, // . + 0x38, // / + 0x27, // 0 + 0x1e, // 1 + 0x1f, // 2 + 0x20, // 3 + 0x21, // 4 + 0x22, // 5 + 0x23, // 6 + 0x24, // 7 + 0x25, // 8 + 0x26, // 9 + 0x33 | SHIFT, // : + 0x33, // ; + 0x36 | SHIFT, // < + 0x2e, // = + 0x37 | SHIFT, // > + 0x38 | SHIFT, // ? + 0x1f | SHIFT, // @ + 0x04 | SHIFT, // A + 0x05 | SHIFT, // B + 0x06 | SHIFT, // C + 0x07 | SHIFT, // D + 0x08 | SHIFT, // E + 0x09 | SHIFT, // F + 0x0a | SHIFT, // G + 0x0b | SHIFT, // H + 0x0c | SHIFT, // I + 0x0d | SHIFT, // J + 0x0e | SHIFT, // K + 0x0f | SHIFT, // L + 0x10 | SHIFT, // M + 0x11 | SHIFT, // N + 0x12 | SHIFT, // O + 0x13 | SHIFT, // P + 0x14 | SHIFT, // Q + 0x15 | SHIFT, // R + 0x16 | SHIFT, // S + 0x17 | SHIFT, // T + 0x18 | SHIFT, // U + 0x19 | SHIFT, // V + 0x1a | SHIFT, // W + 0x1b | SHIFT, // X + 0x1c | SHIFT, // Y + 0x1d | SHIFT, // Z + 0x2f, // [ + 0x31, // bslash + 0x30, // ] + 0x23 | SHIFT, // ^ + 0x2d | SHIFT, // _ + 0x35, // ` + 0x04, // a + 0x05, // b + 0x06, // c + 0x07, // d + 0x08, // e + 0x09, // f + 0x0a, // g + 0x0b, // h + 0x0c, // i + 0x0d, // j + 0x0e, // k + 0x0f, // l + 0x10, // m + 0x11, // n + 0x12, // o + 0x13, // p + 0x14, // q + 0x15, // r + 0x16, // s + 0x17, // t + 0x18, // u + 0x19, // v + 0x1a, // w + 0x1b, // x + 0x1c, // y + 0x1d, // z + 0x2f | SHIFT, // { + 0x31 | SHIFT, // | + 0x30 | SHIFT, // } + 0x35 | SHIFT, // ~ + 0, // DEL +]; + +#[repr(packed)] +struct KeyReport { + modifiers: u8, + reserved: u8, + keys: [u8; 6], +} + +pub struct Keyboard { + server: &'static mut BLEServer, + input_keyboard: Arc>, + output_keyboard: Arc>, + input_media_keys: Arc>, + key_report: KeyReport, +} + +impl Keyboard { + pub fn new() -> anyhow::Result { + let device = BLEDevice::take(); + device + .security() + .set_auth(AuthReq::all()) + .set_io_cap(SecurityIOCap::NoInputNoOutput) + .resolve_rpa(); + + let server = device.get_server(); + let mut hid = BLEHIDDevice::new(server); + + let input_keyboard = hid.input_report(KEYBOARD_ID); + let output_keyboard = hid.output_report(KEYBOARD_ID); + let input_media_keys = hid.input_report(MEDIA_KEYS_ID); + + hid.manufacturer("Espressif"); + hid.pnp(0x02, 0x05ac, 0x820a, 0x0210); + hid.hid_info(0x00, 0x01); + + hid.report_map(HID_REPORT_DISCRIPTOR); + + hid.set_battery_level(100); + + let ble_advertising = device.get_advertising(); + ble_advertising.lock().scan_response(false).set_data( + BLEAdvertisementData::new() + .name("ESP32 Keyboard") + .appearance(0x03C1) + .add_service_uuid(hid.hid_service().lock().uuid()), + )?; + ble_advertising.lock().start()?; + + Ok(Self { + server, + input_keyboard, + output_keyboard, + input_media_keys, + key_report: KeyReport { + modifiers: 0, + reserved: 0, + keys: [0; 6], + }, + }) + } + + pub fn connected(&self) -> bool { + self.server.connected_count() > 0 + } + + pub fn write(&mut self, str: &str) { + for char in str.as_bytes() { + self.press(*char); + self.release(); + } + } + + pub fn press(&mut self, char: u8) { + let mut key = ASCII_MAP[char as usize]; + if (key & SHIFT) > 0 { + self.key_report.modifiers |= 0x02; + key &= !SHIFT; + } + self.key_report.keys[0] = key; + self.send_report(&self.key_report); + } + + pub fn release(&mut self) { + self.key_report.modifiers = 0; + self.key_report.keys.fill(0); + self.send_report(&self.key_report); + } + + fn send_report(&self, keys: &KeyReport) { + self.input_keyboard.lock().set_from(keys).notify(); + esp_idf_svc::hal::delay::Ets::delay_ms(7); + } +} + +// fn main() -> anyhow::Result<()> { +// esp_idf_svc::sys::link_patches(); +// esp_idf_svc::log::EspLogger::initialize_default(); + +// let mut keyboard = Keyboard::new()?; + +// loop { +// if keyboard.connected() { +// ::log::info!("Sending 'Hello world'..."); +// keyboard.write("Hello world\n"); +// } +// esp_idf_svc::hal::delay::FreeRtos::delay_ms(5000); +// } +// } diff --git a/src/enums.rs b/src/enums.rs new file mode 100644 index 0000000..0c22dc3 --- /dev/null +++ b/src/enums.rs @@ -0,0 +1,202 @@ +pub const SHIFT: isize = 0x80; + +pub enum Layer { + Base, + Shift, + Upper, +} + +#[derive(Clone, Copy, Debug)] +pub enum HidMapings { + No = 0x00, + RollOver, /* 0x01 */ + PostFail, /* 0x02 */ + Undefined, /* 0x03 */ + LowerA, /* 0x04 */ + LowerB, /* 0x05 */ + LowerC, /* 0x06 */ + LowerD, /* 0x07 */ + LowerE, /* 0x08 */ + LowerF, /* 0x09 */ + LowerG, /* 0x0A */ + LowerH, /* 0x0B */ + LowerI, /* 0x0C */ + LowerJ, /* 0x0D */ + LowerK, /* 0x0E */ + LowerL, /* 0x0F */ + LowerM, /* 0x10 */ + LowerN, /* 0x11 */ + LowerO, /* 0x12 */ + LowerP, /* 0x13 */ + LowerQ, /* 0x14 */ + LowerR, /* 0x15 */ + LowerS, /* 0x16 */ + LowerT, /* 0x17 */ + LowerU, /* 0x18 */ + LowerV, /* 0x19 */ + LowerW, /* 0x1A */ + LowerX, /* 0x1B */ + LowerY, /* 0x1C */ + LowerZ, /* 0x1D */ + UpperA = 0x04 | SHIFT, /* 0x04 */ + UpperB = 0x05 | SHIFT, /* 0x05 */ + UpperC = 0x06 | SHIFT, /* 0x06 */ + UpperD = 0x07 | SHIFT, /* 0x07 */ + UpperE = 0x08 | SHIFT, /* 0x08 */ + UpperF = 0x09 | SHIFT, /* 0x09 */ + UpperG = 0x0A | SHIFT, /* 0x0A */ + UpperH = 0x0B | SHIFT, /* 0x0B */ + UpperI = 0x0C | SHIFT, /* 0x0C */ + UpperJ = 0x0D | SHIFT, /* 0x0D */ + UpperK = 0x0E | SHIFT, /* 0x0E */ + UpperL = 0x0F | SHIFT, /* 0x0F */ + UpperM = 0x10 | SHIFT, /* 0x10 */ + UpperN = 0x11 | SHIFT, /* 0x11 */ + UpperO = 0x12 | SHIFT, /* 0x12 */ + UpperP = 0x13 | SHIFT, /* 0x13 */ + UpperQ = 0x14 | SHIFT, /* 0x14 */ + UpperR = 0x15 | SHIFT, /* 0x15 */ + UpperS = 0x16 | SHIFT, /* 0x16 */ + UpperT = 0x17 | SHIFT, /* 0x17 */ + UpperU = 0x18 | SHIFT, /* 0x18 */ + UpperV = 0x19 | SHIFT, /* 0x19 */ + UpperW = 0x1A | SHIFT, /* 0x1A */ + UpperX = 0x1B | SHIFT, /* 0x1B */ + UpperY = 0x1C | SHIFT, /* 0x1C */ + UpperZ = 0x1D | SHIFT, /* 0x1D */ + Num1, /* 0x1E */ + Num2, /* 0x1F */ + Num3, /* 0x20 */ + Num4, /* 0x21 */ + Num5, /* 0x22 */ + Num6, /* 0x23 */ + Num7, /* 0x24 */ + Num8, /* 0x25 */ + Num9, /* 0x26 */ + Num0, /* 0x27 */ + Enter, /* 0x28 */ + Escape, /* 0x29 */ + Bspace, /* 0x2A */ + Tab, /* 0x2B */ + Space, /* 0x2C */ + Minus, /* 0x2D */ + Equal, /* 0x2E */ + Lbracket, /* 0x2F */ + Rbracket, /* 0x30 */ + Bslash, /* 0x31 *//* \ (and |) */ + NonusHash, /* 0x32 *//* Non-US # and ~ (Typically near the Enter key) */ + Scolon, /* 0x33 *//* ; (and :) */ + Quote, /* 0x34 *//* ' and " */ + Grave, /* 0x35 *//* Grave accent and tilde */ + Comma, /* 0x36 *//* , and < */ + Dot, /* 0x37 *//* . and > */ + Slash, /* 0x38 *//* / and ? */ + Capslock, /* 0x39 */ + F1, /* 0x3A */ + F2, /* 0x3B */ + F3, /* 0x3C */ + F4, /* 0x3D */ + F5, /* 0x3E */ + F6, /* 0x3F */ + F7, /* 0x40 */ + F8, /* 0x41 */ + F9, /* 0x42 */ + F10, /* 0x43 */ + F11, /* 0x44 */ + F12, /* 0x45 */ + Pscreen, /* 0x46 */ + Scrolllock, /* 0x47 */ + Pause, /* 0x48 */ + Insert, /* 0x49 */ + Home, /* 0x4A */ + Pgup, /* 0x4B */ + Delete, /* 0x4C */ + End, /* 0x4D */ + Pgdown, /* 0x4E */ + Right, /* 0x4F */ + Left, /* 0x50 */ + Down, /* 0x51 */ + Up, /* 0x52 */ + Numlock, /* 0x53 */ + KpSlash, /* 0x54 */ + KpAsterisk, /* 0x55 */ + KpMinus, /* 0x56 */ + KpPlus, /* 0x57 */ + KpEnter, /* 0x58 */ + Kp1, /* 0x59 */ + Kp2, /* 0x5A */ + Kp3, /* 0x5B */ + Kp4, /* 0x5C */ + Kp5, /* 0x5D */ + Kp6, /* 0x5E */ + Kp7, /* 0x5F */ + Kp8, /* 0x60 */ + Kp9, /* 0x61 */ + Kp0, /* 0x62 */ + KpDot, /* 0x63 */ + NonusBslash, /* 0x64 *//* Non-US \ and | (Typically near the Left-Shift key) */ + Application, /* 0x65 */ + Power, /* 0x66 */ + KpEqual, /* 0x67 */ + F13, /* 0x68 */ + F14, /* 0x69 */ + F15, /* 0x6A */ + F16, /* 0x6B */ + F17, /* 0x6C */ + F18, /* 0x6D */ + F19, /* 0x6E */ + F20, /* 0x6F */ + F21, /* 0x70 */ + F22, /* 0x71 */ + F23, /* 0x72 */ + F24, /* 0x73 */ + Execute, /* 0x74 */ + Help, /* 0x75 */ + Menu, /* 0x76 */ + Select, /* 0x77 */ + Stop, /* 0x78 */ + Again, /* 0x79 */ + Undo, /* 0x7A */ + Cut, /* 0x7B */ + Copy, /* 0x7C */ + Paste, /* 0x7D */ + Find, /* 0x7E */ + Mute, /* 0x7F */ + Volup, /* 0x80 */ + Voldown, /* 0x81 */ + LockingCaps, /* 0x82 *//* locking Caps Lock */ + LockingNum, /* 0x83 *//* locking Num Lock */ + LockingScroll, /* 0x84 *//* locking Scroll Lock */ + KpComma, /* 0x85 */ + KpEqualAs400, /* 0x86 *//* equal sign on AS/400 */ + Int1, /* 0x87 */ + Int2, /* 0x88 */ + Int3, /* 0x89 */ + Int4, /* 0x8A */ + Int5, /* 0x8B */ + Int6, /* 0x8C */ + Int7, /* 0x8D */ + Int8, /* 0x8E */ + Int9, /* 0x8F */ + Lang1, /* 0x90 */ + Lang2, /* 0x91 */ + Lang3, /* 0x92 */ + Lang4, /* 0x93 */ + Lang5, /* 0x94 */ + Lang6, /* 0x95 */ + Lang7, /* 0x96 */ + Lang8, /* 0x97 */ + Lang9, /* 0x98 */ + AltErase, /* 0x99 */ + Sysreq, /* 0x9A */ + Cancel, /* 0x9B */ + Clear, /* 0x9C */ + Prior, /* 0x9D */ + Return, /* 0x9E */ + Separator, /* 0x9F */ + Out, /* 0xA0 */ + Oper, /* 0xA1 */ + ClearAgain, /* 0xA2 */ + Crsel, /* 0xA3 */ + Exsel, /* 0xA4 */ +} diff --git a/src/lib.rs b/src/lib.rs index 39be131..7b45087 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,19 +32,22 @@ PINS| 2 | 3 | 10 | 6 | 7 | 4 | PINS| 2 | 3 | 10 | 6 */ use esp_idf_hal::gpio::*; // use esp_idf_hal::peripherals::Peripherals; +use crate::enums::*; use esp_idf_svc::hal::delay::FreeRtos; use std::collections::HashMap; pub const DELAY_DEFAULT: u32 = 20; pub const DELAY_SAME_KEY: u32 = 60; - pub const PIN_INACTIVE: i32 = -1; +pub mod ble_keyboard; +pub mod enums; + #[derive(Clone, Default, Debug)] pub struct KeyboardLeftSide { - pub base_layer: HashMap<(i32, i32), &'static str>, - pub shift_layer: HashMap<(i32, i32), &'static str>, - pub upper_layer: HashMap<(i32, i32), &'static str>, + pub base_layer: HashMap<(i32, i32), HidMapings>, + pub shift_layer: HashMap<(i32, i32), HidMapings>, + pub upper_layer: HashMap<(i32, i32), HidMapings>, } impl KeyboardLeftSide { @@ -63,123 +66,117 @@ impl KeyboardLeftSide { } fn initialie_base_layer(&mut self) { - self.base_layer.insert((0, 2), "ESC"); - self.base_layer.insert((0, 3), "1"); - self.base_layer.insert((0, 10), "2"); - self.base_layer.insert((0, 6), "3"); - self.base_layer.insert((0, 7), "4"); - self.base_layer.insert((0, 4), "5"); - - self.base_layer.insert((1, 2), "TAB"); - self.base_layer.insert((1, 3), "q"); - self.base_layer.insert((1, 10), "w"); - self.base_layer.insert((1, 6), "e"); - self.base_layer.insert((1, 7), "r"); - self.base_layer.insert((1, 4), "t"); - - self.base_layer.insert((12, 2), "CAP"); - self.base_layer.insert((12, 3), "a"); - self.base_layer.insert((12, 10), "s"); - self.base_layer.insert((12, 6), "d"); - self.base_layer.insert((12, 7), "f"); - self.base_layer.insert((12, 4), "g"); - - self.base_layer.insert((18, 2), ""); - self.base_layer.insert((18, 3), "z"); - self.base_layer.insert((18, 10), "x"); - self.base_layer.insert((18, 6), "c"); - self.base_layer.insert((18, 7), "v"); - self.base_layer.insert((18, 4), "b"); - - self.base_layer.insert((19, 2), ""); - self.base_layer.insert((19, 3), ""); - self.base_layer.insert((19, 10), "LYR"); - self.base_layer.insert((19, 6), "CTL"); - self.base_layer.insert((19, 7), "SFT"); - self.base_layer.insert((19, 4), "ENT"); + self.base_layer.insert((0, 2), HidMapings::Escape); // ESC + self.base_layer.insert((0, 3), HidMapings::Num1); // 1 + self.base_layer.insert((0, 10), HidMapings::Num2); // 2 + self.base_layer.insert((0, 6), HidMapings::Num3); // 3 + self.base_layer.insert((0, 7), HidMapings::Num4); // 4 + self.base_layer.insert((0, 4), HidMapings::Num5); // 5 + + self.base_layer.insert((1, 2), HidMapings::Tab); // TAB + self.base_layer.insert((1, 3), HidMapings::LowerQ); // q + self.base_layer.insert((1, 10), HidMapings::LowerW); // w + self.base_layer.insert((1, 6), HidMapings::LowerE); // e + self.base_layer.insert((1, 7), HidMapings::LowerR); // r + self.base_layer.insert((1, 4), HidMapings::LowerT); // t + + self.base_layer.insert((12, 2), HidMapings::Capslock); // CAP + self.base_layer.insert((12, 3), HidMapings::LowerA); // a + self.base_layer.insert((12, 10), HidMapings::LowerS); // s + self.base_layer.insert((12, 6), HidMapings::LowerD); // d + self.base_layer.insert((12, 7), HidMapings::LowerF); // f + self.base_layer.insert((12, 4), HidMapings::LowerG); // g + + self.base_layer.insert((18, 2), HidMapings::No); // + self.base_layer.insert((18, 3), HidMapings::LowerZ); // z + self.base_layer.insert((18, 10), HidMapings::LowerX); // x + self.base_layer.insert((18, 6), HidMapings::LowerC); // c + self.base_layer.insert((18, 7), HidMapings::LowerV); // v + self.base_layer.insert((18, 4), HidMapings::LowerB); // b + + self.base_layer.insert((19, 2), HidMapings::No); // + self.base_layer.insert((19, 3), HidMapings::No); // + self.base_layer.insert((19, 10), HidMapings::No); // LAYER + self.base_layer.insert((19, 6), HidMapings::No); // CONTROL + self.base_layer.insert((19, 7), HidMapings::No); // SHIFT + self.base_layer.insert((19, 4), HidMapings::Enter); // ENTER } fn initialie_shift_layer(&mut self) { - self.shift_layer.insert((0, 2), "ESC"); - self.shift_layer.insert((0, 3), "!"); - self.shift_layer.insert((0, 10), "@"); - self.shift_layer.insert((0, 6), "#"); - self.shift_layer.insert((0, 7), "$"); - self.shift_layer.insert((0, 4), "%"); - - self.shift_layer.insert((1, 2), "TAB"); - self.shift_layer.insert((1, 3), "Q"); - self.shift_layer.insert((1, 10), "W"); - self.shift_layer.insert((1, 6), "E"); - self.shift_layer.insert((1, 7), "R"); - self.shift_layer.insert((1, 4), "T"); - - self.shift_layer.insert((12, 2), "CAP"); - self.shift_layer.insert((12, 3), "A"); - self.shift_layer.insert((12, 10), "S"); - self.shift_layer.insert((12, 6), "D"); - self.shift_layer.insert((12, 7), "F"); - self.shift_layer.insert((12, 4), "G"); - - self.shift_layer.insert((18, 2), ""); - self.shift_layer.insert((18, 3), "Z"); - self.shift_layer.insert((18, 10), "X"); - self.shift_layer.insert((18, 6), "C"); - self.shift_layer.insert((18, 7), "V"); - self.shift_layer.insert((18, 4), "B"); - - self.shift_layer.insert((19, 2), ""); - self.shift_layer.insert((19, 3), ""); - self.shift_layer.insert((19, 10), "LYR"); - self.shift_layer.insert((19, 6), "CTL"); - self.shift_layer.insert((19, 7), "SFT"); - self.shift_layer.insert((19, 4), "ENT"); + self.shift_layer.insert((0, 2), HidMapings::Escape); // ESC + self.shift_layer.insert((0, 3), HidMapings::No); // ! + self.shift_layer.insert((0, 10), HidMapings::No); // @ + self.shift_layer.insert((0, 6), HidMapings::No); // # + self.shift_layer.insert((0, 7), HidMapings::No); // $ + self.shift_layer.insert((0, 4), HidMapings::No); // % + + self.shift_layer.insert((1, 2), HidMapings::Tab); // TAB + self.shift_layer.insert((1, 3), HidMapings::UpperQ); // Q + self.shift_layer.insert((1, 10), HidMapings::UpperW); // W + self.shift_layer.insert((1, 6), HidMapings::UpperE); // E + self.shift_layer.insert((1, 7), HidMapings::UpperR); // R + self.shift_layer.insert((1, 4), HidMapings::UpperT); // T + + self.shift_layer.insert((12, 2), HidMapings::Capslock); // CAPSLOCK + self.shift_layer.insert((12, 3), HidMapings::UpperA); // A + self.shift_layer.insert((12, 10), HidMapings::UpperS); // S + self.shift_layer.insert((12, 6), HidMapings::UpperD); // D + self.shift_layer.insert((12, 7), HidMapings::UpperF); // F + self.shift_layer.insert((12, 4), HidMapings::UpperG); // G + + self.shift_layer.insert((18, 2), HidMapings::No); // + self.shift_layer.insert((18, 3), HidMapings::UpperZ); // Z + self.shift_layer.insert((18, 10), HidMapings::UpperX); // X + self.shift_layer.insert((18, 6), HidMapings::UpperC); // C + self.shift_layer.insert((18, 7), HidMapings::UpperV); // V + self.shift_layer.insert((18, 4), HidMapings::UpperB); // B + + self.shift_layer.insert((19, 2), HidMapings::No); // + self.shift_layer.insert((19, 3), HidMapings::No); // + self.shift_layer.insert((19, 10), HidMapings::No); // LAYER + self.shift_layer.insert((19, 6), HidMapings::No); // CONTROL + self.shift_layer.insert((19, 7), HidMapings::No); // SHIFT + self.shift_layer.insert((19, 4), HidMapings::Enter); // ENTER } fn initialie_upper_layer(&mut self) { - self.upper_layer.insert((0, 2), "ESC"); - self.upper_layer.insert((0, 3), "-"); - self.upper_layer.insert((0, 10), "-"); - self.upper_layer.insert((0, 6), "-"); - self.upper_layer.insert((0, 7), "-"); - self.upper_layer.insert((0, 4), "-"); - - self.upper_layer.insert((1, 2), "TAB"); - self.upper_layer.insert((1, 3), "-"); - self.upper_layer.insert((1, 10), "UP"); - self.upper_layer.insert((1, 6), "-"); - self.upper_layer.insert((1, 7), "-"); - self.upper_layer.insert((1, 4), "-"); - - self.upper_layer.insert((12, 2), "CAP"); - self.upper_layer.insert((12, 3), "LFT"); - self.upper_layer.insert((12, 10), "DWN"); - self.upper_layer.insert((12, 6), "RGT"); - self.upper_layer.insert((12, 7), "-"); - self.upper_layer.insert((12, 4), "-"); - - self.upper_layer.insert((18, 2), "-"); - self.upper_layer.insert((18, 3), "-"); - self.upper_layer.insert((18, 10), "-"); - self.upper_layer.insert((18, 6), "-"); - self.upper_layer.insert((18, 7), "-"); - self.upper_layer.insert((18, 4), "-"); - - self.upper_layer.insert((19, 2), "-"); - self.upper_layer.insert((19, 3), "-"); - self.upper_layer.insert((19, 10), "LYR"); - self.upper_layer.insert((19, 6), "CTL"); - self.upper_layer.insert((19, 7), "SFT"); - self.upper_layer.insert((19, 4), "ENT"); + self.upper_layer.insert((0, 2), HidMapings::Escape); // ESC + self.upper_layer.insert((0, 3), HidMapings::No); // + self.upper_layer.insert((0, 10), HidMapings::No); // + self.upper_layer.insert((0, 6), HidMapings::No); // + self.upper_layer.insert((0, 7), HidMapings::No); // + self.upper_layer.insert((0, 4), HidMapings::No); // + + self.upper_layer.insert((1, 2), HidMapings::Tab); // TAB + self.upper_layer.insert((1, 3), HidMapings::No); // + self.upper_layer.insert((1, 10), HidMapings::Up); // UP + self.upper_layer.insert((1, 6), HidMapings::No); // + self.upper_layer.insert((1, 7), HidMapings::No); // + self.upper_layer.insert((1, 4), HidMapings::No); // + + self.upper_layer.insert((12, 2), HidMapings::Capslock); // CAPSLOCK + self.upper_layer.insert((12, 3), HidMapings::Left); // LEFT + self.upper_layer.insert((12, 10), HidMapings::Down); // DOWN + self.upper_layer.insert((12, 6), HidMapings::Right); // RIGHT + self.upper_layer.insert((12, 7), HidMapings::No); // + self.upper_layer.insert((12, 4), HidMapings::No); // + + self.upper_layer.insert((18, 2), HidMapings::No); // + self.upper_layer.insert((18, 3), HidMapings::No); // + self.upper_layer.insert((18, 10), HidMapings::No); // + self.upper_layer.insert((18, 6), HidMapings::No); // + self.upper_layer.insert((18, 7), HidMapings::No); // + self.upper_layer.insert((18, 4), HidMapings::No); // + + self.upper_layer.insert((19, 2), HidMapings::No); // + self.upper_layer.insert((19, 3), HidMapings::No); // + self.upper_layer.insert((19, 10), HidMapings::No); // LAYER + self.upper_layer.insert((19, 6), HidMapings::No); // CONTROL + self.upper_layer.insert((19, 7), HidMapings::No); // SHIFT + self.upper_layer.insert((19, 4), HidMapings::Enter); // ENTER } } -pub enum Layer { - Base, - Shift, - Upper, -} - pub fn check_pins( pins_active: &mut (i32, i32), gpio2: &PinDriver, diff --git a/src/main.rs b/src/main.rs index 5522732..4852179 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,12 +2,15 @@ to flash: espflash flash ../target/riscv32imc-esp-espidf/debug/esp32-rust-split-keyboard --monitor */ + +use crate::ble_keyboard::*; +use crate::enums::*; +use anyhow; use esp32_rust_split_keyboard::*; use esp_idf_svc::hal::delay::FreeRtos; use esp_idf_svc::hal::gpio::*; use esp_idf_svc::hal::peripherals::Peripherals; - -fn main() { +fn main() -> anyhow::Result<()> { esp_idf_svc::sys::link_patches(); // Bind the log crate to the ESP Logging facilities @@ -15,22 +18,24 @@ fn main() { log::info!("Hello, world!"); - let peripherals = Peripherals::take().unwrap(); + let mut keyboard = Keyboard::new()?; + + let peripherals = Peripherals::take()?; /* rows */ - let gpio0 = &mut PinDriver::output(peripherals.pins.gpio0).unwrap(); - let gpio1 = &mut PinDriver::output(peripherals.pins.gpio1).unwrap(); - let gpio12 = &mut PinDriver::output(peripherals.pins.gpio12).unwrap(); - let gpio18 = &mut PinDriver::output(peripherals.pins.gpio18).unwrap(); - let gpio19 = &mut PinDriver::output(peripherals.pins.gpio19).unwrap(); + let gpio0 = &mut PinDriver::output(peripherals.pins.gpio0)?; + let gpio1 = &mut PinDriver::output(peripherals.pins.gpio1)?; + let gpio12 = &mut PinDriver::output(peripherals.pins.gpio12)?; + let gpio18 = &mut PinDriver::output(peripherals.pins.gpio18)?; + let gpio19 = &mut PinDriver::output(peripherals.pins.gpio19)?; /* cols */ - let gpio2 = &mut PinDriver::input(peripherals.pins.gpio2).unwrap(); - let gpio3 = &mut PinDriver::input(peripherals.pins.gpio3).unwrap(); - let gpio10 = &mut PinDriver::input(peripherals.pins.gpio10).unwrap(); - let gpio6 = &mut PinDriver::input(peripherals.pins.gpio6).unwrap(); - let gpio7 = &mut PinDriver::input(peripherals.pins.gpio7).unwrap(); - let gpio4 = &mut PinDriver::input(peripherals.pins.gpio4).unwrap(); + let gpio2 = &mut PinDriver::input(peripherals.pins.gpio2)?; + let gpio3 = &mut PinDriver::input(peripherals.pins.gpio3)?; + let gpio10 = &mut PinDriver::input(peripherals.pins.gpio10)?; + let gpio6 = &mut PinDriver::input(peripherals.pins.gpio6)?; + let gpio7 = &mut PinDriver::input(peripherals.pins.gpio7)?; + let gpio4 = &mut PinDriver::input(peripherals.pins.gpio4)?; let mut row_pin_active: u32 = 0; @@ -44,86 +49,94 @@ fn main() { let mut layer; loop { - match row_pin_active { - 0 => { - gpio0.set_high().unwrap(); - pins_active.0 = gpio0.pin() - } - 1 => { - gpio1.set_high().unwrap(); - pins_active.0 = gpio1.pin() + if keyboard.connected() { + match row_pin_active { + 0 => { + gpio0.set_high()?; + pins_active.0 = gpio0.pin() + } + 1 => { + gpio1.set_high()?; + pins_active.0 = gpio1.pin() + } + 2 => { + gpio12.set_high()?; + pins_active.0 = gpio12.pin() + } + 3 => { + gpio18.set_high()?; + pins_active.0 = gpio18.pin() + } + 4 => { + gpio19.set_high()?; + pins_active.0 = gpio19.pin() + } + _ => {} } - 2 => { - gpio12.set_high().unwrap(); - pins_active.0 = gpio12.pin() + + /* Shift pressed */ + if gpio7.is_high() && gpio19.is_set_high() { + layer = Layer::Shift; } - 3 => { - gpio18.set_high().unwrap(); - pins_active.0 = gpio18.pin() + /* Upper layer pressed */ + else if gpio10.is_high() && gpio19.is_set_high() { + layer = Layer::Upper; } - 4 => { - gpio19.set_high().unwrap(); - pins_active.0 = gpio19.pin() + /* Noting is pressed */ + else { + layer = Layer::Base; } - _ => {} - } - /* Shift pressed */ - if gpio7.is_high() && gpio19.is_set_high() { - layer = Layer::Shift; - } - /* Upper layer pressed */ - else if gpio10.is_high() && gpio19.is_set_high() { - layer = Layer::Upper; - } - /* Noting is pressed */ - else { - layer = Layer::Base; - } - - check_pins(&mut pins_active, gpio2, gpio3, gpio10, gpio6, gpio7, gpio4); + check_pins(&mut pins_active, gpio2, gpio3, gpio10, gpio6, gpio7, gpio4); - match layer { - Layer::Base => { - /* Check if the pins pressed have a valid combination in the hashmap */ - if let Some(valid_key) = keyboard_left.base_layer.get(&pins_active) { - /* If the previos key is same as the active key */ + match layer { + Layer::Base => { + /* Check if the pins pressed have a valid combination in the hashmap */ + if let Some(valid_key) = keyboard_left.base_layer.get(&pins_active) { + /* If the previos key is same as the active key */ - log::info!("{}", *valid_key); + log::info!("{:?}", *valid_key); + keyboard.press(*valid_key as u8); + keyboard.release(); + } } - } - Layer::Shift => { - /* Check if the pins pressed have a valid combination in the hashmap */ - if let Some(valid_key) = keyboard_left.shift_layer.get(&pins_active) { - /* If the previos key is same as the active key */ - - log::info!("{}", *valid_key); + Layer::Shift => { + /* Check if the pins pressed have a valid combination in the hashmap */ + if let Some(valid_key) = keyboard_left.shift_layer.get(&pins_active) { + /* If the previos key is same as the active key */ + + log::info!("{:?}", *valid_key); + keyboard.press(*valid_key as u8); + keyboard.release(); + } } - } - Layer::Upper => { - /* Check if the pins pressed have a valid combination in the hashmap */ - if let Some(valid_key) = keyboard_left.upper_layer.get(&pins_active) { - /* If the previos key is same as the active key */ - - log::info!("{}", *valid_key); + Layer::Upper => { + /* Check if the pins pressed have a valid combination in the hashmap */ + if let Some(valid_key) = keyboard_left.upper_layer.get(&pins_active) { + /* If the previos key is same as the active key */ + + log::info!("{:?}", *valid_key); + keyboard.press(*valid_key as u8); + keyboard.release(); + } } } - } - match row_pin_active { - 0 => gpio0.set_low().unwrap(), - 1 => gpio1.set_low().unwrap(), - 2 => gpio12.set_low().unwrap(), - 3 => gpio18.set_low().unwrap(), - 4 => gpio19.set_low().unwrap(), - _ => {} - } + match row_pin_active { + 0 => gpio0.set_low()?, + 1 => gpio1.set_low()?, + 2 => gpio12.set_low()?, + 3 => gpio18.set_low()?, + 4 => gpio19.set_low()?, + _ => {} + } - row_pin_active = (row_pin_active + 1) % 5; + row_pin_active = (row_pin_active + 1) % 5; - /* reset pins_active */ - pins_active = (PIN_INACTIVE, PIN_INACTIVE); + /* reset pins_active */ + pins_active = (PIN_INACTIVE, PIN_INACTIVE); - FreeRtos::delay_ms(delay); + FreeRtos::delay_ms(delay); + } } }