1use std::convert::TryFrom;
2use std::mem;
3use std::slice;
4
5use enumflags2::BitFlags;
6
7use enumflags2::bitflags;
8use uhidrs_sys as sys;
9
10use crate::uhid_device::CreateParams;
11
12pub enum StreamError {
15 Io(std::io::Error),
16 UnknownEventType(u32),
17}
18
19#[bitflags]
23#[derive(Copy, Clone, PartialEq)]
24#[repr(u64)]
25pub enum DevFlags {
26 FeatureReportsNumbered = 0b0000_0001,
27 OutputReportsNumbered = 0b0000_0010,
28 InputReportsNumbered = 0b0000_0100,
29}
30
31#[derive(Debug, Copy, Clone, PartialEq)]
33pub enum ReportType {
34 Feature = 0,
35 Output = 1,
36 Input = 2,
37}
38
39#[derive(Debug, Copy, Clone, PartialEq)]
41#[allow(non_camel_case_types)]
42pub enum Bus {
43 PCI = 1,
44 ISAPNP = 2,
45 USB = 3,
46 HIL = 4,
47 BLUETOOTH = 5,
48 VIRTUAL = 6,
49 ISA = 16,
50 I8042 = 17,
51 XTKBD = 18,
52 RS232 = 19,
53 GAMEPORT = 20,
54 PARPORT = 21,
55 AMIGA = 22,
56 ADB = 23,
57 I2C = 24,
58 HOST = 25,
59 GSC = 26,
60 ATARI = 27,
61 SPI = 28,
62 RMI = 29,
63 CEC = 30,
64 INTEL_ISHTP = 31,
65}
66
67pub const UHID_EVENT_SIZE: usize = mem::size_of::<sys::uhid_event>();
68
69pub enum InputEvent<'a> {
71 Create(CreateParams),
72 Destroy,
73 Input {
74 data: &'a [u8],
75 },
76 Output {
77 data: Vec<u8>,
78 },
79 OutputEv {
80 type_: u16,
81 code: u16,
82 value: i32,
83 },
84 GetReportReply {
85 id: u32,
86 err: u16,
87 data: Vec<u8>,
88 },
89 SetReportReply {
90 id: u32,
91 err: u16,
92 },
93 Feature {
94 id: u32,
95 report_num: u8,
96 },
97 FeatureAnswer {
98 id: u32,
99 err: u16,
100 data: Vec<u8>,
101 },
102 SetReport {
103 id: u32,
104 report_num: u8,
105 data: Vec<u8>,
106 },
107}
108
109impl<'a> From<InputEvent<'a>> for sys::uhid_event {
110 fn from(input: InputEvent<'a>) -> Self {
111 let mut event: sys::uhid_event = unsafe { mem::zeroed() };
112
113 match input {
114 InputEvent::Create(CreateParams {
115 name,
116 phys,
117 uniq,
118 bus,
119 vendor,
120 product,
121 version,
122 country,
123 rd_data,
124 }) => {
125 event.type_ = sys::uhid_event_type_UHID_CREATE2;
126 let payload = unsafe { &mut event.u.create2 };
127 name.as_bytes()
128 .iter()
129 .enumerate()
130 .for_each(|(i, x)| payload.name[i] = *x);
131 phys.as_bytes()
132 .iter()
133 .enumerate()
134 .for_each(|(i, x)| payload.phys[i] = *x);
135 uniq.as_bytes()
136 .iter()
137 .enumerate()
138 .for_each(|(i, x)| payload.uniq[i] = *x);
139 rd_data
140 .iter()
141 .enumerate()
142 .for_each(|(i, x)| payload.rd_data[i] = *x);
143 payload.rd_size = rd_data.len() as u16;
144 payload.bus = bus as u16;
145 payload.vendor = vendor;
146 payload.product = product;
147 payload.version = version;
148 payload.country = country;
149 }
150 InputEvent::Destroy => {
151 event.type_ = sys::uhid_event_type_UHID_DESTROY;
152 }
153 InputEvent::Input { data } => {
154 event.type_ = sys::uhid_event_type_UHID_INPUT2;
155 let payload = unsafe { &mut event.u.input2 };
156 data.iter()
157 .enumerate()
158 .for_each(|(i, x)| payload.data[i] = *x);
159 payload.size = data.len() as u16;
160 }
161 InputEvent::Output { data } => {
162 event.type_ = sys::uhid_event_type_UHID_OUTPUT;
163 let payload = unsafe { &mut event.u.output };
164 data.iter()
165 .enumerate()
166 .for_each(|(i, x)| payload.data[i] = *x);
167 payload.size = data.len() as u16;
168 payload.rtype = sys::hid_report_type_HID_OUTPUT_REPORT as u8;
169 }
170 InputEvent::OutputEv { type_, code, value } => {
171 event.type_ = sys::uhid_event_type___UHID_LEGACY_OUTPUT_EV;
172 let payload = unsafe { &mut event.u.output_ev };
173 payload.type_ = type_;
174 payload.code = code;
175 payload.value = value;
176 }
177 InputEvent::GetReportReply { err, id, data, .. } => {
178 event.type_ = sys::uhid_event_type_UHID_GET_REPORT_REPLY;
179 let payload = unsafe { &mut event.u.get_report_reply };
180 payload.err = err;
181 data.iter()
182 .enumerate()
183 .for_each(|(i, x)| payload.data[i] = *x);
184 payload.size = data.len() as u16;
185 payload.id = id;
186 }
187 InputEvent::SetReportReply { err, id, .. } => {
188 event.type_ = sys::uhid_event_type_UHID_SET_REPORT_REPLY;
189 let payload = unsafe { &mut event.u.set_report_reply };
190 payload.err = err;
191 payload.id = id;
192 }
193 InputEvent::Feature { id, report_num } => {
194 event.type_ = sys::uhid_legacy_event_type_UHID_FEATURE;
195 let payload = unsafe { &mut event.u.feature };
196 payload.id = id;
197 payload.rnum = report_num;
198 payload.rtype = sys::hid_report_type_HID_INPUT_REPORT as u8;
199 }
200 InputEvent::FeatureAnswer { err, id, data, .. } => {
201 event.type_ = sys::uhid_event_type_UHID_GET_REPORT_REPLY;
202 let payload = unsafe { &mut event.u.get_report_reply };
203 payload.err = err;
204 data.iter()
205 .enumerate()
206 .for_each(|(i, x)| payload.data[i] = *x);
207 payload.size = data.len() as u16;
208 payload.id = id;
209 }
210 InputEvent::SetReport {
211 id,
212 report_num,
213 data,
214 } => {
215 event.type_ = sys::uhid_event_type_UHID_SET_REPORT;
216 let payload = unsafe { &mut event.u.set_report };
217 data.iter()
218 .enumerate()
219 .for_each(|(i, x)| payload.data[i] = *x);
220 payload.size = data.len() as u16;
221 payload.id = id;
222 payload.rnum = report_num;
223 payload.rtype = sys::hid_report_type_HID_INPUT_REPORT as u8;
224 }
225 };
226
227 event
228 }
229}
230
231pub enum OutputEvent {
233 Start {
234 dev_flags: Vec<DevFlags>,
235 },
236 Stop,
237 Open,
238 Close,
239 Output {
240 data: Vec<u8>,
241 },
242 GetReport {
243 id: u32,
244 report_number: u8,
245 report_type: ReportType,
246 },
247 SetReport {
248 id: u32,
249 report_number: u8,
250 report_type: ReportType,
251 data: Vec<u8>,
252 },
253}
254
255fn to_uhid_event_type(value: u32) -> Option<sys::uhid_event_type> {
256 let last_valid_value = sys::uhid_event_type_UHID_SET_REPORT_REPLY;
257 if value <= last_valid_value {
258 Some(value)
259 } else {
260 None
261 }
262}
263
264impl TryFrom<sys::uhid_event> for OutputEvent {
265 type Error = StreamError;
266 fn try_from(event: sys::uhid_event) -> Result<Self, Self::Error> {
267 if let Some(event_type) = to_uhid_event_type(event.type_) {
268 match event_type {
269 sys::uhid_event_type_UHID_START => Ok(unsafe {
270 OutputEvent::Start {
271 dev_flags: BitFlags::from_bits_truncate(event.u.start.dev_flags)
272 .iter()
273 .collect(),
274 }
275 }),
276 sys::uhid_event_type_UHID_STOP => Ok(OutputEvent::Stop),
277 sys::uhid_event_type_UHID_OPEN => Ok(OutputEvent::Open),
278 sys::uhid_event_type_UHID_CLOSE => Ok(OutputEvent::Close),
279 sys::uhid_event_type_UHID_OUTPUT => Ok(unsafe {
280 let payload = &event.u.output;
281 assert_eq!(
282 payload.rtype,
283 sys::uhid_report_type_UHID_OUTPUT_REPORT as u8
284 );
285 OutputEvent::Output {
286 data: slice::from_raw_parts(
287 &payload.data[0] as *const u8,
288 payload.size as usize,
289 )
290 .to_vec(),
291 }
292 }),
293 sys::uhid_event_type_UHID_GET_REPORT => Ok(unsafe {
294 let payload = &event.u.get_report;
295 OutputEvent::GetReport {
296 id: payload.id,
297 report_number: payload.rnum,
298 report_type: mem::transmute(payload.rtype),
299 }
300 }),
301 sys::uhid_event_type_UHID_SET_REPORT => Ok(unsafe {
302 let payload = &event.u.set_report;
303 OutputEvent::SetReport {
304 id: payload.id,
305 report_number: payload.rnum,
306 report_type: mem::transmute(payload.rtype),
307 data: slice::from_raw_parts(
308 &payload.data[0] as *const u8,
309 payload.size as usize,
310 )
311 .to_vec(),
312 }
313 }),
314 _ => Err(StreamError::UnknownEventType(event.type_)),
315 }
316 } else {
317 Err(StreamError::UnknownEventType(event.type_))
318 }
319 }
320}
321
322impl TryFrom<[u8; UHID_EVENT_SIZE]> for OutputEvent {
323 type Error = StreamError;
324 fn try_from(src: [u8; UHID_EVENT_SIZE]) -> Result<Self, Self::Error> {
325 OutputEvent::try_from(unsafe { *(src.as_ptr() as *const sys::uhid_event) })
326 }
327}
328
329impl<'a> From<InputEvent<'a>> for [u8; UHID_EVENT_SIZE] {
330 fn from(input: InputEvent<'a>) -> Self {
331 let event: sys::uhid_event = input.into();
332 unsafe { mem::transmute_copy(&event) }
333 }
334}
335
336#[cfg(test)]
337mod tests {
338 use super::*;
339
340 const RDESC: [u8; 85] = [
341 0x05, 0x01, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x01, 0xa1, 0x00, 0x85, 0x01, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03, 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01, 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01, 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x09, 0x38, 0x15, 0x81, 0x25, 0x7f, 0x75, 0x08, 0x95, 0x03, 0x81, 0x06, 0xc0, 0xc0, 0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x85, 0x02, 0x05, 0x08, 0x19, 0x01, 0x29, 0x03, 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01, 0x91, 0x02, 0x95, 0x01, 0x75, 0x05, 0x91, 0x01, 0xc0, ];
386
387 fn assert_bytes_eq(actual: &[u8], expected: &[u8]) {
388 assert_eq!(actual.len(), expected.len(), "Size of slices differs");
389 for index in 0..actual.len() {
390 assert_eq!(
391 actual[index], expected[index],
392 "Bytes differ at index {}",
393 index
394 );
395 }
396 }
397
398 #[test]
399 fn encode_create_request() {
400 let mut expected = [0; UHID_EVENT_SIZE];
401 expected[0] = 0x0b;
402 expected[4] = 0x74;
403 expected[5] = 0x65;
404 expected[6] = 0x73;
405 expected[7] = 0x74;
406 expected[8] = 0x2d;
407 expected[9] = 0x75;
408 expected[10] = 0x68;
409 expected[11] = 0x69;
410 expected[12] = 0x64;
411 expected[13] = 0x2d;
412 expected[14] = 0x64;
413 expected[15] = 0x65;
414 expected[16] = 0x76;
415 expected[17] = 0x69;
416 expected[18] = 0x63;
417 expected[19] = 0x65;
418 expected[260] = 0x55;
419 expected[262] = 0x03;
420 expected[264] = 0xd9;
421 expected[265] = 0x15;
422 expected[268] = 0x37;
423 expected[269] = 0x0a;
424 expected[280] = 0x05;
425 expected[281] = 0x01;
426 expected[282] = 0x09;
427 expected[283] = 0x02;
428 expected[284] = 0xa1;
429 expected[285] = 0x01;
430 expected[286] = 0x09;
431 expected[287] = 0x01;
432 expected[288] = 0xa1;
433 expected[290] = 0x85;
434 expected[291] = 0x01;
435 expected[292] = 0x05;
436 expected[293] = 0x09;
437 expected[294] = 0x19;
438 expected[295] = 0x01;
439 expected[296] = 0x29;
440 expected[297] = 0x03;
441 expected[298] = 0x15;
442 expected[300] = 0x25;
443 expected[301] = 0x01;
444 expected[302] = 0x95;
445 expected[303] = 0x03;
446 expected[304] = 0x75;
447 expected[305] = 0x01;
448 expected[306] = 0x81;
449 expected[307] = 0x02;
450 expected[308] = 0x95;
451 expected[309] = 0x01;
452 expected[310] = 0x75;
453 expected[311] = 0x05;
454 expected[312] = 0x81;
455 expected[313] = 0x01;
456 expected[314] = 0x05;
457 expected[315] = 0x01;
458 expected[316] = 0x09;
459 expected[317] = 0x30;
460 expected[318] = 0x09;
461 expected[319] = 0x31;
462 expected[320] = 0x09;
463 expected[321] = 0x38;
464 expected[322] = 0x15;
465 expected[323] = 0x81;
466 expected[324] = 0x25;
467 expected[325] = 0x7f;
468 expected[326] = 0x75;
469 expected[327] = 0x08;
470 expected[328] = 0x95;
471 expected[329] = 0x03;
472 expected[330] = 0x81;
473 expected[331] = 0x06;
474 expected[332] = 0xc0;
475 expected[333] = 0xc0;
476 expected[334] = 0x05;
477 expected[335] = 0x01;
478 expected[336] = 0x09;
479 expected[337] = 0x06;
480 expected[338] = 0xa1;
481 expected[339] = 0x01;
482 expected[340] = 0x85;
483 expected[341] = 0x02;
484 expected[342] = 0x05;
485 expected[343] = 0x08;
486 expected[344] = 0x19;
487 expected[345] = 0x01;
488 expected[346] = 0x29;
489 expected[347] = 0x03;
490 expected[348] = 0x15;
491 expected[350] = 0x25;
492 expected[351] = 0x01;
493 expected[352] = 0x95;
494 expected[353] = 0x03;
495 expected[354] = 0x75;
496 expected[355] = 0x01;
497 expected[356] = 0x91;
498 expected[357] = 0x02;
499 expected[358] = 0x95;
500 expected[359] = 0x01;
501 expected[360] = 0x75;
502 expected[361] = 0x05;
503 expected[362] = 0x91;
504 expected[363] = 0x01;
505 expected[364] = 0xc0;
506
507 let result: [u8; UHID_EVENT_SIZE] = InputEvent::Create(CreateParams {
508 name: String::from("test-uhid-device"),
509 phys: String::from(""),
510 uniq: String::from(""),
511 bus: Bus::USB,
512 vendor: 0x15d9,
513 product: 0x0a37,
514 version: 0,
515 country: 0,
516 rd_data: RDESC.to_vec(),
517 })
518 .into();
519
520 assert_bytes_eq(&result[..], &expected);
521 }
522
523 #[test]
524 fn encode_destroy_request() {
525 let mut expected = vec![0; mem::size_of::<sys::uhid_event>()];
526 expected[0] = 0x01;
527
528 let result: [u8; UHID_EVENT_SIZE] = InputEvent::Destroy.into();
529 assert_bytes_eq(&result[..], &expected);
530 }
531}