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 /// Logi Bolt receiver.
46 Bolt(bolt::Receiver),
47 /// Logitech Unifying receiver.
48 Unifying(unifying::Receiver),
49}
50
51impl Receiver {
52 /// Provides a human-readable name for the receiver.
53 pub fn name(&self) -> String {
54 match self {
55 Self::Bolt(_) => "Logi Bolt Receiver",
56 Self::Unifying(_) => "Unifying Receiver",
57 }
58 .to_string()
59 }
60
61 /// Provides a string that uniquely identifies the specific receiver.
62 ///
63 /// This MAY be the serial number, but it may also be any other value that
64 /// is defined as unique.
65 pub async fn get_unique_id(&self) -> Result<String, ReceiverError> {
66 match self {
67 Self::Bolt(bolt) => bolt.get_unique_id().await,
68 Self::Unifying(unifying) => unifying.get_unique_id().await,
69 }
70 }
71}
72
73/// Represents an error returned by a receiver.
74#[derive(Debug, Error)]
75#[non_exhaustive]
76pub enum ReceiverError {
77 /// Indicates that no supported receiver could be identified on a HID++
78 /// channel.
79 #[error("no (supported) receiver could be found")]
80 UnknownReceiver,
81
82 /// Indicates that a HID++1.0 register access resulted in an error.
83 #[error("a HID++1.0 error occurred")]
84 Protocol(#[from] Hidpp10Error),
85}