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