use std::fmt::Display;
const BOSE_VID: u16 = 0x05a7;
const BOSE_HID_USAGE_PAGE: u16 = 0xff00;
const COMPATIBLE_DEVICES: &[DeviceIds] = &[
bose_dev(0x40fe, 0x400d),
];
const INCOMPATIBLE_DEVICES: &[UsbId] = &[
bose_pid(0x40fc),
];
const fn bose_dev(normal_pid: u16, dfu_pid: u16) -> DeviceIds {
DeviceIds {
normal_mode: UsbId {
vid: BOSE_VID,
pid: normal_pid,
},
dfu_mode: UsbId {
vid: BOSE_VID,
pid: dfu_pid,
},
}
}
const fn bose_pid(pid: u16) -> UsbId {
UsbId { vid: BOSE_VID, pid }
}
pub fn identify_device(id: UsbId, usage_page: u16) -> DeviceCompat {
if ![0, BOSE_HID_USAGE_PAGE].contains(&usage_page) {
return DeviceCompat::Incompatible;
}
for candidate in COMPATIBLE_DEVICES {
if let Some(mode) = candidate.match_id(id) {
return DeviceCompat::Compatible(mode);
}
}
if INCOMPATIBLE_DEVICES.contains(&id) {
return DeviceCompat::Incompatible;
}
if id.vid == BOSE_VID {
DeviceCompat::Untested(DeviceMode::Unknown)
} else {
DeviceCompat::Incompatible
}
}
pub enum DeviceCompat {
Compatible(DeviceMode),
Untested(DeviceMode),
Incompatible,
}
impl Display for DeviceCompat {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
DeviceCompat::Compatible(mode) => write!(f, "compatible device in {} mode", mode),
DeviceCompat::Untested(mode) => write!(f, "UNTESTED device in {} mode", mode),
DeviceCompat::Incompatible => write!(f, "incompatible device"),
}
}
}
#[derive(Copy, Clone, Debug)]
struct DeviceIds {
normal_mode: UsbId,
dfu_mode: UsbId,
}
impl DeviceIds {
fn match_id(&self, id: UsbId) -> Option<DeviceMode> {
if id == self.normal_mode {
Some(DeviceMode::Normal)
} else if id == self.dfu_mode {
Some(DeviceMode::Dfu)
} else {
None
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum DeviceMode {
Normal,
Dfu,
Unknown,
}
impl Display for DeviceMode {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
DeviceMode::Normal => write!(f, "normal"),
DeviceMode::Dfu => write!(f, "DFU"),
DeviceMode::Unknown => write!(f, "unknown"),
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct UsbId {
pub vid: u16,
pub pid: u16,
}
impl Display for UsbId {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:04x}:{:04x}", self.vid, self.pid)
}
}