use crate::error::Result;
use rusb::{DeviceHandle, UsbContext};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct FirmwareVersion {
pub major: u8,
pub minor: u8,
pub patch: u8,
}
impl std::fmt::Display for FirmwareVersion {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
}
}
pub const I2C_ADDRESS: u8 = 0x42;
pub const I2C_RESID_DFU: u8 = 240;
pub const I2C_RESID_CONFIG: u8 = 241;
pub(crate) const NO_USB_CONTROL: &str =
"reSpeaker Lite exposes no USB control protocol (audio + DFU only); \
use the XMOS I2C command transport at address 0x42 from an I2C master";
pub struct Lite<'a, T: UsbContext> {
handle: &'a DeviceHandle<T>,
}
impl<'a, T: UsbContext> Lite<'a, T> {
pub(crate) fn new(handle: &'a DeviceHandle<T>) -> Self {
Self { handle }
}
pub fn firmware_version(&self) -> Result<FirmwareVersion> {
let desc = self.handle.device().device_descriptor()?;
let v = desc.device_version();
Ok(FirmwareVersion {
major: v.major(),
minor: v.minor(),
patch: v.sub_minor(),
})
}
pub fn version_string(&self) -> Result<String> {
Ok(self.firmware_version()?.to_string())
}
pub fn product_name(&self) -> Result<String> {
let desc = self.handle.device().device_descriptor()?;
Ok(self.handle.read_product_string_ascii(&desc)?)
}
pub fn serial_number(&self) -> Result<String> {
let desc = self.handle.device().device_descriptor()?;
Ok(self.handle.read_serial_number_string_ascii(&desc)?)
}
pub const fn has_usb_control(&self) -> bool {
false
}
}