aboutsummaryrefslogtreecommitdiff
path: root/src/protocol.rs
diff options
context:
space:
mode:
authorjamie <git@skilet.ro>2026-08-29 22:51:38 +0100
committerjamie <git@skilet.ro>2026-08-29 22:55:36 +0100
commit6ade07db214e8571a439b474e6c4e6a4c861d098 (patch)
tree0c4864b5d4a2abc0b05cfdb83596d87edb018dac /src/protocol.rs
parent4c42e8c9d7ec1b2e94267038d5ee38a714ca2955 (diff)
feat(cli): adopt clap and strict clippy configHEADmain
Diffstat (limited to 'src/protocol.rs')
-rw-r--r--src/protocol.rs51
1 files changed, 35 insertions, 16 deletions
diff --git a/src/protocol.rs b/src/protocol.rs
index d6fce5f..39afac0 100644
--- a/src/protocol.rs
+++ b/src/protocol.rs
@@ -62,7 +62,8 @@ pub enum Transition {
}
/// Builds the link query output report (report id `0x3a` + payload).
-pub fn link_query_frame() -> [u8; LINK_QUERY_LEN] {
+#[must_use]
+pub const fn link_query_frame() -> [u8; LINK_QUERY_LEN] {
let mut frame = [0u8; LINK_QUERY_LEN];
frame[0] = reports::OUT_60_C;
frame[1] = CMD_PREFIX[0];
@@ -73,19 +74,29 @@ pub fn link_query_frame() -> [u8; LINK_QUERY_LEN] {
/// 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] == LINK_RESPONSE_REPORT && data[1] == LINK_SELECTOR
+#[must_use]
+pub const fn is_link_response(data: &[u8]) -> bool {
+ matches!(
+ data,
+ [id, selector, ..] if *id == LINK_RESPONSE_REPORT && *selector == LINK_SELECTOR
+ )
}
/// Queries the dongle once for the headset link state. Returns
/// `Ok(Disconnected)` if no response arrives within the timeout window.
+///
+/// # Errors
+///
+/// Propagates I/O errors from writing the query or reading the response.
pub fn link_status(hid: &mut Hidraw) -> io::Result<LinkState> {
hid.write(&link_query_frame())?;
- let deadline = Instant::now() + LINK_RESPONSE_TIMEOUT;
+ let deadline = Instant::now()
+ .checked_add(LINK_RESPONSE_TIMEOUT)
+ .unwrap_or_else(Instant::now);
while let Some(remaining) = deadline.checked_duration_since(Instant::now()) {
match hid.read_with_timeout(remaining)? {
Some(data) if is_link_response(&data) => return Ok(LinkState::Connected),
- Some(_) => continue,
+ Some(_) => {}
None => break,
}
}
@@ -93,9 +104,11 @@ pub fn link_status(hid: &mut Hidraw) -> io::Result<LinkState> {
}
/// Tracks link state across polls, debouncing disconnects and reporting
-/// transitions. State starts unknown (`None`) and is pinned by the first
-/// confirmed determination; `fire_initial` controls whether that first
-/// determination is reported as a transition.
+/// transitions.
+///
+/// State starts unknown (`None`) and is pinned by the first confirmed
+/// determination; `fire_initial` controls whether that first determination
+/// is reported as a transition.
#[derive(Debug)]
pub struct StateTracker {
state: Option<LinkState>,
@@ -104,8 +117,10 @@ pub struct StateTracker {
}
impl StateTracker {
- pub fn new(fire_initial: bool) -> StateTracker {
- StateTracker {
+ /// Creates a tracker. See the struct docs for `fire_initial`.
+ #[must_use]
+ pub const fn new(fire_initial: bool) -> Self {
+ Self {
state: None,
misses: 0,
fire_initial,
@@ -113,22 +128,26 @@ impl StateTracker {
}
/// Current confirmed state, `None` until the first determination.
- pub fn state(&self) -> Option<LinkState> {
+ #[must_use]
+ pub const fn state(&self) -> Option<LinkState> {
self.state
}
/// Feed one poll result (`true` = link response seen) and get any
/// confirmed transition.
- pub fn update(&mut self, link_up: bool) -> Option<Transition> {
+ #[must_use]
+ pub const fn update(&mut self, link_up: bool) -> Option<Transition> {
if link_up {
self.misses = 0;
- if self.state == Some(LinkState::Connected) {
+ if matches!(self.state, Some(LinkState::Connected)) {
return None;
}
self.settle(LinkState::Connected)
} else {
- self.misses += 1;
- if self.misses < LINK_DEBOUNCE_MISSES || self.state == Some(LinkState::Disconnected) {
+ self.misses = self.misses.saturating_add(1);
+ if self.misses < LINK_DEBOUNCE_MISSES
+ || matches!(self.state, Some(LinkState::Disconnected))
+ {
return None;
}
self.settle(LinkState::Disconnected)
@@ -137,7 +156,7 @@ impl StateTracker {
/// 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> {
+ const fn settle(&mut self, state: LinkState) -> Option<Transition> {
let initial = self.state.is_none();
self.state = Some(state);
let transition = match state {