1use crate::error::{Error, Result};
4use crate::hid::KeyboardReport;
5use crate::platform::HidBackend;
6use crate::Device;
7use bitflags::bitflags;
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10
11bitflags! {
12 #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
14 pub struct Modifiers: u8 {
15 const LEFT_CTRL = 0x01;
16 const LEFT_SHIFT = 0x02;
17 const LEFT_ALT = 0x04;
18 const LEFT_GUI = 0x08;
19 const RIGHT_CTRL = 0x10;
20 const RIGHT_SHIFT = 0x20;
21 const RIGHT_ALT = 0x40;
22 const RIGHT_GUI = 0x80;
23
24 const CTRL = Self::LEFT_CTRL.bits();
25 const SHIFT = Self::LEFT_SHIFT.bits();
26 const ALT = Self::LEFT_ALT.bits();
27 const GUI = Self::LEFT_GUI.bits();
28 const CMD = Self::LEFT_GUI.bits();
29 }
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
34#[repr(u8)]
35pub enum Key {
36 A = 0x04, B = 0x05, C = 0x06, D = 0x07, E = 0x08, F = 0x09,
38 G = 0x0A, H = 0x0B, I = 0x0C, J = 0x0D, K = 0x0E, L = 0x0F,
39 M = 0x10, N = 0x11, O = 0x12, P = 0x13, Q = 0x14, R = 0x15,
40 S = 0x16, T = 0x17, U = 0x18, V = 0x19, W = 0x1A, X = 0x1B,
41 Y = 0x1C, Z = 0x1D,
42
43 Num1 = 0x1E, Num2 = 0x1F, Num3 = 0x20, Num4 = 0x21, Num5 = 0x22,
45 Num6 = 0x23, Num7 = 0x24, Num8 = 0x25, Num9 = 0x26, Num0 = 0x27,
46
47 Enter = 0x28,
49 Escape = 0x29,
50 Backspace = 0x2A,
51 Tab = 0x2B,
52 Space = 0x2C,
53 Minus = 0x2D,
54 Equal = 0x2E,
55 LeftBracket = 0x2F,
56 RightBracket = 0x30,
57 Backslash = 0x31,
58 Semicolon = 0x33,
59 Quote = 0x34,
60 Grave = 0x35,
61 Comma = 0x36,
62 Period = 0x37,
63 Slash = 0x38,
64 CapsLock = 0x39,
65
66 F1 = 0x3A, F2 = 0x3B, F3 = 0x3C, F4 = 0x3D, F5 = 0x3E, F6 = 0x3F,
68 F7 = 0x40, F8 = 0x41, F9 = 0x42, F10 = 0x43, F11 = 0x44, F12 = 0x45,
69
70 PrintScreen = 0x46,
72 ScrollLock = 0x47,
73 Pause = 0x48,
74 Insert = 0x49,
75 Home = 0x4A,
76 PageUp = 0x4B,
77 Delete = 0x4C,
78 End = 0x4D,
79 PageDown = 0x4E,
80 Right = 0x4F,
81 Left = 0x50,
82 Down = 0x51,
83 Up = 0x52,
84}
85
86impl Key {
87 pub fn from_str(s: &str) -> Result<Self> {
89 let key = match s.to_lowercase().as_str() {
90 "a" => Key::A, "b" => Key::B, "c" => Key::C, "d" => Key::D,
91 "e" => Key::E, "f" => Key::F, "g" => Key::G, "h" => Key::H,
92 "i" => Key::I, "j" => Key::J, "k" => Key::K, "l" => Key::L,
93 "m" => Key::M, "n" => Key::N, "o" => Key::O, "p" => Key::P,
94 "q" => Key::Q, "r" => Key::R, "s" => Key::S, "t" => Key::T,
95 "u" => Key::U, "v" => Key::V, "w" => Key::W, "x" => Key::X,
96 "y" => Key::Y, "z" => Key::Z,
97 "1" => Key::Num1, "2" => Key::Num2, "3" => Key::Num3,
98 "4" => Key::Num4, "5" => Key::Num5, "6" => Key::Num6,
99 "7" => Key::Num7, "8" => Key::Num8, "9" => Key::Num9, "0" => Key::Num0,
100 "enter" | "return" => Key::Enter,
101 "escape" | "esc" => Key::Escape,
102 "backspace" => Key::Backspace,
103 "tab" => Key::Tab,
104 "space" | " " => Key::Space,
105 "up" => Key::Up,
106 "down" => Key::Down,
107 "left" => Key::Left,
108 "right" => Key::Right,
109 "home" => Key::Home,
110 "end" => Key::End,
111 "pageup" => Key::PageUp,
112 "pagedown" => Key::PageDown,
113 "delete" => Key::Delete,
114 "insert" => Key::Insert,
115 "f1" => Key::F1, "f2" => Key::F2, "f3" => Key::F3, "f4" => Key::F4,
116 "f5" => Key::F5, "f6" => Key::F6, "f7" => Key::F7, "f8" => Key::F8,
117 "f9" => Key::F9, "f10" => Key::F10, "f11" => Key::F11, "f12" => Key::F12,
118 _ => return Err(Error::InvalidKey(s.to_string())),
119 };
120 Ok(key)
121 }
122}
123
124pub struct Keyboard {
126 backend: Option<Box<dyn HidBackend>>,
127 report: KeyboardReport,
128 name: String,
129 char_map: HashMap<char, (Key, bool)>, }
131
132impl Keyboard {
133 pub fn new() -> Self {
135 Self::with_name("useHID Virtual Keyboard")
136 }
137
138 pub fn with_name(name: &str) -> Self {
140 let mut kb = Self {
141 backend: None,
142 report: KeyboardReport::default(),
143 name: name.to_string(),
144 char_map: HashMap::new(),
145 };
146 kb.init_char_map();
147 kb
148 }
149
150 fn init_char_map(&mut self) {
151 for c in 'a'..='z' {
153 let key = match c {
154 'a' => Key::A, 'b' => Key::B, 'c' => Key::C, 'd' => Key::D,
155 'e' => Key::E, 'f' => Key::F, 'g' => Key::G, 'h' => Key::H,
156 'i' => Key::I, 'j' => Key::J, 'k' => Key::K, 'l' => Key::L,
157 'm' => Key::M, 'n' => Key::N, 'o' => Key::O, 'p' => Key::P,
158 'q' => Key::Q, 'r' => Key::R, 's' => Key::S, 't' => Key::T,
159 'u' => Key::U, 'v' => Key::V, 'w' => Key::W, 'x' => Key::X,
160 'y' => Key::Y, 'z' => Key::Z,
161 _ => unreachable!(),
162 };
163 self.char_map.insert(c, (key, false));
164 self.char_map.insert(c.to_ascii_uppercase(), (key, true));
165 }
166
167 let numbers = [
169 ('1', Key::Num1), ('2', Key::Num2), ('3', Key::Num3),
170 ('4', Key::Num4), ('5', Key::Num5), ('6', Key::Num6),
171 ('7', Key::Num7), ('8', Key::Num8), ('9', Key::Num9), ('0', Key::Num0),
172 ];
173 for (c, key) in numbers {
174 self.char_map.insert(c, (key, false));
175 }
176
177 let shifted = [
179 ('!', Key::Num1), ('@', Key::Num2), ('#', Key::Num3),
180 ('$', Key::Num4), ('%', Key::Num5), ('^', Key::Num6),
181 ('&', Key::Num7), ('*', Key::Num8), ('(', Key::Num9), (')', Key::Num0),
182 ];
183 for (c, key) in shifted {
184 self.char_map.insert(c, (key, true));
185 }
186
187 self.char_map.insert(' ', (Key::Space, false));
189 self.char_map.insert('\n', (Key::Enter, false));
190 self.char_map.insert('\t', (Key::Tab, false));
191 self.char_map.insert('-', (Key::Minus, false));
192 self.char_map.insert('_', (Key::Minus, true));
193 self.char_map.insert('=', (Key::Equal, false));
194 self.char_map.insert('+', (Key::Equal, true));
195 self.char_map.insert('[', (Key::LeftBracket, false));
196 self.char_map.insert('{', (Key::LeftBracket, true));
197 self.char_map.insert(']', (Key::RightBracket, false));
198 self.char_map.insert('}', (Key::RightBracket, true));
199 self.char_map.insert('\\', (Key::Backslash, false));
200 self.char_map.insert('|', (Key::Backslash, true));
201 self.char_map.insert(';', (Key::Semicolon, false));
202 self.char_map.insert(':', (Key::Semicolon, true));
203 self.char_map.insert('\'', (Key::Quote, false));
204 self.char_map.insert('"', (Key::Quote, true));
205 self.char_map.insert('`', (Key::Grave, false));
206 self.char_map.insert('~', (Key::Grave, true));
207 self.char_map.insert(',', (Key::Comma, false));
208 self.char_map.insert('<', (Key::Comma, true));
209 self.char_map.insert('.', (Key::Period, false));
210 self.char_map.insert('>', (Key::Period, true));
211 self.char_map.insert('/', (Key::Slash, false));
212 self.char_map.insert('?', (Key::Slash, true));
213 }
214
215 pub fn press_key(&mut self, key: Key) -> Result<()> {
217 for i in 0..6 {
219 if self.report.keys[i] == 0 {
220 self.report.keys[i] = key as u8;
221 break;
222 }
223 }
224 self.send_report()
225 }
226
227 pub fn release_key(&mut self, key: Key) -> Result<()> {
229 for i in 0..6 {
230 if self.report.keys[i] == key as u8 {
231 self.report.keys[i] = 0;
232 break;
233 }
234 }
235 self.send_report()
236 }
237
238 pub fn press_modifiers(&mut self, mods: Modifiers) -> Result<()> {
240 self.report.modifiers |= mods.bits();
241 self.send_report()
242 }
243
244 pub fn release_modifiers(&mut self, mods: Modifiers) -> Result<()> {
246 self.report.modifiers &= !mods.bits();
247 self.send_report()
248 }
249
250 pub fn tap(&mut self, key: Key) -> Result<()> {
252 self.press_key(key)?;
253 std::thread::sleep(std::time::Duration::from_millis(10));
254 self.release_key(key)
255 }
256
257 pub fn press_combo(&mut self, mods: Modifiers, key: Key) -> Result<()> {
259 self.press_modifiers(mods)?;
260 self.tap(key)?;
261 self.release_modifiers(mods)
262 }
263
264 pub fn type_text(&mut self, text: &str) -> Result<()> {
266 for c in text.chars() {
267 if let Some(&(key, shift)) = self.char_map.get(&c) {
268 if shift {
269 self.press_modifiers(Modifiers::SHIFT)?;
270 }
271 self.tap(key)?;
272 if shift {
273 self.release_modifiers(Modifiers::SHIFT)?;
274 }
275 std::thread::sleep(std::time::Duration::from_millis(5));
276 }
277 }
278 Ok(())
279 }
280
281 pub fn release_all(&mut self) -> Result<()> {
283 self.report = KeyboardReport::default();
284 self.send_report()
285 }
286
287 fn send_report(&self) -> Result<()> {
288 if let Some(backend) = &self.backend {
289 backend.send_report(self.report.as_bytes())
290 } else {
291 Err(Error::DeviceNotCreated)
292 }
293 }
294}
295
296impl Default for Keyboard {
297 fn default() -> Self {
298 Self::new()
299 }
300}
301
302impl Device for Keyboard {
303 fn create(&mut self) -> Result<()> {
304 if self.backend.is_some() {
305 return Err(Error::DeviceAlreadyExists);
306 }
307
308 let backend = crate::platform::create_keyboard_backend(&self.name)?;
309 self.backend = Some(backend);
310 Ok(())
311 }
312
313 fn destroy(&mut self) -> Result<()> {
314 if let Some(backend) = self.backend.take() {
315 backend.destroy()
316 } else {
317 Err(Error::DeviceNotCreated)
318 }
319 }
320
321 fn is_created(&self) -> bool {
322 self.backend.is_some()
323 }
324}