hid_api_rs/gadgets/
keyboard.rs

1use std::{fs::File, sync::RwLock, thread};
2use std::fmt::{self, Debug};
3use std::fs::OpenOptions;
4use std::io::{BufWriter, Error, ErrorKind, Read, Write};
5use std::path::Path;
6use std::str::FromStr;
7use std::time::Duration;
8
9use num_enum::FromPrimitive;
10use strum_macros::EnumString;
11
12use crate::hid;
13
14pub struct Keyboard {
15    pub keyboard_device_file: File,
16    pub keyboard_path: String,
17}
18
19pub struct KeyboardState {
20    pub keys_down: RwLock<Vec<i32>>,
21    pub modifiers_down: RwLock<Vec<i32>>,
22}
23
24impl Default for KeyboardState {
25    fn default() -> Self {
26        KeyboardState {
27            keys_down: RwLock::new(Vec::new()),
28            modifiers_down: RwLock::new(Vec::new()),
29        }
30    }
31}
32
33// https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h
34#[derive(FromPrimitive, Debug, Clone, Copy)]
35#[repr(i16)]
36enum LinuxKeyCode {
37    #[num_enum(default)]
38    KEYRESERVED = 0,
39    KEYESC = 1,
40    KEY1 = 2,
41    KEY2 = 3,
42    KEY3 = 4,
43    KEY4 = 5,
44    KEY5 = 6,
45    KEY6 = 7,
46    KEY7 = 8,
47    KEY8 = 9,
48    KEY9 = 10,
49    KEY0 = 11,
50    KEYMINUS = 12,
51    KEYEQUAL = 13,
52    KEYBACKSPACE = 14,
53    KEYTAB = 15,
54    KEYQ = 16,
55    KEYW = 17,
56    KEYE = 18,
57    KEYR = 19,
58    KEYT = 20,
59    KEYY = 21,
60    KEYU = 22,
61    KEYI = 23,
62    KEYO = 24,
63    KEYP = 25,
64    KEYLEFTBRACE = 26,
65    KEYRIGHTBRACE = 27,
66    KEYENTER = 28,
67    KEYLEFTCTRL = 29,
68    KEYA = 30,
69    KEYS = 31,
70    KEYD = 32,
71    KEYF = 33,
72    KEYG = 34,
73    KEYH = 35,
74    KEYJ = 36,
75    KEYK = 37,
76    KEYL = 38,
77    KEYSEMICOLON = 39,
78    KEYAPOSTROPHE = 40,
79    KEYGRAVE = 41,
80    KEYLEFTSHIFT = 42,
81    KEYBACKSLASH = 43,
82    KEYZ = 44,
83    KEYX = 45,
84    KEYC = 46,
85    KEYV = 47,
86    KEYB = 48,
87    KEYN = 49,
88    KEYM = 50,
89    KEYCOMMA = 51,
90    KEYDOT = 52,
91    KEYSLASH = 53,
92    KEYRIGHTSHIFT = 54,
93    KEYKPASTERISK = 55,
94    KEYLEFTALT = 56,
95    KEYSPACE = 57,
96    KEYCAPSLOCK = 58,
97    // KEYF1 = 59,
98    // KEYF2 = 60,
99    // KEYF3 = 61,
100    // KEYF4 = 62,
101    // KEYF5 = 63,
102    // KEYF6 = 64,
103    // KEYF7 = 65,
104    // KEYF8 = 66,
105    // KEYF9 = 67,
106    // KEYF10 = 68,
107    KEYNUMLOCK = 69,
108    KEYSCROLLLOCK = 70,
109    KEYKP7 = 71,
110    KEYKP8 = 72,
111    KEYKP9 = 73,
112    KEYKPMINUS = 74,
113    KEYKP4 = 75,
114    KEYKP5 = 76,
115    KEYKP6 = 77,
116    KEYKPPLUS = 78,
117    KEYKP1 = 79,
118    KEYKP2 = 80,
119    KEYKP3 = 81,
120    KEYKP0 = 82,
121    KEYKPDOT = 83,
122
123    KEYZENKAKUHANKAKU = 85,
124    KEY102ND = 86,
125    // KEYF11 = 87,
126    // KEYF12 = 88,
127    KEYRO = 89,
128    KEYKATAKANA = 90,
129    KEYHIRAGANA = 91,
130    KEYHENKAN = 92,
131    KEYKATAKANAHIRAGANA = 93,
132    KEYMUHENKAN = 94,
133    KEYKPJPCOMMA = 95,
134    KEYKPENTER = 96,
135    KEYRIGHTCTRL = 97,
136    KEYKPSLASH = 98,
137    KEYSYSRQ = 99,
138    KEYRIGHTALT = 100,
139    KEYLINEFEED = 101,
140    KEYHOME = 102,
141    KEYUP = 103,
142    KEYPAGEUP = 104,
143    KEYLEFT = 105,
144    KEYRIGHT = 106,
145    KEYEND = 107,
146    KEYDOWN = 108,
147    KEYPAGEDOWN = 109,
148    KEYINSERT = 110,
149    KEYDELETE = 111,
150    KEYMACRO = 112,
151    KEYPOWER = 116,
152    KEYKPEQUAL = 117,
153    KEYKPPLUSMINUS = 118,
154    KEYPAUSE = 119,
155
156    KEYKPCOMMA = 121,
157
158    KEYHANJA = 123,
159    KEYYEN = 124,
160    KEYLEFTMETA = 125,
161    KEYRIGHTMETA = 126,
162    KEYCOMPOSE = 127,
163
164    KEYSTOP = 128,
165    KEYAGAIN = 129,
166    KEYPROPS = 130,
167    KEYUNDO = 131,
168    KEYFRONT = 132,
169    KEYCOPY = 133,
170    KEYOPEN = 134,
171    KEYPASTE = 135,
172    KEYFIND = 136,
173    KEYCUT = 137,
174    KEYHELP = 138,
175    KEYMENU = 139,
176    KEYCALC = 140,
177    KEYSETUP = 141,
178    KEYSLEEP = 142,
179    KEYWAKEUP = 143,
180    KEYFILE = 144,
181    KEYSENDFILE = 145,
182    KEYDELETEFILE = 146,
183    KEYXFER = 147,
184    KEYPROG1 = 148,
185    KEYPROG2 = 149,
186    KEYWWW = 150,
187    KEYFORWARD = 159,
188    KEYCLOSECD = 160,
189    KEYEJECTCD = 161,
190    KEYEJECTCLOSECD = 162,
191    KEYSTOPCD = 166,
192    KEYRECORD = 167,
193    KEYREWIND = 168,
194    KEYPHONE = 169,
195    KEYISO = 170,
196    KEYCONFIG = 171,
197    KEYHOMEPAGE = 172,
198    KEYREFRESH = 173,
199    KEYEXIT = 174,
200    KEYMOVE = 175,
201    KEYEDIT = 176,
202    KEYSCROLLUP = 177,
203    KEYSCROLLDOWN = 178,
204    KEYKPLEFTPAREN = 179,
205    KEYKPRIGHTPAREN = 180,
206    KEYNEW = 181,
207    KEYREDO = 182,
208
209    KEYF13 = 183,
210    KEYF14 = 184,
211    KEYF15 = 185,
212    KEYF16 = 186,
213    KEYF17 = 187,
214    KEYF18 = 188,
215    KEYF19 = 189,
216    KEYF20 = 190,
217    KEYF21 = 191,
218    KEYF22 = 192,
219    KEYF23 = 193,
220    KEYF24 = 194,
221
222    KEYPLAYCD = 200,
223    KEYPAUSECD = 201,
224    KEYPROG3 = 202,
225    KEYPROG4 = 203,
226    KEYSUSPEND = 205,
227    KEYCLOSE = 206,
228    KEYPLAY = 207,
229    KEYFASTFORWARD = 208,
230    KEYBASSBOOST = 209,
231    KEYPRINT = 210,
232    KEYHP = 211,
233    KEYCAMERA = 212,
234    KEYSOUND = 213,
235    KEYQUESTION = 214,
236    KEYEMAIL = 215,
237    KEYCHAT = 216,
238    KEYSEARCH = 217,
239    KEYCONNECT = 218,
240    KEYFINANCE = 219,
241    KEYSPORT = 220,
242    KEYSHOP = 221,
243    KEYALTERASE = 222,
244    KEYCANCEL = 223,
245
246    // Multi Media Keys
247
248    // KEYBRIGHTNESSDOWN = 224,
249    // KEYBRIGHTNESSUP = 225,
250    // KEYSCALE = 120,
251    // KEYDASHBOARD = 204,
252    // KEYKBDILLUMDOWN = 229,
253    // KEYKBDILLUMUP = 230,
254    // KEYPREVIOUSSONG = 165,
255    // KEYPLAYPAUSE = 164,
256    // KEYNEXTSONG = 163,
257    // KEYMUTE = 113,
258    // KEYVOLUMEDOWN = 114,
259    // KEYVOLUMEUP = 115,
260
261    KEYF1 = 224,
262    KEYF2 = 225,
263    KEYF3 = 120,
264    KEYF4 = 204,
265    KEYF5 = 229,
266    KEYF6 = 230,
267    KEYF7 = 165,
268    KEYF8 = 164,
269    KEYF9 = 163,
270    KEYF10 = 113,
271    KEYF11 = 114,
272    KEYF12 = 115,
273
274    KEYMEDIA = 226,
275
276    KEYSWITCHVIDEOMODE = 227,
277    KEYKBDILLUMTOGGLE = 228,
278
279    KEYSEND = 231,
280    KEYREPLY = 232,
281    KEYFORWARDMAIL = 233,
282    KEYSAVE = 234,
283    KEYDOCUMENTS = 235,
284
285    KEYBATTERY = 236,
286
287    KEYBLUETOOTH = 237,
288    KEYWLAN = 238,
289    KEYUWB = 239,
290
291    KEYUNKNOWN = 240,
292
293    KEYVIDEONEXT = 241,
294    KEYVIDEOPREV = 242,
295    KEYBRIGHTNESSCYCLE = 243,
296    KEYBRIGHTNESSZERO = 244,
297    KEYDISPLAYOFF = 245,
298}
299
300impl fmt::Display for LinuxKeyCode {
301    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
302        write!(f, "{:?}", self)
303    }
304}
305
306// USB Hid Key Codes
307#[derive(FromPrimitive, Clone, Copy, EnumString, Debug)]
308#[repr(i16)]
309pub enum UsbKeyCode {
310    #[num_enum(default)]
311    KEYRESERVED = 0x00,
312    KEYA = 0x04,
313    KEYB = 0x05,
314    KEYC = 0x06,
315    KEYD = 0x07,
316    KEYE = 0x08,
317    KEYF = 0x09,
318    KEYG = 0x0a,
319    KEYH = 0x0b,
320    KEYI = 0x0c,
321    KEYJ = 0x0d,
322    KEYK = 0x0e,
323    KEYL = 0x0f,
324    KEYM = 0x10,
325    KEYN = 0x11,
326    KEYO = 0x12,
327    KEYP = 0x13,
328    KEYQ = 0x14,
329    KEYR = 0x15,
330    KEYS = 0x16,
331    KEYT = 0x17,
332    KEYU = 0x18,
333    KEYV = 0x19,
334    KEYW = 0x1a,
335    KEYX = 0x1b,
336    KEYY = 0x1c,
337    KEYZ = 0x1d,
338
339    KEY1 = 0x1e,
340    KEY2 = 0x1f,
341    KEY3 = 0x20,
342    KEY4 = 0x21,
343    KEY5 = 0x22,
344    KEY6 = 0x23,
345    KEY7 = 0x24,
346    KEY8 = 0x25,
347    KEY9 = 0x26,
348    KEY0 = 0x27,
349
350    KEYENTER = 0x28,
351    KEYESC = 0x29,
352    KEYBACKSPACE = 0x2a,
353    KEYTAB = 0x2b,
354    KEYSPACE = 0x2c,
355    KEYMINUS = 0x2d,
356    KEYEQUAL = 0x2e,
357    KEYLEFTBRACE = 0x2f,
358    KEYRIGHTBRACE = 0x30,
359    KEYBACKSLASH = 0x31,
360    KEYHASHTILDE = 0x32,
361    KEYSEMICOLON = 0x33,
362    KEYAPOSTROPHE = 0x34,
363    KEYGRAVE = 0x35,
364    KEYCOMMA = 0x36,
365    KEYDOT = 0x37,
366    KEYSLASH = 0x38,
367    KEYCAPSLOCK = 0x39,
368
369    KEYF1 = 0x3a,
370    KEYF2 = 0x3b,
371    KEYF3 = 0x3c,
372    KEYF4 = 0x3d,
373    KEYF5 = 0x3e,
374    KEYF6 = 0x3f,
375    KEYF7 = 0x40,
376    KEYF8 = 0x41,
377    KEYF9 = 0x42,
378    KEYF10 = 0x43,
379    KEYF11 = 0x44,
380    KEYF12 = 0x45,
381
382    KEYSYSRQ = 0x46,
383    KEYSCROLLLOCK = 0x47,
384    KEYPAUSE = 0x48,
385    KEYINSERT = 0x49,
386    KEYHOME = 0x4a,
387    KEYPAGEUP = 0x4b,
388    KEYDELETE = 0x4c,
389    KEYEND = 0x4d,
390    KEYPAGEDOWN = 0x4e,
391    KEYRIGHT = 0x4f,
392    KEYLEFT = 0x50,
393    KEYDOWN = 0x51,
394    KEYUP = 0x52,
395
396    KEYNUMLOCK = 0x53,
397    KEYKPSLASH = 0x54,
398    KEYKPASTERISK = 0x55,
399    KEYKPMINUS = 0x56,
400    KEYKPPLUS = 0x57,
401    KEYKPENTER = 0x58,
402    KEYKP1 = 0x59,
403    KEYKP2 = 0x5a,
404    KEYKP3 = 0x5b,
405    KEYKP4 = 0x5c,
406    KEYKP5 = 0x5d,
407    KEYKP6 = 0x5e,
408    KEYKP7 = 0x5f,
409    KEYKP8 = 0x60,
410    KEYKP9 = 0x61,
411    KEYKP0 = 0x62,
412    KEYKPDOT = 0x63,
413
414    KEY102ND = 0x64,
415    KEYCOMPOSE = 0x65,
416    KEYPOWER = 0x66,
417    KEYKPEQUAL = 0x67,
418
419    KEYF13 = 0x68,
420    KEYF14 = 0x69,
421    KEYF15 = 0x6a,
422    KEYF16 = 0x6b,
423    KEYF17 = 0x6c,
424    KEYF18 = 0x6d,
425    KEYF19 = 0x6e,
426    KEYF20 = 0x6f,
427    KEYF21 = 0x70,
428    KEYF22 = 0x71,
429    KEYF23 = 0x72,
430    KEYF24 = 0x73,
431
432    KEYOPEN = 0x74,
433    KEYHELP = 0x75,
434    KEYPROPS = 0x76,
435    KEYFRONT = 0x77,
436    KEYSTOP = 0x78,
437    KEYAGAIN = 0x79,
438    KEYUNDO = 0x7a,
439    KEYCUT = 0x7b,
440    KEYCOPY = 0x7c,
441    KEYPASTE = 0x7d,
442    KEYFIND = 0x7e,
443    KEYMUTE = 0x7f,
444    KEYVOLUMEUP = 0x80,
445    KEYVOLUMEDOWN = 0x81,
446}
447
448impl fmt::Display for UsbKeyCode {
449    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
450        write!(f, "{:?}", self)
451    }
452}
453
454#[derive(PartialEq, FromPrimitive, Debug)]
455#[repr(i16)]
456enum EventType {
457    #[num_enum(default)]
458    EvSyn,
459    EvKey,
460    EvRel,
461    EvAbs,
462    EvMsc,
463    EvSw,
464    EvLed,
465    EvSnd,
466    EvRep,
467    EvFf,
468    EvPwr,
469    EvFfStatus,
470}
471
472#[derive(FromPrimitive, Debug)]
473#[repr(i32)]
474enum KeyState {
475    KeyUp,
476    #[num_enum(default)]
477    KeyDown,
478    KeyHold,
479}
480
481#[derive(FromPrimitive, EnumString, Clone, Copy, Debug)]
482#[repr(i32)]
483pub enum KeyCodeModifier {
484    #[num_enum(default)]
485    KEYLEFTCTRL = 0,
486    KEYLEFTSHIFT = 1,
487    KEYLEFTALT = 2,
488    KEYLEFTMETA = 3,
489    KEYRIGHTCTRL = 4,
490    KEYRIGHTSHIFT = 5,
491    KEYRIGHTALT = 6,
492    KEYRIGHTMETA = 7,
493}
494
495impl fmt::Display for KeyCodeModifier {
496    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
497        write!(f, "{:?}", self)
498    }
499}
500
501#[cfg(target_pointer_width = "64")]
502const BUFFER_LENGTH: usize = 24;
503
504#[cfg(target_pointer_width = "32")]
505const BUFFER_LENGTH: usize = 12;
506
507pub fn attempt_read(
508    keyboard: &mut Keyboard,
509    global_keyboard_state: &'static mut KeyboardState,
510    writer: &mut BufWriter<&mut File>
511) -> Result<(), Error> {
512    let mut keyboard_buffer = [0u8; BUFFER_LENGTH];
513
514    let keyboard_read_length = keyboard.keyboard_device_file.read(&mut keyboard_buffer)?;
515
516    if keyboard_read_length >= BUFFER_LENGTH {
517        let mut offset = match BUFFER_LENGTH {
518            24 => 16,
519            12 => 8,
520            _ => 8,
521        };
522
523        let key_type = i16::from_ne_bytes([keyboard_buffer[offset], keyboard_buffer[{ offset += 1; offset }]]);
524        let key_code = i16::from_ne_bytes([keyboard_buffer[{ offset += 1; offset }], keyboard_buffer[{ offset += 1; offset }]]);
525        let key_value = i32::from_ne_bytes([
526            keyboard_buffer[{ offset += 1; offset }],
527            keyboard_buffer[{ offset += 1; offset }],
528            keyboard_buffer[{ offset += 1; offset }],
529            keyboard_buffer[{ offset += 1; offset }],
530        ]);
531
532        let linux_code: LinuxKeyCode = LinuxKeyCode::from(key_code);
533        let usb_code = match UsbKeyCode::from_str(LinuxKeyCode::to_string(&linux_code).as_str()) {
534            Ok(code) => Some(code),
535            Err(_) => None
536        };
537
538        let event_type: EventType = EventType::from(key_type);
539        let key_state: KeyState = KeyState::from(key_value);
540
541        let key_modifier = match KeyCodeModifier::from_str(LinuxKeyCode::to_string(&linux_code).as_str()) {
542            Ok(modifier) => Some(modifier),
543            Err(_) => None
544        };
545
546        if event_type == EventType::EvKey {
547            let mut result: Result<(), Error> = Ok(());
548            
549            match key_state {
550                KeyState::KeyDown | KeyState::KeyHold => {
551                    match key_modifier {
552                        Some(modifier) => {
553                            result = add_generic_down(modifier as i32, &global_keyboard_state.modifiers_down);
554                        }
555                        None => {
556                            if let Some(code) = usb_code {
557                                result = add_generic_down(code as i32, &global_keyboard_state.keys_down);
558                            }
559                        }
560                    }
561                }
562                KeyState::KeyUp => {
563                    match key_modifier {
564                        Some(modifier) => {
565                            result = remove_generic_down(modifier as i32, &global_keyboard_state.modifiers_down);
566                        }
567                        None => {
568                            if let Some(code) = usb_code {
569                                result = remove_generic_down(code as i32, &global_keyboard_state.keys_down);
570                            }
571                        }
572                    }
573                }
574            };
575
576            attempt_flush(global_keyboard_state, writer)?;
577
578            return result;
579        }
580    }
581
582    Ok(())
583}
584
585pub fn attempt_flush(
586    global_keyboard_state: &'static mut KeyboardState,
587    gadget_writer: &mut BufWriter<&mut File>,
588) -> Result<(), Error> {
589    hid::write_keyboard(global_keyboard_state, gadget_writer)
590}
591
592pub fn add_generic_down(key: i32, key_vec: &RwLock<Vec<i32>>) -> Result<(), Error> {
593    if let Ok(generic_keyvec) = key_vec.read() {
594        if generic_keyvec.contains(&(key)) {
595            return Ok(());
596        }
597    }
598
599    if let Ok(mut generic_keyvec_writer) = key_vec.write() {
600        generic_keyvec_writer.push(key);
601
602        return Ok(());
603    }
604
605    Err(Error::new(
606        ErrorKind::Other,
607        String::from("Failed to push key to generic keyvec (Modifier / Key)"),
608    ))
609}
610
611pub fn remove_generic_down(key: i32, key_vec: &RwLock<Vec<i32>>) -> Result<(), Error> {
612    if let Ok(mut key_vec) = key_vec.write() {
613        key_vec.retain(|k| *k != key);
614        return Ok(());
615    }
616
617    Err(Error::new(
618        ErrorKind::Other,
619        String::from("Failed to remove key from generic keyvec (Modifier / Key)"),
620    ))
621}
622
623pub fn check_keyboards(keyboard_inputs: &Vec<String>, keyboard_interfaces: &'static mut Vec<Keyboard>) {
624    for keyboard_input in keyboard_inputs {
625        if keyboard_interfaces.iter().any(|keyboard_interface| &keyboard_interface.keyboard_path == keyboard_input) {
626            thread::sleep(Duration::from_millis(1));
627            continue;
628        }
629
630        let keyboard_path = Path::new(&keyboard_input);
631
632        if Path::exists(keyboard_path) {
633            let keyboard = match OpenOptions::new()
634                .write(true)
635                .read(true)
636                .open(keyboard_path)
637            {
638                Ok(result) => result,
639                Err(_) => {
640                    continue;
641                }
642            };
643
644            let mut keyboard_interface = Keyboard {
645                keyboard_device_file: keyboard,
646                keyboard_path: keyboard_input.clone(),
647            };
648
649            _ = write_scancode_set(&mut keyboard_interface);
650
651            keyboard_interfaces.push(keyboard_interface);
652        }
653    }
654}
655
656pub fn is_key_down(
657    key: UsbKeyCode,
658    global_keyboard_state: &&'static mut KeyboardState,
659) -> bool {
660    if let Ok(keyboard_state) = global_keyboard_state.keys_down.try_read() {
661        return keyboard_state.contains(&(key as i32));
662    }
663
664    false
665}
666
667pub fn is_modifier_down(
668    modifier: KeyCodeModifier,
669    global_keyboard_state: &&'static mut KeyboardState,
670) -> bool {
671    if let Ok(modifiers_down) = global_keyboard_state.modifiers_down.try_read() {
672        return modifiers_down.contains(&(modifier as i32));
673    }
674
675    false
676}
677
678// https://wiki.osdev.org/PS/2_Keyboard
679pub fn write_scancode_set(keyboard: &mut Keyboard) -> Result<(), Error> {
680    let keyboard_scancode_packet: [u8; 2] = [0xF0, 2];
681
682    match keyboard.keyboard_device_file.write_all(&keyboard_scancode_packet) {
683        Ok(_) => {
684            match keyboard.keyboard_device_file.flush() {
685                Ok(_) => Ok(()),
686                Err(err) => Err(err),
687            }
688        }
689        Err(err) => Err(err)
690    }
691}