use std::{
ffi::OsString,
io::{Error, ErrorKind, Result},
};
use super::{
util::{FunctionDir, Status},
Function, Handle,
};
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct HidBuilder {
pub sub_class: u8,
pub protocol: u8,
pub report_desc: Vec<u8>,
pub report_len: u8,
pub no_out_endpoint: bool,
}
impl HidBuilder {
pub fn build(self) -> (Hid, Handle) {
let dir = FunctionDir::new();
(Hid { dir: dir.clone() }, Handle::new(HidFunction { builder: self, dir }))
}
}
#[derive(Debug)]
struct HidFunction {
builder: HidBuilder,
dir: FunctionDir,
}
impl Function for HidFunction {
fn driver(&self) -> OsString {
"hid".into()
}
fn dir(&self) -> FunctionDir {
self.dir.clone()
}
fn register(&self) -> Result<()> {
self.dir.write("subclass", self.builder.sub_class.to_string())?;
self.dir.write("protocol", self.builder.protocol.to_string())?;
self.dir.write("report_desc", &self.builder.report_desc)?;
self.dir.write("report_length", self.builder.report_len.to_string())?;
self.dir.write("no_out_endpoint", if self.builder.no_out_endpoint { "1" } else { "0" })?;
Ok(())
}
}
#[derive(Debug)]
pub struct Hid {
dir: FunctionDir,
}
impl Hid {
pub fn builder() -> HidBuilder {
HidBuilder { sub_class: 0, protocol: 0, report_desc: Vec::new(), report_len: 0, no_out_endpoint: false }
}
pub fn status(&self) -> Status {
self.dir.status()
}
pub fn device(&self) -> Result<(u32, u32)> {
let dev = self.dir.read_string("dev")?;
let Some((major, minor)) = dev.split_once(':') else {
return Err(Error::new(ErrorKind::InvalidData, "invalid device number format"));
};
let major = major.parse().map_err(|err| Error::new(ErrorKind::InvalidData, err))?;
let minor = minor.parse().map_err(|err| Error::new(ErrorKind::InvalidData, err))?;
Ok((major, minor))
}
}