openlogi_device_registry/
litra.rs1use crate::LOGITECH_VENDOR_ID;
4
5pub const LITRA_DRIVER_ID: &str = "litra";
7pub const LITRA_GLOW_PRODUCT_ID: u16 = 0xc900;
9pub const LITRA_BEAM_PRODUCT_ID: u16 = 0xc901;
11pub const LITRA_USAGE_PAGE: u16 = 0xff43;
13pub const LITRA_USAGE_ID: u16 = 0x0202;
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum LitraModel {
19 Glow,
21 Beam,
23}
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub struct LitraDescriptor {
28 pub vendor_id: u16,
30 pub product_id: u16,
32 pub usage_page: u16,
34 pub usage_id: u16,
36 pub model: LitraModel,
38 pub driver_id: &'static str,
40 pub registry_model_id: &'static str,
42}
43
44impl LitraDescriptor {
45 const fn logitech(product_id: u16, model: LitraModel, registry_model_id: &'static str) -> Self {
46 Self {
47 vendor_id: LOGITECH_VENDOR_ID,
48 product_id,
49 usage_page: LITRA_USAGE_PAGE,
50 usage_id: LITRA_USAGE_ID,
51 model,
52 driver_id: LITRA_DRIVER_ID,
53 registry_model_id,
54 }
55 }
56}
57
58pub const LITRA_DEVICES: &[LitraDescriptor] = &[
60 LitraDescriptor::logitech(LITRA_GLOW_PRODUCT_ID, LitraModel::Glow, "8c900"),
61 LitraDescriptor::logitech(LITRA_BEAM_PRODUCT_ID, LitraModel::Beam, "8c901"),
62];
63
64#[must_use]
66pub fn find_litra(
67 vendor_id: u16,
68 product_id: u16,
69 usage_page: u16,
70 usage_id: u16,
71) -> Option<&'static LitraDescriptor> {
72 LITRA_DEVICES.iter().find(|device| {
73 device.vendor_id == vendor_id
74 && device.product_id == product_id
75 && device.usage_page == usage_page
76 && device.usage_id == usage_id
77 })
78}
79
80#[must_use]
82pub fn matches_litra(vendor_id: u16, product_id: u16, usage_page: u16, usage_id: u16) -> bool {
83 find_litra(vendor_id, product_id, usage_page, usage_id).is_some()
84}
85
86#[cfg(test)]
87mod tests {
88 use super::{LITRA_DEVICES, LITRA_DRIVER_ID, LitraModel, find_litra};
89 use crate::LOGITECH_VENDOR_ID;
90
91 #[test]
92 fn litra_identities_are_unique() {
93 for (index, device) in LITRA_DEVICES.iter().enumerate() {
94 assert!(
95 LITRA_DEVICES[..index].iter().all(|other| {
96 (
97 other.vendor_id,
98 other.product_id,
99 other.usage_page,
100 other.usage_id,
101 ) != (
102 device.vendor_id,
103 device.product_id,
104 device.usage_page,
105 device.usage_id,
106 )
107 }),
108 "duplicate Litra identity {:04x}:{:04x}/{:04x}:{:04x}",
109 device.vendor_id,
110 device.product_id,
111 device.usage_page,
112 device.usage_id
113 );
114 }
115 }
116
117 #[test]
118 fn complete_identity_selects_glow_metadata() {
119 let glow =
120 find_litra(LOGITECH_VENDOR_ID, 0xc900, 0xff43, 0x0202).expect("Litra Glow identity");
121
122 assert_eq!(glow.model, LitraModel::Glow);
123 assert_eq!(glow.driver_id, LITRA_DRIVER_ID);
124 assert_eq!(glow.registry_model_id, "8c900");
125 assert!(find_litra(LOGITECH_VENDOR_ID, 0xc900, 0xff43, 0x0203).is_none());
126 }
127
128 #[test]
129 fn complete_identity_selects_beam_metadata() {
130 let beam =
131 find_litra(LOGITECH_VENDOR_ID, 0xc901, 0xff43, 0x0202).expect("Litra Beam identity");
132
133 assert_eq!(beam.model, LitraModel::Beam);
134 assert_eq!(beam.registry_model_id, "8c901");
135 }
136}