tokio_linux_uhid/
uhid_codec.rs

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