use crate::error::Result;
use crate::protocol::Report;
pub(crate) trait Transport: Send {
fn send(&self, buf: &Report) -> Result<()>;
fn recv(&self, buf: &mut Report) -> Result<()>;
}
pub(crate) struct HidTransport {
dev: hidapi::HidDevice,
}
impl HidTransport {
pub(crate) fn new(dev: hidapi::HidDevice) -> HidTransport {
HidTransport { dev }
}
}
impl Transport for HidTransport {
fn send(&self, buf: &Report) -> Result<()> {
self.dev.send_feature_report(buf)?;
Ok(())
}
fn recv(&self, buf: &mut Report) -> Result<()> {
self.dev.send_feature_report(buf)?;
self.dev.get_feature_report(buf)?;
Ok(())
}
}
#[cfg(test)]
pub(crate) mod mock {
use super::*;
use crate::error::Error;
use std::sync::Mutex;
#[derive(Default)]
pub(crate) struct MockTransport {
inner: Mutex<Inner>,
}
#[derive(Default)]
struct Inner {
sent: Vec<Report>,
responses: Vec<Report>,
fail_after: Option<usize>,
}
impl MockTransport {
pub(crate) fn new() -> MockTransport {
MockTransport::default()
}
pub(crate) fn push_response(&self, r: Report) -> &Self {
self.inner.lock().unwrap().responses.push(r);
self
}
pub(crate) fn fail_after(&self, n: usize) -> &Self {
self.inner.lock().unwrap().fail_after = Some(n);
self
}
pub(crate) fn sent(&self) -> Vec<Report> {
self.inner.lock().unwrap().sent.clone()
}
fn record(&self, buf: &Report) -> Result<()> {
let mut inner = self.inner.lock().unwrap();
inner.sent.push(*buf);
match inner.fail_after {
Some(n) if inner.sent.len() > n => {
Err(Error::Hid(hidapi::HidError::HidApiErrorEmpty))
}
_ => Ok(()),
}
}
}
impl Transport for MockTransport {
fn send(&self, buf: &Report) -> Result<()> {
self.record(buf)
}
fn recv(&self, buf: &mut Report) -> Result<()> {
self.record(buf)?;
let mut inner = self.inner.lock().unwrap();
if inner.responses.is_empty() {
return Err(Error::BadResponse);
}
*buf = inner.responses.remove(0);
Ok(())
}
}
}