playdate_device/device/
mod.rs

1use std::hash::Hash;
2pub use nusb::DeviceInfo;
3use crate::usb::mode::DeviceMode;
4use crate::usb::mode::Mode;
5
6pub mod serial;
7pub mod query;
8pub mod command;
9
10mod methods;
11pub use methods::*;
12
13
14/// USB device wrapper
15pub struct Device {
16	// pub serial: Option<SerialNumber>,
17	pub(crate) info: DeviceInfo,
18	pub(crate) mode: Mode,
19
20	/// Opened device handle
21	pub(crate) inner: Option<nusb::Device>,
22
23	// /// Claimed bulk data interface
24	// pub(crate) bulk: Option<crate::usb::Interface>,
25
26	// /// Opened serial fallback interface
27	// pub(crate) serial: Option<crate::serial::blocking::Interface>,
28	pub(crate) interface: Option<crate::interface::Interface>,
29}
30
31impl Eq for Device {}
32impl PartialEq for Device {
33	fn eq(&self, other: &Self) -> bool {
34		self.info.serial_number().is_some() && self.info.serial_number() == other.info.serial_number()
35	}
36}
37
38impl Hash for Device {
39	fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
40		let info = &self.info;
41		info.serial_number().hash(state);
42		info.bus_number().hash(state);
43		info.device_address().hash(state);
44		info.vendor_id().hash(state);
45		info.product_id().hash(state);
46		info.class().hash(state);
47		info.subclass().hash(state);
48		info.protocol().hash(state);
49		info.manufacturer_string().hash(state);
50		info.product_string().hash(state);
51		self.inner.is_some().hash(state);
52		self.interface.is_some().hash(state);
53	}
54}
55
56
57impl AsRef<DeviceInfo> for Device {
58	fn as_ref(&self) -> &DeviceInfo { &self.info }
59}
60
61impl std::fmt::Display for Device {
62	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63		write!(
64		       f,
65		       "{}({})",
66		       self.info.serial_number().unwrap_or("unknown"),
67		       self.info.mode()
68		)
69	}
70}
71
72impl std::fmt::Debug for Device {
73	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74		f.debug_struct("Device")
75		 .field("sn", &self.info.serial_number())
76		 .field("mode", &self.mode)
77		 .field("open", &self.is_open())
78		 .field("interface", &self.interface)
79		 .finish()
80	}
81}
82
83
84impl Device {
85	pub fn new(info: DeviceInfo) -> Self {
86		Self { mode: info.mode(),
87		       info,
88		       inner: None,
89		       interface: None }
90	}
91
92	pub fn info(&self) -> &DeviceInfo { &self.info }
93	pub fn into_info(self) -> DeviceInfo { self.info }
94
95
96	// USB
97
98	/// Cached mode of this device
99	pub fn mode_cached(&self) -> Mode { self.mode }
100	pub fn is_open(&self) -> bool { self.inner.is_some() || self.is_ready() }
101	pub fn is_ready(&self) -> bool {
102		match self.interface.as_ref() {
103			Some(crate::interface::Interface::Usb(_)) => true,
104			Some(crate::interface::Interface::Serial(inner)) => inner.is_open(),
105			None => false,
106		}
107	}
108}