use std::{convert::TryInto, time::Duration};
use cameleon_device::u3v::{
self,
register_map::{abrm, manifest_entry, sbrm, sirm},
};
use crate::{genapi::CompressionType, ControlError, ControlResult, DeviceControl};
#[derive(Clone, Copy, Debug)]
pub struct Abrm {
device_capability: DeviceCapability,
}
impl Abrm {
pub fn new<Ctrl: DeviceControl + ?Sized>(device: &mut Ctrl) -> ControlResult<Self> {
let (capability_addr, capability_len) = abrm::DEVICE_CAPABILITY;
let device_capability = read_register(device, capability_addr, capability_len)?;
Ok(Self { device_capability })
}
pub fn sbrm<Ctrl: DeviceControl + ?Sized>(&self, device: &mut Ctrl) -> ControlResult<Sbrm> {
let sbrm_address = self.sbrm_address(device)?;
Sbrm::new(device, sbrm_address)
}
pub fn manifest_table<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<ManifestTable> {
Ok(ManifestTable::new(self.manifest_table_address(device)?))
}
pub fn gencp_version<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<semver::Version> {
let gencp_version: u32 = self.read_register(device, abrm::GENCP_VERSION)?;
let gencp_version_minor = gencp_version & 0xff;
let gencp_version_major = (gencp_version >> 16_i32) & 0xff;
Ok(semver::Version::new(
u64::from(gencp_version_major),
u64::from(gencp_version_minor),
0,
))
}
pub fn manufacturer_name<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<String> {
self.read_register(device, abrm::MANUFACTURER_NAME)
}
pub fn model_name<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<String> {
self.read_register(device, abrm::MODEL_NAME)
}
pub fn family_name<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<Option<String>> {
if self.device_capability.is_family_name_supported() {
self.read_register(device, abrm::FAMILY_NAME).map(Some)
} else {
Ok(None)
}
}
pub fn device_version<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<String> {
self.read_register(device, abrm::DEVICE_VERSION)
}
pub fn manufacturer_info<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<String> {
self.read_register(device, abrm::MANUFACTURER_INFO)
}
pub fn serial_number<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<String> {
self.read_register(device, abrm::SERIAL_NUMBER)
}
pub fn user_defined_name<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<Option<String>> {
if self.device_capability.is_user_defined_name_supported() {
self.read_register(device, abrm::USER_DEFINED_NAME)
.map(Some)
} else {
Ok(None)
}
}
pub fn set_user_defined_name<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
name: &str,
) -> ControlResult<()> {
if !self.device_capability.is_user_defined_name_supported() {
return Ok(());
}
self.write_register(device, abrm::USER_DEFINED_NAME, name)
}
pub fn manifest_table_address<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<u64> {
self.read_register(device, abrm::MANIFEST_TABLE_ADDRESS)
}
pub fn sbrm_address<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<u64> {
self.read_register(device, abrm::SBRM_ADDRESS)
}
pub fn timestamp<Ctrl: DeviceControl + ?Sized>(&self, device: &mut Ctrl) -> ControlResult<u64> {
self.read_register(device, abrm::TIMESTAMP)
}
pub fn set_timestamp_latch_bit<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<()> {
self.write_register(device, abrm::TIMESTAMP_LATCH, 1_u32)
}
pub fn timestamp_increment<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<u64> {
self.read_register(device, abrm::TIMESTAMP_INCREMENT)
}
pub fn device_software_interface_version<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<Option<String>> {
if self
.device_capability
.is_device_software_interface_version_supported()
{
self.read_register(device, abrm::DEVICE_SOFTWARE_INTERFACE_VERSION)
.map(Some)
} else {
Ok(None)
}
}
pub fn maximum_device_response_time<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<Duration> {
self.read_register(device, abrm::MAXIMUM_DEVICE_RESPONSE_TIME)
}
pub fn device_capability(&self) -> ControlResult<DeviceCapability> {
Ok(self.device_capability)
}
pub fn device_configuration<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<DeviceConfiguration> {
self.read_register(device, abrm::DEVICE_CONFIGURATION)
}
pub fn write_device_configuration<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
config: DeviceConfiguration,
) -> ControlResult<()> {
self.write_register(device, abrm::DEVICE_CONFIGURATION, config)
}
fn read_register<T, Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
register: (u64, u16),
) -> ControlResult<T>
where
T: ParseBytes,
{
read_register(device, register.0, register.1)
}
fn write_register<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
register: (u64, u16),
data: impl DumpBytes,
) -> ControlResult<()> {
let (addr, len) = register;
let mut buf = vec![0; len as usize];
data.dump_bytes(&mut buf)?;
device.write(addr, &buf)
}
}
#[derive(Clone, Copy, Debug)]
pub struct Sbrm {
sbrm_addr: u64,
capability: U3VCapablitiy,
}
impl Sbrm {
pub fn new<Ctrl: DeviceControl + ?Sized>(
device: &mut Ctrl,
sbrm_addr: u64,
) -> ControlResult<Self> {
let (capability_offset, capability_len) = sbrm::U3VCP_CAPABILITY_REGISTER;
let capability_addr = capability_offset + sbrm_addr;
let capability = read_register(device, capability_addr, capability_len)?;
Ok(Self {
sbrm_addr,
capability,
})
}
pub fn u3v_version<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<semver::Version> {
let u3v_version: u32 = self.read_register(device, sbrm::U3V_VERSION)?;
let u3v_version_minor = u3v_version & 0xff;
let u3v_version_major = (u3v_version >> 16_i32) & 0xff;
Ok(semver::Version::new(
u64::from(u3v_version_major),
u64::from(u3v_version_minor),
0,
))
}
pub fn maximum_command_transfer_length<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<u32> {
self.read_register(device, sbrm::MAXIMUM_COMMAND_TRANSFER_LENGTH)
}
pub fn maximum_acknowledge_trasfer_length<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<u32> {
self.read_register(device, sbrm::MAXIMUM_ACKNOWLEDGE_TRANSFER_LENGTH)
}
pub fn number_of_stream_channel<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<u32> {
self.read_register(device, sbrm::NUMBER_OF_STREAM_CHANNELS)
}
pub fn sirm<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<Option<Sirm>> {
Ok(self.sirm_address(device)?.map(Sirm::new))
}
pub fn sirm_address<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<Option<u64>> {
if self.capability.is_sirm_available() {
self.read_register(device, sbrm::SIRM_ADDRESS).map(Some)
} else {
Ok(None)
}
}
pub fn sirm_length<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<Option<u32>> {
if self.capability.is_sirm_available() {
self.read_register(device, sbrm::SIRM_LENGTH).map(Some)
} else {
Ok(None)
}
}
pub fn eirm_address<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<Option<u64>> {
if self.capability.is_eirm_available() {
self.read_register(device, sbrm::EIRM_ADDRESS).map(Some)
} else {
Ok(None)
}
}
pub fn eirm_length<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<Option<u32>> {
if self.capability.is_eirm_available() {
self.read_register(device, sbrm::EIRM_LENGTH).map(Some)
} else {
Ok(None)
}
}
pub fn iidc2_address<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<Option<u64>> {
if self.capability.is_iidc2_available() {
self.read_register(device, sbrm::IIDC2_ADDRESS).map(Some)
} else {
Ok(None)
}
}
pub fn current_speed<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<u3v::BusSpeed> {
self.read_register(device, sbrm::CURRENT_SPEED)
}
pub fn u3v_capability(&self) -> ControlResult<U3VCapablitiy> {
Ok(self.capability)
}
fn read_register<T, Ctrl>(&self, device: &mut Ctrl, register: (u64, u16)) -> ControlResult<T>
where
T: ParseBytes,
Ctrl: DeviceControl + ?Sized,
{
let (offset, len) = register;
let addr = offset + self.sbrm_addr;
read_register(device, addr, len)
}
}
#[derive(Clone, Copy, Debug)]
pub struct Sirm {
sirm_addr: u64,
}
impl Sirm {
#[must_use]
pub fn new(sirm_addr: u64) -> Self {
Self { sirm_addr }
}
pub fn payload_size_alignment<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<usize> {
let si_info: u32 = self.read_register(device, sirm::SI_INFO)?;
Ok(1 << (si_info >> 24_i32))
}
pub fn enable_stream<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<()> {
let value = 1_u32;
self.write_register(device, sirm::SI_CONTROL, value)
}
pub fn disable_stream<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<()> {
let value = 0_u32;
self.write_register(device, sirm::SI_CONTROL, value)
}
pub fn is_stream_enable<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<bool> {
let si_ctrl: u32 = self.read_register(device, sirm::SI_CONTROL)?;
Ok((si_ctrl & 1) == 1)
}
pub fn required_payload_size<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<u64> {
self.read_register(device, sirm::REQUIRED_PAYLOAD_SIZE)
}
pub fn required_leader_size<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<u32> {
self.read_register(device, sirm::REQUIRED_LEADER_SIZE)
}
pub fn required_trailer_size<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<u32> {
self.read_register(device, sirm::REQUIRED_TRAILER_SIZE)
}
pub fn maximum_leader_size<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<u32> {
self.read_register(device, sirm::MAXIMUM_LEADER_SIZE)
}
pub fn set_maximum_leader_size<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
size: u32,
) -> ControlResult<()> {
self.write_register(device, sirm::MAXIMUM_LEADER_SIZE, size)
}
pub fn maximum_trailer_size<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<u32> {
self.read_register(device, sirm::MAXIMUM_TRAILER_SIZE)
}
pub fn set_maximum_trailer_size<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
size: u32,
) -> ControlResult<()> {
self.write_register(device, sirm::MAXIMUM_TRAILER_SIZE, size)
}
pub fn payload_transfer_size<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<u32> {
self.read_register(device, sirm::PAYLOAD_TRANSFER_SIZE)
}
pub fn set_payload_transfer_size<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
size: u32,
) -> ControlResult<()> {
self.write_register(device, sirm::PAYLOAD_TRANSFER_SIZE, size)
}
pub fn payload_transfer_count<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<u32> {
self.read_register(device, sirm::PAYLOAD_TRANSFER_COUNT)
}
pub fn set_payload_transfer_count<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
size: u32,
) -> ControlResult<()> {
self.write_register(device, sirm::PAYLOAD_TRANSFER_COUNT, size)
}
pub fn payload_final_transfer1_size<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<u32> {
self.read_register(device, sirm::PAYLOAD_FINAL_TRANSFER1_SIZE)
}
pub fn set_payload_final_transfer1_size<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
size: u32,
) -> ControlResult<()> {
self.write_register(device, sirm::PAYLOAD_FINAL_TRANSFER1_SIZE, size)
}
pub fn payload_final_transfer2_size<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<u32> {
self.read_register(device, sirm::PAYLOAD_FINAL_TRANSFER2_SIZE)
}
pub fn set_payload_final_transfer2_size<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
size: u32,
) -> ControlResult<()> {
self.write_register(device, sirm::PAYLOAD_FINAL_TRANSFER2_SIZE, size)
}
fn read_register<T, Ctrl>(&self, device: &mut Ctrl, register: (u64, u16)) -> ControlResult<T>
where
T: ParseBytes,
Ctrl: DeviceControl + ?Sized,
{
let (offset, len) = register;
let addr = offset + self.sirm_addr;
read_register(device, addr, len)
}
fn write_register<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
register: (u64, u16),
data: impl DumpBytes,
) -> ControlResult<()> {
let (offset, len) = register;
let addr = self.sirm_addr + offset;
let mut buf = vec![0; len as usize];
data.dump_bytes(&mut buf)?;
device.write(addr, &buf)
}
}
#[derive(Clone, Copy, Debug)]
pub struct ManifestTable {
manifest_address: u64,
}
impl ManifestTable {
#[must_use]
pub fn new(manifest_address: u64) -> Self {
Self { manifest_address }
}
pub fn entries<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<impl Iterator<Item = ManifestEntry>> {
let entry_num: u64 = self.read_register(device, (0, 8))?;
let first_entry_addr = self.manifest_address + 8;
Ok((0..entry_num).map(move |i| ManifestEntry::new(first_entry_addr + i * 64)))
}
fn read_register<T, Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
register: (u64, u16),
) -> ControlResult<T>
where
T: ParseBytes,
{
let (offset, len) = register;
read_register(device, offset + self.manifest_address, len)
}
}
#[derive(Clone, Copy, Debug)]
pub struct ManifestEntry {
entry_addr: u64,
}
impl ManifestEntry {
#[must_use]
pub fn new(entry_addr: u64) -> Self {
Self { entry_addr }
}
pub fn genicam_file_version<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<semver::Version> {
let file_version: u32 = self.read_register(device, manifest_entry::GENICAM_FILE_VERSION)?;
let subminor = file_version & 0xff;
let minor = (file_version >> 16_i32) & 0xff;
let major = (file_version >> 24_i32) & 0xff;
Ok(semver::Version::new(
u64::from(major),
u64::from(minor),
u64::from(subminor),
))
}
pub fn file_address<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<u64> {
self.read_register(device, manifest_entry::REGISTER_ADDRESS)
}
pub fn file_size<Ctrl: DeviceControl + ?Sized>(&self, device: &mut Ctrl) -> ControlResult<u64> {
self.read_register(device, manifest_entry::FILE_SIZE)
}
pub fn file_info<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<GenICamFileInfo> {
self.read_register(device, manifest_entry::FILE_FORMAT_INFO)
}
pub fn sha1_hash<Ctrl: DeviceControl + ?Sized>(
&self,
device: &mut Ctrl,
) -> ControlResult<Option<[u8; 20]>> {
let mut sha1_hash: [u8; 20] = [0; 20];
let addr = self.entry_addr + manifest_entry::SHA1_HASH.0;
device.read(addr, &mut sha1_hash)?;
if sha1_hash.iter().all(|byte| *byte == 0) {
Ok(None)
} else {
Ok(Some(sha1_hash))
}
}
fn read_register<T, Ctrl>(&self, device: &mut Ctrl, register: (u64, u16)) -> ControlResult<T>
where
T: ParseBytes,
Ctrl: DeviceControl + ?Sized,
{
let (offset, len) = register;
let addr = offset + self.entry_addr;
read_register(device, addr, len)
}
}
fn read_register<T, Ctrl: DeviceControl + ?Sized>(
device: &mut Ctrl,
addr: u64,
len: u16,
) -> ControlResult<T>
where
T: ParseBytes,
{
let len = len as usize;
let mut buf = vec![0; len];
device.read(addr, &mut buf[..len])?;
T::parse_bytes(&buf[..len])
}
macro_rules! is_bit_set {
($val:expr, $bit:expr) => {
(($val >> $bit) & 1) == 1
};
}
macro_rules! set_bit {
($val:expr, $bit:expr) => {
$val |= (1 << $bit)
};
}
macro_rules! unset_bit {
($val:expr, $bit:expr) => {
$val &= !(1 << $bit)
};
}
#[derive(Clone, Copy, Debug)]
pub struct DeviceConfiguration(u64);
impl DeviceConfiguration {
#[must_use]
pub fn is_multi_event_enabled(self) -> bool {
is_bit_set!(self.0, 1_i32)
}
pub fn set_multi_event_enable_bit(&mut self) {
set_bit!(self.0, 1_i32)
}
pub fn disable_multi_event(&mut self) {
unset_bit!(self.0, 1_i32)
}
}
#[derive(Clone, Copy, Debug)]
pub struct DeviceCapability(u64);
impl DeviceCapability {
#[must_use]
pub fn is_user_defined_name_supported(self) -> bool {
is_bit_set!(self.0, 0_i32)
}
#[must_use]
pub fn is_family_name_supported(self) -> bool {
is_bit_set!(self.0, 8_i32)
}
#[must_use]
pub fn is_multi_event_supported(self) -> bool {
is_bit_set!(self.0, 12_i32)
}
#[must_use]
pub fn is_stacked_commands_supported(self) -> bool {
is_bit_set!(self.0, 13_i32)
}
#[must_use]
pub fn is_device_software_interface_version_supported(self) -> bool {
is_bit_set!(self.0, 14_i32)
}
}
#[derive(Clone, Copy, Debug)]
pub struct U3VCapablitiy(u64);
impl U3VCapablitiy {
#[must_use]
pub fn is_sirm_available(self) -> bool {
is_bit_set!(&self.0, 0_i32)
}
#[must_use]
pub fn is_eirm_available(self) -> bool {
is_bit_set!(&self.0, 1_i32)
}
#[must_use]
pub fn is_iidc2_available(self) -> bool {
is_bit_set!(&self.0, 2_i32)
}
}
pub struct GenICamFileInfo(u32);
impl GenICamFileInfo {
pub fn file_type(&self) -> ControlResult<GenICamFileType> {
let raw = self.0 & 0b111;
match raw {
0 => Ok(GenICamFileType::DeviceXml),
1 => Ok(GenICamFileType::BufferXml),
_ => Err(ControlError::InvalidDevice(
format!("Invalid U3V GenICamFileType value: {}", raw).into(),
)),
}
}
pub fn compression_type(&self) -> ControlResult<CompressionType> {
let raw = (self.0 >> 10_i32) & 0b11_1111;
match raw {
0 => Ok(CompressionType::Uncompressed),
1 => Ok(CompressionType::Zip),
_ => Err(ControlError::InvalidDevice(
format!("Invalid U3V GenICamFilFormat value: {}", raw).into(),
)),
}
}
#[must_use]
pub fn schema_version(&self) -> semver::Version {
let major = (self.0 >> 24_i32) & 0xff;
let minor = (self.0 >> 16_i32) & 0xff;
semver::Version::new(u64::from(major), u64::from(minor), 0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum GenICamFileType {
DeviceXml,
BufferXml,
}
trait ParseBytes: Sized {
fn parse_bytes(bytes: &[u8]) -> ControlResult<Self>;
}
impl ParseBytes for DeviceConfiguration {
fn parse_bytes(bytes: &[u8]) -> ControlResult<Self> {
Ok(Self(u64::parse_bytes(bytes)?))
}
}
impl ParseBytes for DeviceCapability {
fn parse_bytes(bytes: &[u8]) -> ControlResult<Self> {
Ok(Self(u64::parse_bytes(bytes)?))
}
}
impl ParseBytes for GenICamFileInfo {
fn parse_bytes(bytes: &[u8]) -> ControlResult<Self> {
Ok(Self(u32::parse_bytes(bytes)?))
}
}
impl ParseBytes for String {
fn parse_bytes(bytes: &[u8]) -> ControlResult<Self> {
let len = bytes.iter().position(|&b| b == 0);
let s = len.map_or_else(
|| std::str::from_utf8(bytes),
|len| std::str::from_utf8(&bytes[..len]),
);
let s = s.map_err(|_| {
ControlError::InvalidDevice("device's string register value is broken".into())
})?;
Ok(s.into())
}
}
impl ParseBytes for Duration {
fn parse_bytes(bytes: &[u8]) -> ControlResult<Self> {
let raw = u32::parse_bytes(bytes)?;
Ok(Duration::from_millis(u64::from(raw)))
}
}
impl ParseBytes for U3VCapablitiy {
fn parse_bytes(bytes: &[u8]) -> ControlResult<Self> {
Ok(Self(u64::parse_bytes(bytes)?))
}
}
impl ParseBytes for u3v::BusSpeed {
fn parse_bytes(bytes: &[u8]) -> ControlResult<Self> {
use u3v::BusSpeed::{FullSpeed, HighSpeed, LowSpeed, SuperSpeed, SuperSpeedPlus};
let raw = u32::parse_bytes(bytes)?;
let speed = match raw {
0b1 => LowSpeed,
0b10 => FullSpeed,
0b100 => HighSpeed,
0b1000 => SuperSpeed,
0b10000 => SuperSpeedPlus,
other => {
return Err(ControlError::InvalidDevice(
format!("invalid bus speed defined: {:#b}", other).into(),
))
}
};
Ok(speed)
}
}
macro_rules! impl_parse_bytes_for_numeric {
($ty:ty) => {
impl ParseBytes for $ty {
fn parse_bytes(bytes: &[u8]) -> ControlResult<Self> {
let bytes = bytes.try_into().unwrap();
Ok(<$ty>::from_le_bytes(bytes))
}
}
};
}
impl_parse_bytes_for_numeric!(u8);
impl_parse_bytes_for_numeric!(u16);
impl_parse_bytes_for_numeric!(u32);
impl_parse_bytes_for_numeric!(u64);
impl_parse_bytes_for_numeric!(i8);
impl_parse_bytes_for_numeric!(i16);
impl_parse_bytes_for_numeric!(i32);
impl_parse_bytes_for_numeric!(i64);
trait DumpBytes {
fn dump_bytes(&self, buf: &mut [u8]) -> ControlResult<()>;
}
impl<T> DumpBytes for &T
where
T: DumpBytes,
{
fn dump_bytes(&self, buf: &mut [u8]) -> ControlResult<()> {
(*self).dump_bytes(buf)
}
}
impl DumpBytes for &str {
fn dump_bytes(&self, buf: &mut [u8]) -> ControlResult<()> {
if !self.is_ascii() {
return Err(ControlError::InvalidData(
"string encoding must be ascii".into(),
));
}
let data_len = self.len();
if data_len > buf.len() {
return Err(ControlError::InvalidData("too large string".into()));
}
buf[..data_len].copy_from_slice(self.as_bytes());
if data_len < buf.len() {
buf[data_len] = 0;
}
Ok(())
}
}
impl DumpBytes for DeviceConfiguration {
fn dump_bytes(&self, buf: &mut [u8]) -> ControlResult<()> {
self.0.dump_bytes(buf)
}
}
macro_rules! impl_dump_bytes_for_numeric {
($ty:ty) => {
impl DumpBytes for $ty {
fn dump_bytes(&self, buf: &mut [u8]) -> ControlResult<()> {
let data = self.to_le_bytes();
debug_assert_eq!(data.len(), buf.len());
buf.copy_from_slice(&data);
Ok(())
}
}
};
}
impl_dump_bytes_for_numeric!(u8);
impl_dump_bytes_for_numeric!(u16);
impl_dump_bytes_for_numeric!(u32);
impl_dump_bytes_for_numeric!(u64);
impl_dump_bytes_for_numeric!(i8);
impl_dump_bytes_for_numeric!(i16);
impl_dump_bytes_for_numeric!(i32);
impl_dump_bytes_for_numeric!(i64);