1use 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
24pub type FeatureImplProducer =
27 fn(chan: Arc<HidppChannel>, device_index: u8, feature_index: u8) -> (TypeId, Arc<dyn Feature>);
28
29#[derive(Clone, Copy, Debug, Hash)]
32pub struct FeatureVersion {
33 pub starting_version: u8,
35
36 pub producer: FeatureImplProducer,
38}
39
40#[derive(Clone, Copy, Debug, Hash)]
42pub struct KnownFeature {
43 pub name: &'static str,
47
48 pub versions: &'static [FeatureVersion],
51}
52
53pub fn lookup(feature_id: u16) -> Option<KnownFeature> {
55 KNOWN_FEATURES.get(&feature_id).copied()
56}
57
58pub 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
70fn 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});