1use std::fmt::Display;
2
3const BOSE_VID: u16 = 0x05a7;
4const BOSE_HID_USAGE_PAGE: u16 = 0xff00;
5
6const COMPATIBLE_DEVICES: &[DeviceIds] = &[
7 bose_dev(0x40fe, 0x400d),
9];
10
11const INCOMPATIBLE_DEVICES: &[UsbId] = &[
13 bose_pid(0x40fc),
15];
16
17const fn bose_dev(normal_pid: u16, dfu_pid: u16) -> DeviceIds {
18 DeviceIds {
19 normal_mode: UsbId {
20 vid: BOSE_VID,
21 pid: normal_pid,
22 },
23 dfu_mode: UsbId {
24 vid: BOSE_VID,
25 pid: dfu_pid,
26 },
27 }
28}
29
30const fn bose_pid(pid: u16) -> UsbId {
31 UsbId { vid: BOSE_VID, pid }
32}
33
34pub fn identify_device(id: UsbId, usage_page: u16) -> DeviceCompat {
36 if ![0, BOSE_HID_USAGE_PAGE].contains(&usage_page) {
39 return DeviceCompat::Incompatible;
40 }
41
42 for candidate in COMPATIBLE_DEVICES {
44 if let Some(mode) = candidate.match_id(id) {
45 return DeviceCompat::Compatible(mode);
46 }
47 }
48
49 if INCOMPATIBLE_DEVICES.contains(&id) {
51 return DeviceCompat::Incompatible;
52 }
53
54 if id.vid == BOSE_VID {
56 DeviceCompat::Untested(DeviceMode::Unknown)
57 } else {
58 DeviceCompat::Incompatible
59 }
60}
61
62pub enum DeviceCompat {
64 Compatible(DeviceMode),
66 Untested(DeviceMode),
70 Incompatible,
72}
73
74impl Display for DeviceCompat {
75 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
76 match self {
77 DeviceCompat::Compatible(mode) => write!(f, "compatible device in {} mode", mode),
78 DeviceCompat::Untested(mode) => write!(f, "UNTESTED device in {} mode", mode),
79 DeviceCompat::Incompatible => write!(f, "incompatible device"),
80 }
81 }
82}
83
84#[derive(Copy, Clone, Debug)]
85struct DeviceIds {
86 normal_mode: UsbId,
87 dfu_mode: UsbId,
88}
89
90impl DeviceIds {
91 fn match_id(&self, id: UsbId) -> Option<DeviceMode> {
93 if id == self.normal_mode {
94 Some(DeviceMode::Normal)
95 } else if id == self.dfu_mode {
96 Some(DeviceMode::Dfu)
97 } else {
98 None
99 }
100 }
101}
102
103#[derive(Copy, Clone, Debug, Eq, PartialEq)]
105pub enum DeviceMode {
106 Normal,
107 Dfu,
108 Unknown,
109}
110
111impl Display for DeviceMode {
112 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
113 match self {
114 DeviceMode::Normal => write!(f, "normal"),
115 DeviceMode::Dfu => write!(f, "DFU"),
116 DeviceMode::Unknown => write!(f, "unknown"),
117 }
118 }
119}
120
121#[derive(Copy, Clone, Debug, Eq, PartialEq)]
123pub struct UsbId {
124 pub vid: u16,
125 pub pid: u16,
126}
127
128impl Display for UsbId {
129 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
130 write!(f, "{:04x}:{:04x}", self.vid, self.pid)
131 }
132}