#![forbid(future_incompatible)]
#![deny(bad_style, missing_docs)]
#![doc = include_str!("../README.md")]
#[cfg(not(target_os = "linux"))]
compile_error!("This crate support Linux only");
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[macro_use]
mod macros;
#[cfg(feature = "either")]
mod either_report;
#[cfg(feature = "keyboard")]
mod keyboard;
#[cfg(feature = "mouse")]
mod mouse;
#[cfg(feature = "keyboard")]
pub use keyboard::{
Key, KeyStateChanges, Keyboard, KeyboardInput, KeyboardOutput, Led, LedStateChanges, Leds,
Modifiers,
};
#[cfg(feature = "mouse")]
pub use mouse::{
Button, Buttons, Mouse, MouseInput, MouseInputChange, MouseInputChanges, MouseOutput,
};
use std::{
io::ErrorKind,
path::{Path, PathBuf},
};
pub use std::io::{Error, Result};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Unknown;
impl std::error::Error for Unknown {}
impl core::fmt::Display for Unknown {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.write_str("Unknown")
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct StateChange<T> {
data: T,
state: bool,
}
impl<T> StateChange<T> {
pub fn new(data: T, state: bool) -> Self {
Self { data, state }
}
pub fn press(data: T) -> Self {
Self::new(data, true)
}
pub fn on(data: T) -> Self {
Self::new(data, true)
}
pub fn release(data: T) -> Self {
Self::new(data, false)
}
pub fn off(data: T) -> Self {
Self::new(data, false)
}
pub fn data(&self) -> T
where
T: Copy,
{
self.data
}
pub fn state(&self) -> bool {
self.state
}
pub fn is_press(&self) -> bool {
self.state
}
pub fn is_on(&self) -> bool {
self.state
}
pub fn is_release(&self) -> bool {
!self.state
}
pub fn is_off(&self) -> bool {
!self.state
}
}
impl<T> From<(T, bool)> for StateChange<T> {
fn from((data, state): (T, bool)) -> Self {
Self { data, state }
}
}
impl<T> From<StateChange<T>> for (T, bool) {
fn from(StateChange { data, state }: StateChange<T>) -> Self {
(data, state)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ValueChange<T> {
data: T,
#[cfg_attr(feature = "serde", serde(rename = "rel"))]
relative: bool,
}
impl<T> ValueChange<T> {
pub fn new(data: T, relative: bool) -> Self {
Self { data, relative }
}
pub fn data(&self) -> T
where
T: Copy,
{
self.data
}
pub fn absolute(data: T) -> Self {
Self::new(data, false)
}
pub fn relative(data: T) -> Self {
Self::new(data, true)
}
pub fn is_relative(&self) -> bool {
self.relative
}
pub fn is_absolute(&self) -> bool {
!self.relative
}
}
impl<T> From<(T, bool)> for ValueChange<T> {
fn from((data, relative): (T, bool)) -> Self {
Self { data, relative }
}
}
impl<T> From<ValueChange<T>> for (T, bool) {
fn from(ValueChange { data, relative }: ValueChange<T>) -> Self {
(data, relative)
}
}
deref_impl! {
StateChange<T> => data: T,
ValueChange<T> => data: T,
}
pub trait Class {
type Input;
type Output;
fn input(&self) -> Self::Input;
fn output(&self) -> Self::Output;
}
pub trait AsDevicePath {
fn as_device_path(&self) -> PathBuf;
}
impl AsDevicePath for Path {
fn as_device_path(&self) -> PathBuf {
if self.is_absolute() {
self.to_path_buf()
} else {
Path::new("/dev").join(self)
}
}
}
impl AsDevicePath for &Path {
fn as_device_path(&self) -> PathBuf {
if self.is_absolute() {
self.to_path_buf()
} else {
Path::new("/dev").join(self)
}
}
}
impl AsDevicePath for PathBuf {
fn as_device_path(&self) -> PathBuf {
let path: &Path = self;
path.as_device_path()
}
}
impl AsDevicePath for &PathBuf {
fn as_device_path(&self) -> PathBuf {
let path: &Path = self;
path.as_device_path()
}
}
impl AsDevicePath for &str {
fn as_device_path(&self) -> PathBuf {
Path::new(self).as_device_path()
}
}
impl AsDevicePath for String {
fn as_device_path(&self) -> PathBuf {
let s: &str = self;
s.as_device_path()
}
}
impl AsDevicePath for &String {
fn as_device_path(&self) -> PathBuf {
let s: &str = self;
s.as_device_path()
}
}
impl AsDevicePath for usize {
fn as_device_path(&self) -> PathBuf {
format!("/dev/hidg{self}").as_device_path()
}
}
macro_rules! as_device_path {
($($type:ty),*) => {
$(
impl AsDevicePath for $type {
fn as_device_path(&self) -> PathBuf {
(*self as usize).as_device_path()
}
}
)*
};
}
as_device_path!(u8, u16, u32, u64, i8, i16, i32, i64, isize);
#[derive(Clone, Copy, Default)]
pub struct Internal<T>(T);
impl<T> core::ops::Deref for Internal<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> core::ops::DerefMut for Internal<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
pub fn check_write(actual: usize, expected: usize) -> Result<()> {
if actual == expected {
Ok(())
} else {
Err(Error::new(ErrorKind::Other, "Error when writing report"))
}
}
pub fn check_read(actual: usize, expected: usize) -> Result<()> {
if actual == expected {
Ok(())
} else {
Err(Error::new(ErrorKind::Other, "Error when reading report"))
}
}