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