Skip to main content

hid_types/item/
usage.rs

1//! Types that contain all the information in Usage tags.
2
3use crate::Ident;
4use crate::id::usage::*;
5
6/// A __Usage ID__, that includes its parent __Usage Page__.
7#[derive(Clone, Copy, PartialEq)]
8pub struct ExtendedUsage {
9    /// The Usage Page.
10    pub page: UsagePage,
11    /// The Usage ID.
12    pub id: Usage,
13}
14
15impl ExtendedUsage {
16    /// Create a new `ExtendedUsage` value.
17    pub fn new(page: UsagePage, id: u16) -> Self {
18        let id = Usage::new(page, id);
19        Self { page, id }
20    }
21
22    /// Construct a usage page/id from a single integer
23    pub fn from_u32(value: u32) -> Self {
24        let lsb = (value & 0xFFFF) as u16;
25        let msb = (value >> 16) as u16;
26        let page = UsagePage::from_integer(msb);
27        let id = Usage::new(page, lsb);
28        Self { page, id }
29    }
30
31    /// Convert to a single integer containing both usage page and usage id.
32    ///
33    /// The usage page will be in the upper 16 bits, and the usage id will be
34    /// in the lower 16 bits.
35    pub fn to_integer(&self) -> u32 {
36        let page = self.page.to_integer();
37        let id = self.id.to_integer();
38        (page as u32) << 16 | (id as u32)
39    }
40}
41
42/// A __Usage ID__, that does not encode its parent page.
43#[derive(Clone, Copy, PartialEq)]
44pub enum Usage {
45    /// A Usage value that remembers its parent page.
46    Known(KnownUsage),
47    /// A standalone Usage value that cannot be decoded without page context.
48    Unknown(u16),
49}
50
51// Useful when iterating over a range of Usage values.
52impl PartialOrd for Usage {
53    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
54        let this = self.to_integer();
55        let other = other.to_integer();
56        this.partial_cmp(&other)
57    }
58}
59
60impl PartialEq<KnownUsage> for Usage {
61    fn eq(&self, other: &KnownUsage) -> bool {
62        self.to_integer() == other.to_integer()
63    }
64}
65
66impl Usage {
67    /// Create a new `Usage` value, using context from a specific Usage Page.
68    ///
69    /// If the Usage Page is known, this will attempt to return a `KnownUsage`
70    /// variant corresponding to that page.
71    pub fn new(page: UsagePage, id: u16) -> Self {
72        let usage = match page {
73            Ident::Known(known_page) => KnownUsage::from_page_and_id(known_page, id),
74            Ident::Reserved(_) => None,
75        };
76
77        match usage {
78            Some(known) => Usage::Known(known),
79            None => Usage::Unknown(id),
80        }
81    }
82
83    /// Construct a usage without `UsagePage` context.
84    pub fn without_page(id: u16) -> Self {
85        Usage::Unknown(id)
86    }
87
88    /// Return the u16 value of the usage id.
89    pub fn to_integer(&self) -> u16 {
90        match self {
91            Usage::Known(known_usage) => known_usage.to_integer(),
92            Usage::Unknown(value) => *value,
93        }
94    }
95
96    /// Return the usage value that numerically follows this one.
97    ///
98    /// This function will return `None` if the usage id overflows
99    /// `u16::MAX`.
100    pub fn successor(&self, page: UsagePage) -> Option<Self> {
101        let id = self.to_integer().checked_add(1)?;
102        Some(Usage::new(page, id))
103    }
104}
105
106/// A well-known usage id.
107#[expect(missing_docs)]
108#[derive(Clone, Copy, PartialEq)]
109#[non_exhaustive]
110pub enum KnownUsage {
111    GenericDesktop(generic_desktop::KnownUsage),
112    SimulationControls(simulation_controls::KnownUsage),
113    VrControls(vr_controls::KnownUsage),
114    SportControls(sport_controls::KnownUsage),
115    GameControls(game_controls::KnownUsage),
116    GenericDeviceControls(generic_device_controls::KnownUsage),
117    KeyboardKeypad(keyboard_keypad::KnownUsage),
118    Led(led_page::KnownUsage),
119    Button(u16),
120    Ordinal(u16),
121    TelephonyDevice(telephony_device::KnownUsage),
122    Consumer(consumer::KnownUsage),
123    Digitizers(digitizers::KnownUsage),
124    Haptics(haptics::KnownUsage),
125    PhysicalInputDevice(physical_input_device::KnownUsage),
126    Unicode(u16),
127    Soc(soc::KnownUsage),
128    EyeAndHeadTrackers(eye_head_trackers::KnownUsage),
129    AuxiliaryDisplay(auxiliary_display::KnownUsage),
130    Sensors(sensors::KnownUsage),
131    MedicalInstrument(medical_instrument::KnownUsage),
132    BrailleDisplay(braille_display::KnownUsage),
133    LightingAndIllumination(lighting_illumination::KnownUsage),
134    Monitor(monitor::KnownUsage),
135    MonitorEnumerated(u16),
136    VesaVirtualControls(vesa_virtual_controls::KnownUsage),
137    Power(power::KnownUsage),
138    BatterySystem(battery_system::KnownUsage),
139    BarcodeScanner(barcode_scanner::KnownUsage),
140    Scales(scales::KnownUsage),
141    MagneticStripeReader(magnetic_stripe_reader::KnownUsage),
142    CameraControl(camera_control::KnownUsage),
143    Arcade(arcade::KnownUsage),
144    GamingDevice(u16),
145    FidoAlliance(fido_alliance::KnownUsage),
146}
147
148impl KnownUsage {
149    /// Extract the usage value if it is a known value.
150    ///
151    /// If this returns `None` it could be for multiple reasons:
152    ///
153    /// 1. The Usage Page does not contain distinct IDs (e.g. Button)
154    /// 2. The Usage Page is unknown or reserved.
155    /// 3. The Usage Page is known but the Usage value is unknown or reserved.
156    pub fn from_page_and_id(page: KnownUsagePage, id: u16) -> Option<Self> {
157        match page {
158            KnownUsagePage::Undefined => None,
159            KnownUsagePage::GenericDesktop => generic_desktop::KnownUsage::try_from(id)
160                .ok()
161                .map(KnownUsage::GenericDesktop),
162            KnownUsagePage::SimulationControls => simulation_controls::KnownUsage::try_from(id)
163                .ok()
164                .map(KnownUsage::SimulationControls),
165            KnownUsagePage::VrControls => vr_controls::KnownUsage::try_from(id)
166                .ok()
167                .map(KnownUsage::VrControls),
168            KnownUsagePage::SportControls => sport_controls::KnownUsage::try_from(id)
169                .ok()
170                .map(KnownUsage::SportControls),
171            KnownUsagePage::GameControls => game_controls::KnownUsage::try_from(id)
172                .ok()
173                .map(KnownUsage::GameControls),
174            KnownUsagePage::GenericDeviceControls => {
175                generic_device_controls::KnownUsage::try_from(id)
176                    .ok()
177                    .map(KnownUsage::GenericDeviceControls)
178            }
179            KnownUsagePage::KeyboardKeypad => keyboard_keypad::KnownUsage::try_from(id)
180                .ok()
181                .map(KnownUsage::KeyboardKeypad),
182            KnownUsagePage::Led => led_page::KnownUsage::try_from(id).ok().map(KnownUsage::Led),
183            KnownUsagePage::Button => Some(KnownUsage::Button(id)),
184            KnownUsagePage::Ordinal => Some(KnownUsage::Ordinal(id)),
185            KnownUsagePage::TelephonyDevice => telephony_device::KnownUsage::try_from(id)
186                .ok()
187                .map(KnownUsage::TelephonyDevice),
188            KnownUsagePage::Consumer => consumer::KnownUsage::try_from(id)
189                .ok()
190                .map(KnownUsage::Consumer),
191            KnownUsagePage::Digitizers => digitizers::KnownUsage::try_from(id)
192                .ok()
193                .map(KnownUsage::Digitizers),
194            KnownUsagePage::Haptics => haptics::KnownUsage::try_from(id)
195                .ok()
196                .map(KnownUsage::Haptics),
197            KnownUsagePage::PhysicalInputDevice => physical_input_device::KnownUsage::try_from(id)
198                .ok()
199                .map(KnownUsage::PhysicalInputDevice),
200            KnownUsagePage::Unicode => Some(KnownUsage::Unicode(id)),
201            KnownUsagePage::Soc => soc::KnownUsage::try_from(id).ok().map(KnownUsage::Soc),
202            KnownUsagePage::EyeAndHeadTrackers => eye_head_trackers::KnownUsage::try_from(id)
203                .ok()
204                .map(KnownUsage::EyeAndHeadTrackers),
205            KnownUsagePage::AuxiliaryDisplay => auxiliary_display::KnownUsage::try_from(id)
206                .ok()
207                .map(KnownUsage::AuxiliaryDisplay),
208            KnownUsagePage::Sensors => sensors::KnownUsage::try_from(id)
209                .ok()
210                .map(KnownUsage::Sensors),
211            KnownUsagePage::MedicalInstrument => medical_instrument::KnownUsage::try_from(id)
212                .ok()
213                .map(KnownUsage::MedicalInstrument),
214            KnownUsagePage::BrailleDisplay => braille_display::KnownUsage::try_from(id)
215                .ok()
216                .map(KnownUsage::BrailleDisplay),
217            KnownUsagePage::LightingAndIllumination => {
218                lighting_illumination::KnownUsage::try_from(id)
219                    .ok()
220                    .map(KnownUsage::LightingAndIllumination)
221            }
222            KnownUsagePage::Monitor => monitor::KnownUsage::try_from(id)
223                .ok()
224                .map(KnownUsage::Monitor),
225            KnownUsagePage::MonitorEnumerated => Some(KnownUsage::MonitorEnumerated(id)),
226            KnownUsagePage::VesaVirtualControls => vesa_virtual_controls::KnownUsage::try_from(id)
227                .ok()
228                .map(KnownUsage::VesaVirtualControls),
229            KnownUsagePage::Power => power::KnownUsage::try_from(id).ok().map(KnownUsage::Power),
230            KnownUsagePage::BatterySystem => battery_system::KnownUsage::try_from(id)
231                .ok()
232                .map(KnownUsage::BatterySystem),
233            KnownUsagePage::BarcodeScanner => barcode_scanner::KnownUsage::try_from(id)
234                .ok()
235                .map(KnownUsage::BarcodeScanner),
236            KnownUsagePage::Scales => scales::KnownUsage::try_from(id)
237                .ok()
238                .map(KnownUsage::Scales),
239            KnownUsagePage::MagneticStripeReader => {
240                magnetic_stripe_reader::KnownUsage::try_from(id)
241                    .ok()
242                    .map(KnownUsage::MagneticStripeReader)
243            }
244            KnownUsagePage::CameraControl => camera_control::KnownUsage::try_from(id)
245                .ok()
246                .map(KnownUsage::CameraControl),
247            KnownUsagePage::Arcade => arcade::KnownUsage::try_from(id)
248                .ok()
249                .map(KnownUsage::Arcade),
250            KnownUsagePage::GamingDevice => Some(KnownUsage::GamingDevice(id)),
251            KnownUsagePage::FidoAlliance => fido_alliance::KnownUsage::try_from(id)
252                .ok()
253                .map(KnownUsage::FidoAlliance),
254        }
255    }
256
257    fn to_integer(self) -> u16 {
258        match self {
259            KnownUsage::GenericDesktop(usage) => usage.into(),
260            KnownUsage::SimulationControls(usage) => usage.into(),
261            KnownUsage::VrControls(usage) => usage.into(),
262            KnownUsage::SportControls(usage) => usage.into(),
263            KnownUsage::GameControls(usage) => usage.into(),
264            KnownUsage::GenericDeviceControls(usage) => usage.into(),
265            KnownUsage::KeyboardKeypad(usage) => usage.into(),
266            KnownUsage::Led(usage) => usage.into(),
267            KnownUsage::Button(usage) => usage,
268            KnownUsage::Ordinal(usage) => usage,
269            KnownUsage::TelephonyDevice(usage) => usage.into(),
270            KnownUsage::Consumer(usage) => usage.into(),
271            KnownUsage::Digitizers(usage) => usage.into(),
272            KnownUsage::Haptics(usage) => usage.into(),
273            KnownUsage::PhysicalInputDevice(usage) => usage.into(),
274            KnownUsage::Unicode(usage) => usage,
275            KnownUsage::Soc(usage) => usage.into(),
276            KnownUsage::EyeAndHeadTrackers(usage) => usage.into(),
277            KnownUsage::AuxiliaryDisplay(usage) => usage.into(),
278            KnownUsage::Sensors(usage) => usage.into(),
279            KnownUsage::MedicalInstrument(usage) => usage.into(),
280            KnownUsage::BrailleDisplay(usage) => usage.into(),
281            KnownUsage::LightingAndIllumination(usage) => usage.into(),
282            KnownUsage::Monitor(usage) => usage.into(),
283            KnownUsage::MonitorEnumerated(usage) => usage,
284            KnownUsage::VesaVirtualControls(usage) => usage.into(),
285            KnownUsage::Power(usage) => usage.into(),
286            KnownUsage::BatterySystem(usage) => usage.into(),
287            KnownUsage::BarcodeScanner(usage) => usage.into(),
288            KnownUsage::Scales(usage) => usage.into(),
289            KnownUsage::MagneticStripeReader(usage) => usage.into(),
290            KnownUsage::CameraControl(usage) => usage.into(),
291            KnownUsage::Arcade(usage) => usage.into(),
292            KnownUsage::GamingDevice(usage) => usage,
293            KnownUsage::FidoAlliance(usage) => usage.into(),
294        }
295    }
296}
297
298#[cfg(feature = "std")]
299mod std_impls {
300    use std::fmt::{self, Debug, Display};
301
302    use super::*;
303
304    impl Debug for ExtendedUsage {
305        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
306            let mut debug_struct = f.debug_struct("Usage");
307            debug_struct.field("page", &self.page);
308            debug_struct.field("id", &self.id);
309            debug_struct.finish()
310        }
311    }
312
313    impl Debug for Usage {
314        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
315            let mut debug_struct = f.debug_struct("Usage");
316
317            // Note: we don't print the `page` value, since it was
318            // not meant to be encoded in this item.
319
320            match self {
321                Usage::Known(usage) => {
322                    debug_struct.field("id", &usage);
323                }
324                Usage::Unknown(id) => {
325                    debug_struct.field("id", &id);
326                }
327            }
328            debug_struct.finish()
329        }
330    }
331
332    impl Debug for KnownUsage {
333        // Only prints the inner value.
334        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
335            match self {
336                Self::Button(value)
337                | Self::Ordinal(value)
338                | Self::Unicode(value)
339                | Self::MonitorEnumerated(value)
340                | Self::GamingDevice(value) => {
341                    // 16-bit usage ID without a unique name.
342                    Debug::fmt(&value, f)
343                }
344                Self::GenericDesktop(value) => value.fmt(f),
345                Self::SimulationControls(value) => value.fmt(f),
346                Self::VrControls(value) => value.fmt(f),
347                Self::SportControls(value) => value.fmt(f),
348                Self::GameControls(value) => value.fmt(f),
349                Self::GenericDeviceControls(value) => value.fmt(f),
350                Self::KeyboardKeypad(value) => value.fmt(f),
351                Self::Led(value) => value.fmt(f),
352                Self::TelephonyDevice(value) => value.fmt(f),
353                Self::Consumer(value) => value.fmt(f),
354                Self::Digitizers(value) => value.fmt(f),
355                Self::Haptics(value) => value.fmt(f),
356                Self::PhysicalInputDevice(value) => value.fmt(f),
357                Self::Soc(value) => value.fmt(f),
358                Self::EyeAndHeadTrackers(value) => value.fmt(f),
359                Self::AuxiliaryDisplay(value) => value.fmt(f),
360                Self::Sensors(value) => value.fmt(f),
361                Self::MedicalInstrument(value) => value.fmt(f),
362                Self::BrailleDisplay(value) => value.fmt(f),
363                Self::LightingAndIllumination(value) => value.fmt(f),
364                Self::Monitor(value) => value.fmt(f),
365                Self::VesaVirtualControls(value) => value.fmt(f),
366                Self::Power(value) => value.fmt(f),
367                Self::BatterySystem(value) => value.fmt(f),
368                Self::BarcodeScanner(value) => value.fmt(f),
369                Self::Scales(value) => value.fmt(f),
370                Self::MagneticStripeReader(value) => value.fmt(f),
371                Self::CameraControl(value) => value.fmt(f),
372                Self::Arcade(value) => value.fmt(f),
373                Self::FidoAlliance(value) => value.fmt(f),
374            }
375        }
376    }
377
378    impl Display for KnownUsage {
379        // Only prints the inner value.
380        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
381            match self {
382                Self::Button(value)
383                | Self::Ordinal(value)
384                | Self::Unicode(value)
385                | Self::MonitorEnumerated(value)
386                | Self::GamingDevice(value) => {
387                    // 16-bit usage ID without a unique name.
388                    Display::fmt(&value, f)
389                }
390                Self::GenericDesktop(value) => value.fmt(f),
391                Self::SimulationControls(value) => value.fmt(f),
392                Self::VrControls(value) => value.fmt(f),
393                Self::SportControls(value) => value.fmt(f),
394                Self::GameControls(value) => value.fmt(f),
395                Self::GenericDeviceControls(value) => value.fmt(f),
396                Self::KeyboardKeypad(value) => value.fmt(f),
397                Self::Led(value) => value.fmt(f),
398                Self::TelephonyDevice(value) => value.fmt(f),
399                Self::Consumer(value) => value.fmt(f),
400                Self::Digitizers(value) => value.fmt(f),
401                Self::Haptics(value) => value.fmt(f),
402                Self::PhysicalInputDevice(value) => value.fmt(f),
403                Self::Soc(value) => value.fmt(f),
404                Self::EyeAndHeadTrackers(value) => value.fmt(f),
405                Self::AuxiliaryDisplay(value) => value.fmt(f),
406                Self::Sensors(value) => value.fmt(f),
407                Self::MedicalInstrument(value) => value.fmt(f),
408                Self::BrailleDisplay(value) => value.fmt(f),
409                Self::LightingAndIllumination(value) => value.fmt(f),
410                Self::Monitor(value) => value.fmt(f),
411                Self::VesaVirtualControls(value) => value.fmt(f),
412                Self::Power(value) => value.fmt(f),
413                Self::BatterySystem(value) => value.fmt(f),
414                Self::BarcodeScanner(value) => value.fmt(f),
415                Self::Scales(value) => value.fmt(f),
416                Self::MagneticStripeReader(value) => value.fmt(f),
417                Self::CameraControl(value) => value.fmt(f),
418                Self::Arcade(value) => value.fmt(f),
419                Self::FidoAlliance(value) => value.fmt(f),
420            }
421        }
422    }
423
424    impl Display for Usage {
425        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
426            // Note: we don't print the `page` value, since it was
427            // not meant to be encoded in this item.
428
429            match self {
430                Usage::Known(usage) => Display::fmt(&usage, f),
431                Usage::Unknown(id) => Display::fmt(&format_args!("{id:#04x}"), f),
432            }
433        }
434    }
435}