diff options
Diffstat (limited to 'src/protocol.rs')
| -rw-r--r-- | src/protocol.rs | 55 |
1 files changed, 34 insertions, 21 deletions
diff --git a/src/protocol.rs b/src/protocol.rs index 3a24195..d6fce5f 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -36,6 +36,15 @@ pub const LINK_DEBOUNCE_MISSES: u32 = 2; /// How long to wait for a link response after sending the query. const LINK_RESPONSE_TIMEOUT: Duration = Duration::from_millis(400); +/// Input report id the dongle answers with when the headset is linked. +const LINK_RESPONSE_REPORT: u8 = 0x3c; +/// Selector byte we query with; the response echoes it back. +const LINK_SELECTOR: u8 = 0x01; +/// Command prefix at the start of the query payload. +const CMD_PREFIX: [u8; 2] = [0x09, 0x22]; +/// Link query frame size: report id + 60-byte payload. +const LINK_QUERY_LEN: usize = 61; + /// Headset link state as seen through the dongle. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum LinkState { @@ -52,20 +61,20 @@ pub enum Transition { ToDisconnected { initial: bool }, } -/// Builds the 61-byte link query output report (report id `0x3a` + payload). -pub fn link_query_frame() -> Vec<u8> { - let mut frame = vec![0u8; 61]; +/// Builds the link query output report (report id `0x3a` + payload). +pub fn link_query_frame() -> [u8; LINK_QUERY_LEN] { + let mut frame = [0u8; LINK_QUERY_LEN]; frame[0] = reports::OUT_60_C; - frame[1] = 0x09; - frame[2] = 0x22; - frame[3] = 0x01; + frame[1] = CMD_PREFIX[0]; + frame[2] = CMD_PREFIX[1]; + frame[3] = LINK_SELECTOR; frame } /// True if `data` is a link-status response report (`0x3c` echoing the /// query selector). pub fn is_link_response(data: &[u8]) -> bool { - data.len() >= 2 && data[0] == 0x3c && data[1] == 0x01 + data.len() >= 2 && data[0] == LINK_RESPONSE_REPORT && data[1] == LINK_SELECTOR } /// Queries the dongle once for the headset link state. Returns @@ -116,25 +125,29 @@ impl StateTracker { if self.state == Some(LinkState::Connected) { return None; } - let initial = self.state.is_none(); - self.state = Some(LinkState::Connected); - if initial && !self.fire_initial { - None - } else { - Some(Transition::ToConnected { initial }) - } + self.settle(LinkState::Connected) } else { self.misses += 1; if self.misses < LINK_DEBOUNCE_MISSES || self.state == Some(LinkState::Disconnected) { return None; } - let initial = self.state.is_none(); - self.state = Some(LinkState::Disconnected); - if initial && !self.fire_initial { - None - } else { - Some(Transition::ToDisconnected { initial }) - } + self.settle(LinkState::Disconnected) + } + } + + /// Pin the state, producing the transition unless it is the first + /// determination and initial hooks are suppressed. + fn settle(&mut self, state: LinkState) -> Option<Transition> { + let initial = self.state.is_none(); + self.state = Some(state); + let transition = match state { + LinkState::Connected => Transition::ToConnected { initial }, + LinkState::Disconnected => Transition::ToDisconnected { initial }, + }; + if initial && !self.fire_initial { + None + } else { + Some(transition) } } } |
