1use std::io::{BufWriter, Error, ErrorKind};
2use std::thread;
3use std::time::Duration;
4
5use once_cell::sync::Lazy;
6
7use gadgets::keyboard::{self, Keyboard, KeyboardState};
8use gadgets::mouse::{self, Mouse};
9
10use crate::gadgets::mouse::MouseRaw;
11
12pub mod gadgets;
13pub mod hid;
14
15#[derive(Clone)]
16pub struct HidSpecification {
17 pub mouse_inputs: Option<Vec<HidMouse>>,
18 pub keyboard_inputs: Option<Vec<String>>,
19 pub gadget_output: String,
20}
21
22#[derive(Clone)]
23pub struct HidMouse {
24 pub mouse_path: String,
25 pub mouse_poll_rate: Option<i32>,
26 pub mouse_side_buttons: bool,
27}
28
29static mut HID_SPEC: Option<HidSpecification> = None;
30static mut MOUSE_INTERFACES: Lazy<Vec<Mouse>> = Lazy::new(Vec::new);
31static mut MOUSE_READING: bool = true;
32
33static mut KEYBOARD_INTERFACES: Vec<Keyboard> = Vec::new();
34static mut KEYBOARD_READING: bool = true;
35
36static mut GLOBAL_KEYBOARD_STATE: Lazy<KeyboardState> = Lazy::new(KeyboardState::default);
37
38pub fn start_pass_through(specification: HidSpecification) -> Result<(), Error> {
39 unsafe {
40 HID_SPEC = Some(specification.clone());
41 }
42
43 start_hot_reload(specification.mouse_inputs.clone(), specification.keyboard_inputs.clone());
44
45 unsafe {
46 if specification.mouse_inputs.is_some() {
47 let mouse_spec = specification.clone();
48 thread::spawn(move || {
49 static mut MOUSE_THREADS: Vec<String> = Vec::new();
50 loop {
51 if !MOUSE_READING {
52 return;
53 }
54
55 if MOUSE_INTERFACES.is_empty() {
56 thread::sleep(Duration::from_millis(1));
57 continue;
58 }
59
60 for (mouse_interface_index, mouse) in MOUSE_INTERFACES.iter_mut().enumerate() {
61 if !MOUSE_THREADS.contains(&mouse.mouse_path) || MOUSE_THREADS.is_empty() {
62 let gadget_mouse = match hid::open_gadget_device(mouse_spec.gadget_output.clone()) {
63 Ok(gadget_device) => gadget_device,
64 Err(_) => continue,
65 };
66
67 MOUSE_THREADS.push(mouse.mouse_path.clone());
68
69 let mut mouse_writer = BufWriter::new(gadget_mouse);
70 thread::spawn(move || {
71 loop {
72 if !MOUSE_READING {
73 break;
74 }
75
76 if mouse::attempt_read(mouse, &mut mouse_writer).is_err() {
77 MOUSE_INTERFACES.remove(mouse_interface_index);
78 MOUSE_THREADS.remove(mouse_interface_index);
79
80 break;
81 };
82 }
83 });
84 }
85 }
86
87 thread::sleep(Duration::from_millis(1));
88 }
89 });
90 }
91
92 if specification.keyboard_inputs.is_some() {
93 let keyboard_spec = specification.clone();
94 thread::spawn(move || {
95 static mut KEYBOARD_THREADS: Vec<String> = Vec::new();
96 loop {
97 if !KEYBOARD_READING {
98 break;
99 }
100
101 if KEYBOARD_INTERFACES.is_empty() {
102 thread::sleep(Duration::from_millis(1));
103 continue;
104 }
105
106 for (keyboard_interface_index, keyboard) in KEYBOARD_INTERFACES.iter_mut().enumerate() {
107 if !KEYBOARD_THREADS.contains(&keyboard.keyboard_path) || KEYBOARD_THREADS.is_empty() {
108 let gadget_keyboard = match hid::open_gadget_device(keyboard_spec.gadget_output.clone()) {
109 Ok(gadget_device) => gadget_device,
110 Err(_) => continue,
111 };
112
113 KEYBOARD_THREADS.push(keyboard.keyboard_path.clone());
114
115 let mut keyboard_writer = BufWriter::new(gadget_keyboard);
116 thread::spawn(move || {
117 loop {
118 if !KEYBOARD_READING {
119 break;
120 }
121
122 if keyboard::attempt_read(keyboard, &mut GLOBAL_KEYBOARD_STATE, &mut keyboard_writer).is_err() {
123 KEYBOARD_INTERFACES.remove(keyboard_interface_index);
124 KEYBOARD_THREADS.remove(keyboard_interface_index);
125
126 break;
127 };
128 }
129 });
130 }
131 }
132
133 thread::sleep(Duration::from_millis(1));
134 }
135 });
136 }
137 }
138
139 Ok(())
140}
141
142pub fn stop_pass_through() -> Result<(), Error> {
143 unsafe {
144 MOUSE_READING = false;
145 KEYBOARD_READING = false;
146
147 match &HID_SPEC {
148 Some(spec) => {
149 let gadget_device = match hid::open_gadget_device(spec.gadget_output.clone()) {
150 Ok(gadget_device) => gadget_device,
151 Err(err) => return Err(err),
152 };
153
154 let mut gadget_writer = BufWriter::new(gadget_device);
155
156 MOUSE_INTERFACES.clear();
157 mouse::push_mouse_event(MouseRaw::default(), None, &mut gadget_writer)?;
158
159 KEYBOARD_INTERFACES.clear();
160 static mut DEFAULT_KEYBOARD_STATE: Lazy<KeyboardState> =
161 Lazy::new(KeyboardState::default);
162 keyboard::attempt_flush(&mut DEFAULT_KEYBOARD_STATE, &mut gadget_writer)?;
163
164 Ok(())
165 }
166 None => Err(Error::new(
167 ErrorKind::Other,
168 String::from("Hid specification not defined cannot open gadget device"),
169 ))
170 }
171 }
172}
173
174fn start_hot_reload(
175 mouse_inputs: Option<Vec<HidMouse>>,
176 keyboard_inputs: Option<Vec<String>>,
177) {
178 if let Some(mouse_inputs) = mouse_inputs {
179 if !mouse_inputs.is_empty() {
180 thread::spawn(move || unsafe {
181 loop {
182 if !MOUSE_READING {
183 break;
184 }
185
186 mouse::check_mouses(&mouse_inputs, &mut MOUSE_INTERFACES);
187 }
188 });
189 }
190 }
191
192 if let Some(keyboard_inputs) = keyboard_inputs {
193 if !keyboard_inputs.is_empty() {
194 thread::spawn(move || unsafe {
195 loop {
196 if !KEYBOARD_READING {
197 break;
198 }
199
200 keyboard::check_keyboards(&keyboard_inputs, &mut KEYBOARD_INTERFACES);
201 }
202 });
203 }
204 }
205}
206
207pub fn get_mouses() -> &'static mut Lazy<Vec<Mouse>, fn() -> Vec<Mouse>> {
208 unsafe { &mut MOUSE_INTERFACES }
209}
210
211pub fn get_keyboard() -> &'static mut KeyboardState {
212 unsafe { &mut GLOBAL_KEYBOARD_STATE }
213}