1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use std::convert::TryFrom;
use std::fs::{File, OpenOptions};
use std::io::{self, prelude::*};
use std::os::unix::fs::OpenOptionsExt;
use std::path::Path;
use crate::codec::*;
pub struct UHIDDevice<T: Read + Write> {
handle: T,
}
#[derive(Debug, Clone, PartialEq)]
pub struct CreateParams {
pub name: String,
pub phys: String,
pub uniq: String,
pub bus: Bus,
pub vendor: u32,
pub product: u32,
pub version: u32,
pub country: u32,
pub rd_data: Vec<u8>,
}
impl<T: Read + Write> UHIDDevice<T> {
pub fn write(&mut self, data: &[u8]) -> io::Result<usize> {
let event: [u8; UHID_EVENT_SIZE] = InputEvent::Input { data }.into();
self.handle.write(&event)
}
pub fn read(&mut self) -> Result<OutputEvent, StreamError> {
let mut event = [0u8; UHID_EVENT_SIZE];
self.handle
.read_exact(&mut event)
.map_err(StreamError::Io)?;
OutputEvent::try_from(event)
}
pub fn destroy(&mut self) -> io::Result<usize> {
let event: [u8; UHID_EVENT_SIZE] = InputEvent::Destroy.into();
self.handle.write(&event)
}
}
impl UHIDDevice<File> {
pub fn create(params: CreateParams) -> io::Result<UHIDDevice<File>> {
UHIDDevice::create_with_path(params, Path::new("/dev/uhid"))
}
pub fn create_with_path(params: CreateParams, path: &Path) -> io::Result<UHIDDevice<File>> {
let mut options = OpenOptions::new();
options.read(true);
options.write(true);
if cfg!(unix) {
options.custom_flags(libc::O_RDWR | libc::O_CLOEXEC);
}
let mut handle = options.open(path)?;
let event: [u8; UHID_EVENT_SIZE] = InputEvent::Create(params).into();
handle.write_all(&event)?;
Ok(UHIDDevice { handle })
}
}