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 0xc53a,
76 ReceiverBrand::Lightspeed,
77 ReceiverProtocol::Unifying,
78 ),
79 ReceiverDescriptor::logitech(
81 0xc53f,
82 ReceiverBrand::Lightspeed,
83 ReceiverProtocol::Unifying,
84 ),
85 ReceiverDescriptor::logitech(
87 0xc541,
88 ReceiverBrand::Lightspeed,
89 ReceiverProtocol::Unifying,
90 ),
91 ReceiverDescriptor::logitech(
93 0xc547,
94 ReceiverBrand::Lightspeed,
95 ReceiverProtocol::Unifying,
96 ),
97 ReceiverDescriptor::logitech(0xc548, ReceiverBrand::Bolt, ReceiverProtocol::Bolt),
98 ReceiverDescriptor::logitech(
100 0xc54d,
101 ReceiverBrand::Lightspeed,
102 ReceiverProtocol::Unifying,
103 ),
104];
105
106#[must_use]
108pub fn find_receiver(vendor_id: u16, product_id: u16) -> Option<&'static ReceiverDescriptor> {
109 RECEIVERS
110 .iter()
111 .find(|receiver| receiver.vendor_id == vendor_id && receiver.product_id == product_id)
112}
113
114#[cfg(test)]
115mod tests {
116 use super::{RECEIVERS, ReceiverBrand, ReceiverProtocol, find_receiver};
117 use crate::LOGITECH_VENDOR_ID;
118
119 #[test]
120 fn receiver_identities_are_unique() {
121 for (index, receiver) in RECEIVERS.iter().enumerate() {
122 assert!(
123 RECEIVERS[..index].iter().all(|other| {
124 (other.vendor_id, other.product_id) != (receiver.vendor_id, receiver.product_id)
125 }),
126 "duplicate receiver identity {:04x}:{:04x}",
127 receiver.vendor_id,
128 receiver.product_id
129 );
130 }
131 }
132
133 #[test]
134 fn powerplay_receiver_is_lightspeed_over_unifying_protocol() {
135 let receiver = find_receiver(LOGITECH_VENDOR_ID, 0xc53a).expect("c53a receiver");
136
137 assert_eq!(receiver.brand, ReceiverBrand::Lightspeed);
138 assert_eq!(receiver.protocol, ReceiverProtocol::Unifying);
139 }
140
141 #[test]
142 fn g915_receiver_is_lightspeed_over_unifying_protocol() {
143 let receiver = find_receiver(LOGITECH_VENDOR_ID, 0xc541).expect("c541 receiver");
144
145 assert_eq!(receiver.brand, ReceiverBrand::Lightspeed);
146 assert_eq!(receiver.protocol, ReceiverProtocol::Unifying);
147 }
148
149 #[test]
150 fn superlight_dex_receiver_is_lightspeed_over_unifying_protocol() {
151 let receiver = find_receiver(LOGITECH_VENDOR_ID, 0xc54d).expect("c54d receiver");
152
153 assert_eq!(receiver.brand, ReceiverBrand::Lightspeed);
154 assert_eq!(receiver.protocol, ReceiverProtocol::Unifying);
155 }
156
157 #[test]
158 fn mk270_mk295_nano_receiver_is_nano_over_unifying_protocol() {
159 let receiver = find_receiver(LOGITECH_VENDOR_ID, 0xc534).expect("c534 receiver");
160
161 assert_eq!(receiver.brand, ReceiverBrand::Nano);
162 assert_eq!(receiver.protocol, ReceiverProtocol::Unifying);
163 }
164
165 #[test]
166 fn lookup_requires_the_matching_vendor() {
167 assert!(find_receiver(0xffff, 0xc54d).is_none());
168 }
169}