hidpp/receiver/mod.rs
1//! Implements the different HID++ wireless receivers.
2//!
3//! Because of the lack of public documentation about the different receivers
4//! and their capabilities, and because I currently only own a single Bolt
5//! receiver, this module is largely incomplete. I would be more than happy for
6//! anyone who owns a different receiver, with Unifying having the highest
7//! priority, and who is willing to actively support its implementation by
8//! providing information and testing.
9//!
10//! Receivers can generally only be differentiated by their USB vendor and
11//! product IDs, so the [`detect`] function does nothing more than matching
12//! those values to the sets of known vendor and product ID pairs of the
13//! different receivers.
14
15use std::sync::Arc;
16
17use thiserror::Error;
18
19use crate::{channel::HidppChannel, protocol::v10::Hidpp10Error};
20
21pub mod bolt;
22pub mod unifying;
23
24/// The index to use when communicating with the receiver on any HID++ channel.
25pub const RECEIVER_DEVICE_INDEX: u8 = 0xff;
26
27/// Tries to detect the receiver present on a HID++ channel.
28pub fn detect(chan: Arc<HidppChannel>) -> Option<Receiver> {
29 let vpid_pair = &(chan.vendor_id, chan.product_id);
30
31 if bolt::VPID_PAIRS.contains(vpid_pair) {
32 return bolt::Receiver::new(chan).ok().map(Receiver::Bolt);
33 }
34
35 if unifying::VPID_PAIRS.contains(vpid_pair) {
36 return unifying::Receiver::new(chan).ok().map(Receiver::Unifying);
37 }
38 None
39}
40
41/// Represents a HID++ wireless receiver.
42#[derive(Clone)]
43#[non_exhaustive]
44pub enum Receiver {
45 Bolt(bolt::Receiver),
46 Unifying(unifying::Receiver),
47}
48
49impl Receiver {
50 /// Provides a human-readable name for the receiver.
51 pub fn name(&self) -> String {
52 match self {
53 Self::Bolt(_) => "Logi Bolt Receiver",
54 Self::Unifying(_) => "Unifying Receiver",
55 }
56 .to_string()
57 }
58
59 /// Provides a string that uniquely identifies the specific receiver.
60 ///
61 /// This MAY be the serial number, but it may also be any other value that
62 /// is defined as unique.
63 pub async fn get_unique_id(&self) -> Result<String, ReceiverError> {
64 match self {
65 Self::Bolt(bolt) => bolt.get_unique_id().await,
66 Self::Unifying(unifying) => unifying.get_receiver_info().await.map(|x| x.serial_number),
67 }
68 }
69}
70
71/// Represents an error returned by a receiver.
72#[derive(Debug, Error)]
73#[non_exhaustive]
74pub enum ReceiverError {
75 /// Indicates that no supported receiver could be identified on a HID++
76 /// channel.
77 #[error("no (supported) receiver could be found")]
78 UnknownReceiver,
79
80 /// Indicates that a HID++1.0 register access resulted in an error.
81 #[error("a HID++1.0 error occurred")]
82 Protocol(#[from] Hidpp10Error),
83}