1#![cfg_attr(docsrs, feature(doc_cfg))]
6#![warn(missing_docs)]
7
8use std::str::Utf8Error;
9
10use hidapi::HidError;
11use image::ImageError;
12use thiserror::Error;
13
14mod info;
15mod images;
16mod device;
17mod protocol;
18mod hid;
19
20pub use info::Kind;
21pub use device::{Ajazz, DeviceStateReader};
22pub use images::{
23 convert_image, convert_image_with_format, ImageFormat, ImageMode, ImageMirroring,
24 ImageRect, ImageRotation,
25};
26pub use hid::{new_hidapi, refresh_device_list, list_devices};
27
28#[cfg(feature = "async")]
30#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
31pub mod asynchronous;
32#[cfg(feature = "async")]
33#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
34pub use asynchronous::AsyncAjazz;
35#[cfg(feature = "async")]
36#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
37pub use images::{convert_image_async, convert_image_with_format_async};
38
39#[derive(Debug, Error)]
41pub enum AjazzError {
42 #[error("HidApi error: {0}")]
44 HidError(#[from] HidError),
45
46 #[error("Failed to convert bytes into string: {0}")]
48 Utf8Error(#[from] Utf8Error),
49
50 #[error("Failed to encode image: {0}")]
52 ImageError(#[from] ImageError),
53
54 #[cfg(feature = "async")]
56 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
57 #[error("Tokio join error: {0}")]
58 JoinError(#[from] tokio::task::JoinError),
59
60 #[error("Reader mutex was poisoned")]
62 PoisonError,
63
64 #[error("Key index is invalid: {0}")]
66 InvalidKeyIndex(u8),
67
68 #[error("Unrecognized Product ID: {0}")]
70 UnrecognizedPID(u16),
71
72 #[error("The device doesn't support doing that")]
74 UnsupportedOperation,
75
76 #[error("Device sent unexpected data")]
78 BadData,
79
80 #[error("Invalid image size: {0}x{1}, expected {2}x{3}")]
82 InvalidImageSize(usize, usize, usize, usize),
83
84 #[error("Device didn't respond with ACK")]
86 NoAck,
87}
88
89#[derive(Clone, Debug)]
91pub enum AjazzInput {
92 NoData,
94
95 ButtonStateChange(Vec<bool>),
97
98 EncoderStateChange(Vec<bool>),
100
101 EncoderTwist(Vec<i8>),
103}
104
105impl AjazzInput {
106 pub fn is_empty(&self) -> bool {
108 matches!(self, AjazzInput::NoData)
109 }
110}
111
112#[derive(Copy, Clone, Debug, Hash)]
114pub enum Event {
115 ButtonDown(u8),
117
118 ButtonUp(u8),
120
121 EncoderDown(u8),
123
124 EncoderUp(u8),
126
127 EncoderTwist(u8, i8),
129}
130
131#[derive(Default)]
132struct DeviceState {
133 pub buttons: Vec<bool>,
134 pub encoders: Vec<bool>,
135}