openlogi_device_registry/
receiver.rs1use crate::LOGITECH_VENDOR_ID;
4
5#[derive(Clone, Copy, Debug, Eq, PartialEq)]
7pub enum ReceiverBrand {
8 Bolt,
10 Unifying,
12 Nano,
14 Lightspeed,
16}
17
18#[derive(Clone, Copy, Debug, Eq, PartialEq)]
20pub enum ReceiverProtocol {
21 Bolt,
23 Unifying,
25}
26
27#[derive(Clone, Copy, Debug, Eq, PartialEq)]
29pub struct ReceiverDescriptor {
30 pub vendor_id: u16,
32 pub product_id: u16,
34 pub brand: ReceiverBrand,
36 pub protocol: ReceiverProtocol,
38}
39
40impl ReceiverDescriptor {
41 const fn logitech(product_id: u16, brand: ReceiverBrand, protocol: ReceiverProtocol) -> Self {
42 Self {
43 vendor_id: LOGITECH_VENDOR_ID,
44 product_id,
45 brand,
46 protocol,
47 }
48 }
49}
50
51pub const RECEIVERS: &[ReceiverDescriptor] = &[
58 ReceiverDescriptor::logitech(0xc52b, ReceiverBrand::Unifying, ReceiverProtocol::Unifying),
59 ReceiverDescriptor::logitech(0xc532, ReceiverBrand::Unifying, ReceiverProtocol::Unifying),
60 ReceiverDescriptor::logitech(0xc534, ReceiverBrand::Nano, ReceiverProtocol::Unifying),
64 ReceiverDescriptor::logitech(0xc537, ReceiverBrand::Nano, ReceiverProtocol::Unifying),
66 ReceiverDescriptor::logitech(
69 0xc539,
70 ReceiverBrand::Lightspeed,
71 ReceiverProtocol::Unifying,
72 ),
73 ReceiverDescriptor::logitech(
75 0xc53f,
76 ReceiverBrand::Lightspeed,
77 ReceiverProtocol::Unifying,
78 ),
79 ReceiverDescriptor::logitech(
81 0xc541,
82 ReceiverBrand::Lightspeed,
83 ReceiverProtocol::Unifying,
84 ),
85 ReceiverDescriptor::logitech(
87 0xc547,
88 ReceiverBrand::Lightspeed,
89 ReceiverProtocol::Unifying,
90 ),
91 ReceiverDescriptor::logitech(0xc548, ReceiverBrand::Bolt, ReceiverProtocol::Bolt),
92 ReceiverDescriptor::logitech(
94 0xc54d,
95 ReceiverBrand::Lightspeed,
96 ReceiverProtocol::Unifying,
97 ),
98];
99
100#[must_use]
102pub fn find_receiver(vendor_id: u16, product_id: u16) -> Option<&'static ReceiverDescriptor> {
103 RECEIVERS
104 .iter()
105 .find(|receiver| receiver.vendor_id == vendor_id && receiver.product_id == product_id)
106}
107
108#[cfg(test)]
109mod tests {
110 use super::{RECEIVERS, ReceiverBrand, ReceiverProtocol, find_receiver};
111 use crate::LOGITECH_VENDOR_ID;
112
113 #[test]
114 fn receiver_identities_are_unique() {
115 for (index, receiver) in RECEIVERS.iter().enumerate() {
116 assert!(
117 RECEIVERS[..index].iter().all(|other| {
118 (other.vendor_id, other.product_id) != (receiver.vendor_id, receiver.product_id)
119 }),
120 "duplicate receiver identity {:04x}:{:04x}",
121 receiver.vendor_id,
122 receiver.product_id
123 );
124 }
125 }
126
127 #[test]
128 fn g915_receiver_is_lightspeed_over_unifying_protocol() {
129 let receiver = find_receiver(LOGITECH_VENDOR_ID, 0xc541).expect("c541 receiver");
130
131 assert_eq!(receiver.brand, ReceiverBrand::Lightspeed);
132 assert_eq!(receiver.protocol, ReceiverProtocol::Unifying);
133 }
134
135 #[test]
136 fn superlight_dex_receiver_is_lightspeed_over_unifying_protocol() {
137 let receiver = find_receiver(LOGITECH_VENDOR_ID, 0xc54d).expect("c54d receiver");
138
139 assert_eq!(receiver.brand, ReceiverBrand::Lightspeed);
140 assert_eq!(receiver.protocol, ReceiverProtocol::Unifying);
141 }
142
143 #[test]
144 fn mk270_mk295_nano_receiver_is_nano_over_unifying_protocol() {
145 let receiver = find_receiver(LOGITECH_VENDOR_ID, 0xc534).expect("c534 receiver");
146
147 assert_eq!(receiver.brand, ReceiverBrand::Nano);
148 assert_eq!(receiver.protocol, ReceiverProtocol::Unifying);
149 }
150
151 #[test]
152 fn lookup_requires_the_matching_vendor() {
153 assert!(find_receiver(0xffff, 0xc54d).is_none());
154 }
155}