Skip to main content

hidpp/feature/
registry.rs

1//! Maintains a registry of well-known HID++2.0 features and their default
2//! implementations.
3
4use std::{
5    any::TypeId,
6    collections::HashMap,
7    sync::{Arc, LazyLock},
8};
9
10use super::Feature;
11use crate::{
12    channel::HidppChannel,
13    feature::{
14        CreatableFeature, adjustable_dpi::AdjustableDpiFeature,
15        device_friendly_name::DeviceFriendlyNameFeature,
16        device_information::DeviceInformationFeature,
17        device_type_and_name::DeviceTypeAndNameFeature, feature_set::FeatureSetFeature,
18        hires_wheel::HiResWheelFeature, root::RootFeature, smartshift::SmartShiftFeature,
19        thumbwheel::ThumbwheelFeature, unified_battery::UnifiedBatteryFeature,
20        wireless_device_status::WirelessDeviceStatusFeature,
21    },
22};
23
24/// Represents a function that creates a new dynamically sized feature
25/// implementation.
26pub type FeatureImplProducer =
27    fn(chan: Arc<HidppChannel>, device_index: u8, feature_index: u8) -> (TypeId, Arc<dyn Feature>);
28
29/// Represents a known feature implementation starting from a specific feature
30/// version.
31#[derive(Clone, Copy, Debug, Hash)]
32pub struct FeatureVersion {
33    /// The minimum feature version the implementation supports.
34    pub starting_version: u8,
35
36    /// A pointer to a function producing the feature implementation.
37    pub producer: FeatureImplProducer,
38}
39
40/// Represents a known HID++2.0 device feature.
41#[derive(Clone, Copy, Debug, Hash)]
42pub struct KnownFeature {
43    /// The name of the feature.
44    /// This is usually a slightly modified version of the name found in
45    /// Logitech's documentation.
46    pub name: &'static str,
47
48    /// A list of concrete implementations of the feature, each supporting the
49    /// feature starting from a specific version.
50    pub versions: &'static [FeatureVersion],
51}
52
53/// Looks up a feature by its ID.
54pub fn lookup(feature_id: u16) -> Option<KnownFeature> {
55    KNOWN_FEATURES.get(&feature_id).copied()
56}
57
58/// Looks up all implementations supporting a specific feature ID and version
59/// combination.
60pub fn lookup_version(feature_id: u16, feature_version: u8) -> Option<Vec<FeatureVersion>> {
61    lookup(feature_id).map(|feat| {
62        feat.versions
63            .iter()
64            .filter(|&ver| ver.starting_version <= feature_version)
65            .copied()
66            .collect::<Vec<FeatureVersion>>()
67    })
68}
69
70/// Creates a new feature with a dynamic return type.
71fn new_dyn<F: CreatableFeature>(
72    chan: Arc<HidppChannel>,
73    device_index: u8,
74    feature_index: u8,
75) -> (TypeId, Arc<dyn Feature>) {
76    (
77        TypeId::of::<F>(),
78        Arc::new(F::new(chan, device_index, feature_index)),
79    )
80}
81
82static KNOWN_FEATURES: LazyLock<HashMap<u16, KnownFeature>> = LazyLock::new(|| {
83    HashMap::from([
84        (
85            0x0000,
86            KnownFeature {
87                name: "Root",
88                versions: &[FeatureVersion {
89                    starting_version: RootFeature::STARTING_VERSION,
90                    producer: new_dyn::<RootFeature>,
91                }],
92            },
93        ),
94        (
95            0x0001,
96            KnownFeature {
97                name: "FeatureSet",
98                versions: &[FeatureVersion {
99                    starting_version: FeatureSetFeature::STARTING_VERSION,
100                    producer: new_dyn::<FeatureSetFeature>,
101                }],
102            },
103        ),
104        (
105            0x0002,
106            KnownFeature {
107                name: "FeatureInfo",
108                versions: &[],
109            },
110        ),
111        (
112            0x0003,
113            KnownFeature {
114                name: "DeviceInformation",
115                versions: &[FeatureVersion {
116                    starting_version: DeviceInformationFeature::STARTING_VERSION,
117                    producer: new_dyn::<DeviceInformationFeature>,
118                }],
119            },
120        ),
121        (
122            0x0004,
123            KnownFeature {
124                name: "UnitId",
125                versions: &[],
126            },
127        ),
128        (
129            0x0005,
130            KnownFeature {
131                name: "DeviceTypeAndName",
132                versions: &[FeatureVersion {
133                    starting_version: DeviceTypeAndNameFeature::STARTING_VERSION,
134                    producer: new_dyn::<DeviceTypeAndNameFeature>,
135                }],
136            },
137        ),
138        (
139            0x0006,
140            KnownFeature {
141                name: "DeviceGroups",
142                versions: &[],
143            },
144        ),
145        (
146            0x0007,
147            KnownFeature {
148                name: "DeviceFriendlyName",
149                versions: &[FeatureVersion {
150                    starting_version: DeviceFriendlyNameFeature::STARTING_VERSION,
151                    producer: new_dyn::<DeviceFriendlyNameFeature>,
152                }],
153            },
154        ),
155        (
156            0x0008,
157            KnownFeature {
158                name: "KeepAlive",
159                versions: &[],
160            },
161        ),
162        (
163            0x0020,
164            KnownFeature {
165                name: "ConfigChange",
166                versions: &[],
167            },
168        ),
169        (
170            0x0021,
171            KnownFeature {
172                name: "UniqueRandomId",
173                versions: &[],
174            },
175        ),
176        (
177            0x0030,
178            KnownFeature {
179                name: "TargetSoftware",
180                versions: &[],
181            },
182        ),
183        (
184            0x0080,
185            KnownFeature {
186                name: "WirelessSignalStrength",
187                versions: &[],
188            },
189        ),
190        (
191            0x00c0,
192            KnownFeature {
193                name: "DfuControlLegacy",
194                versions: &[],
195            },
196        ),
197        (
198            0x00c1,
199            KnownFeature {
200                name: "DfuControlUnsigned",
201                versions: &[],
202            },
203        ),
204        (
205            0x00c2,
206            KnownFeature {
207                name: "DfuControlSigned",
208                versions: &[],
209            },
210        ),
211        (
212            0x00c3,
213            KnownFeature {
214                name: "DfuControlBolt",
215                versions: &[],
216            },
217        ),
218        (
219            0x00d0,
220            KnownFeature {
221                name: "Dfu",
222                versions: &[],
223            },
224        ),
225        (
226            0x00d1,
227            KnownFeature {
228                name: "DfuResumable",
229                versions: &[],
230            },
231        ),
232        (
233            0x1000,
234            KnownFeature {
235                name: "BatteryStatus",
236                versions: &[],
237            },
238        ),
239        (
240            0x1001,
241            KnownFeature {
242                name: "BatteryVoltage",
243                versions: &[],
244            },
245        ),
246        (
247            0x1004,
248            KnownFeature {
249                name: "UnifiedBattery",
250                versions: &[FeatureVersion {
251                    starting_version: UnifiedBatteryFeature::STARTING_VERSION,
252                    producer: new_dyn::<UnifiedBatteryFeature>,
253                }],
254            },
255        ),
256        (
257            0x1010,
258            KnownFeature {
259                name: "ChargingControl",
260                versions: &[],
261            },
262        ),
263        (
264            0x1300,
265            KnownFeature {
266                name: "LedControl",
267                versions: &[],
268            },
269        ),
270        (
271            0x1800,
272            KnownFeature {
273                name: "GenericTest",
274                versions: &[],
275            },
276        ),
277        (
278            0x1802,
279            KnownFeature {
280                name: "DeviceReset",
281                versions: &[],
282            },
283        ),
284        (
285            0x1805,
286            KnownFeature {
287                name: "OobState",
288                versions: &[],
289            },
290        ),
291        (
292            0x1806,
293            KnownFeature {
294                name: "ConfigDeviceProps",
295                versions: &[],
296            },
297        ),
298        (
299            0x1814,
300            KnownFeature {
301                name: "ChangeHost",
302                versions: &[],
303            },
304        ),
305        (
306            0x1815,
307            KnownFeature {
308                name: "HostsInfo",
309                versions: &[],
310            },
311        ),
312        (
313            0x1981,
314            KnownFeature {
315                name: "Backlight1",
316                versions: &[],
317            },
318        ),
319        (
320            0x1982,
321            KnownFeature {
322                name: "Backlight2",
323                versions: &[],
324            },
325        ),
326        (
327            0x1983,
328            KnownFeature {
329                name: "Backlight3",
330                versions: &[],
331            },
332        ),
333        (
334            0x1990,
335            KnownFeature {
336                name: "Illumination",
337                versions: &[],
338            },
339        ),
340        (
341            0x19b0,
342            KnownFeature {
343                name: "HapticFeedback",
344                versions: &[],
345            },
346        ),
347        (
348            0x19c0,
349            KnownFeature {
350                name: "ForceSensingButton",
351                versions: &[],
352            },
353        ),
354        (
355            0x1a00,
356            KnownFeature {
357                name: "PresenterControl",
358                versions: &[],
359            },
360        ),
361        (
362            0x1a01,
363            KnownFeature {
364                name: "Sensor3D",
365                versions: &[],
366            },
367        ),
368        (
369            0x1b00,
370            KnownFeature {
371                name: "ReprogControls",
372                versions: &[],
373            },
374        ),
375        (
376            0x1b01,
377            KnownFeature {
378                name: "ReprogControls2",
379                versions: &[],
380            },
381        ),
382        (
383            0x1b02,
384            KnownFeature {
385                name: "ReprogControls3",
386                versions: &[],
387            },
388        ),
389        (
390            0x1b03,
391            KnownFeature {
392                name: "ReprogControls4",
393                versions: &[],
394            },
395        ),
396        (
397            0x1b04,
398            KnownFeature {
399                name: "ReprogControls5",
400                versions: &[],
401            },
402        ),
403        (
404            0x1bc0,
405            KnownFeature {
406                name: "ReportHidUsages",
407                versions: &[],
408            },
409        ),
410        (
411            0x1c00,
412            KnownFeature {
413                name: "PersistentRemappableAction",
414                versions: &[],
415            },
416        ),
417        (
418            0x1d4b,
419            KnownFeature {
420                name: "WirelessDeviceStatus",
421                versions: &[FeatureVersion {
422                    starting_version: WirelessDeviceStatusFeature::STARTING_VERSION,
423                    producer: new_dyn::<WirelessDeviceStatusFeature>,
424                }],
425            },
426        ),
427        (
428            0x1df0,
429            KnownFeature {
430                name: "RemainingPairings",
431                versions: &[],
432            },
433        ),
434        (
435            0x1f1f,
436            KnownFeature {
437                name: "FirmwareProperties",
438                versions: &[],
439            },
440        ),
441        (
442            0x1f20,
443            KnownFeature {
444                name: "AdcMeasurement",
445                versions: &[],
446            },
447        ),
448        (
449            0x2001,
450            KnownFeature {
451                name: "SwapLeftRightButton",
452                versions: &[],
453            },
454        ),
455        (
456            0x2005,
457            KnownFeature {
458                name: "ButtonSwapCancel",
459                versions: &[],
460            },
461        ),
462        (
463            0x2006,
464            KnownFeature {
465                name: "PointerAxesOrientation",
466                versions: &[],
467            },
468        ),
469        (
470            0x2100,
471            KnownFeature {
472                name: "VerticalScrolling",
473                versions: &[],
474            },
475        ),
476        (
477            0x2110,
478            KnownFeature {
479                name: "SmartShiftWheel",
480                versions: &[FeatureVersion {
481                    starting_version: SmartShiftFeature::STARTING_VERSION,
482                    producer: new_dyn::<SmartShiftFeature>,
483                }],
484            },
485        ),
486        (
487            0x2111,
488            KnownFeature {
489                name: "SmartShiftWheelEnhanced",
490                versions: &[],
491            },
492        ),
493        (
494            0x2120,
495            KnownFeature {
496                name: "HighResolutionScrolling",
497                versions: &[],
498            },
499        ),
500        (
501            0x2121,
502            KnownFeature {
503                name: "HiResWheel",
504                versions: &[FeatureVersion {
505                    starting_version: HiResWheelFeature::STARTING_VERSION,
506                    producer: new_dyn::<HiResWheelFeature>,
507                }],
508            },
509        ),
510        (
511            0x2130,
512            KnownFeature {
513                name: "RatchetWheel",
514                versions: &[],
515            },
516        ),
517        (
518            0x2150,
519            KnownFeature {
520                name: "Thumbwheel",
521                versions: &[FeatureVersion {
522                    starting_version: ThumbwheelFeature::STARTING_VERSION,
523                    producer: new_dyn::<ThumbwheelFeature>,
524                }],
525            },
526        ),
527        (
528            0x2200,
529            KnownFeature {
530                name: "MousePointer",
531                versions: &[],
532            },
533        ),
534        (
535            0x2201,
536            KnownFeature {
537                name: "AdjustableDpi",
538                versions: &[FeatureVersion {
539                    starting_version: AdjustableDpiFeature::STARTING_VERSION,
540                    producer: new_dyn::<AdjustableDpiFeature>,
541                }],
542            },
543        ),
544        (
545            0x2202,
546            KnownFeature {
547                name: "ExtendedAdjustableDpi",
548                versions: &[],
549            },
550        ),
551        (
552            0x2205,
553            KnownFeature {
554                name: "PointerMotionScaling",
555                versions: &[],
556            },
557        ),
558        (
559            0x2230,
560            KnownFeature {
561                name: "SensorAngleSnapping",
562                versions: &[],
563            },
564        ),
565        (
566            0x2240,
567            KnownFeature {
568                name: "SurfaceTuning",
569                versions: &[],
570            },
571        ),
572        (
573            0x2250,
574            KnownFeature {
575                name: "XyStats",
576                versions: &[],
577            },
578        ),
579        (
580            0x2251,
581            KnownFeature {
582                name: "WheelStats",
583                versions: &[],
584            },
585        ),
586        (
587            0x2400,
588            KnownFeature {
589                name: "HybridTrackingEngine",
590                versions: &[],
591            },
592        ),
593        (
594            0x40a0,
595            KnownFeature {
596                name: "FnInversion",
597                versions: &[],
598            },
599        ),
600        (
601            0x40a2,
602            KnownFeature {
603                name: "FnInversionWithDefaultState",
604                versions: &[],
605            },
606        ),
607        (
608            0x40a3,
609            KnownFeature {
610                name: "FnInversionForMultiHostDevices",
611                versions: &[],
612            },
613        ),
614        (
615            0x4100,
616            KnownFeature {
617                name: "Encryption",
618                versions: &[],
619            },
620        ),
621        (
622            0x4220,
623            KnownFeature {
624                name: "LockKeyState",
625                versions: &[],
626            },
627        ),
628        (
629            0x4301,
630            KnownFeature {
631                name: "SolarKeyboardDashboard",
632                versions: &[],
633            },
634        ),
635        (
636            0x4520,
637            KnownFeature {
638                name: "KeyboardLayout",
639                versions: &[],
640            },
641        ),
642        (
643            0x4521,
644            KnownFeature {
645                name: "DisableKeys",
646                versions: &[],
647            },
648        ),
649        (
650            0x4522,
651            KnownFeature {
652                name: "DisableKeysByUsage",
653                versions: &[],
654            },
655        ),
656        (
657            0x4530,
658            KnownFeature {
659                name: "DualPlatform",
660                versions: &[],
661            },
662        ),
663        (
664            0x4531,
665            KnownFeature {
666                name: "MultiPlatform",
667                versions: &[],
668            },
669        ),
670        (
671            0x4540,
672            KnownFeature {
673                name: "KeyboardInternationalLayouts",
674                versions: &[],
675            },
676        ),
677        (
678            0x4600,
679            KnownFeature {
680                name: "Crown",
681                versions: &[],
682            },
683        ),
684        (
685            0x6010,
686            KnownFeature {
687                name: "TouchpadFwItems",
688                versions: &[],
689            },
690        ),
691        (
692            0x6011,
693            KnownFeature {
694                name: "TouchpadSwItems",
695                versions: &[],
696            },
697        ),
698        (
699            0x6012,
700            KnownFeature {
701                name: "TouchpadWin8FwItems",
702                versions: &[],
703            },
704        ),
705        (
706            0x6020,
707            KnownFeature {
708                name: "TapEnable",
709                versions: &[],
710            },
711        ),
712        (
713            0x6021,
714            KnownFeature {
715                name: "TapEnableExtended",
716                versions: &[],
717            },
718        ),
719        (
720            0x6030,
721            KnownFeature {
722                name: "CursorBallistic",
723                versions: &[],
724            },
725        ),
726        (
727            0x6040,
728            KnownFeature {
729                name: "TouchpadResolutionDivider",
730                versions: &[],
731            },
732        ),
733        (
734            0x6100,
735            KnownFeature {
736                name: "TouchpadRawXy",
737                versions: &[],
738            },
739        ),
740        (
741            0x6110,
742            KnownFeature {
743                name: "TouchMouseRawTouchPoints",
744                versions: &[],
745            },
746        ),
747        (
748            0x6120,
749            KnownFeature {
750                name: "BtTouchMouseSettings",
751                versions: &[],
752            },
753        ),
754        (
755            0x6500,
756            KnownFeature {
757                name: "Gestures1",
758                versions: &[],
759            },
760        ),
761        (
762            0x6501,
763            KnownFeature {
764                name: "Gestures2",
765                versions: &[],
766            },
767        ),
768        (
769            0x8010,
770            KnownFeature {
771                name: "GamingGKeys",
772                versions: &[],
773            },
774        ),
775        (
776            0x8020,
777            KnownFeature {
778                name: "GamingMKeys",
779                versions: &[],
780            },
781        ),
782        (
783            0x8030,
784            KnownFeature {
785                name: "MacroRecord",
786                versions: &[],
787            },
788        ),
789        (
790            0x8040,
791            KnownFeature {
792                name: "BrightnessControl",
793                versions: &[],
794            },
795        ),
796        (
797            0x8060,
798            KnownFeature {
799                name: "AdjustableReportRate",
800                versions: &[],
801            },
802        ),
803        (
804            0x8061,
805            KnownFeature {
806                name: "ExtendedAdjustableReportRate",
807                versions: &[],
808            },
809        ),
810        (
811            0x8070,
812            KnownFeature {
813                name: "ColorLedEffects",
814                versions: &[],
815            },
816        ),
817        (
818            0x8071,
819            KnownFeature {
820                name: "RgbEffects",
821                versions: &[],
822            },
823        ),
824        (
825            0x8080,
826            KnownFeature {
827                name: "PerKeyLighting",
828                versions: &[],
829            },
830        ),
831        (
832            0x8081,
833            KnownFeature {
834                name: "PerKeyLighting2",
835                versions: &[],
836            },
837        ),
838        (
839            0x8090,
840            KnownFeature {
841                name: "ModeStatus",
842                versions: &[],
843            },
844        ),
845        (
846            0x8100,
847            KnownFeature {
848                name: "OnboardProfiles",
849                versions: &[],
850            },
851        ),
852        (
853            0x8110,
854            KnownFeature {
855                name: "MouseButtonFilter",
856                versions: &[],
857            },
858        ),
859        (
860            0x8111,
861            KnownFeature {
862                name: "LatencyMonitoring",
863                versions: &[],
864            },
865        ),
866        (
867            0x8120,
868            KnownFeature {
869                name: "GamingAttachments",
870                versions: &[],
871            },
872        ),
873        (
874            0x8123,
875            KnownFeature {
876                name: "ForceFeedback",
877                versions: &[],
878            },
879        ),
880        (
881            0x8300,
882            KnownFeature {
883                name: "Sidetone",
884                versions: &[],
885            },
886        ),
887        (
888            0x8310,
889            KnownFeature {
890                name: "Equalizer",
891                versions: &[],
892            },
893        ),
894        (
895            0x8320,
896            KnownFeature {
897                name: "HeadsetOut",
898                versions: &[],
899            },
900        ),
901    ])
902});