linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] HID: bpf: import some more fixes from udev-hid-bpf
@ 2024-06-27  9:54 Benjamin Tissoires
  2024-06-27  9:54 ` [PATCH 1/6] HID: bpf: Add a HID report composition helper macros Benjamin Tissoires
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Benjamin Tissoires @ 2024-06-27  9:54 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: linux-kernel, linux-input, bpf, Benjamin Tissoires,
	Peter Hutterer, José Expósito, K S Iyer

This is a batch update to sync up the testing directory of udev-hid-bpf
and the kernel. The development happens there, and once we are happy,
we merge the bpf there, and then sync up with the kernel.

I've added all of the signed-off by from the various authors, as we
require them there as well.

Currently I don't have full testing for those new bpfs, but the current
test_tablets.py that I'm using for the 2 Artist 16 and 24 are not really
testing the correct bits, as we are more fixing buttons and plain stylus
reports than interactions between stylus and buttons.

Cheers,
Benjamin

Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
---
Benjamin Tissoires (6):
      HID: bpf: Add a HID report composition helper macros
      HID: bpf: add a driver for the Huion Inspiroy 2S (H641P)
      HID: bpf: move the BIT() macro to hid_bpf_helpers.h
      HID: bpf: Add support for the XP-PEN Deco Mini 4
      HID: bpf: Add Huion Dial 2 bpf fixup
      HID: bpf: Thrustmaster TCA Yoke Boeing joystick fix

 drivers/hid/bpf/progs/Huion__Dial-2.bpf.c          |  614 ++++
 drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c    |  534 ++++
 .../bpf/progs/Thrustmaster__TCA-Yoke-Boeing.bpf.c  |  144 +
 drivers/hid/bpf/progs/XPPen__Artist24.bpf.c        |    2 -
 drivers/hid/bpf/progs/XPPen__DecoMini4.bpf.c       |  231 ++
 drivers/hid/bpf/progs/hid_bpf.h                    |    1 +
 drivers/hid/bpf/progs/hid_bpf_helpers.h            |    1 +
 drivers/hid/bpf/progs/hid_report_helpers.h         | 2960 ++++++++++++++++++++
 8 files changed, 4485 insertions(+), 2 deletions(-)
---
base-commit: d3e15189bfd4d0a9d3a7ad8bd0e6ebb1c0419f93
change-id: 20240627-import-bpf-f35faa95b71d

Best regards,
-- 
Benjamin Tissoires <bentiss@kernel.org>


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/6] HID: bpf: Add a HID report composition helper macros
  2024-06-27  9:54 [PATCH 0/6] HID: bpf: import some more fixes from udev-hid-bpf Benjamin Tissoires
@ 2024-06-27  9:54 ` Benjamin Tissoires
  2024-06-27  9:54 ` [PATCH 2/6] HID: bpf: add a driver for the Huion Inspiroy 2S (H641P) Benjamin Tissoires
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Benjamin Tissoires @ 2024-06-27  9:54 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: linux-kernel, linux-input, bpf, Benjamin Tissoires,
	Peter Hutterer

These macros make it slightly easier and more modular to create
a HID report descriptor from scratch. Since they carry the annotation
we don't need to comment it and they cannot get stale.

For comparison, before we had this:

        0x15, 0x00,                    //   Logical Minimum (0)
        0x25, 0x01,                    //   Logical Maximum (1)
        0x95, 0x04,                    //   Report Count (4)
        0x75, 0x01,                    //   Report Size (1)

Now we can write this as:
        LogicalRange_i8(0, 1)
        ReportCount(4)
        ReportSize(1)

Because these macros are for creating new report descriptors,
some bits aren't directly exposed. e.g in the example above:
there is a logical range as one macro that sets both min and max.
There is seldom a good use case for skipping either anyway.

These macros will need to be expanded over time.

For Usage Pages and Usage IDs, we use a tool to parse the HUT JSON
(attached to the HUT 1.5 PDF [1]) and generate all #defines for all
usage pages and usages in the form:

 #define UsagePage_Foo_Bar
 #define Usage_FB_SomeOrOther

Where the FB is simply the acronym based on the capital letters in the
Usage Page name or the first three letters, whichever makes slightly
more sense.

[1] https://usb.org/document-library/hid-usage-tables-15

Link: https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/92
Link: https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/96
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
---
 drivers/hid/bpf/progs/hid_report_helpers.h | 2960 ++++++++++++++++++++++++++++
 1 file changed, 2960 insertions(+)

diff --git a/drivers/hid/bpf/progs/hid_report_helpers.h b/drivers/hid/bpf/progs/hid_report_helpers.h
new file mode 100644
index 000000000000..0aa1df438eeb
--- /dev/null
+++ b/drivers/hid/bpf/progs/hid_report_helpers.h
@@ -0,0 +1,2960 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2024 Red Hat, Inc
+ */
+
+// THIS FILE IS GENERATED, DO NOT EDIT
+
+#pragma once
+
+
+/* Macros for composing HID reports.
+ *
+ * HID Fields are added manually to the template, please add to it as needed
+ * for any individual device. The Usage Pages and Usages are generated.
+ *
+ * Some macros have a _i8, _i16, or _i32 suffix. Pick the
+ * right suffix given the passed-in value.
+ */
+
+/*
+ * This macro behaves like static_assert(), failing to
+ * compile if its argument is not true.  However, it always
+ * returns 0, which allows using it everywhere an expression
+ * can be used.
+ */
+#define must_be(e, msg_)						\
+(									\
+	0 * (int) sizeof(						\
+		struct {						\
+			_Static_assert(e, msg_);			\
+			int  ISO_C_forbids_a_struct_with_no_members;	\
+		}							\
+	)								\
+)
+
+/* Ensure the given value fits within 8/16/32 bits */
+#define i4(v_)  (((__u8)(v_) & 0xf)  + must_be((v_) >= -0x8 && (v_) <= 0x7, "not a i4"))
+#define i8(v_)  ((__u8)(v_)  + must_be((v_) >= -0x80 && (v_) <= 0xff, "not a i8/u8"))
+#define i16(v_) ((__u16)(v_) + must_be((v_) >= -0x8000 && (v_) <= 0xffff, "not a i16/u16"))
+#define i32(v_) ((__u32)(v_) + must_be((v_) >= -0x80000000L && (v_) <= 0xffffffffL, \
+				       "not a i32/u16"))
+
+/* Split a value across multiple bytes in LE order */
+#define LE16(v_) i16(v_) & 0xff, ((v_) >> 8) & 0xff
+#define LE32(v_) i32(v_) & 0xff, ((v_) >> 8) & 0xff, ((v_) >> 16) & 0xff, ((v_) >> 24) & 0xff
+
+/* Collections require two items in the report descriptor, the start
+ * of the collection (0xa?) and the EndCollection item (0xc?).
+ * This macro provides both, use like this:
+ *
+ * static const __u8 fixed_rdesc[] = {
+ *     UsagePage_Generic_Desktop
+ *     Usage_GD_Keyboard
+ *     CollectionApplication(     ← Open the collection
+ *         ReportId(3)
+ *         LogicalRange_i8(0, 1)
+ *         // other fields
+ *     )                          ← End EndCollection
+ *
+ * Collections may be nested.
+ */
+#define Collection(col_, ...)		0xa1, i8(col_), __VA_ARGS__ 0xc0,
+#define CollectionPhysical(...)		Collection(0x00, __VA_ARGS__)
+#define CollectionApplication(...)	Collection(0x01, __VA_ARGS__)
+#define CollectionLogical(...)		Collection(0x02, __VA_ARGS__)
+
+/* See Collections, this macro provides Push and Pop with
+ * elements in between
+ */
+#define PushPop(...)			0xa4, __VA_ARGS__ 0xb4,
+
+/* Arguments to use in bitwise-or for Input, Output, Feature */
+#define Const		0x1
+#define Var		0x2
+#define Arr		0x0
+#define Abs		0x0
+#define Rel		0x4
+
+/* Use like this: Input(Var|Abs) */
+#define Input(i_)			0x081, i8(i_),
+#define Output(i_)			0x091, i8(i_),
+#define Feature(i_)			0x0b1, i8(i_),
+
+#define ReportId(id_)			0x85, i8(id_),
+#define ReportSize(sz_)		        0x75, i8(sz_),
+#define ReportCount(cnt_)		0x95, i8(cnt_),
+
+#define LogicalRange_i8(min_, max_)	0x15, i8(min_), 0x25, i8(max_),
+#define LogicalRange_i16(min_, max_)	0x16, LE16(min_), 0x26, LE16(max_),
+#define LogicalRange_i32(min_, max_)	0x17, LE32(min_), 0x27, LE32(max_),
+
+#define PhysicalRange_i8(min_, max_)	0x35, i8(min_), 0x45, i8(max_),
+#define PhysicalRange_i16(min_, max_)	0x36, LE16(min_), 0x46, LE16(max_),
+#define PhysicalRange_i32(min_, max_)	0x37, LE32(min_), 0x47, LE32(max_),
+
+#define UsageRange_i8(min_, max_)	0x19, i8(min_), 0x29, i8(max_),
+#define UsageRange_i16(min_, max_)	0x1a, LE16(min_), 0x2a, LE16(max_),
+
+#define UsagePage_i8(p_)		0x05, i8(p_),
+#define UsagePage_i16(p_)		0x06, LE16(p_),
+
+#define Usage_i8(u_)			0x09, i8(u_),
+#define Usage_i16(u_)			0x0a, LE16(u_),
+#define Usage_i32(u_)			0x0b, LE32(u_),
+
+#define SILinear			0x1
+#define SIRotation			0x2
+#define EnglishLinear			0x3
+#define EnglishRotation			0x4
+#define cm				(SILinear | (0x1 << 4))
+#define rad				(SIRotation | (0x1 << 4))
+#define deg				(EnglishRotation | (0x1 << 4))
+#define in				(EnglishLinear | (0x1 << 4))
+/* Use as Unit(cm) or Unit(rad) or similar.
+ * This macro currently defaults to exponent 1 only, so no
+ * cm^2 or others
+ */
+#define Unit(u_)                        Unit_i8(u_)
+#define Unit_i8(u_)			0x65, i8(u_),
+#define Unit_i16(u_)			0x66, i16(u_),
+#define Unit_i32(u_)			0x67, i32(u_),
+
+#define UnitExponent(u_)		0x55, i4(u_),
+
+/* A macro to generate a vendor-specific padding-only
+ * report with Report ID 0xac of the given size in bytes.
+ * The size is inclusive of the 1 byte Report ID prefix.
+ *
+ * HID-BPF requires that at least one report has
+ * the same size as the original report from the device.
+ * The easy way to ensure that is to add this
+ * macro as the last element of your CollectionApplication
+ * other reports can be of any size less than this.
+ *
+ * e.g.
+ *   static __u8 fixed_rdesc = [
+ *      UsagePage_Generic_Desktop
+ *      Usage_GD_Keyboard
+ *      CollectionApplication(
+ *          ... intended rdesc items go here ...
+ *          FixedSizeVendorReport(12)
+ *      )
+ *   ];
+ *
+ *   If the FixedSizeVendorReport is placed outside
+ *   a CollectionApplication it will result in
+ *   an extra useless evdev node being created.
+ */
+#define FixedSizeVendorReport(bytes_)			\
+	UsagePage_Vendor(0xffff)			\
+	Usage_i8(0x01)					\
+	CollectionPhysical(				\
+		ReportId(0xac)				\
+		ReportSize(8)				\
+		ReportCount((bytes_) - 1)		\
+		Input(Const)				\
+	)
+
+/* ----- Generated Usage Pages and Usages ------ */
+#define UsagePage_GenericDesktop                 UsagePage_i8(0x1)
+#define UsagePage_SimulationControls             UsagePage_i8(0x2)
+#define UsagePage_VRControls                     UsagePage_i8(0x3)
+#define UsagePage_SportControls                  UsagePage_i8(0x4)
+#define UsagePage_GameControls                   UsagePage_i8(0x5)
+#define UsagePage_GenericDeviceControls          UsagePage_i8(0x6)
+#define UsagePage_KeyboardKeypad                 UsagePage_i8(0x7)
+#define UsagePage_LED                            UsagePage_i8(0x8)
+#define UsagePage_Button                         UsagePage_i8(0x9)
+#define UsagePage_Ordinal                        UsagePage_i8(0xa)
+#define UsagePage_TelephonyDevice                UsagePage_i8(0xb)
+#define UsagePage_Consumer                       UsagePage_i8(0xc)
+#define UsagePage_Digitizers                     UsagePage_i8(0xd)
+#define UsagePage_Haptics                        UsagePage_i8(0xe)
+#define UsagePage_PhysicalInputDevice            UsagePage_i8(0xf)
+#define UsagePage_Unicode                        UsagePage_i8(0x10)
+#define UsagePage_SoC                            UsagePage_i8(0x11)
+#define UsagePage_EyeandHeadTrackers             UsagePage_i8(0x12)
+#define UsagePage_AuxiliaryDisplay               UsagePage_i8(0x14)
+#define UsagePage_Sensors                        UsagePage_i8(0x20)
+#define UsagePage_MedicalInstrument              UsagePage_i8(0x40)
+#define UsagePage_BrailleDisplay                 UsagePage_i8(0x41)
+#define UsagePage_LightingAndIllumination        UsagePage_i8(0x59)
+#define UsagePage_Monitor                        UsagePage_i8(0x80)
+#define UsagePage_MonitorEnumerated              UsagePage_i8(0x81)
+#define UsagePage_VESAVirtualControls            UsagePage_i8(0x82)
+#define UsagePage_Power                          UsagePage_i8(0x84)
+#define UsagePage_BatterySystem                  UsagePage_i8(0x85)
+#define UsagePage_BarcodeScanner                 UsagePage_i8(0x8c)
+#define UsagePage_Scales                         UsagePage_i8(0x8d)
+#define UsagePage_MagneticStripeReader           UsagePage_i8(0x8e)
+#define UsagePage_CameraControl                  UsagePage_i8(0x90)
+#define UsagePage_Arcade                         UsagePage_i8(0x91)
+#define UsagePage_FIDOAlliance                   UsagePage_i16(0xf1d0)
+#define UsagePage_Vendor(u_)	\
+	UsagePage_i16((u_) + must_be(((u_) & 0xff00) == 0xff00, "not a 0xff00 vendor page"))
+
+#define Usage_GD_Pointer                               Usage_i8(0x1)
+#define Usage_GD_Mouse                                 Usage_i8(0x2)
+#define Usage_GD_Joystick                              Usage_i8(0x4)
+#define Usage_GD_Gamepad                               Usage_i8(0x5)
+#define Usage_GD_Keyboard                              Usage_i8(0x6)
+#define Usage_GD_Keypad                                Usage_i8(0x7)
+#define Usage_GD_MultiaxisController                   Usage_i8(0x8)
+#define Usage_GD_TabletPCSystemControls                Usage_i8(0x9)
+#define Usage_GD_WaterCoolingDevice                    Usage_i8(0xa)
+#define Usage_GD_ComputerChassisDevice                 Usage_i8(0xb)
+#define Usage_GD_WirelessRadioControls                 Usage_i8(0xc)
+#define Usage_GD_PortableDeviceControl                 Usage_i8(0xd)
+#define Usage_GD_SystemMultiAxisController             Usage_i8(0xe)
+#define Usage_GD_SpatialController                     Usage_i8(0xf)
+#define Usage_GD_AssistiveControl                      Usage_i8(0x10)
+#define Usage_GD_DeviceDock                            Usage_i8(0x11)
+#define Usage_GD_DockableDevice                        Usage_i8(0x12)
+#define Usage_GD_CallStateManagementControl            Usage_i8(0x13)
+#define Usage_GD_X                                     Usage_i8(0x30)
+#define Usage_GD_Y                                     Usage_i8(0x31)
+#define Usage_GD_Z                                     Usage_i8(0x32)
+#define Usage_GD_Rx                                    Usage_i8(0x33)
+#define Usage_GD_Ry                                    Usage_i8(0x34)
+#define Usage_GD_Rz                                    Usage_i8(0x35)
+#define Usage_GD_Slider                                Usage_i8(0x36)
+#define Usage_GD_Dial                                  Usage_i8(0x37)
+#define Usage_GD_Wheel                                 Usage_i8(0x38)
+#define Usage_GD_HatSwitch                             Usage_i8(0x39)
+#define Usage_GD_CountedBuffer                         Usage_i8(0x3a)
+#define Usage_GD_ByteCount                             Usage_i8(0x3b)
+#define Usage_GD_MotionWakeup                          Usage_i8(0x3c)
+#define Usage_GD_Start                                 Usage_i8(0x3d)
+#define Usage_GD_Select                                Usage_i8(0x3e)
+#define Usage_GD_Vx                                    Usage_i8(0x40)
+#define Usage_GD_Vy                                    Usage_i8(0x41)
+#define Usage_GD_Vz                                    Usage_i8(0x42)
+#define Usage_GD_Vbrx                                  Usage_i8(0x43)
+#define Usage_GD_Vbry                                  Usage_i8(0x44)
+#define Usage_GD_Vbrz                                  Usage_i8(0x45)
+#define Usage_GD_Vno                                   Usage_i8(0x46)
+#define Usage_GD_FeatureNotification                   Usage_i8(0x47)
+#define Usage_GD_ResolutionMultiplier                  Usage_i8(0x48)
+#define Usage_GD_Qx                                    Usage_i8(0x49)
+#define Usage_GD_Qy                                    Usage_i8(0x4a)
+#define Usage_GD_Qz                                    Usage_i8(0x4b)
+#define Usage_GD_Qw                                    Usage_i8(0x4c)
+#define Usage_GD_SystemControl                         Usage_i8(0x80)
+#define Usage_GD_SystemPowerDown                       Usage_i8(0x81)
+#define Usage_GD_SystemSleep                           Usage_i8(0x82)
+#define Usage_GD_SystemWakeUp                          Usage_i8(0x83)
+#define Usage_GD_SystemContextMenu                     Usage_i8(0x84)
+#define Usage_GD_SystemMainMenu                        Usage_i8(0x85)
+#define Usage_GD_SystemAppMenu                         Usage_i8(0x86)
+#define Usage_GD_SystemMenuHelp                        Usage_i8(0x87)
+#define Usage_GD_SystemMenuExit                        Usage_i8(0x88)
+#define Usage_GD_SystemMenuSelect                      Usage_i8(0x89)
+#define Usage_GD_SystemMenuRight                       Usage_i8(0x8a)
+#define Usage_GD_SystemMenuLeft                        Usage_i8(0x8b)
+#define Usage_GD_SystemMenuUp                          Usage_i8(0x8c)
+#define Usage_GD_SystemMenuDown                        Usage_i8(0x8d)
+#define Usage_GD_SystemColdRestart                     Usage_i8(0x8e)
+#define Usage_GD_SystemWarmRestart                     Usage_i8(0x8f)
+#define Usage_GD_DpadUp                                Usage_i8(0x90)
+#define Usage_GD_DpadDown                              Usage_i8(0x91)
+#define Usage_GD_DpadRight                             Usage_i8(0x92)
+#define Usage_GD_DpadLeft                              Usage_i8(0x93)
+#define Usage_GD_IndexTrigger                          Usage_i8(0x94)
+#define Usage_GD_PalmTrigger                           Usage_i8(0x95)
+#define Usage_GD_Thumbstick                            Usage_i8(0x96)
+#define Usage_GD_SystemFunctionShift                   Usage_i8(0x97)
+#define Usage_GD_SystemFunctionShiftLock               Usage_i8(0x98)
+#define Usage_GD_SystemFunctionShiftLockIndicator      Usage_i8(0x99)
+#define Usage_GD_SystemDismissNotification             Usage_i8(0x9a)
+#define Usage_GD_SystemDoNotDisturb                    Usage_i8(0x9b)
+#define Usage_GD_SystemDock                            Usage_i8(0xa0)
+#define Usage_GD_SystemUndock                          Usage_i8(0xa1)
+#define Usage_GD_SystemSetup                           Usage_i8(0xa2)
+#define Usage_GD_SystemBreak                           Usage_i8(0xa3)
+#define Usage_GD_SystemDebuggerBreak                   Usage_i8(0xa4)
+#define Usage_GD_ApplicationBreak                      Usage_i8(0xa5)
+#define Usage_GD_ApplicationDebuggerBreak              Usage_i8(0xa6)
+#define Usage_GD_SystemSpeakerMute                     Usage_i8(0xa7)
+#define Usage_GD_SystemHibernate                       Usage_i8(0xa8)
+#define Usage_GD_SystemMicrophoneMute                  Usage_i8(0xa9)
+#define Usage_GD_SystemDisplayInvert                   Usage_i8(0xb0)
+#define Usage_GD_SystemDisplayInternal                 Usage_i8(0xb1)
+#define Usage_GD_SystemDisplayExternal                 Usage_i8(0xb2)
+#define Usage_GD_SystemDisplayBoth                     Usage_i8(0xb3)
+#define Usage_GD_SystemDisplayDual                     Usage_i8(0xb4)
+#define Usage_GD_SystemDisplayToggleIntExtMode         Usage_i8(0xb5)
+#define Usage_GD_SystemDisplaySwapPrimarySecondary     Usage_i8(0xb6)
+#define Usage_GD_SystemDisplayToggleLCDAutoscale       Usage_i8(0xb7)
+#define Usage_GD_SensorZone                            Usage_i8(0xc0)
+#define Usage_GD_RPM                                   Usage_i8(0xc1)
+#define Usage_GD_CoolantLevel                          Usage_i8(0xc2)
+#define Usage_GD_CoolantCriticalLevel                  Usage_i8(0xc3)
+#define Usage_GD_CoolantPump                           Usage_i8(0xc4)
+#define Usage_GD_ChassisEnclosure                      Usage_i8(0xc5)
+#define Usage_GD_WirelessRadioButton                   Usage_i8(0xc6)
+#define Usage_GD_WirelessRadioLED                      Usage_i8(0xc7)
+#define Usage_GD_WirelessRadioSliderSwitch             Usage_i8(0xc8)
+#define Usage_GD_SystemDisplayRotationLockButton       Usage_i8(0xc9)
+#define Usage_GD_SystemDisplayRotationLockSliderSwitch Usage_i8(0xca)
+#define Usage_GD_ControlEnable                         Usage_i8(0xcb)
+#define Usage_GD_DockableDeviceUniqueID                Usage_i8(0xd0)
+#define Usage_GD_DockableDeviceVendorID                Usage_i8(0xd1)
+#define Usage_GD_DockableDevicePrimaryUsagePage        Usage_i8(0xd2)
+#define Usage_GD_DockableDevicePrimaryUsageID          Usage_i8(0xd3)
+#define Usage_GD_DockableDeviceDockingState            Usage_i8(0xd4)
+#define Usage_GD_DockableDeviceDisplayOcclusion        Usage_i8(0xd5)
+#define Usage_GD_DockableDeviceObjectType              Usage_i8(0xd6)
+#define Usage_GD_CallActiveLED                         Usage_i8(0xe0)
+#define Usage_GD_CallMuteToggle                        Usage_i8(0xe1)
+#define Usage_GD_CallMuteLED                           Usage_i8(0xe2)
+#define Usage_SC_FlightSimulationDevice                Usage_i8(0x1)
+#define Usage_SC_AutomobileSimulationDevice            Usage_i8(0x2)
+#define Usage_SC_TankSimulationDevice                  Usage_i8(0x3)
+#define Usage_SC_SpaceshipSimulationDevice             Usage_i8(0x4)
+#define Usage_SC_SubmarineSimulationDevice             Usage_i8(0x5)
+#define Usage_SC_SailingSimulationDevice               Usage_i8(0x6)
+#define Usage_SC_MotorcycleSimulationDevice            Usage_i8(0x7)
+#define Usage_SC_SportsSimulationDevice                Usage_i8(0x8)
+#define Usage_SC_AirplaneSimulationDevice              Usage_i8(0x9)
+#define Usage_SC_HelicopterSimulationDevice            Usage_i8(0xa)
+#define Usage_SC_MagicCarpetSimulationDevice           Usage_i8(0xb)
+#define Usage_SC_BicycleSimulationDevice               Usage_i8(0xc)
+#define Usage_SC_FlightControlStick                    Usage_i8(0x20)
+#define Usage_SC_FlightStick                           Usage_i8(0x21)
+#define Usage_SC_CyclicControl                         Usage_i8(0x22)
+#define Usage_SC_CyclicTrim                            Usage_i8(0x23)
+#define Usage_SC_FlightYoke                            Usage_i8(0x24)
+#define Usage_SC_TrackControl                          Usage_i8(0x25)
+#define Usage_SC_Aileron                               Usage_i8(0xb0)
+#define Usage_SC_AileronTrim                           Usage_i8(0xb1)
+#define Usage_SC_AntiTorqueControl                     Usage_i8(0xb2)
+#define Usage_SC_AutopilotEnable                       Usage_i8(0xb3)
+#define Usage_SC_ChaffRelease                          Usage_i8(0xb4)
+#define Usage_SC_CollectiveControl                     Usage_i8(0xb5)
+#define Usage_SC_DiveBrake                             Usage_i8(0xb6)
+#define Usage_SC_ElectronicCountermeasures             Usage_i8(0xb7)
+#define Usage_SC_Elevator                              Usage_i8(0xb8)
+#define Usage_SC_ElevatorTrim                          Usage_i8(0xb9)
+#define Usage_SC_Rudder                                Usage_i8(0xba)
+#define Usage_SC_Throttle                              Usage_i8(0xbb)
+#define Usage_SC_FlightCommunications                  Usage_i8(0xbc)
+#define Usage_SC_FlareRelease                          Usage_i8(0xbd)
+#define Usage_SC_LandingGear                           Usage_i8(0xbe)
+#define Usage_SC_ToeBrake                              Usage_i8(0xbf)
+#define Usage_SC_Trigger                               Usage_i8(0xc0)
+#define Usage_SC_WeaponsArm                            Usage_i8(0xc1)
+#define Usage_SC_WeaponsSelect                         Usage_i8(0xc2)
+#define Usage_SC_WingFlaps                             Usage_i8(0xc3)
+#define Usage_SC_Accelerator                           Usage_i8(0xc4)
+#define Usage_SC_Brake                                 Usage_i8(0xc5)
+#define Usage_SC_Clutch                                Usage_i8(0xc6)
+#define Usage_SC_Shifter                               Usage_i8(0xc7)
+#define Usage_SC_Steering                              Usage_i8(0xc8)
+#define Usage_SC_TurretDirection                       Usage_i8(0xc9)
+#define Usage_SC_BarrelElevation                       Usage_i8(0xca)
+#define Usage_SC_DivePlane                             Usage_i8(0xcb)
+#define Usage_SC_Ballast                               Usage_i8(0xcc)
+#define Usage_SC_BicycleCrank                          Usage_i8(0xcd)
+#define Usage_SC_HandleBars                            Usage_i8(0xce)
+#define Usage_SC_FrontBrake                            Usage_i8(0xcf)
+#define Usage_SC_RearBrake                             Usage_i8(0xd0)
+#define Usage_VRC_Belt                                 Usage_i8(0x1)
+#define Usage_VRC_BodySuit                             Usage_i8(0x2)
+#define Usage_VRC_Flexor                               Usage_i8(0x3)
+#define Usage_VRC_Glove                                Usage_i8(0x4)
+#define Usage_VRC_HeadTracker                          Usage_i8(0x5)
+#define Usage_VRC_HeadMountedDisplay                   Usage_i8(0x6)
+#define Usage_VRC_HandTracker                          Usage_i8(0x7)
+#define Usage_VRC_Oculometer                           Usage_i8(0x8)
+#define Usage_VRC_Vest                                 Usage_i8(0x9)
+#define Usage_VRC_AnimatronicDevice                    Usage_i8(0xa)
+#define Usage_VRC_StereoEnable                         Usage_i8(0x20)
+#define Usage_VRC_DisplayEnable                        Usage_i8(0x21)
+#define Usage_SC_BaseballBat                           Usage_i8(0x1)
+#define Usage_SC_GolfClub                              Usage_i8(0x2)
+#define Usage_SC_RowingMachine                         Usage_i8(0x3)
+#define Usage_SC_Treadmill                             Usage_i8(0x4)
+#define Usage_SC_Oar                                   Usage_i8(0x30)
+#define Usage_SC_Slope                                 Usage_i8(0x31)
+#define Usage_SC_Rate                                  Usage_i8(0x32)
+#define Usage_SC_StickSpeed                            Usage_i8(0x33)
+#define Usage_SC_StickFaceAngle                        Usage_i8(0x34)
+#define Usage_SC_StickHeelToe                          Usage_i8(0x35)
+#define Usage_SC_StickFollowThrough                    Usage_i8(0x36)
+#define Usage_SC_StickTempo                            Usage_i8(0x37)
+#define Usage_SC_StickType                             Usage_i8(0x38)
+#define Usage_SC_StickHeight                           Usage_i8(0x39)
+#define Usage_SC_Putter                                Usage_i8(0x50)
+#define Usage_SC_OneIron                               Usage_i8(0x51)
+#define Usage_SC_TwoIron                               Usage_i8(0x52)
+#define Usage_SC_ThreeIron                             Usage_i8(0x53)
+#define Usage_SC_FourIron                              Usage_i8(0x54)
+#define Usage_SC_FiveIron                              Usage_i8(0x55)
+#define Usage_SC_SixIron                               Usage_i8(0x56)
+#define Usage_SC_SevenIron                             Usage_i8(0x57)
+#define Usage_SC_EightIron                             Usage_i8(0x58)
+#define Usage_SC_NineIron                              Usage_i8(0x59)
+#define Usage_SC_One0Iron                              Usage_i8(0x5a)
+#define Usage_SC_One1Iron                              Usage_i8(0x5b)
+#define Usage_SC_SandWedge                             Usage_i8(0x5c)
+#define Usage_SC_LoftWedge                             Usage_i8(0x5d)
+#define Usage_SC_PowerWedge                            Usage_i8(0x5e)
+#define Usage_SC_OneWood                               Usage_i8(0x5f)
+#define Usage_SC_ThreeWood                             Usage_i8(0x60)
+#define Usage_SC_FiveWood                              Usage_i8(0x61)
+#define Usage_SC_SevenWood                             Usage_i8(0x62)
+#define Usage_SC_NineWood                              Usage_i8(0x63)
+#define Usage_GC_ThreeDGameController                  Usage_i8(0x1)
+#define Usage_GC_PinballDevice                         Usage_i8(0x2)
+#define Usage_GC_GunDevice                             Usage_i8(0x3)
+#define Usage_GC_PointofView                           Usage_i8(0x20)
+#define Usage_GC_TurnRightLeft                         Usage_i8(0x21)
+#define Usage_GC_PitchForwardBackward                  Usage_i8(0x22)
+#define Usage_GC_RollRightLeft                         Usage_i8(0x23)
+#define Usage_GC_MoveRightLeft                         Usage_i8(0x24)
+#define Usage_GC_MoveForwardBackward                   Usage_i8(0x25)
+#define Usage_GC_MoveUpDown                            Usage_i8(0x26)
+#define Usage_GC_LeanRightLeft                         Usage_i8(0x27)
+#define Usage_GC_LeanForwardBackward                   Usage_i8(0x28)
+#define Usage_GC_HeightofPOV                           Usage_i8(0x29)
+#define Usage_GC_Flipper                               Usage_i8(0x2a)
+#define Usage_GC_SecondaryFlipper                      Usage_i8(0x2b)
+#define Usage_GC_Bump                                  Usage_i8(0x2c)
+#define Usage_GC_NewGame                               Usage_i8(0x2d)
+#define Usage_GC_ShootBall                             Usage_i8(0x2e)
+#define Usage_GC_Player                                Usage_i8(0x2f)
+#define Usage_GC_GunBolt                               Usage_i8(0x30)
+#define Usage_GC_GunClip                               Usage_i8(0x31)
+#define Usage_GC_GunSelector                           Usage_i8(0x32)
+#define Usage_GC_GunSingleShot                         Usage_i8(0x33)
+#define Usage_GC_GunBurst                              Usage_i8(0x34)
+#define Usage_GC_GunAutomatic                          Usage_i8(0x35)
+#define Usage_GC_GunSafety                             Usage_i8(0x36)
+#define Usage_GC_GamepadFireJump                       Usage_i8(0x37)
+#define Usage_GC_GamepadTrigger                        Usage_i8(0x39)
+#define Usage_GC_FormfittingGamepad                    Usage_i8(0x3a)
+#define Usage_GDC_BackgroundNonuserControls            Usage_i8(0x1)
+#define Usage_GDC_BatteryStrength                      Usage_i8(0x20)
+#define Usage_GDC_WirelessChannel                      Usage_i8(0x21)
+#define Usage_GDC_WirelessID                           Usage_i8(0x22)
+#define Usage_GDC_DiscoverWirelessControl              Usage_i8(0x23)
+#define Usage_GDC_SecurityCodeCharacterEntered         Usage_i8(0x24)
+#define Usage_GDC_SecurityCodeCharacterErased          Usage_i8(0x25)
+#define Usage_GDC_SecurityCodeCleared                  Usage_i8(0x26)
+#define Usage_GDC_SequenceID                           Usage_i8(0x27)
+#define Usage_GDC_SequenceIDReset                      Usage_i8(0x28)
+#define Usage_GDC_RFSignalStrength                     Usage_i8(0x29)
+#define Usage_GDC_SoftwareVersion                      Usage_i8(0x2a)
+#define Usage_GDC_ProtocolVersion                      Usage_i8(0x2b)
+#define Usage_GDC_HardwareVersion                      Usage_i8(0x2c)
+#define Usage_GDC_Major                                Usage_i8(0x2d)
+#define Usage_GDC_Minor                                Usage_i8(0x2e)
+#define Usage_GDC_Revision                             Usage_i8(0x2f)
+#define Usage_GDC_Handedness                           Usage_i8(0x30)
+#define Usage_GDC_EitherHand                           Usage_i8(0x31)
+#define Usage_GDC_LeftHand                             Usage_i8(0x32)
+#define Usage_GDC_RightHand                            Usage_i8(0x33)
+#define Usage_GDC_BothHands                            Usage_i8(0x34)
+#define Usage_GDC_GripPoseOffset                       Usage_i8(0x40)
+#define Usage_GDC_PointerPoseOffset                    Usage_i8(0x41)
+#define Usage_KK_ErrorRollOver                         Usage_i8(0x1)
+#define Usage_KK_POSTFail                              Usage_i8(0x2)
+#define Usage_KK_ErrorUndefined                        Usage_i8(0x3)
+#define Usage_KK_KeyboardA                             Usage_i8(0x4)
+#define Usage_KK_KeyboardB                             Usage_i8(0x5)
+#define Usage_KK_KeyboardC                             Usage_i8(0x6)
+#define Usage_KK_KeyboardD                             Usage_i8(0x7)
+#define Usage_KK_KeyboardE                             Usage_i8(0x8)
+#define Usage_KK_KeyboardF                             Usage_i8(0x9)
+#define Usage_KK_KeyboardG                             Usage_i8(0xa)
+#define Usage_KK_KeyboardH                             Usage_i8(0xb)
+#define Usage_KK_KeyboardI                             Usage_i8(0xc)
+#define Usage_KK_KeyboardJ                             Usage_i8(0xd)
+#define Usage_KK_KeyboardK                             Usage_i8(0xe)
+#define Usage_KK_KeyboardL                             Usage_i8(0xf)
+#define Usage_KK_KeyboardM                             Usage_i8(0x10)
+#define Usage_KK_KeyboardN                             Usage_i8(0x11)
+#define Usage_KK_KeyboardO                             Usage_i8(0x12)
+#define Usage_KK_KeyboardP                             Usage_i8(0x13)
+#define Usage_KK_KeyboardQ                             Usage_i8(0x14)
+#define Usage_KK_KeyboardR                             Usage_i8(0x15)
+#define Usage_KK_KeyboardS                             Usage_i8(0x16)
+#define Usage_KK_KeyboardT                             Usage_i8(0x17)
+#define Usage_KK_KeyboardU                             Usage_i8(0x18)
+#define Usage_KK_KeyboardV                             Usage_i8(0x19)
+#define Usage_KK_KeyboardW                             Usage_i8(0x1a)
+#define Usage_KK_KeyboardX                             Usage_i8(0x1b)
+#define Usage_KK_KeyboardY                             Usage_i8(0x1c)
+#define Usage_KK_KeyboardZ                             Usage_i8(0x1d)
+#define Usage_KK_Keyboard1andBang                      Usage_i8(0x1e)
+#define Usage_KK_Keyboard2andAt                        Usage_i8(0x1f)
+#define Usage_KK_Keyboard3andHash                      Usage_i8(0x20)
+#define Usage_KK_Keyboard4andDollar                    Usage_i8(0x21)
+#define Usage_KK_Keyboard5andPercent                   Usage_i8(0x22)
+#define Usage_KK_Keyboard6andCaret                     Usage_i8(0x23)
+#define Usage_KK_Keyboard7andAmpersand                 Usage_i8(0x24)
+#define Usage_KK_Keyboard8andStar                      Usage_i8(0x25)
+#define Usage_KK_Keyboard9andLeftBracket               Usage_i8(0x26)
+#define Usage_KK_Keyboard0andRightBracket              Usage_i8(0x27)
+#define Usage_KK_KeyboardReturnEnter                   Usage_i8(0x28)
+#define Usage_KK_KeyboardEscape                        Usage_i8(0x29)
+#define Usage_KK_KeyboardDelete                        Usage_i8(0x2a)
+#define Usage_KK_KeyboardTab                           Usage_i8(0x2b)
+#define Usage_KK_KeyboardSpacebar                      Usage_i8(0x2c)
+#define Usage_KK_KeyboardDashandUnderscore             Usage_i8(0x2d)
+#define Usage_KK_KeyboardEqualsandPlus                 Usage_i8(0x2e)
+#define Usage_KK_KeyboardLeftBrace                     Usage_i8(0x2f)
+#define Usage_KK_KeyboardRightBrace                    Usage_i8(0x30)
+#define Usage_KK_KeyboardBackslashandPipe              Usage_i8(0x31)
+#define Usage_KK_KeyboardNonUSHashandTilde             Usage_i8(0x32)
+#define Usage_KK_KeyboardSemiColonandColon             Usage_i8(0x33)
+#define Usage_KK_KeyboardLeftAposandDouble             Usage_i8(0x34)
+#define Usage_KK_KeyboardGraveAccentandTilde           Usage_i8(0x35)
+#define Usage_KK_KeyboardCommaandLessThan              Usage_i8(0x36)
+#define Usage_KK_KeyboardPeriodandGreaterThan          Usage_i8(0x37)
+#define Usage_KK_KeyboardForwardSlashandQuestionMark   Usage_i8(0x38)
+#define Usage_KK_KeyboardCapsLock                      Usage_i8(0x39)
+#define Usage_KK_KeyboardF1                            Usage_i8(0x3a)
+#define Usage_KK_KeyboardF2                            Usage_i8(0x3b)
+#define Usage_KK_KeyboardF3                            Usage_i8(0x3c)
+#define Usage_KK_KeyboardF4                            Usage_i8(0x3d)
+#define Usage_KK_KeyboardF5                            Usage_i8(0x3e)
+#define Usage_KK_KeyboardF6                            Usage_i8(0x3f)
+#define Usage_KK_KeyboardF7                            Usage_i8(0x40)
+#define Usage_KK_KeyboardF8                            Usage_i8(0x41)
+#define Usage_KK_KeyboardF9                            Usage_i8(0x42)
+#define Usage_KK_KeyboardF10                           Usage_i8(0x43)
+#define Usage_KK_KeyboardF11                           Usage_i8(0x44)
+#define Usage_KK_KeyboardF12                           Usage_i8(0x45)
+#define Usage_KK_KeyboardPrintScreen                   Usage_i8(0x46)
+#define Usage_KK_KeyboardScrollLock                    Usage_i8(0x47)
+#define Usage_KK_KeyboardPause                         Usage_i8(0x48)
+#define Usage_KK_KeyboardInsert                        Usage_i8(0x49)
+#define Usage_KK_KeyboardHome                          Usage_i8(0x4a)
+#define Usage_KK_KeyboardPageUp                        Usage_i8(0x4b)
+#define Usage_KK_KeyboardDeleteForward                 Usage_i8(0x4c)
+#define Usage_KK_KeyboardEnd                           Usage_i8(0x4d)
+#define Usage_KK_KeyboardPageDown                      Usage_i8(0x4e)
+#define Usage_KK_KeyboardRightArrow                    Usage_i8(0x4f)
+#define Usage_KK_KeyboardLeftArrow                     Usage_i8(0x50)
+#define Usage_KK_KeyboardDownArrow                     Usage_i8(0x51)
+#define Usage_KK_KeyboardUpArrow                       Usage_i8(0x52)
+#define Usage_KK_KeypadNumLockandClear                 Usage_i8(0x53)
+#define Usage_KK_KeypadForwardSlash                    Usage_i8(0x54)
+#define Usage_KK_KeypadStar                            Usage_i8(0x55)
+#define Usage_KK_KeypadDash                            Usage_i8(0x56)
+#define Usage_KK_KeypadPlus                            Usage_i8(0x57)
+#define Usage_KK_KeypadENTER                           Usage_i8(0x58)
+#define Usage_KK_Keypad1andEnd                         Usage_i8(0x59)
+#define Usage_KK_Keypad2andDownArrow                   Usage_i8(0x5a)
+#define Usage_KK_Keypad3andPageDn                      Usage_i8(0x5b)
+#define Usage_KK_Keypad4andLeftArrow                   Usage_i8(0x5c)
+#define Usage_KK_Keypad5                               Usage_i8(0x5d)
+#define Usage_KK_Keypad6andRightArrow                  Usage_i8(0x5e)
+#define Usage_KK_Keypad7andHome                        Usage_i8(0x5f)
+#define Usage_KK_Keypad8andUpArrow                     Usage_i8(0x60)
+#define Usage_KK_Keypad9andPageUp                      Usage_i8(0x61)
+#define Usage_KK_Keypad0andInsert                      Usage_i8(0x62)
+#define Usage_KK_KeypadPeriodandDelete                 Usage_i8(0x63)
+#define Usage_KK_KeyboardNonUSBackslashandPipe         Usage_i8(0x64)
+#define Usage_KK_KeyboardApplication                   Usage_i8(0x65)
+#define Usage_KK_KeyboardPower                         Usage_i8(0x66)
+#define Usage_KK_KeypadEquals                          Usage_i8(0x67)
+#define Usage_KK_KeyboardF13                           Usage_i8(0x68)
+#define Usage_KK_KeyboardF14                           Usage_i8(0x69)
+#define Usage_KK_KeyboardF15                           Usage_i8(0x6a)
+#define Usage_KK_KeyboardF16                           Usage_i8(0x6b)
+#define Usage_KK_KeyboardF17                           Usage_i8(0x6c)
+#define Usage_KK_KeyboardF18                           Usage_i8(0x6d)
+#define Usage_KK_KeyboardF19                           Usage_i8(0x6e)
+#define Usage_KK_KeyboardF20                           Usage_i8(0x6f)
+#define Usage_KK_KeyboardF21                           Usage_i8(0x70)
+#define Usage_KK_KeyboardF22                           Usage_i8(0x71)
+#define Usage_KK_KeyboardF23                           Usage_i8(0x72)
+#define Usage_KK_KeyboardF24                           Usage_i8(0x73)
+#define Usage_KK_KeyboardExecute                       Usage_i8(0x74)
+#define Usage_KK_KeyboardHelp                          Usage_i8(0x75)
+#define Usage_KK_KeyboardMenu                          Usage_i8(0x76)
+#define Usage_KK_KeyboardSelect                        Usage_i8(0x77)
+#define Usage_KK_KeyboardStop                          Usage_i8(0x78)
+#define Usage_KK_KeyboardAgain                         Usage_i8(0x79)
+#define Usage_KK_KeyboardUndo                          Usage_i8(0x7a)
+#define Usage_KK_KeyboardCut                           Usage_i8(0x7b)
+#define Usage_KK_KeyboardCopy                          Usage_i8(0x7c)
+#define Usage_KK_KeyboardPaste                         Usage_i8(0x7d)
+#define Usage_KK_KeyboardFind                          Usage_i8(0x7e)
+#define Usage_KK_KeyboardMute                          Usage_i8(0x7f)
+#define Usage_KK_KeyboardVolumeUp                      Usage_i8(0x80)
+#define Usage_KK_KeyboardVolumeDown                    Usage_i8(0x81)
+#define Usage_KK_KeyboardLockingCapsLock               Usage_i8(0x82)
+#define Usage_KK_KeyboardLockingNumLock                Usage_i8(0x83)
+#define Usage_KK_KeyboardLockingScrollLock             Usage_i8(0x84)
+#define Usage_KK_KeypadComma                           Usage_i8(0x85)
+#define Usage_KK_KeypadEqualSign                       Usage_i8(0x86)
+#define Usage_KK_KeyboardInternational1                Usage_i8(0x87)
+#define Usage_KK_KeyboardInternational2                Usage_i8(0x88)
+#define Usage_KK_KeyboardInternational3                Usage_i8(0x89)
+#define Usage_KK_KeyboardInternational4                Usage_i8(0x8a)
+#define Usage_KK_KeyboardInternational5                Usage_i8(0x8b)
+#define Usage_KK_KeyboardInternational6                Usage_i8(0x8c)
+#define Usage_KK_KeyboardInternational7                Usage_i8(0x8d)
+#define Usage_KK_KeyboardInternational8                Usage_i8(0x8e)
+#define Usage_KK_KeyboardInternational9                Usage_i8(0x8f)
+#define Usage_KK_KeyboardLANG1                         Usage_i8(0x90)
+#define Usage_KK_KeyboardLANG2                         Usage_i8(0x91)
+#define Usage_KK_KeyboardLANG3                         Usage_i8(0x92)
+#define Usage_KK_KeyboardLANG4                         Usage_i8(0x93)
+#define Usage_KK_KeyboardLANG5                         Usage_i8(0x94)
+#define Usage_KK_KeyboardLANG6                         Usage_i8(0x95)
+#define Usage_KK_KeyboardLANG7                         Usage_i8(0x96)
+#define Usage_KK_KeyboardLANG8                         Usage_i8(0x97)
+#define Usage_KK_KeyboardLANG9                         Usage_i8(0x98)
+#define Usage_KK_KeyboardAlternateErase                Usage_i8(0x99)
+#define Usage_KK_KeyboardSysReqAttention               Usage_i8(0x9a)
+#define Usage_KK_KeyboardCancel                        Usage_i8(0x9b)
+#define Usage_KK_KeyboardClear                         Usage_i8(0x9c)
+#define Usage_KK_KeyboardPrior                         Usage_i8(0x9d)
+#define Usage_KK_KeyboardReturn                        Usage_i8(0x9e)
+#define Usage_KK_KeyboardSeparator                     Usage_i8(0x9f)
+#define Usage_KK_KeyboardOut                           Usage_i8(0xa0)
+#define Usage_KK_KeyboardOper                          Usage_i8(0xa1)
+#define Usage_KK_KeyboardClearAgain                    Usage_i8(0xa2)
+#define Usage_KK_KeyboardCrSelProps                    Usage_i8(0xa3)
+#define Usage_KK_KeyboardExSel                         Usage_i8(0xa4)
+#define Usage_KK_KeypadDouble0                         Usage_i8(0xb0)
+#define Usage_KK_KeypadTriple0                         Usage_i8(0xb1)
+#define Usage_KK_ThousandsSeparator                    Usage_i8(0xb2)
+#define Usage_KK_DecimalSeparator                      Usage_i8(0xb3)
+#define Usage_KK_CurrencyUnit                          Usage_i8(0xb4)
+#define Usage_KK_CurrencySubunit                       Usage_i8(0xb5)
+#define Usage_KK_KeypadLeftBracket                     Usage_i8(0xb6)
+#define Usage_KK_KeypadRightBracket                    Usage_i8(0xb7)
+#define Usage_KK_KeypadLeftBrace                       Usage_i8(0xb8)
+#define Usage_KK_KeypadRightBrace                      Usage_i8(0xb9)
+#define Usage_KK_KeypadTab                             Usage_i8(0xba)
+#define Usage_KK_KeypadBackspace                       Usage_i8(0xbb)
+#define Usage_KK_KeypadA                               Usage_i8(0xbc)
+#define Usage_KK_KeypadB                               Usage_i8(0xbd)
+#define Usage_KK_KeypadC                               Usage_i8(0xbe)
+#define Usage_KK_KeypadD                               Usage_i8(0xbf)
+#define Usage_KK_KeypadE                               Usage_i8(0xc0)
+#define Usage_KK_KeypadF                               Usage_i8(0xc1)
+#define Usage_KK_KeypadXOR                             Usage_i8(0xc2)
+#define Usage_KK_KeypadCaret                           Usage_i8(0xc3)
+#define Usage_KK_KeypadPercentage                      Usage_i8(0xc4)
+#define Usage_KK_KeypadLess                            Usage_i8(0xc5)
+#define Usage_KK_KeypadGreater                         Usage_i8(0xc6)
+#define Usage_KK_KeypadAmpersand                       Usage_i8(0xc7)
+#define Usage_KK_KeypadDoubleAmpersand                 Usage_i8(0xc8)
+#define Usage_KK_KeypadBar                             Usage_i8(0xc9)
+#define Usage_KK_KeypadDoubleBar                       Usage_i8(0xca)
+#define Usage_KK_KeypadColon                           Usage_i8(0xcb)
+#define Usage_KK_KeypadHash                            Usage_i8(0xcc)
+#define Usage_KK_KeypadSpace                           Usage_i8(0xcd)
+#define Usage_KK_KeypadAt                              Usage_i8(0xce)
+#define Usage_KK_KeypadBang                            Usage_i8(0xcf)
+#define Usage_KK_KeypadMemoryStore                     Usage_i8(0xd0)
+#define Usage_KK_KeypadMemoryRecall                    Usage_i8(0xd1)
+#define Usage_KK_KeypadMemoryClear                     Usage_i8(0xd2)
+#define Usage_KK_KeypadMemoryAdd                       Usage_i8(0xd3)
+#define Usage_KK_KeypadMemorySubtract                  Usage_i8(0xd4)
+#define Usage_KK_KeypadMemoryMultiply                  Usage_i8(0xd5)
+#define Usage_KK_KeypadMemoryDivide                    Usage_i8(0xd6)
+#define Usage_KK_KeypadPlusMinus                       Usage_i8(0xd7)
+#define Usage_KK_KeypadClear                           Usage_i8(0xd8)
+#define Usage_KK_KeypadClearEntry                      Usage_i8(0xd9)
+#define Usage_KK_KeypadBinary                          Usage_i8(0xda)
+#define Usage_KK_KeypadOctal                           Usage_i8(0xdb)
+#define Usage_KK_KeypadDecimal                         Usage_i8(0xdc)
+#define Usage_KK_KeypadHexadecimal                     Usage_i8(0xdd)
+#define Usage_KK_KeyboardLeftControl                   Usage_i8(0xe0)
+#define Usage_KK_KeyboardLeftShift                     Usage_i8(0xe1)
+#define Usage_KK_KeyboardLeftAlt                       Usage_i8(0xe2)
+#define Usage_KK_KeyboardLeftGUI                       Usage_i8(0xe3)
+#define Usage_KK_KeyboardRightControl                  Usage_i8(0xe4)
+#define Usage_KK_KeyboardRightShift                    Usage_i8(0xe5)
+#define Usage_KK_KeyboardRightAlt                      Usage_i8(0xe6)
+#define Usage_KK_KeyboardRightGUI                      Usage_i8(0xe7)
+#define Usage_LED_NumLock                              Usage_i8(0x1)
+#define Usage_LED_CapsLock                             Usage_i8(0x2)
+#define Usage_LED_ScrollLock                           Usage_i8(0x3)
+#define Usage_LED_Compose                              Usage_i8(0x4)
+#define Usage_LED_Kana                                 Usage_i8(0x5)
+#define Usage_LED_Power                                Usage_i8(0x6)
+#define Usage_LED_Shift                                Usage_i8(0x7)
+#define Usage_LED_DoNotDisturb                         Usage_i8(0x8)
+#define Usage_LED_Mute                                 Usage_i8(0x9)
+#define Usage_LED_ToneEnable                           Usage_i8(0xa)
+#define Usage_LED_HighCutFilter                        Usage_i8(0xb)
+#define Usage_LED_LowCutFilter                         Usage_i8(0xc)
+#define Usage_LED_EqualizerEnable                      Usage_i8(0xd)
+#define Usage_LED_SoundFieldOn                         Usage_i8(0xe)
+#define Usage_LED_SurroundOn                           Usage_i8(0xf)
+#define Usage_LED_Repeat                               Usage_i8(0x10)
+#define Usage_LED_Stereo                               Usage_i8(0x11)
+#define Usage_LED_SamplingRateDetect                   Usage_i8(0x12)
+#define Usage_LED_Spinning                             Usage_i8(0x13)
+#define Usage_LED_CAV                                  Usage_i8(0x14)
+#define Usage_LED_CLV                                  Usage_i8(0x15)
+#define Usage_LED_RecordingFormatDetect                Usage_i8(0x16)
+#define Usage_LED_OffHook                              Usage_i8(0x17)
+#define Usage_LED_Ring                                 Usage_i8(0x18)
+#define Usage_LED_MessageWaiting                       Usage_i8(0x19)
+#define Usage_LED_DataMode                             Usage_i8(0x1a)
+#define Usage_LED_BatteryOperation                     Usage_i8(0x1b)
+#define Usage_LED_BatteryOK                            Usage_i8(0x1c)
+#define Usage_LED_BatteryLow                           Usage_i8(0x1d)
+#define Usage_LED_Speaker                              Usage_i8(0x1e)
+#define Usage_LED_Headset                              Usage_i8(0x1f)
+#define Usage_LED_Hold                                 Usage_i8(0x20)
+#define Usage_LED_Microphone                           Usage_i8(0x21)
+#define Usage_LED_Coverage                             Usage_i8(0x22)
+#define Usage_LED_NightMode                            Usage_i8(0x23)
+#define Usage_LED_SendCalls                            Usage_i8(0x24)
+#define Usage_LED_CallPickup                           Usage_i8(0x25)
+#define Usage_LED_Conference                           Usage_i8(0x26)
+#define Usage_LED_Standby                              Usage_i8(0x27)
+#define Usage_LED_CameraOn                             Usage_i8(0x28)
+#define Usage_LED_CameraOff                            Usage_i8(0x29)
+#define Usage_LED_OnLine                               Usage_i8(0x2a)
+#define Usage_LED_OffLine                              Usage_i8(0x2b)
+#define Usage_LED_Busy                                 Usage_i8(0x2c)
+#define Usage_LED_Ready                                Usage_i8(0x2d)
+#define Usage_LED_PaperOut                             Usage_i8(0x2e)
+#define Usage_LED_PaperJam                             Usage_i8(0x2f)
+#define Usage_LED_Remote                               Usage_i8(0x30)
+#define Usage_LED_Forward                              Usage_i8(0x31)
+#define Usage_LED_Reverse                              Usage_i8(0x32)
+#define Usage_LED_Stop                                 Usage_i8(0x33)
+#define Usage_LED_Rewind                               Usage_i8(0x34)
+#define Usage_LED_FastForward                          Usage_i8(0x35)
+#define Usage_LED_Play                                 Usage_i8(0x36)
+#define Usage_LED_Pause                                Usage_i8(0x37)
+#define Usage_LED_Record                               Usage_i8(0x38)
+#define Usage_LED_Error                                Usage_i8(0x39)
+#define Usage_LED_UsageSelectedIndicator               Usage_i8(0x3a)
+#define Usage_LED_UsageInUseIndicator                  Usage_i8(0x3b)
+#define Usage_LED_UsageMultiModeIndicator              Usage_i8(0x3c)
+#define Usage_LED_IndicatorOn                          Usage_i8(0x3d)
+#define Usage_LED_IndicatorFlash                       Usage_i8(0x3e)
+#define Usage_LED_IndicatorSlowBlink                   Usage_i8(0x3f)
+#define Usage_LED_IndicatorFastBlink                   Usage_i8(0x40)
+#define Usage_LED_IndicatorOff                         Usage_i8(0x41)
+#define Usage_LED_FlashOnTime                          Usage_i8(0x42)
+#define Usage_LED_SlowBlinkOnTime                      Usage_i8(0x43)
+#define Usage_LED_SlowBlinkOffTime                     Usage_i8(0x44)
+#define Usage_LED_FastBlinkOnTime                      Usage_i8(0x45)
+#define Usage_LED_FastBlinkOffTime                     Usage_i8(0x46)
+#define Usage_LED_UsageIndicatorColor                  Usage_i8(0x47)
+#define Usage_LED_IndicatorRed                         Usage_i8(0x48)
+#define Usage_LED_IndicatorGreen                       Usage_i8(0x49)
+#define Usage_LED_IndicatorAmber                       Usage_i8(0x4a)
+#define Usage_LED_GenericIndicator                     Usage_i8(0x4b)
+#define Usage_LED_SystemSuspend                        Usage_i8(0x4c)
+#define Usage_LED_ExternalPowerConnected               Usage_i8(0x4d)
+#define Usage_LED_IndicatorBlue                        Usage_i8(0x4e)
+#define Usage_LED_IndicatorOrange                      Usage_i8(0x4f)
+#define Usage_LED_GoodStatus                           Usage_i8(0x50)
+#define Usage_LED_WarningStatus                        Usage_i8(0x51)
+#define Usage_LED_RGBLED                               Usage_i8(0x52)
+#define Usage_LED_RedLEDChannel                        Usage_i8(0x53)
+#define Usage_LED_BlueLEDChannel                       Usage_i8(0x54)
+#define Usage_LED_GreenLEDChannel                      Usage_i8(0x55)
+#define Usage_LED_LEDIntensity                         Usage_i8(0x56)
+#define Usage_LED_SystemMicrophoneMute                 Usage_i8(0x57)
+#define Usage_LED_PlayerIndicator                      Usage_i8(0x60)
+#define Usage_LED_Player1                              Usage_i8(0x61)
+#define Usage_LED_Player2                              Usage_i8(0x62)
+#define Usage_LED_Player3                              Usage_i8(0x63)
+#define Usage_LED_Player4                              Usage_i8(0x64)
+#define Usage_LED_Player5                              Usage_i8(0x65)
+#define Usage_LED_Player6                              Usage_i8(0x66)
+#define Usage_LED_Player7                              Usage_i8(0x67)
+#define Usage_LED_Player8                              Usage_i8(0x68)
+#define Usage_TD_Phone                                 Usage_i8(0x1)
+#define Usage_TD_AnsweringMachine                      Usage_i8(0x2)
+#define Usage_TD_MessageControls                       Usage_i8(0x3)
+#define Usage_TD_Handset                               Usage_i8(0x4)
+#define Usage_TD_Headset                               Usage_i8(0x5)
+#define Usage_TD_TelephonyKeyPad                       Usage_i8(0x6)
+#define Usage_TD_ProgrammableButton                    Usage_i8(0x7)
+#define Usage_TD_HookSwitch                            Usage_i8(0x20)
+#define Usage_TD_Flash                                 Usage_i8(0x21)
+#define Usage_TD_Feature                               Usage_i8(0x22)
+#define Usage_TD_Hold                                  Usage_i8(0x23)
+#define Usage_TD_Redial                                Usage_i8(0x24)
+#define Usage_TD_Transfer                              Usage_i8(0x25)
+#define Usage_TD_Drop                                  Usage_i8(0x26)
+#define Usage_TD_Park                                  Usage_i8(0x27)
+#define Usage_TD_ForwardCalls                          Usage_i8(0x28)
+#define Usage_TD_AlternateFunction                     Usage_i8(0x29)
+#define Usage_TD_Line                                  Usage_i8(0x2a)
+#define Usage_TD_SpeakerPhone                          Usage_i8(0x2b)
+#define Usage_TD_Conference                            Usage_i8(0x2c)
+#define Usage_TD_RingEnable                            Usage_i8(0x2d)
+#define Usage_TD_RingSelect                            Usage_i8(0x2e)
+#define Usage_TD_PhoneMute                             Usage_i8(0x2f)
+#define Usage_TD_CallerID                              Usage_i8(0x30)
+#define Usage_TD_Send                                  Usage_i8(0x31)
+#define Usage_TD_SpeedDial                             Usage_i8(0x50)
+#define Usage_TD_StoreNumber                           Usage_i8(0x51)
+#define Usage_TD_RecallNumber                          Usage_i8(0x52)
+#define Usage_TD_PhoneDirectory                        Usage_i8(0x53)
+#define Usage_TD_VoiceMail                             Usage_i8(0x70)
+#define Usage_TD_ScreenCalls                           Usage_i8(0x71)
+#define Usage_TD_DoNotDisturb                          Usage_i8(0x72)
+#define Usage_TD_Message                               Usage_i8(0x73)
+#define Usage_TD_AnswerOnOff                           Usage_i8(0x74)
+#define Usage_TD_InsideDialTone                        Usage_i8(0x90)
+#define Usage_TD_OutsideDialTone                       Usage_i8(0x91)
+#define Usage_TD_InsideRingTone                        Usage_i8(0x92)
+#define Usage_TD_OutsideRingTone                       Usage_i8(0x93)
+#define Usage_TD_PriorityRingTone                      Usage_i8(0x94)
+#define Usage_TD_InsideRingback                        Usage_i8(0x95)
+#define Usage_TD_PriorityRingback                      Usage_i8(0x96)
+#define Usage_TD_LineBusyTone                          Usage_i8(0x97)
+#define Usage_TD_ReorderTone                           Usage_i8(0x98)
+#define Usage_TD_CallWaitingTone                       Usage_i8(0x99)
+#define Usage_TD_ConfirmationTone1                     Usage_i8(0x9a)
+#define Usage_TD_ConfirmationTone2                     Usage_i8(0x9b)
+#define Usage_TD_TonesOff                              Usage_i8(0x9c)
+#define Usage_TD_OutsideRingback                       Usage_i8(0x9d)
+#define Usage_TD_Ringer                                Usage_i8(0x9e)
+#define Usage_TD_PhoneKey0                             Usage_i8(0xb0)
+#define Usage_TD_PhoneKey1                             Usage_i8(0xb1)
+#define Usage_TD_PhoneKey2                             Usage_i8(0xb2)
+#define Usage_TD_PhoneKey3                             Usage_i8(0xb3)
+#define Usage_TD_PhoneKey4                             Usage_i8(0xb4)
+#define Usage_TD_PhoneKey5                             Usage_i8(0xb5)
+#define Usage_TD_PhoneKey6                             Usage_i8(0xb6)
+#define Usage_TD_PhoneKey7                             Usage_i8(0xb7)
+#define Usage_TD_PhoneKey8                             Usage_i8(0xb8)
+#define Usage_TD_PhoneKey9                             Usage_i8(0xb9)
+#define Usage_TD_PhoneKeyStar                          Usage_i8(0xba)
+#define Usage_TD_PhoneKeyPound                         Usage_i8(0xbb)
+#define Usage_TD_PhoneKeyA                             Usage_i8(0xbc)
+#define Usage_TD_PhoneKeyB                             Usage_i8(0xbd)
+#define Usage_TD_PhoneKeyC                             Usage_i8(0xbe)
+#define Usage_TD_PhoneKeyD                             Usage_i8(0xbf)
+#define Usage_TD_PhoneCallHistoryKey                   Usage_i8(0xc0)
+#define Usage_TD_PhoneCallerIDKey                      Usage_i8(0xc1)
+#define Usage_TD_PhoneSettingsKey                      Usage_i8(0xc2)
+#define Usage_TD_HostControl                           Usage_i8(0xf0)
+#define Usage_TD_HostAvailable                         Usage_i8(0xf1)
+#define Usage_TD_HostCallActive                        Usage_i8(0xf2)
+#define Usage_TD_ActivateHandsetAudio                  Usage_i8(0xf3)
+#define Usage_TD_RingType                              Usage_i8(0xf4)
+#define Usage_TD_RedialablePhoneNumber                 Usage_i8(0xf5)
+#define Usage_TD_StopRingTone                          Usage_i8(0xf8)
+#define Usage_TD_PSTNRingTone                          Usage_i8(0xf9)
+#define Usage_TD_HostRingTone                          Usage_i8(0xfa)
+#define Usage_TD_AlertSoundError                       Usage_i8(0xfb)
+#define Usage_TD_AlertSoundConfirm                     Usage_i8(0xfc)
+#define Usage_TD_AlertSoundNotification                Usage_i8(0xfd)
+#define Usage_TD_SilentRing                            Usage_i8(0xfe)
+#define Usage_TD_EmailMessageWaiting                   Usage_i16(0x108)
+#define Usage_TD_VoicemailMessageWaiting               Usage_i16(0x109)
+#define Usage_TD_HostHold                              Usage_i16(0x10a)
+#define Usage_TD_IncomingCallHistoryCount              Usage_i16(0x110)
+#define Usage_TD_OutgoingCallHistoryCount              Usage_i16(0x111)
+#define Usage_TD_IncomingCallHistory                   Usage_i16(0x112)
+#define Usage_TD_OutgoingCallHistory                   Usage_i16(0x113)
+#define Usage_TD_PhoneLocale                           Usage_i16(0x114)
+#define Usage_TD_PhoneTimeSecond                       Usage_i16(0x140)
+#define Usage_TD_PhoneTimeMinute                       Usage_i16(0x141)
+#define Usage_TD_PhoneTimeHour                         Usage_i16(0x142)
+#define Usage_TD_PhoneDateDay                          Usage_i16(0x143)
+#define Usage_TD_PhoneDateMonth                        Usage_i16(0x144)
+#define Usage_TD_PhoneDateYear                         Usage_i16(0x145)
+#define Usage_TD_HandsetNickname                       Usage_i16(0x146)
+#define Usage_TD_AddressBookID                         Usage_i16(0x147)
+#define Usage_TD_CallDuration                          Usage_i16(0x14a)
+#define Usage_TD_DualModePhone                         Usage_i16(0x14b)
+#define Usage_Con_ConsumerControl                      Usage_i8(0x1)
+#define Usage_Con_NumericKeyPad                        Usage_i8(0x2)
+#define Usage_Con_ProgrammableButtons                  Usage_i8(0x3)
+#define Usage_Con_Microphone                           Usage_i8(0x4)
+#define Usage_Con_Headphone                            Usage_i8(0x5)
+#define Usage_Con_GraphicEqualizer                     Usage_i8(0x6)
+#define Usage_Con_Plus10                               Usage_i8(0x20)
+#define Usage_Con_Plus100                              Usage_i8(0x21)
+#define Usage_Con_AMPM                                 Usage_i8(0x22)
+#define Usage_Con_Power                                Usage_i8(0x30)
+#define Usage_Con_Reset                                Usage_i8(0x31)
+#define Usage_Con_Sleep                                Usage_i8(0x32)
+#define Usage_Con_SleepAfter                           Usage_i8(0x33)
+#define Usage_Con_SleepMode                            Usage_i8(0x34)
+#define Usage_Con_Illumination                         Usage_i8(0x35)
+#define Usage_Con_FunctionButtons                      Usage_i8(0x36)
+#define Usage_Con_Menu                                 Usage_i8(0x40)
+#define Usage_Con_MenuPick                             Usage_i8(0x41)
+#define Usage_Con_MenuUp                               Usage_i8(0x42)
+#define Usage_Con_MenuDown                             Usage_i8(0x43)
+#define Usage_Con_MenuLeft                             Usage_i8(0x44)
+#define Usage_Con_MenuRight                            Usage_i8(0x45)
+#define Usage_Con_MenuEscape                           Usage_i8(0x46)
+#define Usage_Con_MenuValueIncrease                    Usage_i8(0x47)
+#define Usage_Con_MenuValueDecrease                    Usage_i8(0x48)
+#define Usage_Con_DataOnScreen                         Usage_i8(0x60)
+#define Usage_Con_ClosedCaption                        Usage_i8(0x61)
+#define Usage_Con_ClosedCaptionSelect                  Usage_i8(0x62)
+#define Usage_Con_VCRTV                                Usage_i8(0x63)
+#define Usage_Con_BroadcastMode                        Usage_i8(0x64)
+#define Usage_Con_Snapshot                             Usage_i8(0x65)
+#define Usage_Con_Still                                Usage_i8(0x66)
+#define Usage_Con_PictureinPictureToggle               Usage_i8(0x67)
+#define Usage_Con_PictureinPictureSwap                 Usage_i8(0x68)
+#define Usage_Con_RedMenuButton                        Usage_i8(0x69)
+#define Usage_Con_GreenMenuButton                      Usage_i8(0x6a)
+#define Usage_Con_BlueMenuButton                       Usage_i8(0x6b)
+#define Usage_Con_YellowMenuButton                     Usage_i8(0x6c)
+#define Usage_Con_Aspect                               Usage_i8(0x6d)
+#define Usage_Con_ThreeDModeSelect                     Usage_i8(0x6e)
+#define Usage_Con_DisplayBrightnessIncrement           Usage_i8(0x6f)
+#define Usage_Con_DisplayBrightnessDecrement           Usage_i8(0x70)
+#define Usage_Con_DisplayBrightness                    Usage_i8(0x71)
+#define Usage_Con_DisplayBacklightToggle               Usage_i8(0x72)
+#define Usage_Con_DisplaySetBrightnesstoMinimum        Usage_i8(0x73)
+#define Usage_Con_DisplaySetBrightnesstoMaximum        Usage_i8(0x74)
+#define Usage_Con_DisplaySetAutoBrightness             Usage_i8(0x75)
+#define Usage_Con_CameraAccessEnabled                  Usage_i8(0x76)
+#define Usage_Con_CameraAccessDisabled                 Usage_i8(0x77)
+#define Usage_Con_CameraAccessToggle                   Usage_i8(0x78)
+#define Usage_Con_KeyboardBrightnessIncrement          Usage_i8(0x79)
+#define Usage_Con_KeyboardBrightnessDecrement          Usage_i8(0x7a)
+#define Usage_Con_KeyboardBacklightSetLevel            Usage_i8(0x7b)
+#define Usage_Con_KeyboardBacklightOOC                 Usage_i8(0x7c)
+#define Usage_Con_KeyboardBacklightSetMinimum          Usage_i8(0x7d)
+#define Usage_Con_KeyboardBacklightSetMaximum          Usage_i8(0x7e)
+#define Usage_Con_KeyboardBacklightAuto                Usage_i8(0x7f)
+#define Usage_Con_Selection                            Usage_i8(0x80)
+#define Usage_Con_AssignSelection                      Usage_i8(0x81)
+#define Usage_Con_ModeStep                             Usage_i8(0x82)
+#define Usage_Con_RecallLast                           Usage_i8(0x83)
+#define Usage_Con_EnterChannel                         Usage_i8(0x84)
+#define Usage_Con_OrderMovie                           Usage_i8(0x85)
+#define Usage_Con_Channel                              Usage_i8(0x86)
+#define Usage_Con_MediaSelection                       Usage_i8(0x87)
+#define Usage_Con_MediaSelectComputer                  Usage_i8(0x88)
+#define Usage_Con_MediaSelectTV                        Usage_i8(0x89)
+#define Usage_Con_MediaSelectWWW                       Usage_i8(0x8a)
+#define Usage_Con_MediaSelectDVD                       Usage_i8(0x8b)
+#define Usage_Con_MediaSelectTelephone                 Usage_i8(0x8c)
+#define Usage_Con_MediaSelectProgramGuide              Usage_i8(0x8d)
+#define Usage_Con_MediaSelectVideoPhone                Usage_i8(0x8e)
+#define Usage_Con_MediaSelectGames                     Usage_i8(0x8f)
+#define Usage_Con_MediaSelectMessages                  Usage_i8(0x90)
+#define Usage_Con_MediaSelectCD                        Usage_i8(0x91)
+#define Usage_Con_MediaSelectVCR                       Usage_i8(0x92)
+#define Usage_Con_MediaSelectTuner                     Usage_i8(0x93)
+#define Usage_Con_Quit                                 Usage_i8(0x94)
+#define Usage_Con_Help                                 Usage_i8(0x95)
+#define Usage_Con_MediaSelectTape                      Usage_i8(0x96)
+#define Usage_Con_MediaSelectCable                     Usage_i8(0x97)
+#define Usage_Con_MediaSelectSatellite                 Usage_i8(0x98)
+#define Usage_Con_MediaSelectSecurity                  Usage_i8(0x99)
+#define Usage_Con_MediaSelectHome                      Usage_i8(0x9a)
+#define Usage_Con_MediaSelectCall                      Usage_i8(0x9b)
+#define Usage_Con_ChannelIncrement                     Usage_i8(0x9c)
+#define Usage_Con_ChannelDecrement                     Usage_i8(0x9d)
+#define Usage_Con_MediaSelectSAP                       Usage_i8(0x9e)
+#define Usage_Con_VCRPlus                              Usage_i8(0xa0)
+#define Usage_Con_Once                                 Usage_i8(0xa1)
+#define Usage_Con_Daily                                Usage_i8(0xa2)
+#define Usage_Con_Weekly                               Usage_i8(0xa3)
+#define Usage_Con_Monthly                              Usage_i8(0xa4)
+#define Usage_Con_Play                                 Usage_i8(0xb0)
+#define Usage_Con_Pause                                Usage_i8(0xb1)
+#define Usage_Con_Record                               Usage_i8(0xb2)
+#define Usage_Con_FastForward                          Usage_i8(0xb3)
+#define Usage_Con_Rewind                               Usage_i8(0xb4)
+#define Usage_Con_ScanNextTrack                        Usage_i8(0xb5)
+#define Usage_Con_ScanPreviousTrack                    Usage_i8(0xb6)
+#define Usage_Con_Stop                                 Usage_i8(0xb7)
+#define Usage_Con_Eject                                Usage_i8(0xb8)
+#define Usage_Con_RandomPlay                           Usage_i8(0xb9)
+#define Usage_Con_SelectDisc                           Usage_i8(0xba)
+#define Usage_Con_EnterDisc                            Usage_i8(0xbb)
+#define Usage_Con_Repeat                               Usage_i8(0xbc)
+#define Usage_Con_Tracking                             Usage_i8(0xbd)
+#define Usage_Con_TrackNormal                          Usage_i8(0xbe)
+#define Usage_Con_SlowTracking                         Usage_i8(0xbf)
+#define Usage_Con_FrameForward                         Usage_i8(0xc0)
+#define Usage_Con_FrameBack                            Usage_i8(0xc1)
+#define Usage_Con_Mark                                 Usage_i8(0xc2)
+#define Usage_Con_ClearMark                            Usage_i8(0xc3)
+#define Usage_Con_RepeatFromMark                       Usage_i8(0xc4)
+#define Usage_Con_ReturnToMark                         Usage_i8(0xc5)
+#define Usage_Con_SearchMarkForward                    Usage_i8(0xc6)
+#define Usage_Con_SearchMarkBackwards                  Usage_i8(0xc7)
+#define Usage_Con_CounterReset                         Usage_i8(0xc8)
+#define Usage_Con_ShowCounter                          Usage_i8(0xc9)
+#define Usage_Con_TrackingIncrement                    Usage_i8(0xca)
+#define Usage_Con_TrackingDecrement                    Usage_i8(0xcb)
+#define Usage_Con_StopEject                            Usage_i8(0xcc)
+#define Usage_Con_PlayPause                            Usage_i8(0xcd)
+#define Usage_Con_PlaySkip                             Usage_i8(0xce)
+#define Usage_Con_VoiceCommand                         Usage_i8(0xcf)
+#define Usage_Con_InvokeCaptureInterface               Usage_i8(0xd0)
+#define Usage_Con_StartorStopGameRecording             Usage_i8(0xd1)
+#define Usage_Con_HistoricalGameCapture                Usage_i8(0xd2)
+#define Usage_Con_CaptureGameScreenshot                Usage_i8(0xd3)
+#define Usage_Con_ShoworHideRecordingIndicator         Usage_i8(0xd4)
+#define Usage_Con_StartorStopMicrophoneCapture         Usage_i8(0xd5)
+#define Usage_Con_StartorStopCameraCapture             Usage_i8(0xd6)
+#define Usage_Con_StartorStopGameBroadcast             Usage_i8(0xd7)
+#define Usage_Con_StartorStopVoiceDictationSession     Usage_i8(0xd8)
+#define Usage_Con_InvokeDismissEmojiPicker             Usage_i8(0xd9)
+#define Usage_Con_Volume                               Usage_i8(0xe0)
+#define Usage_Con_Balance                              Usage_i8(0xe1)
+#define Usage_Con_Mute                                 Usage_i8(0xe2)
+#define Usage_Con_Bass                                 Usage_i8(0xe3)
+#define Usage_Con_Treble                               Usage_i8(0xe4)
+#define Usage_Con_BassBoost                            Usage_i8(0xe5)
+#define Usage_Con_SurroundMode                         Usage_i8(0xe6)
+#define Usage_Con_Loudness                             Usage_i8(0xe7)
+#define Usage_Con_MPX                                  Usage_i8(0xe8)
+#define Usage_Con_VolumeIncrement                      Usage_i8(0xe9)
+#define Usage_Con_VolumeDecrement                      Usage_i8(0xea)
+#define Usage_Con_SpeedSelect                          Usage_i8(0xf0)
+#define Usage_Con_PlaybackSpeed                        Usage_i8(0xf1)
+#define Usage_Con_StandardPlay                         Usage_i8(0xf2)
+#define Usage_Con_LongPlay                             Usage_i8(0xf3)
+#define Usage_Con_ExtendedPlay                         Usage_i8(0xf4)
+#define Usage_Con_Slow                                 Usage_i8(0xf5)
+#define Usage_Con_FanEnable                            Usage_i16(0x100)
+#define Usage_Con_FanSpeed                             Usage_i16(0x101)
+#define Usage_Con_LightEnable                          Usage_i16(0x102)
+#define Usage_Con_LightIlluminationLevel               Usage_i16(0x103)
+#define Usage_Con_ClimateControlEnable                 Usage_i16(0x104)
+#define Usage_Con_RoomTemperature                      Usage_i16(0x105)
+#define Usage_Con_SecurityEnable                       Usage_i16(0x106)
+#define Usage_Con_FireAlarm                            Usage_i16(0x107)
+#define Usage_Con_PoliceAlarm                          Usage_i16(0x108)
+#define Usage_Con_Proximity                            Usage_i16(0x109)
+#define Usage_Con_Motion                               Usage_i16(0x10a)
+#define Usage_Con_DuressAlarm                          Usage_i16(0x10b)
+#define Usage_Con_HoldupAlarm                          Usage_i16(0x10c)
+#define Usage_Con_MedicalAlarm                         Usage_i16(0x10d)
+#define Usage_Con_BalanceRight                         Usage_i16(0x150)
+#define Usage_Con_BalanceLeft                          Usage_i16(0x151)
+#define Usage_Con_BassIncrement                        Usage_i16(0x152)
+#define Usage_Con_BassDecrement                        Usage_i16(0x153)
+#define Usage_Con_TrebleIncrement                      Usage_i16(0x154)
+#define Usage_Con_TrebleDecrement                      Usage_i16(0x155)
+#define Usage_Con_SpeakerSystem                        Usage_i16(0x160)
+#define Usage_Con_ChannelLeft                          Usage_i16(0x161)
+#define Usage_Con_ChannelRight                         Usage_i16(0x162)
+#define Usage_Con_ChannelCenter                        Usage_i16(0x163)
+#define Usage_Con_ChannelFront                         Usage_i16(0x164)
+#define Usage_Con_ChannelCenterFront                   Usage_i16(0x165)
+#define Usage_Con_ChannelSide                          Usage_i16(0x166)
+#define Usage_Con_ChannelSurround                      Usage_i16(0x167)
+#define Usage_Con_ChannelLowFrequencyEnhancement       Usage_i16(0x168)
+#define Usage_Con_ChannelTop                           Usage_i16(0x169)
+#define Usage_Con_ChannelUnknown                       Usage_i16(0x16a)
+#define Usage_Con_Subchannel                           Usage_i16(0x170)
+#define Usage_Con_SubchannelIncrement                  Usage_i16(0x171)
+#define Usage_Con_SubchannelDecrement                  Usage_i16(0x172)
+#define Usage_Con_AlternateAudioIncrement              Usage_i16(0x173)
+#define Usage_Con_AlternateAudioDecrement              Usage_i16(0x174)
+#define Usage_Con_ApplicationLaunchButtons             Usage_i16(0x180)
+#define Usage_Con_ALLaunchButtonConfigurationTool      Usage_i16(0x181)
+#define Usage_Con_ALProgrammableButtonConfiguration    Usage_i16(0x182)
+#define Usage_Con_ALConsumerControlConfiguration       Usage_i16(0x183)
+#define Usage_Con_ALWordProcessor                      Usage_i16(0x184)
+#define Usage_Con_ALTextEditor                         Usage_i16(0x185)
+#define Usage_Con_ALSpreadsheet                        Usage_i16(0x186)
+#define Usage_Con_ALGraphicsEditor                     Usage_i16(0x187)
+#define Usage_Con_ALPresentationApp                    Usage_i16(0x188)
+#define Usage_Con_ALDatabaseApp                        Usage_i16(0x189)
+#define Usage_Con_ALEmailReader                        Usage_i16(0x18a)
+#define Usage_Con_ALNewsreader                         Usage_i16(0x18b)
+#define Usage_Con_ALVoicemail                          Usage_i16(0x18c)
+#define Usage_Con_ALContactsAddressBook                Usage_i16(0x18d)
+#define Usage_Con_ALCalendarSchedule                   Usage_i16(0x18e)
+#define Usage_Con_ALTaskProjectManager                 Usage_i16(0x18f)
+#define Usage_Con_ALLogJournalTimecard                 Usage_i16(0x190)
+#define Usage_Con_ALCheckbookFinance                   Usage_i16(0x191)
+#define Usage_Con_ALCalculator                         Usage_i16(0x192)
+#define Usage_Con_ALAVCapturePlayback                  Usage_i16(0x193)
+#define Usage_Con_ALLocalMachineBrowser                Usage_i16(0x194)
+#define Usage_Con_ALLANWANBrowser                      Usage_i16(0x195)
+#define Usage_Con_ALInternetBrowser                    Usage_i16(0x196)
+#define Usage_Con_ALRemoteNetworkingISPConnect         Usage_i16(0x197)
+#define Usage_Con_ALNetworkConference                  Usage_i16(0x198)
+#define Usage_Con_ALNetworkChat                        Usage_i16(0x199)
+#define Usage_Con_ALTelephonyDialer                    Usage_i16(0x19a)
+#define Usage_Con_ALLogon                              Usage_i16(0x19b)
+#define Usage_Con_ALLogoff                             Usage_i16(0x19c)
+#define Usage_Con_ALLogonLogoff                        Usage_i16(0x19d)
+#define Usage_Con_ALTerminalLockScreensaver            Usage_i16(0x19e)
+#define Usage_Con_ALControlPanel                       Usage_i16(0x19f)
+#define Usage_Con_ALCommandLineProcessorRun            Usage_i16(0x1a0)
+#define Usage_Con_ALProcessTaskManager                 Usage_i16(0x1a1)
+#define Usage_Con_ALSelectTaskApplication              Usage_i16(0x1a2)
+#define Usage_Con_ALNextTaskApplication                Usage_i16(0x1a3)
+#define Usage_Con_ALPreviousTaskApplication            Usage_i16(0x1a4)
+#define Usage_Con_ALPreemptiveHaltTaskApplication      Usage_i16(0x1a5)
+#define Usage_Con_ALIntegratedHelpCenter               Usage_i16(0x1a6)
+#define Usage_Con_ALDocuments                          Usage_i16(0x1a7)
+#define Usage_Con_ALThesaurus                          Usage_i16(0x1a8)
+#define Usage_Con_ALDictionary                         Usage_i16(0x1a9)
+#define Usage_Con_ALDesktop                            Usage_i16(0x1aa)
+#define Usage_Con_ALSpellCheck                         Usage_i16(0x1ab)
+#define Usage_Con_ALGrammarCheck                       Usage_i16(0x1ac)
+#define Usage_Con_ALWirelessStatus                     Usage_i16(0x1ad)
+#define Usage_Con_ALKeyboardLayout                     Usage_i16(0x1ae)
+#define Usage_Con_ALVirusProtection                    Usage_i16(0x1af)
+#define Usage_Con_ALEncryption                         Usage_i16(0x1b0)
+#define Usage_Con_ALScreenSaver                        Usage_i16(0x1b1)
+#define Usage_Con_ALAlarms                             Usage_i16(0x1b2)
+#define Usage_Con_ALClock                              Usage_i16(0x1b3)
+#define Usage_Con_ALFileBrowser                        Usage_i16(0x1b4)
+#define Usage_Con_ALPowerStatus                        Usage_i16(0x1b5)
+#define Usage_Con_ALImageBrowser                       Usage_i16(0x1b6)
+#define Usage_Con_ALAudioBrowser                       Usage_i16(0x1b7)
+#define Usage_Con_ALMovieBrowser                       Usage_i16(0x1b8)
+#define Usage_Con_ALDigitalRightsManager               Usage_i16(0x1b9)
+#define Usage_Con_ALDigitalWallet                      Usage_i16(0x1ba)
+#define Usage_Con_ALInstantMessaging                   Usage_i16(0x1bc)
+#define Usage_Con_ALOEMFeaturesTipsTutorialBrowser     Usage_i16(0x1bd)
+#define Usage_Con_ALOEMHelp                            Usage_i16(0x1be)
+#define Usage_Con_ALOnlineCommunity                    Usage_i16(0x1bf)
+#define Usage_Con_ALEntertainmentContentBrowser        Usage_i16(0x1c0)
+#define Usage_Con_ALOnlineShoppingBrowser              Usage_i16(0x1c1)
+#define Usage_Con_ALSmartCardInformationHelp           Usage_i16(0x1c2)
+#define Usage_Con_ALMarketMonitorFinanceBrowser        Usage_i16(0x1c3)
+#define Usage_Con_ALCustomizedCorporateNewsBrowser     Usage_i16(0x1c4)
+#define Usage_Con_ALOnlineActivityBrowser              Usage_i16(0x1c5)
+#define Usage_Con_ALResearchSearchBrowser              Usage_i16(0x1c6)
+#define Usage_Con_ALAudioPlayer                        Usage_i16(0x1c7)
+#define Usage_Con_ALMessageStatus                      Usage_i16(0x1c8)
+#define Usage_Con_ALContactSync                        Usage_i16(0x1c9)
+#define Usage_Con_ALNavigation                         Usage_i16(0x1ca)
+#define Usage_Con_ALContextawareDesktopAssistant       Usage_i16(0x1cb)
+#define Usage_Con_GenericGUIApplicationControls        Usage_i16(0x200)
+#define Usage_Con_ACNew                                Usage_i16(0x201)
+#define Usage_Con_ACOpen                               Usage_i16(0x202)
+#define Usage_Con_ACClose                              Usage_i16(0x203)
+#define Usage_Con_ACExit                               Usage_i16(0x204)
+#define Usage_Con_ACMaximize                           Usage_i16(0x205)
+#define Usage_Con_ACMinimize                           Usage_i16(0x206)
+#define Usage_Con_ACSave                               Usage_i16(0x207)
+#define Usage_Con_ACPrint                              Usage_i16(0x208)
+#define Usage_Con_ACProperties                         Usage_i16(0x209)
+#define Usage_Con_ACUndo                               Usage_i16(0x21a)
+#define Usage_Con_ACCopy                               Usage_i16(0x21b)
+#define Usage_Con_ACCut                                Usage_i16(0x21c)
+#define Usage_Con_ACPaste                              Usage_i16(0x21d)
+#define Usage_Con_ACSelectAll                          Usage_i16(0x21e)
+#define Usage_Con_ACFind                               Usage_i16(0x21f)
+#define Usage_Con_ACFindandReplace                     Usage_i16(0x220)
+#define Usage_Con_ACSearch                             Usage_i16(0x221)
+#define Usage_Con_ACGoTo                               Usage_i16(0x222)
+#define Usage_Con_ACHome                               Usage_i16(0x223)
+#define Usage_Con_ACBack                               Usage_i16(0x224)
+#define Usage_Con_ACForward                            Usage_i16(0x225)
+#define Usage_Con_ACStop                               Usage_i16(0x226)
+#define Usage_Con_ACRefresh                            Usage_i16(0x227)
+#define Usage_Con_ACPreviousLink                       Usage_i16(0x228)
+#define Usage_Con_ACNextLink                           Usage_i16(0x229)
+#define Usage_Con_ACBookmarks                          Usage_i16(0x22a)
+#define Usage_Con_ACHistory                            Usage_i16(0x22b)
+#define Usage_Con_ACSubscriptions                      Usage_i16(0x22c)
+#define Usage_Con_ACZoomIn                             Usage_i16(0x22d)
+#define Usage_Con_ACZoomOut                            Usage_i16(0x22e)
+#define Usage_Con_ACZoom                               Usage_i16(0x22f)
+#define Usage_Con_ACFullScreenView                     Usage_i16(0x230)
+#define Usage_Con_ACNormalView                         Usage_i16(0x231)
+#define Usage_Con_ACViewToggle                         Usage_i16(0x232)
+#define Usage_Con_ACScrollUp                           Usage_i16(0x233)
+#define Usage_Con_ACScrollDown                         Usage_i16(0x234)
+#define Usage_Con_ACScroll                             Usage_i16(0x235)
+#define Usage_Con_ACPanLeft                            Usage_i16(0x236)
+#define Usage_Con_ACPanRight                           Usage_i16(0x237)
+#define Usage_Con_ACPan                                Usage_i16(0x238)
+#define Usage_Con_ACNewWindow                          Usage_i16(0x239)
+#define Usage_Con_ACTileHorizontally                   Usage_i16(0x23a)
+#define Usage_Con_ACTileVertically                     Usage_i16(0x23b)
+#define Usage_Con_ACFormat                             Usage_i16(0x23c)
+#define Usage_Con_ACEdit                               Usage_i16(0x23d)
+#define Usage_Con_ACBold                               Usage_i16(0x23e)
+#define Usage_Con_ACItalics                            Usage_i16(0x23f)
+#define Usage_Con_ACUnderline                          Usage_i16(0x240)
+#define Usage_Con_ACStrikethrough                      Usage_i16(0x241)
+#define Usage_Con_ACSubscript                          Usage_i16(0x242)
+#define Usage_Con_ACSuperscript                        Usage_i16(0x243)
+#define Usage_Con_ACAllCaps                            Usage_i16(0x244)
+#define Usage_Con_ACRotate                             Usage_i16(0x245)
+#define Usage_Con_ACResize                             Usage_i16(0x246)
+#define Usage_Con_ACFlipHorizontal                     Usage_i16(0x247)
+#define Usage_Con_ACFlipVertical                       Usage_i16(0x248)
+#define Usage_Con_ACMirrorHorizontal                   Usage_i16(0x249)
+#define Usage_Con_ACMirrorVertical                     Usage_i16(0x24a)
+#define Usage_Con_ACFontSelect                         Usage_i16(0x24b)
+#define Usage_Con_ACFontColor                          Usage_i16(0x24c)
+#define Usage_Con_ACFontSize                           Usage_i16(0x24d)
+#define Usage_Con_ACJustifyLeft                        Usage_i16(0x24e)
+#define Usage_Con_ACJustifyCenterH                     Usage_i16(0x24f)
+#define Usage_Con_ACJustifyRight                       Usage_i16(0x250)
+#define Usage_Con_ACJustifyBlockH                      Usage_i16(0x251)
+#define Usage_Con_ACJustifyTop                         Usage_i16(0x252)
+#define Usage_Con_ACJustifyCenterV                     Usage_i16(0x253)
+#define Usage_Con_ACJustifyBottom                      Usage_i16(0x254)
+#define Usage_Con_ACJustifyBlockV                      Usage_i16(0x255)
+#define Usage_Con_ACIndentDecrease                     Usage_i16(0x256)
+#define Usage_Con_ACIndentIncrease                     Usage_i16(0x257)
+#define Usage_Con_ACNumberedList                       Usage_i16(0x258)
+#define Usage_Con_ACRestartNumbering                   Usage_i16(0x259)
+#define Usage_Con_ACBulletedList                       Usage_i16(0x25a)
+#define Usage_Con_ACPromote                            Usage_i16(0x25b)
+#define Usage_Con_ACDemote                             Usage_i16(0x25c)
+#define Usage_Con_ACYes                                Usage_i16(0x25d)
+#define Usage_Con_ACNo                                 Usage_i16(0x25e)
+#define Usage_Con_ACCancel                             Usage_i16(0x25f)
+#define Usage_Con_ACCatalog                            Usage_i16(0x260)
+#define Usage_Con_ACBuyCheckout                        Usage_i16(0x261)
+#define Usage_Con_ACAddtoCart                          Usage_i16(0x262)
+#define Usage_Con_ACExpand                             Usage_i16(0x263)
+#define Usage_Con_ACExpandAll                          Usage_i16(0x264)
+#define Usage_Con_ACCollapse                           Usage_i16(0x265)
+#define Usage_Con_ACCollapseAll                        Usage_i16(0x266)
+#define Usage_Con_ACPrintPreview                       Usage_i16(0x267)
+#define Usage_Con_ACPasteSpecial                       Usage_i16(0x268)
+#define Usage_Con_ACInsertMode                         Usage_i16(0x269)
+#define Usage_Con_ACDelete                             Usage_i16(0x26a)
+#define Usage_Con_ACLock                               Usage_i16(0x26b)
+#define Usage_Con_ACUnlock                             Usage_i16(0x26c)
+#define Usage_Con_ACProtect                            Usage_i16(0x26d)
+#define Usage_Con_ACUnprotect                          Usage_i16(0x26e)
+#define Usage_Con_ACAttachComment                      Usage_i16(0x26f)
+#define Usage_Con_ACDeleteComment                      Usage_i16(0x270)
+#define Usage_Con_ACViewComment                        Usage_i16(0x271)
+#define Usage_Con_ACSelectWord                         Usage_i16(0x272)
+#define Usage_Con_ACSelectSentence                     Usage_i16(0x273)
+#define Usage_Con_ACSelectParagraph                    Usage_i16(0x274)
+#define Usage_Con_ACSelectColumn                       Usage_i16(0x275)
+#define Usage_Con_ACSelectRow                          Usage_i16(0x276)
+#define Usage_Con_ACSelectTable                        Usage_i16(0x277)
+#define Usage_Con_ACSelectObject                       Usage_i16(0x278)
+#define Usage_Con_ACRedoRepeat                         Usage_i16(0x279)
+#define Usage_Con_ACSort                               Usage_i16(0x27a)
+#define Usage_Con_ACSortAscending                      Usage_i16(0x27b)
+#define Usage_Con_ACSortDescending                     Usage_i16(0x27c)
+#define Usage_Con_ACFilter                             Usage_i16(0x27d)
+#define Usage_Con_ACSetClock                           Usage_i16(0x27e)
+#define Usage_Con_ACViewClock                          Usage_i16(0x27f)
+#define Usage_Con_ACSelectTimeZone                     Usage_i16(0x280)
+#define Usage_Con_ACEditTimeZones                      Usage_i16(0x281)
+#define Usage_Con_ACSetAlarm                           Usage_i16(0x282)
+#define Usage_Con_ACClearAlarm                         Usage_i16(0x283)
+#define Usage_Con_ACSnoozeAlarm                        Usage_i16(0x284)
+#define Usage_Con_ACResetAlarm                         Usage_i16(0x285)
+#define Usage_Con_ACSynchronize                        Usage_i16(0x286)
+#define Usage_Con_ACSendReceive                        Usage_i16(0x287)
+#define Usage_Con_ACSendTo                             Usage_i16(0x288)
+#define Usage_Con_ACReply                              Usage_i16(0x289)
+#define Usage_Con_ACReplyAll                           Usage_i16(0x28a)
+#define Usage_Con_ACForwardMsg                         Usage_i16(0x28b)
+#define Usage_Con_ACSend                               Usage_i16(0x28c)
+#define Usage_Con_ACAttachFile                         Usage_i16(0x28d)
+#define Usage_Con_ACUpload                             Usage_i16(0x28e)
+#define Usage_Con_ACDownloadSaveTargetAs               Usage_i16(0x28f)
+#define Usage_Con_ACSetBorders                         Usage_i16(0x290)
+#define Usage_Con_ACInsertRow                          Usage_i16(0x291)
+#define Usage_Con_ACInsertColumn                       Usage_i16(0x292)
+#define Usage_Con_ACInsertFile                         Usage_i16(0x293)
+#define Usage_Con_ACInsertPicture                      Usage_i16(0x294)
+#define Usage_Con_ACInsertObject                       Usage_i16(0x295)
+#define Usage_Con_ACInsertSymbol                       Usage_i16(0x296)
+#define Usage_Con_ACSaveandClose                       Usage_i16(0x297)
+#define Usage_Con_ACRename                             Usage_i16(0x298)
+#define Usage_Con_ACMerge                              Usage_i16(0x299)
+#define Usage_Con_ACSplit                              Usage_i16(0x29a)
+#define Usage_Con_ACDisributeHorizontally              Usage_i16(0x29b)
+#define Usage_Con_ACDistributeVertically               Usage_i16(0x29c)
+#define Usage_Con_ACNextKeyboardLayoutSelect           Usage_i16(0x29d)
+#define Usage_Con_ACNavigationGuidance                 Usage_i16(0x29e)
+#define Usage_Con_ACDesktopShowAllWindows              Usage_i16(0x29f)
+#define Usage_Con_ACSoftKeyLeft                        Usage_i16(0x2a0)
+#define Usage_Con_ACSoftKeyRight                       Usage_i16(0x2a1)
+#define Usage_Con_ACDesktopShowAllApplications         Usage_i16(0x2a2)
+#define Usage_Con_ACIdleKeepAlive                      Usage_i16(0x2b0)
+#define Usage_Con_ExtendedKeyboardAttributesCollection Usage_i16(0x2c0)
+#define Usage_Con_KeyboardFormFactor                   Usage_i16(0x2c1)
+#define Usage_Con_KeyboardKeyType                      Usage_i16(0x2c2)
+#define Usage_Con_KeyboardPhysicalLayout               Usage_i16(0x2c3)
+#define Usage_Con_VendorSpecificKeyboardPhysicalLayout Usage_i16(0x2c4)
+#define Usage_Con_KeyboardIETFLanguageTagIndex         Usage_i16(0x2c5)
+#define Usage_Con_ImplementedKeyboardInputAssistControls Usage_i16(0x2c6)
+#define Usage_Con_KeyboardInputAssistPrevious          Usage_i16(0x2c7)
+#define Usage_Con_KeyboardInputAssistNext              Usage_i16(0x2c8)
+#define Usage_Con_KeyboardInputAssistPreviousGroup     Usage_i16(0x2c9)
+#define Usage_Con_KeyboardInputAssistNextGroup         Usage_i16(0x2ca)
+#define Usage_Con_KeyboardInputAssistAccept            Usage_i16(0x2cb)
+#define Usage_Con_KeyboardInputAssistCancel            Usage_i16(0x2cc)
+#define Usage_Con_PrivacyScreenToggle                  Usage_i16(0x2d0)
+#define Usage_Con_PrivacyScreenLevelDecrement          Usage_i16(0x2d1)
+#define Usage_Con_PrivacyScreenLevelIncrement          Usage_i16(0x2d2)
+#define Usage_Con_PrivacyScreenLevelMinimum            Usage_i16(0x2d3)
+#define Usage_Con_PrivacyScreenLevelMaximum            Usage_i16(0x2d4)
+#define Usage_Con_ContactEdited                        Usage_i16(0x500)
+#define Usage_Con_ContactAdded                         Usage_i16(0x501)
+#define Usage_Con_ContactRecordActive                  Usage_i16(0x502)
+#define Usage_Con_ContactIndex                         Usage_i16(0x503)
+#define Usage_Con_ContactNickname                      Usage_i16(0x504)
+#define Usage_Con_ContactFirstName                     Usage_i16(0x505)
+#define Usage_Con_ContactLastName                      Usage_i16(0x506)
+#define Usage_Con_ContactFullName                      Usage_i16(0x507)
+#define Usage_Con_ContactPhoneNumberPersonal           Usage_i16(0x508)
+#define Usage_Con_ContactPhoneNumberBusiness           Usage_i16(0x509)
+#define Usage_Con_ContactPhoneNumberMobile             Usage_i16(0x50a)
+#define Usage_Con_ContactPhoneNumberPager              Usage_i16(0x50b)
+#define Usage_Con_ContactPhoneNumberFax                Usage_i16(0x50c)
+#define Usage_Con_ContactPhoneNumberOther              Usage_i16(0x50d)
+#define Usage_Con_ContactEmailPersonal                 Usage_i16(0x50e)
+#define Usage_Con_ContactEmailBusiness                 Usage_i16(0x50f)
+#define Usage_Con_ContactEmailOther                    Usage_i16(0x510)
+#define Usage_Con_ContactEmailMain                     Usage_i16(0x511)
+#define Usage_Con_ContactSpeedDialNumber               Usage_i16(0x512)
+#define Usage_Con_ContactStatusFlag                    Usage_i16(0x513)
+#define Usage_Con_ContactMisc                          Usage_i16(0x514)
+#define Usage_Dig_Digitizer                            Usage_i8(0x1)
+#define Usage_Dig_Pen                                  Usage_i8(0x2)
+#define Usage_Dig_LightPen                             Usage_i8(0x3)
+#define Usage_Dig_TouchScreen                          Usage_i8(0x4)
+#define Usage_Dig_TouchPad                             Usage_i8(0x5)
+#define Usage_Dig_Whiteboard                           Usage_i8(0x6)
+#define Usage_Dig_CoordinateMeasuringMachine           Usage_i8(0x7)
+#define Usage_Dig_ThreeDDigitizer                      Usage_i8(0x8)
+#define Usage_Dig_StereoPlotter                        Usage_i8(0x9)
+#define Usage_Dig_ArticulatedArm                       Usage_i8(0xa)
+#define Usage_Dig_Armature                             Usage_i8(0xb)
+#define Usage_Dig_MultiplePointDigitizer               Usage_i8(0xc)
+#define Usage_Dig_FreeSpaceWand                        Usage_i8(0xd)
+#define Usage_Dig_DeviceConfiguration                  Usage_i8(0xe)
+#define Usage_Dig_CapacitiveHeatMapDigitizer           Usage_i8(0xf)
+#define Usage_Dig_Stylus                               Usage_i8(0x20)
+#define Usage_Dig_Puck                                 Usage_i8(0x21)
+#define Usage_Dig_Finger                               Usage_i8(0x22)
+#define Usage_Dig_Devicesettings                       Usage_i8(0x23)
+#define Usage_Dig_CharacterGesture                     Usage_i8(0x24)
+#define Usage_Dig_TipPressure                          Usage_i8(0x30)
+#define Usage_Dig_BarrelPressure                       Usage_i8(0x31)
+#define Usage_Dig_InRange                              Usage_i8(0x32)
+#define Usage_Dig_Touch                                Usage_i8(0x33)
+#define Usage_Dig_Untouch                              Usage_i8(0x34)
+#define Usage_Dig_Tap                                  Usage_i8(0x35)
+#define Usage_Dig_Quality                              Usage_i8(0x36)
+#define Usage_Dig_DataValid                            Usage_i8(0x37)
+#define Usage_Dig_TransducerIndex                      Usage_i8(0x38)
+#define Usage_Dig_TabletFunctionKeys                   Usage_i8(0x39)
+#define Usage_Dig_ProgramChangeKeys                    Usage_i8(0x3a)
+#define Usage_Dig_BatteryStrength                      Usage_i8(0x3b)
+#define Usage_Dig_Invert                               Usage_i8(0x3c)
+#define Usage_Dig_XTilt                                Usage_i8(0x3d)
+#define Usage_Dig_YTilt                                Usage_i8(0x3e)
+#define Usage_Dig_Azimuth                              Usage_i8(0x3f)
+#define Usage_Dig_Altitude                             Usage_i8(0x40)
+#define Usage_Dig_Twist                                Usage_i8(0x41)
+#define Usage_Dig_TipSwitch                            Usage_i8(0x42)
+#define Usage_Dig_SecondaryTipSwitch                   Usage_i8(0x43)
+#define Usage_Dig_BarrelSwitch                         Usage_i8(0x44)
+#define Usage_Dig_Eraser                               Usage_i8(0x45)
+#define Usage_Dig_TabletPick                           Usage_i8(0x46)
+#define Usage_Dig_TouchValid                           Usage_i8(0x47)
+#define Usage_Dig_Width                                Usage_i8(0x48)
+#define Usage_Dig_Height                               Usage_i8(0x49)
+#define Usage_Dig_ContactIdentifier                    Usage_i8(0x51)
+#define Usage_Dig_DeviceMode                           Usage_i8(0x52)
+#define Usage_Dig_DeviceIdentifier                     Usage_i8(0x53)
+#define Usage_Dig_ContactCount                         Usage_i8(0x54)
+#define Usage_Dig_ContactCountMaximum                  Usage_i8(0x55)
+#define Usage_Dig_ScanTime                             Usage_i8(0x56)
+#define Usage_Dig_SurfaceSwitch                        Usage_i8(0x57)
+#define Usage_Dig_ButtonSwitch                         Usage_i8(0x58)
+#define Usage_Dig_PadType                              Usage_i8(0x59)
+#define Usage_Dig_SecondaryBarrelSwitch                Usage_i8(0x5a)
+#define Usage_Dig_TransducerSerialNumber               Usage_i8(0x5b)
+#define Usage_Dig_PreferredColor                       Usage_i8(0x5c)
+#define Usage_Dig_PreferredColorisLocked               Usage_i8(0x5d)
+#define Usage_Dig_PreferredLineWidth                   Usage_i8(0x5e)
+#define Usage_Dig_PreferredLineWidthisLocked           Usage_i8(0x5f)
+#define Usage_Dig_LatencyMode                          Usage_i8(0x60)
+#define Usage_Dig_GestureCharacterQuality              Usage_i8(0x61)
+#define Usage_Dig_CharacterGestureDataLength           Usage_i8(0x62)
+#define Usage_Dig_CharacterGestureData                 Usage_i8(0x63)
+#define Usage_Dig_GestureCharacterEncoding             Usage_i8(0x64)
+#define Usage_Dig_UTF8CharacterGestureEncoding         Usage_i8(0x65)
+#define Usage_Dig_UTF16LittleEndianCharacterGestureEncoding Usage_i8(0x66)
+#define Usage_Dig_UTF16BigEndianCharacterGestureEncoding Usage_i8(0x67)
+#define Usage_Dig_UTF32LittleEndianCharacterGestureEncoding Usage_i8(0x68)
+#define Usage_Dig_UTF32BigEndianCharacterGestureEncoding Usage_i8(0x69)
+#define Usage_Dig_CapacitiveHeatMapProtocolVendorID    Usage_i8(0x6a)
+#define Usage_Dig_CapacitiveHeatMapProtocolVersion     Usage_i8(0x6b)
+#define Usage_Dig_CapacitiveHeatMapFrameData           Usage_i8(0x6c)
+#define Usage_Dig_GestureCharacterEnable               Usage_i8(0x6d)
+#define Usage_Dig_TransducerSerialNumberPart2          Usage_i8(0x6e)
+#define Usage_Dig_NoPreferredColor                     Usage_i8(0x6f)
+#define Usage_Dig_PreferredLineStyle                   Usage_i8(0x70)
+#define Usage_Dig_PreferredLineStyleisLocked           Usage_i8(0x71)
+#define Usage_Dig_Ink                                  Usage_i8(0x72)
+#define Usage_Dig_Pencil                               Usage_i8(0x73)
+#define Usage_Dig_Highlighter                          Usage_i8(0x74)
+#define Usage_Dig_ChiselMarker                         Usage_i8(0x75)
+#define Usage_Dig_Brush                                Usage_i8(0x76)
+#define Usage_Dig_NoPreference                         Usage_i8(0x77)
+#define Usage_Dig_DigitizerDiagnostic                  Usage_i8(0x80)
+#define Usage_Dig_DigitizerError                       Usage_i8(0x81)
+#define Usage_Dig_ErrNormalStatus                      Usage_i8(0x82)
+#define Usage_Dig_ErrTransducersExceeded               Usage_i8(0x83)
+#define Usage_Dig_ErrFullTransFeaturesUnavailable      Usage_i8(0x84)
+#define Usage_Dig_ErrChargeLow                         Usage_i8(0x85)
+#define Usage_Dig_TransducerSoftwareInfo               Usage_i8(0x90)
+#define Usage_Dig_TransducerVendorId                   Usage_i8(0x91)
+#define Usage_Dig_TransducerProductId                  Usage_i8(0x92)
+#define Usage_Dig_DeviceSupportedProtocols             Usage_i8(0x93)
+#define Usage_Dig_TransducerSupportedProtocols         Usage_i8(0x94)
+#define Usage_Dig_NoProtocol                           Usage_i8(0x95)
+#define Usage_Dig_WacomAESProtocol                     Usage_i8(0x96)
+#define Usage_Dig_USIProtocol                          Usage_i8(0x97)
+#define Usage_Dig_MicrosoftPenProtocol                 Usage_i8(0x98)
+#define Usage_Dig_SupportedReportRates                 Usage_i8(0xa0)
+#define Usage_Dig_ReportRate                           Usage_i8(0xa1)
+#define Usage_Dig_TransducerConnected                  Usage_i8(0xa2)
+#define Usage_Dig_SwitchDisabled                       Usage_i8(0xa3)
+#define Usage_Dig_SwitchUnimplemented                  Usage_i8(0xa4)
+#define Usage_Dig_TransducerSwitches                   Usage_i8(0xa5)
+#define Usage_Dig_TransducerIndexSelector              Usage_i8(0xa6)
+#define Usage_Dig_ButtonPressThreshold                 Usage_i8(0xb0)
+#define Usage_Hap_SimpleHapticController               Usage_i8(0x1)
+#define Usage_Hap_WaveformList                         Usage_i8(0x10)
+#define Usage_Hap_DurationList                         Usage_i8(0x11)
+#define Usage_Hap_AutoTrigger                          Usage_i8(0x20)
+#define Usage_Hap_ManualTrigger                        Usage_i8(0x21)
+#define Usage_Hap_AutoTriggerAssociatedControl         Usage_i8(0x22)
+#define Usage_Hap_Intensity                            Usage_i8(0x23)
+#define Usage_Hap_RepeatCount                          Usage_i8(0x24)
+#define Usage_Hap_RetriggerPeriod                      Usage_i8(0x25)
+#define Usage_Hap_WaveformVendorPage                   Usage_i8(0x26)
+#define Usage_Hap_WaveformVendorID                     Usage_i8(0x27)
+#define Usage_Hap_WaveformCutoffTime                   Usage_i8(0x28)
+#define Usage_Hap_WaveformNone                         Usage_i16(0x1001)
+#define Usage_Hap_WaveformStop                         Usage_i16(0x1002)
+#define Usage_Hap_WaveformClick                        Usage_i16(0x1003)
+#define Usage_Hap_WaveformBuzzContinuous               Usage_i16(0x1004)
+#define Usage_Hap_WaveformRumbleContinuous             Usage_i16(0x1005)
+#define Usage_Hap_WaveformPress                        Usage_i16(0x1006)
+#define Usage_Hap_WaveformRelease                      Usage_i16(0x1007)
+#define Usage_Hap_WaveformHover                        Usage_i16(0x1008)
+#define Usage_Hap_WaveformSuccess                      Usage_i16(0x1009)
+#define Usage_Hap_WaveformError                        Usage_i16(0x100a)
+#define Usage_Hap_WaveformInkContinuous                Usage_i16(0x100b)
+#define Usage_Hap_WaveformPencilContinuous             Usage_i16(0x100c)
+#define Usage_Hap_WaveformMarkerContinuous             Usage_i16(0x100d)
+#define Usage_Hap_WaveformChiselMarkerContinuous       Usage_i16(0x100e)
+#define Usage_Hap_WaveformBrushContinuous              Usage_i16(0x100f)
+#define Usage_Hap_WaveformEraserContinuous             Usage_i16(0x1010)
+#define Usage_Hap_WaveformSparkleContinuous            Usage_i16(0x1011)
+#define Usage_PID_PhysicalInputDevice                  Usage_i8(0x1)
+#define Usage_PID_Normal                               Usage_i8(0x20)
+#define Usage_PID_SetEffectReport                      Usage_i8(0x21)
+#define Usage_PID_EffectParameterBlockIndex            Usage_i8(0x22)
+#define Usage_PID_ParameterBlockOffset                 Usage_i8(0x23)
+#define Usage_PID_ROMFlag                              Usage_i8(0x24)
+#define Usage_PID_EffectType                           Usage_i8(0x25)
+#define Usage_PID_ETConstantForce                      Usage_i8(0x26)
+#define Usage_PID_ETRamp                               Usage_i8(0x27)
+#define Usage_PID_ETCustomForce                        Usage_i8(0x28)
+#define Usage_PID_ETSquare                             Usage_i8(0x30)
+#define Usage_PID_ETSine                               Usage_i8(0x31)
+#define Usage_PID_ETTriangle                           Usage_i8(0x32)
+#define Usage_PID_ETSawtoothUp                         Usage_i8(0x33)
+#define Usage_PID_ETSawtoothDown                       Usage_i8(0x34)
+#define Usage_PID_ETSpring                             Usage_i8(0x40)
+#define Usage_PID_ETDamper                             Usage_i8(0x41)
+#define Usage_PID_ETInertia                            Usage_i8(0x42)
+#define Usage_PID_ETFriction                           Usage_i8(0x43)
+#define Usage_PID_Duration                             Usage_i8(0x50)
+#define Usage_PID_SamplePeriod                         Usage_i8(0x51)
+#define Usage_PID_Gain                                 Usage_i8(0x52)
+#define Usage_PID_TriggerButton                        Usage_i8(0x53)
+#define Usage_PID_TriggerRepeatInterval                Usage_i8(0x54)
+#define Usage_PID_AxesEnable                           Usage_i8(0x55)
+#define Usage_PID_DirectionEnable                      Usage_i8(0x56)
+#define Usage_PID_Direction                            Usage_i8(0x57)
+#define Usage_PID_TypeSpecificBlockOffset              Usage_i8(0x58)
+#define Usage_PID_BlockType                            Usage_i8(0x59)
+#define Usage_PID_SetEnvelopeReport                    Usage_i8(0x5a)
+#define Usage_PID_AttackLevel                          Usage_i8(0x5b)
+#define Usage_PID_AttackTime                           Usage_i8(0x5c)
+#define Usage_PID_FadeLevel                            Usage_i8(0x5d)
+#define Usage_PID_FadeTime                             Usage_i8(0x5e)
+#define Usage_PID_SetConditionReport                   Usage_i8(0x5f)
+#define Usage_PID_CenterPointOffset                    Usage_i8(0x60)
+#define Usage_PID_PositiveCoefficient                  Usage_i8(0x61)
+#define Usage_PID_NegativeCoefficient                  Usage_i8(0x62)
+#define Usage_PID_PositiveSaturation                   Usage_i8(0x63)
+#define Usage_PID_NegativeSaturation                   Usage_i8(0x64)
+#define Usage_PID_DeadBand                             Usage_i8(0x65)
+#define Usage_PID_DownloadForceSample                  Usage_i8(0x66)
+#define Usage_PID_IsochCustomForceEnable               Usage_i8(0x67)
+#define Usage_PID_CustomForceDataReport                Usage_i8(0x68)
+#define Usage_PID_CustomForceData                      Usage_i8(0x69)
+#define Usage_PID_CustomForceVendorDefinedData         Usage_i8(0x6a)
+#define Usage_PID_SetCustomForceReport                 Usage_i8(0x6b)
+#define Usage_PID_CustomForceDataOffset                Usage_i8(0x6c)
+#define Usage_PID_SampleCount                          Usage_i8(0x6d)
+#define Usage_PID_SetPeriodicReport                    Usage_i8(0x6e)
+#define Usage_PID_Offset                               Usage_i8(0x6f)
+#define Usage_PID_Magnitude                            Usage_i8(0x70)
+#define Usage_PID_Phase                                Usage_i8(0x71)
+#define Usage_PID_Period                               Usage_i8(0x72)
+#define Usage_PID_SetConstantForceReport               Usage_i8(0x73)
+#define Usage_PID_SetRampForceReport                   Usage_i8(0x74)
+#define Usage_PID_RampStart                            Usage_i8(0x75)
+#define Usage_PID_RampEnd                              Usage_i8(0x76)
+#define Usage_PID_EffectOperationReport                Usage_i8(0x77)
+#define Usage_PID_EffectOperation                      Usage_i8(0x78)
+#define Usage_PID_OpEffectStart                        Usage_i8(0x79)
+#define Usage_PID_OpEffectStartSolo                    Usage_i8(0x7a)
+#define Usage_PID_OpEffectStop                         Usage_i8(0x7b)
+#define Usage_PID_LoopCount                            Usage_i8(0x7c)
+#define Usage_PID_DeviceGainReport                     Usage_i8(0x7d)
+#define Usage_PID_DeviceGain                           Usage_i8(0x7e)
+#define Usage_PID_ParameterBlockPoolsReport            Usage_i8(0x7f)
+#define Usage_PID_RAMPoolSize                          Usage_i8(0x80)
+#define Usage_PID_ROMPoolSize                          Usage_i8(0x81)
+#define Usage_PID_ROMEffectBlockCount                  Usage_i8(0x82)
+#define Usage_PID_SimultaneousEffectsMax               Usage_i8(0x83)
+#define Usage_PID_PoolAlignment                        Usage_i8(0x84)
+#define Usage_PID_ParameterBlockMoveReport             Usage_i8(0x85)
+#define Usage_PID_MoveSource                           Usage_i8(0x86)
+#define Usage_PID_MoveDestination                      Usage_i8(0x87)
+#define Usage_PID_MoveLength                           Usage_i8(0x88)
+#define Usage_PID_EffectParameterBlockLoadReport       Usage_i8(0x89)
+#define Usage_PID_EffectParameterBlockLoadStatus       Usage_i8(0x8b)
+#define Usage_PID_BlockLoadSuccess                     Usage_i8(0x8c)
+#define Usage_PID_BlockLoadFull                        Usage_i8(0x8d)
+#define Usage_PID_BlockLoadError                       Usage_i8(0x8e)
+#define Usage_PID_BlockHandle                          Usage_i8(0x8f)
+#define Usage_PID_EffectParameterBlockFreeReport       Usage_i8(0x90)
+#define Usage_PID_TypeSpecificBlockHandle              Usage_i8(0x91)
+#define Usage_PID_PIDStateReport                       Usage_i8(0x92)
+#define Usage_PID_EffectPlaying                        Usage_i8(0x94)
+#define Usage_PID_PIDDeviceControlReport               Usage_i8(0x95)
+#define Usage_PID_PIDDeviceControl                     Usage_i8(0x96)
+#define Usage_PID_DCEnableActuators                    Usage_i8(0x97)
+#define Usage_PID_DCDisableActuators                   Usage_i8(0x98)
+#define Usage_PID_DCStopAllEffects                     Usage_i8(0x99)
+#define Usage_PID_DCReset                              Usage_i8(0x9a)
+#define Usage_PID_DCPause                              Usage_i8(0x9b)
+#define Usage_PID_DCContinue                           Usage_i8(0x9c)
+#define Usage_PID_DevicePaused                         Usage_i8(0x9f)
+#define Usage_PID_ActuatorsEnabled                     Usage_i8(0xa0)
+#define Usage_PID_SafetySwitch                         Usage_i8(0xa4)
+#define Usage_PID_ActuatorOverrideSwitch               Usage_i8(0xa5)
+#define Usage_PID_ActuatorPower                        Usage_i8(0xa6)
+#define Usage_PID_StartDelay                           Usage_i8(0xa7)
+#define Usage_PID_ParameterBlockSize                   Usage_i8(0xa8)
+#define Usage_PID_DeviceManagedPool                    Usage_i8(0xa9)
+#define Usage_PID_SharedParameterBlocks                Usage_i8(0xaa)
+#define Usage_PID_CreateNewEffectParameterBlockReport  Usage_i8(0xab)
+#define Usage_PID_RAMPoolAvailable                     Usage_i8(0xac)
+#define Usage_SC_SocControl                            Usage_i8(0x1)
+#define Usage_SC_FirmwareTransfer                      Usage_i8(0x2)
+#define Usage_SC_FirmwareFileId                        Usage_i8(0x3)
+#define Usage_SC_FileOffsetInBytes                     Usage_i8(0x4)
+#define Usage_SC_FileTransferSizeMaxInBytes            Usage_i8(0x5)
+#define Usage_SC_FilePayload                           Usage_i8(0x6)
+#define Usage_SC_FilePayloadSizeInBytes                Usage_i8(0x7)
+#define Usage_SC_FilePayloadContainsLastBytes          Usage_i8(0x8)
+#define Usage_SC_FileTransferStop                      Usage_i8(0x9)
+#define Usage_SC_FileTransferTillEnd                   Usage_i8(0xa)
+#define Usage_EHT_EyeTracker                           Usage_i8(0x1)
+#define Usage_EHT_HeadTracker                          Usage_i8(0x2)
+#define Usage_EHT_TrackingData                         Usage_i8(0x10)
+#define Usage_EHT_Capabilities                         Usage_i8(0x11)
+#define Usage_EHT_Configuration                        Usage_i8(0x12)
+#define Usage_EHT_Status                               Usage_i8(0x13)
+#define Usage_EHT_Control                              Usage_i8(0x14)
+#define Usage_EHT_SensorTimestamp                      Usage_i8(0x20)
+#define Usage_EHT_PositionX                            Usage_i8(0x21)
+#define Usage_EHT_PositionY                            Usage_i8(0x22)
+#define Usage_EHT_PositionZ                            Usage_i8(0x23)
+#define Usage_EHT_GazePoint                            Usage_i8(0x24)
+#define Usage_EHT_LeftEyePosition                      Usage_i8(0x25)
+#define Usage_EHT_RightEyePosition                     Usage_i8(0x26)
+#define Usage_EHT_HeadPosition                         Usage_i8(0x27)
+#define Usage_EHT_HeadDirectionPoint                   Usage_i8(0x28)
+#define Usage_EHT_RotationaboutXaxis                   Usage_i8(0x29)
+#define Usage_EHT_RotationaboutYaxis                   Usage_i8(0x2a)
+#define Usage_EHT_RotationaboutZaxis                   Usage_i8(0x2b)
+#define Usage_EHT_TrackerQuality                       Usage_i16(0x100)
+#define Usage_EHT_MinimumTrackingDistance              Usage_i16(0x101)
+#define Usage_EHT_OptimumTrackingDistance              Usage_i16(0x102)
+#define Usage_EHT_MaximumTrackingDistance              Usage_i16(0x103)
+#define Usage_EHT_MaximumScreenPlaneWidth              Usage_i16(0x104)
+#define Usage_EHT_MaximumScreenPlaneHeight             Usage_i16(0x105)
+#define Usage_EHT_DisplayManufacturerID                Usage_i16(0x200)
+#define Usage_EHT_DisplayProductID                     Usage_i16(0x201)
+#define Usage_EHT_DisplaySerialNumber                  Usage_i16(0x202)
+#define Usage_EHT_DisplayManufacturerDate              Usage_i16(0x203)
+#define Usage_EHT_CalibratedScreenWidth                Usage_i16(0x204)
+#define Usage_EHT_CalibratedScreenHeight               Usage_i16(0x205)
+#define Usage_EHT_SamplingFrequency                    Usage_i16(0x300)
+#define Usage_EHT_ConfigurationStatus                  Usage_i16(0x301)
+#define Usage_EHT_DeviceModeRequest                    Usage_i16(0x400)
+#define Usage_AD_AlphanumericDisplay                   Usage_i8(0x1)
+#define Usage_AD_AuxiliaryDisplay                      Usage_i8(0x2)
+#define Usage_AD_DisplayAttributesReport               Usage_i8(0x20)
+#define Usage_AD_ASCIICharacterSet                     Usage_i8(0x21)
+#define Usage_AD_DataReadBack                          Usage_i8(0x22)
+#define Usage_AD_FontReadBack                          Usage_i8(0x23)
+#define Usage_AD_DisplayControlReport                  Usage_i8(0x24)
+#define Usage_AD_ClearDisplay                          Usage_i8(0x25)
+#define Usage_AD_DisplayEnable                         Usage_i8(0x26)
+#define Usage_AD_ScreenSaverDelay                      Usage_i8(0x27)
+#define Usage_AD_ScreenSaverEnable                     Usage_i8(0x28)
+#define Usage_AD_VerticalScroll                        Usage_i8(0x29)
+#define Usage_AD_HorizontalScroll                      Usage_i8(0x2a)
+#define Usage_AD_CharacterReport                       Usage_i8(0x2b)
+#define Usage_AD_DisplayData                           Usage_i8(0x2c)
+#define Usage_AD_DisplayStatus                         Usage_i8(0x2d)
+#define Usage_AD_StatNotReady                          Usage_i8(0x2e)
+#define Usage_AD_StatReady                             Usage_i8(0x2f)
+#define Usage_AD_ErrNotaloadablecharacter              Usage_i8(0x30)
+#define Usage_AD_ErrFontdatacannotberead               Usage_i8(0x31)
+#define Usage_AD_CursorPositionReport                  Usage_i8(0x32)
+#define Usage_AD_Row                                   Usage_i8(0x33)
+#define Usage_AD_Column                                Usage_i8(0x34)
+#define Usage_AD_Rows                                  Usage_i8(0x35)
+#define Usage_AD_Columns                               Usage_i8(0x36)
+#define Usage_AD_CursorPixelPositioning                Usage_i8(0x37)
+#define Usage_AD_CursorMode                            Usage_i8(0x38)
+#define Usage_AD_CursorEnable                          Usage_i8(0x39)
+#define Usage_AD_CursorBlink                           Usage_i8(0x3a)
+#define Usage_AD_FontReport                            Usage_i8(0x3b)
+#define Usage_AD_FontData                              Usage_i8(0x3c)
+#define Usage_AD_CharacterWidth                        Usage_i8(0x3d)
+#define Usage_AD_CharacterHeight                       Usage_i8(0x3e)
+#define Usage_AD_CharacterSpacingHorizontal            Usage_i8(0x3f)
+#define Usage_AD_CharacterSpacingVertical              Usage_i8(0x40)
+#define Usage_AD_UnicodeCharacterSet                   Usage_i8(0x41)
+#define Usage_AD_Font7Segment                          Usage_i8(0x42)
+#define Usage_AD_SevenSegmentDirectMap                 Usage_i8(0x43)
+#define Usage_AD_Font14Segment                         Usage_i8(0x44)
+#define Usage_AD_One4SegmentDirectMap                  Usage_i8(0x45)
+#define Usage_AD_DisplayBrightness                     Usage_i8(0x46)
+#define Usage_AD_DisplayContrast                       Usage_i8(0x47)
+#define Usage_AD_CharacterAttribute                    Usage_i8(0x48)
+#define Usage_AD_AttributeReadback                     Usage_i8(0x49)
+#define Usage_AD_AttributeData                         Usage_i8(0x4a)
+#define Usage_AD_CharAttrEnhance                       Usage_i8(0x4b)
+#define Usage_AD_CharAttrUnderline                     Usage_i8(0x4c)
+#define Usage_AD_CharAttrBlink                         Usage_i8(0x4d)
+#define Usage_AD_BitmapSizeX                           Usage_i8(0x80)
+#define Usage_AD_BitmapSizeY                           Usage_i8(0x81)
+#define Usage_AD_MaxBlitSize                           Usage_i8(0x82)
+#define Usage_AD_BitDepthFormat                        Usage_i8(0x83)
+#define Usage_AD_DisplayOrientation                    Usage_i8(0x84)
+#define Usage_AD_PaletteReport                         Usage_i8(0x85)
+#define Usage_AD_PaletteDataSize                       Usage_i8(0x86)
+#define Usage_AD_PaletteDataOffset                     Usage_i8(0x87)
+#define Usage_AD_PaletteData                           Usage_i8(0x88)
+#define Usage_AD_BlitReport                            Usage_i8(0x8a)
+#define Usage_AD_BlitRectangleX1                       Usage_i8(0x8b)
+#define Usage_AD_BlitRectangleY1                       Usage_i8(0x8c)
+#define Usage_AD_BlitRectangleX2                       Usage_i8(0x8d)
+#define Usage_AD_BlitRectangleY2                       Usage_i8(0x8e)
+#define Usage_AD_BlitData                              Usage_i8(0x8f)
+#define Usage_AD_SoftButton                            Usage_i8(0x90)
+#define Usage_AD_SoftButtonID                          Usage_i8(0x91)
+#define Usage_AD_SoftButtonSide                        Usage_i8(0x92)
+#define Usage_AD_SoftButtonOffset1                     Usage_i8(0x93)
+#define Usage_AD_SoftButtonOffset2                     Usage_i8(0x94)
+#define Usage_AD_SoftButtonReport                      Usage_i8(0x95)
+#define Usage_AD_SoftKeys                              Usage_i8(0xc2)
+#define Usage_AD_DisplayDataExtensions                 Usage_i8(0xcc)
+#define Usage_AD_CharacterMapping                      Usage_i8(0xcf)
+#define Usage_AD_UnicodeEquivalent                     Usage_i8(0xdd)
+#define Usage_AD_CharacterPageMapping                  Usage_i8(0xdf)
+#define Usage_AD_RequestReport                         Usage_i16(0xff)
+#define Usage_Sen_Sensor                               Usage_i8(0x1)
+#define Usage_Sen_Biometric                            Usage_i8(0x10)
+#define Usage_Sen_BiometricHumanPresence               Usage_i8(0x11)
+#define Usage_Sen_BiometricHumanProximity              Usage_i8(0x12)
+#define Usage_Sen_BiometricHumanTouch                  Usage_i8(0x13)
+#define Usage_Sen_BiometricBloodPressure               Usage_i8(0x14)
+#define Usage_Sen_BiometricBodyTemperature             Usage_i8(0x15)
+#define Usage_Sen_BiometricHeartRate                   Usage_i8(0x16)
+#define Usage_Sen_BiometricHeartRateVariability        Usage_i8(0x17)
+#define Usage_Sen_BiometricPeripheralOxygenSaturation  Usage_i8(0x18)
+#define Usage_Sen_BiometricRespiratoryRate             Usage_i8(0x19)
+#define Usage_Sen_Electrical                           Usage_i8(0x20)
+#define Usage_Sen_ElectricalCapacitance                Usage_i8(0x21)
+#define Usage_Sen_ElectricalCurrent                    Usage_i8(0x22)
+#define Usage_Sen_ElectricalPower                      Usage_i8(0x23)
+#define Usage_Sen_ElectricalInductance                 Usage_i8(0x24)
+#define Usage_Sen_ElectricalResistance                 Usage_i8(0x25)
+#define Usage_Sen_ElectricalVoltage                    Usage_i8(0x26)
+#define Usage_Sen_ElectricalPotentiometer              Usage_i8(0x27)
+#define Usage_Sen_ElectricalFrequency                  Usage_i8(0x28)
+#define Usage_Sen_ElectricalPeriod                     Usage_i8(0x29)
+#define Usage_Sen_Environmental                        Usage_i8(0x30)
+#define Usage_Sen_EnvironmentalAtmosphericPressure     Usage_i8(0x31)
+#define Usage_Sen_EnvironmentalHumidity                Usage_i8(0x32)
+#define Usage_Sen_EnvironmentalTemperature             Usage_i8(0x33)
+#define Usage_Sen_EnvironmentalWindDirection           Usage_i8(0x34)
+#define Usage_Sen_EnvironmentalWindSpeed               Usage_i8(0x35)
+#define Usage_Sen_EnvironmentalAirQuality              Usage_i8(0x36)
+#define Usage_Sen_EnvironmentalHeatIndex               Usage_i8(0x37)
+#define Usage_Sen_EnvironmentalSurfaceTemperature      Usage_i8(0x38)
+#define Usage_Sen_EnvironmentalVolatileOrganicCompounds Usage_i8(0x39)
+#define Usage_Sen_EnvironmentalObjectPresence          Usage_i8(0x3a)
+#define Usage_Sen_EnvironmentalObjectProximity         Usage_i8(0x3b)
+#define Usage_Sen_Light                                Usage_i8(0x40)
+#define Usage_Sen_LightAmbientLight                    Usage_i8(0x41)
+#define Usage_Sen_LightConsumerInfrared                Usage_i8(0x42)
+#define Usage_Sen_LightInfraredLight                   Usage_i8(0x43)
+#define Usage_Sen_LightVisibleLight                    Usage_i8(0x44)
+#define Usage_Sen_LightUltravioletLight                Usage_i8(0x45)
+#define Usage_Sen_Location                             Usage_i8(0x50)
+#define Usage_Sen_LocationBroadcast                    Usage_i8(0x51)
+#define Usage_Sen_LocationDeadReckoning                Usage_i8(0x52)
+#define Usage_Sen_LocationGPSGlobalPositioningSystem   Usage_i8(0x53)
+#define Usage_Sen_LocationLookup                       Usage_i8(0x54)
+#define Usage_Sen_LocationOther                        Usage_i8(0x55)
+#define Usage_Sen_LocationStatic                       Usage_i8(0x56)
+#define Usage_Sen_LocationTriangulation                Usage_i8(0x57)
+#define Usage_Sen_Mechanical                           Usage_i8(0x60)
+#define Usage_Sen_MechanicalBooleanSwitch              Usage_i8(0x61)
+#define Usage_Sen_MechanicalBooleanSwitchArray         Usage_i8(0x62)
+#define Usage_Sen_MechanicalMultivalueSwitch           Usage_i8(0x63)
+#define Usage_Sen_MechanicalForce                      Usage_i8(0x64)
+#define Usage_Sen_MechanicalPressure                   Usage_i8(0x65)
+#define Usage_Sen_MechanicalStrain                     Usage_i8(0x66)
+#define Usage_Sen_MechanicalWeight                     Usage_i8(0x67)
+#define Usage_Sen_MechanicalHapticVibrator             Usage_i8(0x68)
+#define Usage_Sen_MechanicalHallEffectSwitch           Usage_i8(0x69)
+#define Usage_Sen_Motion                               Usage_i8(0x70)
+#define Usage_Sen_MotionAccelerometer1D                Usage_i8(0x71)
+#define Usage_Sen_MotionAccelerometer2D                Usage_i8(0x72)
+#define Usage_Sen_MotionAccelerometer3D                Usage_i8(0x73)
+#define Usage_Sen_MotionGyrometer1D                    Usage_i8(0x74)
+#define Usage_Sen_MotionGyrometer2D                    Usage_i8(0x75)
+#define Usage_Sen_MotionGyrometer3D                    Usage_i8(0x76)
+#define Usage_Sen_MotionMotionDetector                 Usage_i8(0x77)
+#define Usage_Sen_MotionSpeedometer                    Usage_i8(0x78)
+#define Usage_Sen_MotionAccelerometer                  Usage_i8(0x79)
+#define Usage_Sen_MotionGyrometer                      Usage_i8(0x7a)
+#define Usage_Sen_MotionGravityVector                  Usage_i8(0x7b)
+#define Usage_Sen_MotionLinearAccelerometer            Usage_i8(0x7c)
+#define Usage_Sen_Orientation                          Usage_i8(0x80)
+#define Usage_Sen_OrientationCompass1D                 Usage_i8(0x81)
+#define Usage_Sen_OrientationCompass2D                 Usage_i8(0x82)
+#define Usage_Sen_OrientationCompass3D                 Usage_i8(0x83)
+#define Usage_Sen_OrientationInclinometer1D            Usage_i8(0x84)
+#define Usage_Sen_OrientationInclinometer2D            Usage_i8(0x85)
+#define Usage_Sen_OrientationInclinometer3D            Usage_i8(0x86)
+#define Usage_Sen_OrientationDistance1D                Usage_i8(0x87)
+#define Usage_Sen_OrientationDistance2D                Usage_i8(0x88)
+#define Usage_Sen_OrientationDistance3D                Usage_i8(0x89)
+#define Usage_Sen_OrientationDeviceOrientation         Usage_i8(0x8a)
+#define Usage_Sen_OrientationCompass                   Usage_i8(0x8b)
+#define Usage_Sen_OrientationInclinometer              Usage_i8(0x8c)
+#define Usage_Sen_OrientationDistance                  Usage_i8(0x8d)
+#define Usage_Sen_OrientationRelativeOrientation       Usage_i8(0x8e)
+#define Usage_Sen_OrientationSimpleOrientation         Usage_i8(0x8f)
+#define Usage_Sen_Scanner                              Usage_i8(0x90)
+#define Usage_Sen_ScannerBarcode                       Usage_i8(0x91)
+#define Usage_Sen_ScannerRFID                          Usage_i8(0x92)
+#define Usage_Sen_ScannerNFC                           Usage_i8(0x93)
+#define Usage_Sen_Time                                 Usage_i8(0xa0)
+#define Usage_Sen_TimeAlarmTimer                       Usage_i8(0xa1)
+#define Usage_Sen_TimeRealTimeClock                    Usage_i8(0xa2)
+#define Usage_Sen_PersonalActivity                     Usage_i8(0xb0)
+#define Usage_Sen_PersonalActivityActivityDetection    Usage_i8(0xb1)
+#define Usage_Sen_PersonalActivityDevicePosition       Usage_i8(0xb2)
+#define Usage_Sen_PersonalActivityFloorTracker         Usage_i8(0xb3)
+#define Usage_Sen_PersonalActivityPedometer            Usage_i8(0xb4)
+#define Usage_Sen_PersonalActivityStepDetection        Usage_i8(0xb5)
+#define Usage_Sen_OrientationExtended                  Usage_i8(0xc0)
+#define Usage_Sen_OrientationExtendedGeomagneticOrientation Usage_i8(0xc1)
+#define Usage_Sen_OrientationExtendedMagnetometer      Usage_i8(0xc2)
+#define Usage_Sen_Gesture                              Usage_i8(0xd0)
+#define Usage_Sen_GestureChassisFlipGesture            Usage_i8(0xd1)
+#define Usage_Sen_GestureHingeFoldGesture              Usage_i8(0xd2)
+#define Usage_Sen_Other                                Usage_i8(0xe0)
+#define Usage_Sen_OtherCustom                          Usage_i8(0xe1)
+#define Usage_Sen_OtherGeneric                         Usage_i8(0xe2)
+#define Usage_Sen_OtherGenericEnumerator               Usage_i8(0xe3)
+#define Usage_Sen_OtherHingeAngle                      Usage_i8(0xe4)
+#define Usage_Sen_VendorReserved1                      Usage_i8(0xf0)
+#define Usage_Sen_VendorReserved2                      Usage_i8(0xf1)
+#define Usage_Sen_VendorReserved3                      Usage_i8(0xf2)
+#define Usage_Sen_VendorReserved4                      Usage_i8(0xf3)
+#define Usage_Sen_VendorReserved5                      Usage_i8(0xf4)
+#define Usage_Sen_VendorReserved6                      Usage_i8(0xf5)
+#define Usage_Sen_VendorReserved7                      Usage_i8(0xf6)
+#define Usage_Sen_VendorReserved8                      Usage_i8(0xf7)
+#define Usage_Sen_VendorReserved9                      Usage_i8(0xf8)
+#define Usage_Sen_VendorReserved10                     Usage_i8(0xf9)
+#define Usage_Sen_VendorReserved11                     Usage_i8(0xfa)
+#define Usage_Sen_VendorReserved12                     Usage_i8(0xfb)
+#define Usage_Sen_VendorReserved13                     Usage_i8(0xfc)
+#define Usage_Sen_VendorReserved14                     Usage_i8(0xfd)
+#define Usage_Sen_VendorReserved15                     Usage_i8(0xfe)
+#define Usage_Sen_VendorReserved16                     Usage_i16(0xff)
+#define Usage_Sen_Event                                Usage_i16(0x200)
+#define Usage_Sen_EventSensorState                     Usage_i16(0x201)
+#define Usage_Sen_EventSensorEvent                     Usage_i16(0x202)
+#define Usage_Sen_Property                             Usage_i16(0x300)
+#define Usage_Sen_PropertyFriendlyName                 Usage_i16(0x301)
+#define Usage_Sen_PropertyPersistentUniqueID           Usage_i16(0x302)
+#define Usage_Sen_PropertySensorStatus                 Usage_i16(0x303)
+#define Usage_Sen_PropertyMinimumReportInterval        Usage_i16(0x304)
+#define Usage_Sen_PropertySensorManufacturer           Usage_i16(0x305)
+#define Usage_Sen_PropertySensorModel                  Usage_i16(0x306)
+#define Usage_Sen_PropertySensorSerialNumber           Usage_i16(0x307)
+#define Usage_Sen_PropertySensorDescription            Usage_i16(0x308)
+#define Usage_Sen_PropertySensorConnectionType         Usage_i16(0x309)
+#define Usage_Sen_PropertySensorDevicePath             Usage_i16(0x30a)
+#define Usage_Sen_PropertyHardwareRevision             Usage_i16(0x30b)
+#define Usage_Sen_PropertyFirmwareVersion              Usage_i16(0x30c)
+#define Usage_Sen_PropertyReleaseDate                  Usage_i16(0x30d)
+#define Usage_Sen_PropertyReportInterval               Usage_i16(0x30e)
+#define Usage_Sen_PropertyChangeSensitivityAbsolute    Usage_i16(0x30f)
+#define Usage_Sen_PropertyChangeSensitivityPercentofRange Usage_i16(0x310)
+#define Usage_Sen_PropertyChangeSensitivityPercentRelative Usage_i16(0x311)
+#define Usage_Sen_PropertyAccuracy                     Usage_i16(0x312)
+#define Usage_Sen_PropertyResolution                   Usage_i16(0x313)
+#define Usage_Sen_PropertyMaximum                      Usage_i16(0x314)
+#define Usage_Sen_PropertyMinimum                      Usage_i16(0x315)
+#define Usage_Sen_PropertyReportingState               Usage_i16(0x316)
+#define Usage_Sen_PropertySamplingRate                 Usage_i16(0x317)
+#define Usage_Sen_PropertyResponseCurve                Usage_i16(0x318)
+#define Usage_Sen_PropertyPowerState                   Usage_i16(0x319)
+#define Usage_Sen_PropertyMaximumFIFOEvents            Usage_i16(0x31a)
+#define Usage_Sen_PropertyReportLatency                Usage_i16(0x31b)
+#define Usage_Sen_PropertyFlushFIFOEvents              Usage_i16(0x31c)
+#define Usage_Sen_PropertyMaximumPowerConsumption      Usage_i16(0x31d)
+#define Usage_Sen_PropertyIsPrimary                    Usage_i16(0x31e)
+#define Usage_Sen_PropertyHumanPresenceDetectionType   Usage_i16(0x31f)
+#define Usage_Sen_DataFieldLocation                    Usage_i16(0x400)
+#define Usage_Sen_DataFieldAltitudeAntennaSeaLevel     Usage_i16(0x402)
+#define Usage_Sen_DataFieldDifferentialReferenceStationID Usage_i16(0x403)
+#define Usage_Sen_DataFieldAltitudeEllipsoidError      Usage_i16(0x404)
+#define Usage_Sen_DataFieldAltitudeEllipsoid           Usage_i16(0x405)
+#define Usage_Sen_DataFieldAltitudeSeaLevelError       Usage_i16(0x406)
+#define Usage_Sen_DataFieldAltitudeSeaLevel            Usage_i16(0x407)
+#define Usage_Sen_DataFieldDifferentialGPSDataAge      Usage_i16(0x408)
+#define Usage_Sen_DataFieldErrorRadius                 Usage_i16(0x409)
+#define Usage_Sen_DataFieldFixQuality                  Usage_i16(0x40a)
+#define Usage_Sen_DataFieldFixType                     Usage_i16(0x40b)
+#define Usage_Sen_DataFieldGeoidalSeparation           Usage_i16(0x40c)
+#define Usage_Sen_DataFieldGPSOperationMode            Usage_i16(0x40d)
+#define Usage_Sen_DataFieldGPSSelectionMode            Usage_i16(0x40e)
+#define Usage_Sen_DataFieldGPSStatus                   Usage_i16(0x40f)
+#define Usage_Sen_DataFieldPositionDilutionofPrecision Usage_i16(0x410)
+#define Usage_Sen_DataFieldHorizontalDilutionofPrecision Usage_i16(0x411)
+#define Usage_Sen_DataFieldVerticalDilutionofPrecision Usage_i16(0x412)
+#define Usage_Sen_DataFieldLatitude                    Usage_i16(0x413)
+#define Usage_Sen_DataFieldLongitude                   Usage_i16(0x414)
+#define Usage_Sen_DataFieldTrueHeading                 Usage_i16(0x415)
+#define Usage_Sen_DataFieldMagneticHeading             Usage_i16(0x416)
+#define Usage_Sen_DataFieldMagneticVariation           Usage_i16(0x417)
+#define Usage_Sen_DataFieldSpeed                       Usage_i16(0x418)
+#define Usage_Sen_DataFieldSatellitesinView            Usage_i16(0x419)
+#define Usage_Sen_DataFieldSatellitesinViewAzimuth     Usage_i16(0x41a)
+#define Usage_Sen_DataFieldSatellitesinViewElevation   Usage_i16(0x41b)
+#define Usage_Sen_DataFieldSatellitesinViewIDs         Usage_i16(0x41c)
+#define Usage_Sen_DataFieldSatellitesinViewPRNs        Usage_i16(0x41d)
+#define Usage_Sen_DataFieldSatellitesinViewSNRatios    Usage_i16(0x41e)
+#define Usage_Sen_DataFieldSatellitesUsedCount         Usage_i16(0x41f)
+#define Usage_Sen_DataFieldSatellitesUsedPRNs          Usage_i16(0x420)
+#define Usage_Sen_DataFieldNMEASentence                Usage_i16(0x421)
+#define Usage_Sen_DataFieldAddressLine1                Usage_i16(0x422)
+#define Usage_Sen_DataFieldAddressLine2                Usage_i16(0x423)
+#define Usage_Sen_DataFieldCity                        Usage_i16(0x424)
+#define Usage_Sen_DataFieldStateorProvince             Usage_i16(0x425)
+#define Usage_Sen_DataFieldCountryorRegion             Usage_i16(0x426)
+#define Usage_Sen_DataFieldPostalCode                  Usage_i16(0x427)
+#define Usage_Sen_PropertyLocation                     Usage_i16(0x42a)
+#define Usage_Sen_PropertyLocationDesiredAccuracy      Usage_i16(0x42b)
+#define Usage_Sen_DataFieldEnvironmental               Usage_i16(0x430)
+#define Usage_Sen_DataFieldAtmosphericPressure         Usage_i16(0x431)
+#define Usage_Sen_DataFieldRelativeHumidity            Usage_i16(0x433)
+#define Usage_Sen_DataFieldTemperature                 Usage_i16(0x434)
+#define Usage_Sen_DataFieldWindDirection               Usage_i16(0x435)
+#define Usage_Sen_DataFieldWindSpeed                   Usage_i16(0x436)
+#define Usage_Sen_DataFieldAirQualityIndex             Usage_i16(0x437)
+#define Usage_Sen_DataFieldEquivalentCO2               Usage_i16(0x438)
+#define Usage_Sen_DataFieldVolatileOrganicCompoundConcentration Usage_i16(0x439)
+#define Usage_Sen_DataFieldObjectPresence              Usage_i16(0x43a)
+#define Usage_Sen_DataFieldObjectProximityRange        Usage_i16(0x43b)
+#define Usage_Sen_DataFieldObjectProximityOutofRange   Usage_i16(0x43c)
+#define Usage_Sen_PropertyEnvironmental                Usage_i16(0x440)
+#define Usage_Sen_PropertyReferencePressure            Usage_i16(0x441)
+#define Usage_Sen_DataFieldMotion                      Usage_i16(0x450)
+#define Usage_Sen_DataFieldMotionState                 Usage_i16(0x451)
+#define Usage_Sen_DataFieldAcceleration                Usage_i16(0x452)
+#define Usage_Sen_DataFieldAccelerationAxisX           Usage_i16(0x453)
+#define Usage_Sen_DataFieldAccelerationAxisY           Usage_i16(0x454)
+#define Usage_Sen_DataFieldAccelerationAxisZ           Usage_i16(0x455)
+#define Usage_Sen_DataFieldAngularVelocity             Usage_i16(0x456)
+#define Usage_Sen_DataFieldAngularVelocityaboutXAxis   Usage_i16(0x457)
+#define Usage_Sen_DataFieldAngularVelocityaboutYAxis   Usage_i16(0x458)
+#define Usage_Sen_DataFieldAngularVelocityaboutZAxis   Usage_i16(0x459)
+#define Usage_Sen_DataFieldAngularPosition             Usage_i16(0x45a)
+#define Usage_Sen_DataFieldAngularPositionaboutXAxis   Usage_i16(0x45b)
+#define Usage_Sen_DataFieldAngularPositionaboutYAxis   Usage_i16(0x45c)
+#define Usage_Sen_DataFieldAngularPositionaboutZAxis   Usage_i16(0x45d)
+#define Usage_Sen_DataFieldMotionSpeed                 Usage_i16(0x45e)
+#define Usage_Sen_DataFieldMotionIntensity             Usage_i16(0x45f)
+#define Usage_Sen_DataFieldOrientation                 Usage_i16(0x470)
+#define Usage_Sen_DataFieldHeading                     Usage_i16(0x471)
+#define Usage_Sen_DataFieldHeadingXAxis                Usage_i16(0x472)
+#define Usage_Sen_DataFieldHeadingYAxis                Usage_i16(0x473)
+#define Usage_Sen_DataFieldHeadingZAxis                Usage_i16(0x474)
+#define Usage_Sen_DataFieldHeadingCompensatedMagneticNorth Usage_i16(0x475)
+#define Usage_Sen_DataFieldHeadingCompensatedTrueNorth Usage_i16(0x476)
+#define Usage_Sen_DataFieldHeadingMagneticNorth        Usage_i16(0x477)
+#define Usage_Sen_DataFieldHeadingTrueNorth            Usage_i16(0x478)
+#define Usage_Sen_DataFieldDistance                    Usage_i16(0x479)
+#define Usage_Sen_DataFieldDistanceXAxis               Usage_i16(0x47a)
+#define Usage_Sen_DataFieldDistanceYAxis               Usage_i16(0x47b)
+#define Usage_Sen_DataFieldDistanceZAxis               Usage_i16(0x47c)
+#define Usage_Sen_DataFieldDistanceOutofRange          Usage_i16(0x47d)
+#define Usage_Sen_DataFieldTilt                        Usage_i16(0x47e)
+#define Usage_Sen_DataFieldTiltXAxis                   Usage_i16(0x47f)
+#define Usage_Sen_DataFieldTiltYAxis                   Usage_i16(0x480)
+#define Usage_Sen_DataFieldTiltZAxis                   Usage_i16(0x481)
+#define Usage_Sen_DataFieldRotationMatrix              Usage_i16(0x482)
+#define Usage_Sen_DataFieldQuaternion                  Usage_i16(0x483)
+#define Usage_Sen_DataFieldMagneticFlux                Usage_i16(0x484)
+#define Usage_Sen_DataFieldMagneticFluxXAxis           Usage_i16(0x485)
+#define Usage_Sen_DataFieldMagneticFluxYAxis           Usage_i16(0x486)
+#define Usage_Sen_DataFieldMagneticFluxZAxis           Usage_i16(0x487)
+#define Usage_Sen_DataFieldMagnetometerAccuracy        Usage_i16(0x488)
+#define Usage_Sen_DataFieldSimpleOrientationDirection  Usage_i16(0x489)
+#define Usage_Sen_DataFieldMechanical                  Usage_i16(0x490)
+#define Usage_Sen_DataFieldBooleanSwitchState          Usage_i16(0x491)
+#define Usage_Sen_DataFieldBooleanSwitchArrayStates    Usage_i16(0x492)
+#define Usage_Sen_DataFieldMultivalueSwitchValue       Usage_i16(0x493)
+#define Usage_Sen_DataFieldForce                       Usage_i16(0x494)
+#define Usage_Sen_DataFieldAbsolutePressure            Usage_i16(0x495)
+#define Usage_Sen_DataFieldGaugePressure               Usage_i16(0x496)
+#define Usage_Sen_DataFieldStrain                      Usage_i16(0x497)
+#define Usage_Sen_DataFieldWeight                      Usage_i16(0x498)
+#define Usage_Sen_PropertyMechanical                   Usage_i16(0x4a0)
+#define Usage_Sen_PropertyVibrationState               Usage_i16(0x4a1)
+#define Usage_Sen_PropertyForwardVibrationSpeed        Usage_i16(0x4a2)
+#define Usage_Sen_PropertyBackwardVibrationSpeed       Usage_i16(0x4a3)
+#define Usage_Sen_DataFieldBiometric                   Usage_i16(0x4b0)
+#define Usage_Sen_DataFieldHumanPresence               Usage_i16(0x4b1)
+#define Usage_Sen_DataFieldHumanProximityRange         Usage_i16(0x4b2)
+#define Usage_Sen_DataFieldHumanProximityOutofRange    Usage_i16(0x4b3)
+#define Usage_Sen_DataFieldHumanTouchState             Usage_i16(0x4b4)
+#define Usage_Sen_DataFieldBloodPressure               Usage_i16(0x4b5)
+#define Usage_Sen_DataFieldBloodPressureDiastolic      Usage_i16(0x4b6)
+#define Usage_Sen_DataFieldBloodPressureSystolic       Usage_i16(0x4b7)
+#define Usage_Sen_DataFieldHeartRate                   Usage_i16(0x4b8)
+#define Usage_Sen_DataFieldRestingHeartRate            Usage_i16(0x4b9)
+#define Usage_Sen_DataFieldHeartbeatInterval           Usage_i16(0x4ba)
+#define Usage_Sen_DataFieldRespiratoryRate             Usage_i16(0x4bb)
+#define Usage_Sen_DataFieldSpO2                        Usage_i16(0x4bc)
+#define Usage_Sen_DataFieldHumanAttentionDetected      Usage_i16(0x4bd)
+#define Usage_Sen_DataFieldHumanHeadAzimuth            Usage_i16(0x4be)
+#define Usage_Sen_DataFieldHumanHeadAltitude           Usage_i16(0x4bf)
+#define Usage_Sen_DataFieldHumanHeadRoll               Usage_i16(0x4c0)
+#define Usage_Sen_DataFieldHumanHeadPitch              Usage_i16(0x4c1)
+#define Usage_Sen_DataFieldHumanHeadYaw                Usage_i16(0x4c2)
+#define Usage_Sen_DataFieldHumanCorrelationId          Usage_i16(0x4c3)
+#define Usage_Sen_DataFieldLight                       Usage_i16(0x4d0)
+#define Usage_Sen_DataFieldIlluminance                 Usage_i16(0x4d1)
+#define Usage_Sen_DataFieldColorTemperature            Usage_i16(0x4d2)
+#define Usage_Sen_DataFieldChromaticity                Usage_i16(0x4d3)
+#define Usage_Sen_DataFieldChromaticityX               Usage_i16(0x4d4)
+#define Usage_Sen_DataFieldChromaticityY               Usage_i16(0x4d5)
+#define Usage_Sen_DataFieldConsumerIRSentenceReceive   Usage_i16(0x4d6)
+#define Usage_Sen_DataFieldInfraredLight               Usage_i16(0x4d7)
+#define Usage_Sen_DataFieldRedLight                    Usage_i16(0x4d8)
+#define Usage_Sen_DataFieldGreenLight                  Usage_i16(0x4d9)
+#define Usage_Sen_DataFieldBlueLight                   Usage_i16(0x4da)
+#define Usage_Sen_DataFieldUltravioletALight           Usage_i16(0x4db)
+#define Usage_Sen_DataFieldUltravioletBLight           Usage_i16(0x4dc)
+#define Usage_Sen_DataFieldUltravioletIndex            Usage_i16(0x4dd)
+#define Usage_Sen_DataFieldNearInfraredLight           Usage_i16(0x4de)
+#define Usage_Sen_PropertyLight                        Usage_i16(0x4df)
+#define Usage_Sen_PropertyConsumerIRSentenceSend       Usage_i16(0x4e0)
+#define Usage_Sen_PropertyAutoBrightnessPreferred      Usage_i16(0x4e2)
+#define Usage_Sen_PropertyAutoColorPreferred           Usage_i16(0x4e3)
+#define Usage_Sen_DataFieldScanner                     Usage_i16(0x4f0)
+#define Usage_Sen_DataFieldRFIDTag40Bit                Usage_i16(0x4f1)
+#define Usage_Sen_DataFieldNFCSentenceReceive          Usage_i16(0x4f2)
+#define Usage_Sen_PropertyScanner                      Usage_i16(0x4f8)
+#define Usage_Sen_PropertyNFCSentenceSend              Usage_i16(0x4f9)
+#define Usage_Sen_DataFieldElectrical                  Usage_i16(0x500)
+#define Usage_Sen_DataFieldCapacitance                 Usage_i16(0x501)
+#define Usage_Sen_DataFieldCurrent                     Usage_i16(0x502)
+#define Usage_Sen_DataFieldElectricalPower             Usage_i16(0x503)
+#define Usage_Sen_DataFieldInductance                  Usage_i16(0x504)
+#define Usage_Sen_DataFieldResistance                  Usage_i16(0x505)
+#define Usage_Sen_DataFieldVoltage                     Usage_i16(0x506)
+#define Usage_Sen_DataFieldFrequency                   Usage_i16(0x507)
+#define Usage_Sen_DataFieldPeriod                      Usage_i16(0x508)
+#define Usage_Sen_DataFieldPercentofRange              Usage_i16(0x509)
+#define Usage_Sen_DataFieldTime                        Usage_i16(0x520)
+#define Usage_Sen_DataFieldYear                        Usage_i16(0x521)
+#define Usage_Sen_DataFieldMonth                       Usage_i16(0x522)
+#define Usage_Sen_DataFieldDay                         Usage_i16(0x523)
+#define Usage_Sen_DataFieldDayofWeek                   Usage_i16(0x524)
+#define Usage_Sen_DataFieldHour                        Usage_i16(0x525)
+#define Usage_Sen_DataFieldMinute                      Usage_i16(0x526)
+#define Usage_Sen_DataFieldSecond                      Usage_i16(0x527)
+#define Usage_Sen_DataFieldMillisecond                 Usage_i16(0x528)
+#define Usage_Sen_DataFieldTimestamp                   Usage_i16(0x529)
+#define Usage_Sen_DataFieldJulianDayofYear             Usage_i16(0x52a)
+#define Usage_Sen_DataFieldTimeSinceSystemBoot         Usage_i16(0x52b)
+#define Usage_Sen_PropertyTime                         Usage_i16(0x530)
+#define Usage_Sen_PropertyTimeZoneOffsetfromUTC        Usage_i16(0x531)
+#define Usage_Sen_PropertyTimeZoneName                 Usage_i16(0x532)
+#define Usage_Sen_PropertyDaylightSavingsTimeObserved  Usage_i16(0x533)
+#define Usage_Sen_PropertyTimeTrimAdjustment           Usage_i16(0x534)
+#define Usage_Sen_PropertyArmAlarm                     Usage_i16(0x535)
+#define Usage_Sen_DataFieldCustom                      Usage_i16(0x540)
+#define Usage_Sen_DataFieldCustomUsage                 Usage_i16(0x541)
+#define Usage_Sen_DataFieldCustomBooleanArray          Usage_i16(0x542)
+#define Usage_Sen_DataFieldCustomValue                 Usage_i16(0x543)
+#define Usage_Sen_DataFieldCustomValue1                Usage_i16(0x544)
+#define Usage_Sen_DataFieldCustomValue2                Usage_i16(0x545)
+#define Usage_Sen_DataFieldCustomValue3                Usage_i16(0x546)
+#define Usage_Sen_DataFieldCustomValue4                Usage_i16(0x547)
+#define Usage_Sen_DataFieldCustomValue5                Usage_i16(0x548)
+#define Usage_Sen_DataFieldCustomValue6                Usage_i16(0x549)
+#define Usage_Sen_DataFieldCustomValue7                Usage_i16(0x54a)
+#define Usage_Sen_DataFieldCustomValue8                Usage_i16(0x54b)
+#define Usage_Sen_DataFieldCustomValue9                Usage_i16(0x54c)
+#define Usage_Sen_DataFieldCustomValue10               Usage_i16(0x54d)
+#define Usage_Sen_DataFieldCustomValue11               Usage_i16(0x54e)
+#define Usage_Sen_DataFieldCustomValue12               Usage_i16(0x54f)
+#define Usage_Sen_DataFieldCustomValue13               Usage_i16(0x550)
+#define Usage_Sen_DataFieldCustomValue14               Usage_i16(0x551)
+#define Usage_Sen_DataFieldCustomValue15               Usage_i16(0x552)
+#define Usage_Sen_DataFieldCustomValue16               Usage_i16(0x553)
+#define Usage_Sen_DataFieldCustomValue17               Usage_i16(0x554)
+#define Usage_Sen_DataFieldCustomValue18               Usage_i16(0x555)
+#define Usage_Sen_DataFieldCustomValue19               Usage_i16(0x556)
+#define Usage_Sen_DataFieldCustomValue20               Usage_i16(0x557)
+#define Usage_Sen_DataFieldCustomValue21               Usage_i16(0x558)
+#define Usage_Sen_DataFieldCustomValue22               Usage_i16(0x559)
+#define Usage_Sen_DataFieldCustomValue23               Usage_i16(0x55a)
+#define Usage_Sen_DataFieldCustomValue24               Usage_i16(0x55b)
+#define Usage_Sen_DataFieldCustomValue25               Usage_i16(0x55c)
+#define Usage_Sen_DataFieldCustomValue26               Usage_i16(0x55d)
+#define Usage_Sen_DataFieldCustomValue27               Usage_i16(0x55e)
+#define Usage_Sen_DataFieldCustomValue28               Usage_i16(0x55f)
+#define Usage_Sen_DataFieldGeneric                     Usage_i16(0x560)
+#define Usage_Sen_DataFieldGenericGUIDorPROPERTYKEY    Usage_i16(0x561)
+#define Usage_Sen_DataFieldGenericCategoryGUID         Usage_i16(0x562)
+#define Usage_Sen_DataFieldGenericTypeGUID             Usage_i16(0x563)
+#define Usage_Sen_DataFieldGenericEventPROPERTYKEY     Usage_i16(0x564)
+#define Usage_Sen_DataFieldGenericPropertyPROPERTYKEY  Usage_i16(0x565)
+#define Usage_Sen_DataFieldGenericDataFieldPROPERTYKEY Usage_i16(0x566)
+#define Usage_Sen_DataFieldGenericEvent                Usage_i16(0x567)
+#define Usage_Sen_DataFieldGenericProperty             Usage_i16(0x568)
+#define Usage_Sen_DataFieldGenericDataField            Usage_i16(0x569)
+#define Usage_Sen_DataFieldEnumeratorTableRowIndex     Usage_i16(0x56a)
+#define Usage_Sen_DataFieldEnumeratorTableRowCount     Usage_i16(0x56b)
+#define Usage_Sen_DataFieldGenericGUIDorPROPERTYKEYkind Usage_i16(0x56c)
+#define Usage_Sen_DataFieldGenericGUID                 Usage_i16(0x56d)
+#define Usage_Sen_DataFieldGenericPROPERTYKEY          Usage_i16(0x56e)
+#define Usage_Sen_DataFieldGenericTopLevelCollectionID Usage_i16(0x56f)
+#define Usage_Sen_DataFieldGenericReportID             Usage_i16(0x570)
+#define Usage_Sen_DataFieldGenericReportItemPositionIndex Usage_i16(0x571)
+#define Usage_Sen_DataFieldGenericFirmwareVARTYPE      Usage_i16(0x572)
+#define Usage_Sen_DataFieldGenericUnitofMeasure        Usage_i16(0x573)
+#define Usage_Sen_DataFieldGenericUnitExponent         Usage_i16(0x574)
+#define Usage_Sen_DataFieldGenericReportSize           Usage_i16(0x575)
+#define Usage_Sen_DataFieldGenericReportCount          Usage_i16(0x576)
+#define Usage_Sen_PropertyGeneric                      Usage_i16(0x580)
+#define Usage_Sen_PropertyEnumeratorTableRowIndex      Usage_i16(0x581)
+#define Usage_Sen_PropertyEnumeratorTableRowCount      Usage_i16(0x582)
+#define Usage_Sen_DataFieldPersonalActivity            Usage_i16(0x590)
+#define Usage_Sen_DataFieldActivityType                Usage_i16(0x591)
+#define Usage_Sen_DataFieldActivityState               Usage_i16(0x592)
+#define Usage_Sen_DataFieldDevicePosition              Usage_i16(0x593)
+#define Usage_Sen_DataFieldStepCount                   Usage_i16(0x594)
+#define Usage_Sen_DataFieldStepCountReset              Usage_i16(0x595)
+#define Usage_Sen_DataFieldStepDuration                Usage_i16(0x596)
+#define Usage_Sen_DataFieldStepType                    Usage_i16(0x597)
+#define Usage_Sen_PropertyMinimumActivityDetectionInterval Usage_i16(0x5a0)
+#define Usage_Sen_PropertySupportedActivityTypes       Usage_i16(0x5a1)
+#define Usage_Sen_PropertySubscribedActivityTypes      Usage_i16(0x5a2)
+#define Usage_Sen_PropertySupportedStepTypes           Usage_i16(0x5a3)
+#define Usage_Sen_PropertySubscribedStepTypes          Usage_i16(0x5a4)
+#define Usage_Sen_PropertyFloorHeight                  Usage_i16(0x5a5)
+#define Usage_Sen_DataFieldCustomTypeID                Usage_i16(0x5b0)
+#define Usage_Sen_PropertyCustom                       Usage_i16(0x5c0)
+#define Usage_Sen_PropertyCustomValue1                 Usage_i16(0x5c1)
+#define Usage_Sen_PropertyCustomValue2                 Usage_i16(0x5c2)
+#define Usage_Sen_PropertyCustomValue3                 Usage_i16(0x5c3)
+#define Usage_Sen_PropertyCustomValue4                 Usage_i16(0x5c4)
+#define Usage_Sen_PropertyCustomValue5                 Usage_i16(0x5c5)
+#define Usage_Sen_PropertyCustomValue6                 Usage_i16(0x5c6)
+#define Usage_Sen_PropertyCustomValue7                 Usage_i16(0x5c7)
+#define Usage_Sen_PropertyCustomValue8                 Usage_i16(0x5c8)
+#define Usage_Sen_PropertyCustomValue9                 Usage_i16(0x5c9)
+#define Usage_Sen_PropertyCustomValue10                Usage_i16(0x5ca)
+#define Usage_Sen_PropertyCustomValue11                Usage_i16(0x5cb)
+#define Usage_Sen_PropertyCustomValue12                Usage_i16(0x5cc)
+#define Usage_Sen_PropertyCustomValue13                Usage_i16(0x5cd)
+#define Usage_Sen_PropertyCustomValue14                Usage_i16(0x5ce)
+#define Usage_Sen_PropertyCustomValue15                Usage_i16(0x5cf)
+#define Usage_Sen_PropertyCustomValue16                Usage_i16(0x5d0)
+#define Usage_Sen_DataFieldHinge                       Usage_i16(0x5e0)
+#define Usage_Sen_DataFieldHingeAngle                  Usage_i16(0x5e1)
+#define Usage_Sen_DataFieldGestureSensor               Usage_i16(0x5f0)
+#define Usage_Sen_DataFieldGestureState                Usage_i16(0x5f1)
+#define Usage_Sen_DataFieldHingeFoldInitialAngle       Usage_i16(0x5f2)
+#define Usage_Sen_DataFieldHingeFoldFinalAngle         Usage_i16(0x5f3)
+#define Usage_Sen_DataFieldHingeFoldContributingPanel  Usage_i16(0x5f4)
+#define Usage_Sen_DataFieldHingeFoldType               Usage_i16(0x5f5)
+#define Usage_Sen_SensorStateUndefined                 Usage_i16(0x800)
+#define Usage_Sen_SensorStateReady                     Usage_i16(0x801)
+#define Usage_Sen_SensorStateNotAvailable              Usage_i16(0x802)
+#define Usage_Sen_SensorStateNoData                    Usage_i16(0x803)
+#define Usage_Sen_SensorStateInitializing              Usage_i16(0x804)
+#define Usage_Sen_SensorStateAccessDenied              Usage_i16(0x805)
+#define Usage_Sen_SensorStateError                     Usage_i16(0x806)
+#define Usage_Sen_SensorEventUnknown                   Usage_i16(0x810)
+#define Usage_Sen_SensorEventStateChanged              Usage_i16(0x811)
+#define Usage_Sen_SensorEventPropertyChanged           Usage_i16(0x812)
+#define Usage_Sen_SensorEventDataUpdated               Usage_i16(0x813)
+#define Usage_Sen_SensorEventPollResponse              Usage_i16(0x814)
+#define Usage_Sen_SensorEventChangeSensitivity         Usage_i16(0x815)
+#define Usage_Sen_SensorEventRangeMaximumReached       Usage_i16(0x816)
+#define Usage_Sen_SensorEventRangeMinimumReached       Usage_i16(0x817)
+#define Usage_Sen_SensorEventHighThresholdCrossUpward  Usage_i16(0x818)
+#define Usage_Sen_SensorEventHighThresholdCrossDownward Usage_i16(0x819)
+#define Usage_Sen_SensorEventLowThresholdCrossUpward   Usage_i16(0x81a)
+#define Usage_Sen_SensorEventLowThresholdCrossDownward Usage_i16(0x81b)
+#define Usage_Sen_SensorEventZeroThresholdCrossUpward  Usage_i16(0x81c)
+#define Usage_Sen_SensorEventZeroThresholdCrossDownward Usage_i16(0x81d)
+#define Usage_Sen_SensorEventPeriodExceeded            Usage_i16(0x81e)
+#define Usage_Sen_SensorEventFrequencyExceeded         Usage_i16(0x81f)
+#define Usage_Sen_SensorEventComplexTrigger            Usage_i16(0x820)
+#define Usage_Sen_ConnectionTypePCIntegrated           Usage_i16(0x830)
+#define Usage_Sen_ConnectionTypePCAttached             Usage_i16(0x831)
+#define Usage_Sen_ConnectionTypePCExternal             Usage_i16(0x832)
+#define Usage_Sen_ReportingStateReportNoEvents         Usage_i16(0x840)
+#define Usage_Sen_ReportingStateReportAllEvents        Usage_i16(0x841)
+#define Usage_Sen_ReportingStateReportThresholdEvents  Usage_i16(0x842)
+#define Usage_Sen_ReportingStateWakeOnNoEvents         Usage_i16(0x843)
+#define Usage_Sen_ReportingStateWakeOnAllEvents        Usage_i16(0x844)
+#define Usage_Sen_ReportingStateWakeOnThresholdEvents  Usage_i16(0x845)
+#define Usage_Sen_ReportingStateAnytime                Usage_i16(0x846)
+#define Usage_Sen_PowerStateUndefined                  Usage_i16(0x850)
+#define Usage_Sen_PowerStateD0FullPower                Usage_i16(0x851)
+#define Usage_Sen_PowerStateD1LowPower                 Usage_i16(0x852)
+#define Usage_Sen_PowerStateD2StandbyPowerwithWakeup   Usage_i16(0x853)
+#define Usage_Sen_PowerStateD3SleepwithWakeup          Usage_i16(0x854)
+#define Usage_Sen_PowerStateD4PowerOff                 Usage_i16(0x855)
+#define Usage_Sen_AccuracyDefault                      Usage_i16(0x860)
+#define Usage_Sen_AccuracyHigh                         Usage_i16(0x861)
+#define Usage_Sen_AccuracyMedium                       Usage_i16(0x862)
+#define Usage_Sen_AccuracyLow                          Usage_i16(0x863)
+#define Usage_Sen_FixQualityNoFix                      Usage_i16(0x870)
+#define Usage_Sen_FixQualityGPS                        Usage_i16(0x871)
+#define Usage_Sen_FixQualityDGPS                       Usage_i16(0x872)
+#define Usage_Sen_FixTypeNoFix                         Usage_i16(0x880)
+#define Usage_Sen_FixTypeGPSSPSModeFixValid            Usage_i16(0x881)
+#define Usage_Sen_FixTypeDGPSSPSModeFixValid           Usage_i16(0x882)
+#define Usage_Sen_FixTypeGPSPPSModeFixValid            Usage_i16(0x883)
+#define Usage_Sen_FixTypeRealTimeKinematic             Usage_i16(0x884)
+#define Usage_Sen_FixTypeFloatRTK                      Usage_i16(0x885)
+#define Usage_Sen_FixTypeEstimateddeadreckoned         Usage_i16(0x886)
+#define Usage_Sen_FixTypeManualInputMode               Usage_i16(0x887)
+#define Usage_Sen_FixTypeSimulatorMode                 Usage_i16(0x888)
+#define Usage_Sen_GPSOperationModeManual               Usage_i16(0x890)
+#define Usage_Sen_GPSOperationModeAutomatic            Usage_i16(0x891)
+#define Usage_Sen_GPSSelectionModeAutonomous           Usage_i16(0x8a0)
+#define Usage_Sen_GPSSelectionModeDGPS                 Usage_i16(0x8a1)
+#define Usage_Sen_GPSSelectionModeEstimateddeadreckoned Usage_i16(0x8a2)
+#define Usage_Sen_GPSSelectionModeManualInput          Usage_i16(0x8a3)
+#define Usage_Sen_GPSSelectionModeSimulator            Usage_i16(0x8a4)
+#define Usage_Sen_GPSSelectionModeDataNotValid         Usage_i16(0x8a5)
+#define Usage_Sen_GPSStatusDataValid                   Usage_i16(0x8b0)
+#define Usage_Sen_GPSStatusDataNotValid                Usage_i16(0x8b1)
+#define Usage_Sen_DayofWeekSunday                      Usage_i16(0x8c0)
+#define Usage_Sen_DayofWeekMonday                      Usage_i16(0x8c1)
+#define Usage_Sen_DayofWeekTuesday                     Usage_i16(0x8c2)
+#define Usage_Sen_DayofWeekWednesday                   Usage_i16(0x8c3)
+#define Usage_Sen_DayofWeekThursday                    Usage_i16(0x8c4)
+#define Usage_Sen_DayofWeekFriday                      Usage_i16(0x8c5)
+#define Usage_Sen_DayofWeekSaturday                    Usage_i16(0x8c6)
+#define Usage_Sen_KindCategory                         Usage_i16(0x8d0)
+#define Usage_Sen_KindType                             Usage_i16(0x8d1)
+#define Usage_Sen_KindEvent                            Usage_i16(0x8d2)
+#define Usage_Sen_KindProperty                         Usage_i16(0x8d3)
+#define Usage_Sen_KindDataField                        Usage_i16(0x8d4)
+#define Usage_Sen_MagnetometerAccuracyLow              Usage_i16(0x8e0)
+#define Usage_Sen_MagnetometerAccuracyMedium           Usage_i16(0x8e1)
+#define Usage_Sen_MagnetometerAccuracyHigh             Usage_i16(0x8e2)
+#define Usage_Sen_SimpleOrientationDirectionNotRotated Usage_i16(0x8f0)
+#define Usage_Sen_SimpleOrientationDirectionRotated90DegreesCCW Usage_i16(0x8f1)
+#define Usage_Sen_SimpleOrientationDirectionRotated180DegreesCCW Usage_i16(0x8f2)
+#define Usage_Sen_SimpleOrientationDirectionRotated270DegreesCCW Usage_i16(0x8f3)
+#define Usage_Sen_SimpleOrientationDirectionFaceUp     Usage_i16(0x8f4)
+#define Usage_Sen_SimpleOrientationDirectionFaceDown   Usage_i16(0x8f5)
+#define Usage_Sen_VT_NULL                              Usage_i16(0x900)
+#define Usage_Sen_VT_BOOL                              Usage_i16(0x901)
+#define Usage_Sen_VT_UI1                               Usage_i16(0x902)
+#define Usage_Sen_VT_I1                                Usage_i16(0x903)
+#define Usage_Sen_VT_UI2                               Usage_i16(0x904)
+#define Usage_Sen_VT_I2                                Usage_i16(0x905)
+#define Usage_Sen_VT_UI4                               Usage_i16(0x906)
+#define Usage_Sen_VT_I4                                Usage_i16(0x907)
+#define Usage_Sen_VT_UI8                               Usage_i16(0x908)
+#define Usage_Sen_VT_I8                                Usage_i16(0x909)
+#define Usage_Sen_VT_R4                                Usage_i16(0x90a)
+#define Usage_Sen_VT_R8                                Usage_i16(0x90b)
+#define Usage_Sen_VT_WSTR                              Usage_i16(0x90c)
+#define Usage_Sen_VT_STR                               Usage_i16(0x90d)
+#define Usage_Sen_VT_CLSID                             Usage_i16(0x90e)
+#define Usage_Sen_VT_VECTORVT_UI1                      Usage_i16(0x90f)
+#define Usage_Sen_VT_F16E0                             Usage_i16(0x910)
+#define Usage_Sen_VT_F16E1                             Usage_i16(0x911)
+#define Usage_Sen_VT_F16E2                             Usage_i16(0x912)
+#define Usage_Sen_VT_F16E3                             Usage_i16(0x913)
+#define Usage_Sen_VT_F16E4                             Usage_i16(0x914)
+#define Usage_Sen_VT_F16E5                             Usage_i16(0x915)
+#define Usage_Sen_VT_F16E6                             Usage_i16(0x916)
+#define Usage_Sen_VT_F16E7                             Usage_i16(0x917)
+#define Usage_Sen_VT_F16E8                             Usage_i16(0x918)
+#define Usage_Sen_VT_F16E9                             Usage_i16(0x919)
+#define Usage_Sen_VT_F16EA                             Usage_i16(0x91a)
+#define Usage_Sen_VT_F16EB                             Usage_i16(0x91b)
+#define Usage_Sen_VT_F16EC                             Usage_i16(0x91c)
+#define Usage_Sen_VT_F16ED                             Usage_i16(0x91d)
+#define Usage_Sen_VT_F16EE                             Usage_i16(0x91e)
+#define Usage_Sen_VT_F16EF                             Usage_i16(0x91f)
+#define Usage_Sen_VT_F32E0                             Usage_i16(0x920)
+#define Usage_Sen_VT_F32E1                             Usage_i16(0x921)
+#define Usage_Sen_VT_F32E2                             Usage_i16(0x922)
+#define Usage_Sen_VT_F32E3                             Usage_i16(0x923)
+#define Usage_Sen_VT_F32E4                             Usage_i16(0x924)
+#define Usage_Sen_VT_F32E5                             Usage_i16(0x925)
+#define Usage_Sen_VT_F32E6                             Usage_i16(0x926)
+#define Usage_Sen_VT_F32E7                             Usage_i16(0x927)
+#define Usage_Sen_VT_F32E8                             Usage_i16(0x928)
+#define Usage_Sen_VT_F32E9                             Usage_i16(0x929)
+#define Usage_Sen_VT_F32EA                             Usage_i16(0x92a)
+#define Usage_Sen_VT_F32EB                             Usage_i16(0x92b)
+#define Usage_Sen_VT_F32EC                             Usage_i16(0x92c)
+#define Usage_Sen_VT_F32ED                             Usage_i16(0x92d)
+#define Usage_Sen_VT_F32EE                             Usage_i16(0x92e)
+#define Usage_Sen_VT_F32EF                             Usage_i16(0x92f)
+#define Usage_Sen_ActivityTypeUnknown                  Usage_i16(0x930)
+#define Usage_Sen_ActivityTypeStationary               Usage_i16(0x931)
+#define Usage_Sen_ActivityTypeFidgeting                Usage_i16(0x932)
+#define Usage_Sen_ActivityTypeWalking                  Usage_i16(0x933)
+#define Usage_Sen_ActivityTypeRunning                  Usage_i16(0x934)
+#define Usage_Sen_ActivityTypeInVehicle                Usage_i16(0x935)
+#define Usage_Sen_ActivityTypeBiking                   Usage_i16(0x936)
+#define Usage_Sen_ActivityTypeIdle                     Usage_i16(0x937)
+#define Usage_Sen_UnitNotSpecified                     Usage_i16(0x940)
+#define Usage_Sen_UnitLux                              Usage_i16(0x941)
+#define Usage_Sen_UnitDegreesKelvin                    Usage_i16(0x942)
+#define Usage_Sen_UnitDegreesCelsius                   Usage_i16(0x943)
+#define Usage_Sen_UnitPascal                           Usage_i16(0x944)
+#define Usage_Sen_UnitNewton                           Usage_i16(0x945)
+#define Usage_Sen_UnitMetersSecond                     Usage_i16(0x946)
+#define Usage_Sen_UnitKilogram                         Usage_i16(0x947)
+#define Usage_Sen_UnitMeter                            Usage_i16(0x948)
+#define Usage_Sen_UnitMetersSecondSecond               Usage_i16(0x949)
+#define Usage_Sen_UnitFarad                            Usage_i16(0x94a)
+#define Usage_Sen_UnitAmpere                           Usage_i16(0x94b)
+#define Usage_Sen_UnitWatt                             Usage_i16(0x94c)
+#define Usage_Sen_UnitHenry                            Usage_i16(0x94d)
+#define Usage_Sen_UnitOhm                              Usage_i16(0x94e)
+#define Usage_Sen_UnitVolt                             Usage_i16(0x94f)
+#define Usage_Sen_UnitHertz                            Usage_i16(0x950)
+#define Usage_Sen_UnitBar                              Usage_i16(0x951)
+#define Usage_Sen_UnitDegreesAnticlockwise             Usage_i16(0x952)
+#define Usage_Sen_UnitDegreesClockwise                 Usage_i16(0x953)
+#define Usage_Sen_UnitDegrees                          Usage_i16(0x954)
+#define Usage_Sen_UnitDegreesSecond                    Usage_i16(0x955)
+#define Usage_Sen_UnitDegreesSecondSecond              Usage_i16(0x956)
+#define Usage_Sen_UnitKnot                             Usage_i16(0x957)
+#define Usage_Sen_UnitPercent                          Usage_i16(0x958)
+#define Usage_Sen_UnitSecond                           Usage_i16(0x959)
+#define Usage_Sen_UnitMillisecond                      Usage_i16(0x95a)
+#define Usage_Sen_UnitG                                Usage_i16(0x95b)
+#define Usage_Sen_UnitBytes                            Usage_i16(0x95c)
+#define Usage_Sen_UnitMilligauss                       Usage_i16(0x95d)
+#define Usage_Sen_UnitBits                             Usage_i16(0x95e)
+#define Usage_Sen_ActivityStateNoStateChange           Usage_i16(0x960)
+#define Usage_Sen_ActivityStateStartActivity           Usage_i16(0x961)
+#define Usage_Sen_ActivityStateEndActivity             Usage_i16(0x962)
+#define Usage_Sen_Exponent0                            Usage_i16(0x970)
+#define Usage_Sen_Exponent1                            Usage_i16(0x971)
+#define Usage_Sen_Exponent2                            Usage_i16(0x972)
+#define Usage_Sen_Exponent3                            Usage_i16(0x973)
+#define Usage_Sen_Exponent4                            Usage_i16(0x974)
+#define Usage_Sen_Exponent5                            Usage_i16(0x975)
+#define Usage_Sen_Exponent6                            Usage_i16(0x976)
+#define Usage_Sen_Exponent7                            Usage_i16(0x977)
+#define Usage_Sen_Exponent8                            Usage_i16(0x978)
+#define Usage_Sen_Exponent9                            Usage_i16(0x979)
+#define Usage_Sen_ExponentA                            Usage_i16(0x97a)
+#define Usage_Sen_ExponentB                            Usage_i16(0x97b)
+#define Usage_Sen_ExponentC                            Usage_i16(0x97c)
+#define Usage_Sen_ExponentD                            Usage_i16(0x97d)
+#define Usage_Sen_ExponentE                            Usage_i16(0x97e)
+#define Usage_Sen_ExponentF                            Usage_i16(0x97f)
+#define Usage_Sen_DevicePositionUnknown                Usage_i16(0x980)
+#define Usage_Sen_DevicePositionUnchanged              Usage_i16(0x981)
+#define Usage_Sen_DevicePositionOnDesk                 Usage_i16(0x982)
+#define Usage_Sen_DevicePositionInHand                 Usage_i16(0x983)
+#define Usage_Sen_DevicePositionMovinginBag            Usage_i16(0x984)
+#define Usage_Sen_DevicePositionStationaryinBag        Usage_i16(0x985)
+#define Usage_Sen_StepTypeUnknown                      Usage_i16(0x990)
+#define Usage_Sen_StepTypeWalking                      Usage_i16(0x991)
+#define Usage_Sen_StepTypeRunning                      Usage_i16(0x992)
+#define Usage_Sen_GestureStateUnknown                  Usage_i16(0x9a0)
+#define Usage_Sen_GestureStateStarted                  Usage_i16(0x9a1)
+#define Usage_Sen_GestureStateCompleted                Usage_i16(0x9a2)
+#define Usage_Sen_GestureStateCancelled                Usage_i16(0x9a3)
+#define Usage_Sen_HingeFoldContributingPanelUnknown    Usage_i16(0x9b0)
+#define Usage_Sen_HingeFoldContributingPanelPanel1     Usage_i16(0x9b1)
+#define Usage_Sen_HingeFoldContributingPanelPanel2     Usage_i16(0x9b2)
+#define Usage_Sen_HingeFoldContributingPanelBoth       Usage_i16(0x9b3)
+#define Usage_Sen_HingeFoldTypeUnknown                 Usage_i16(0x9b4)
+#define Usage_Sen_HingeFoldTypeIncreasing              Usage_i16(0x9b5)
+#define Usage_Sen_HingeFoldTypeDecreasing              Usage_i16(0x9b6)
+#define Usage_Sen_HumanPresenceDetectionTypeVendorDefinedNonBiometric Usage_i16(0x9c0)
+#define Usage_Sen_HumanPresenceDetectionTypeVendorDefinedBiometric Usage_i16(0x9c1)
+#define Usage_Sen_HumanPresenceDetectionTypeFacialBiometric Usage_i16(0x9c2)
+#define Usage_Sen_HumanPresenceDetectionTypeAudioBiometric Usage_i16(0x9c3)
+#define Usage_Sen_ModifierChangeSensitivityAbsolute    Usage_i16(0x1000)
+#define Usage_Sen_ModifierMaximum                      Usage_i16(0x2000)
+#define Usage_Sen_ModifierMinimum                      Usage_i16(0x3000)
+#define Usage_Sen_ModifierAccuracy                     Usage_i16(0x4000)
+#define Usage_Sen_ModifierResolution                   Usage_i16(0x5000)
+#define Usage_Sen_ModifierThresholdHigh                Usage_i16(0x6000)
+#define Usage_Sen_ModifierThresholdLow                 Usage_i16(0x7000)
+#define Usage_Sen_ModifierCalibrationOffset            Usage_i16(0x8000)
+#define Usage_Sen_ModifierCalibrationMultiplier        Usage_i16(0x9000)
+#define Usage_Sen_ModifierReportInterval               Usage_i16(0xa000)
+#define Usage_Sen_ModifierFrequencyMax                 Usage_i16(0xb000)
+#define Usage_Sen_ModifierPeriodMax                    Usage_i16(0xc000)
+#define Usage_Sen_ModifierChangeSensitivityPercentofRange Usage_i16(0xd000)
+#define Usage_Sen_ModifierChangeSensitivityPercentRelative Usage_i16(0xe000)
+#define Usage_Sen_ModifierVendorReserved               Usage_i16(0xf000)
+#define Usage_MI_MedicalUltrasound                     Usage_i8(0x1)
+#define Usage_MI_VCRAcquisition                        Usage_i8(0x20)
+#define Usage_MI_FreezeThaw                            Usage_i8(0x21)
+#define Usage_MI_ClipStore                             Usage_i8(0x22)
+#define Usage_MI_Update                                Usage_i8(0x23)
+#define Usage_MI_Next                                  Usage_i8(0x24)
+#define Usage_MI_Save                                  Usage_i8(0x25)
+#define Usage_MI_Print                                 Usage_i8(0x26)
+#define Usage_MI_MicrophoneEnable                      Usage_i8(0x27)
+#define Usage_MI_Cine                                  Usage_i8(0x40)
+#define Usage_MI_TransmitPower                         Usage_i8(0x41)
+#define Usage_MI_Volume                                Usage_i8(0x42)
+#define Usage_MI_Focus                                 Usage_i8(0x43)
+#define Usage_MI_Depth                                 Usage_i8(0x44)
+#define Usage_MI_SoftStepPrimary                       Usage_i8(0x60)
+#define Usage_MI_SoftStepSecondary                     Usage_i8(0x61)
+#define Usage_MI_DepthGainCompensation                 Usage_i8(0x70)
+#define Usage_MI_ZoomSelect                            Usage_i8(0x80)
+#define Usage_MI_ZoomAdjust                            Usage_i8(0x81)
+#define Usage_MI_SpectralDopplerModeSelect             Usage_i8(0x82)
+#define Usage_MI_SpectralDopplerAdjust                 Usage_i8(0x83)
+#define Usage_MI_ColorDopplerModeSelect                Usage_i8(0x84)
+#define Usage_MI_ColorDopplerAdjust                    Usage_i8(0x85)
+#define Usage_MI_MotionModeSelect                      Usage_i8(0x86)
+#define Usage_MI_MotionModeAdjust                      Usage_i8(0x87)
+#define Usage_MI_TwoDModeSelect                        Usage_i8(0x88)
+#define Usage_MI_TwoDModeAdjust                        Usage_i8(0x89)
+#define Usage_MI_SoftControlSelect                     Usage_i8(0xa0)
+#define Usage_MI_SoftControlAdjust                     Usage_i8(0xa1)
+#define Usage_BD_BrailleDisplay                        Usage_i8(0x1)
+#define Usage_BD_BrailleRow                            Usage_i8(0x2)
+#define Usage_BD_EightDotBrailleCell                   Usage_i8(0x3)
+#define Usage_BD_SixDotBrailleCell                     Usage_i8(0x4)
+#define Usage_BD_NumberofBrailleCells                  Usage_i8(0x5)
+#define Usage_BD_ScreenReaderControl                   Usage_i8(0x6)
+#define Usage_BD_ScreenReaderIdentifier                Usage_i8(0x7)
+#define Usage_BD_RouterSet1                            Usage_i8(0xfa)
+#define Usage_BD_RouterSet2                            Usage_i8(0xfb)
+#define Usage_BD_RouterSet3                            Usage_i8(0xfc)
+#define Usage_BD_RouterKey                             Usage_i16(0x100)
+#define Usage_BD_RowRouterKey                          Usage_i16(0x101)
+#define Usage_BD_BrailleButtons                        Usage_i16(0x200)
+#define Usage_BD_BrailleKeyboardDot1                   Usage_i16(0x201)
+#define Usage_BD_BrailleKeyboardDot2                   Usage_i16(0x202)
+#define Usage_BD_BrailleKeyboardDot3                   Usage_i16(0x203)
+#define Usage_BD_BrailleKeyboardDot4                   Usage_i16(0x204)
+#define Usage_BD_BrailleKeyboardDot5                   Usage_i16(0x205)
+#define Usage_BD_BrailleKeyboardDot6                   Usage_i16(0x206)
+#define Usage_BD_BrailleKeyboardDot7                   Usage_i16(0x207)
+#define Usage_BD_BrailleKeyboardDot8                   Usage_i16(0x208)
+#define Usage_BD_BrailleKeyboardSpace                  Usage_i16(0x209)
+#define Usage_BD_BrailleKeyboardLeftSpace              Usage_i16(0x20a)
+#define Usage_BD_BrailleKeyboardRightSpace             Usage_i16(0x20b)
+#define Usage_BD_BrailleFaceControls                   Usage_i16(0x20c)
+#define Usage_BD_BrailleLeftControls                   Usage_i16(0x20d)
+#define Usage_BD_BrailleRightControls                  Usage_i16(0x20e)
+#define Usage_BD_BrailleTopControls                    Usage_i16(0x20f)
+#define Usage_BD_BrailleJoystickCenter                 Usage_i16(0x210)
+#define Usage_BD_BrailleJoystickUp                     Usage_i16(0x211)
+#define Usage_BD_BrailleJoystickDown                   Usage_i16(0x212)
+#define Usage_BD_BrailleJoystickLeft                   Usage_i16(0x213)
+#define Usage_BD_BrailleJoystickRight                  Usage_i16(0x214)
+#define Usage_BD_BrailleDPadCenter                     Usage_i16(0x215)
+#define Usage_BD_BrailleDPadUp                         Usage_i16(0x216)
+#define Usage_BD_BrailleDPadDown                       Usage_i16(0x217)
+#define Usage_BD_BrailleDPadLeft                       Usage_i16(0x218)
+#define Usage_BD_BrailleDPadRight                      Usage_i16(0x219)
+#define Usage_BD_BraillePanLeft                        Usage_i16(0x21a)
+#define Usage_BD_BraillePanRight                       Usage_i16(0x21b)
+#define Usage_BD_BrailleRockerUp                       Usage_i16(0x21c)
+#define Usage_BD_BrailleRockerDown                     Usage_i16(0x21d)
+#define Usage_BD_BrailleRockerPress                    Usage_i16(0x21e)
+#define Usage_LAI_LampArray                            Usage_i8(0x1)
+#define Usage_LAI_LampArrayAttributesReport            Usage_i8(0x2)
+#define Usage_LAI_LampCount                            Usage_i8(0x3)
+#define Usage_LAI_BoundingBoxWidthInMicrometers        Usage_i8(0x4)
+#define Usage_LAI_BoundingBoxHeightInMicrometers       Usage_i8(0x5)
+#define Usage_LAI_BoundingBoxDepthInMicrometers        Usage_i8(0x6)
+#define Usage_LAI_LampArrayKind                        Usage_i8(0x7)
+#define Usage_LAI_MinUpdateIntervalInMicroseconds      Usage_i8(0x8)
+#define Usage_LAI_LampAttributesRequestReport          Usage_i8(0x20)
+#define Usage_LAI_LampId                               Usage_i8(0x21)
+#define Usage_LAI_LampAttributesResponseReport         Usage_i8(0x22)
+#define Usage_LAI_PositionXInMicrometers               Usage_i8(0x23)
+#define Usage_LAI_PositionYInMicrometers               Usage_i8(0x24)
+#define Usage_LAI_PositionZInMicrometers               Usage_i8(0x25)
+#define Usage_LAI_LampPurposes                         Usage_i8(0x26)
+#define Usage_LAI_UpdateLatencyInMicroseconds          Usage_i8(0x27)
+#define Usage_LAI_RedLevelCount                        Usage_i8(0x28)
+#define Usage_LAI_GreenLevelCount                      Usage_i8(0x29)
+#define Usage_LAI_BlueLevelCount                       Usage_i8(0x2a)
+#define Usage_LAI_IntensityLevelCount                  Usage_i8(0x2b)
+#define Usage_LAI_IsProgrammable                       Usage_i8(0x2c)
+#define Usage_LAI_InputBinding                         Usage_i8(0x2d)
+#define Usage_LAI_LampMultiUpdateReport                Usage_i8(0x50)
+#define Usage_LAI_RedUpdateChannel                     Usage_i8(0x51)
+#define Usage_LAI_GreenUpdateChannel                   Usage_i8(0x52)
+#define Usage_LAI_BlueUpdateChannel                    Usage_i8(0x53)
+#define Usage_LAI_IntensityUpdateChannel               Usage_i8(0x54)
+#define Usage_LAI_LampUpdateFlags                      Usage_i8(0x55)
+#define Usage_LAI_LampRangeUpdateReport                Usage_i8(0x60)
+#define Usage_LAI_LampIdStart                          Usage_i8(0x61)
+#define Usage_LAI_LampIdEnd                            Usage_i8(0x62)
+#define Usage_LAI_LampArrayControlReport               Usage_i8(0x70)
+#define Usage_LAI_AutonomousMode                       Usage_i8(0x71)
+#define Usage_Mon_MonitorControl                       Usage_i8(0x1)
+#define Usage_Mon_EDIDInformation                      Usage_i8(0x2)
+#define Usage_Mon_VDIFInformation                      Usage_i8(0x3)
+#define Usage_Mon_VESAVersion                          Usage_i8(0x4)
+#define Usage_VESAVC_Degauss                           Usage_i8(0x1)
+#define Usage_VESAVC_Brightness                        Usage_i8(0x10)
+#define Usage_VESAVC_Contrast                          Usage_i8(0x12)
+#define Usage_VESAVC_RedVideoGain                      Usage_i8(0x16)
+#define Usage_VESAVC_GreenVideoGain                    Usage_i8(0x18)
+#define Usage_VESAVC_BlueVideoGain                     Usage_i8(0x1a)
+#define Usage_VESAVC_Focus                             Usage_i8(0x1c)
+#define Usage_VESAVC_HorizontalPosition                Usage_i8(0x20)
+#define Usage_VESAVC_HorizontalSize                    Usage_i8(0x22)
+#define Usage_VESAVC_HorizontalPincushion              Usage_i8(0x24)
+#define Usage_VESAVC_HorizontalPincushionBalance       Usage_i8(0x26)
+#define Usage_VESAVC_HorizontalMisconvergence          Usage_i8(0x28)
+#define Usage_VESAVC_HorizontalLinearity               Usage_i8(0x2a)
+#define Usage_VESAVC_HorizontalLinearityBalance        Usage_i8(0x2c)
+#define Usage_VESAVC_VerticalPosition                  Usage_i8(0x30)
+#define Usage_VESAVC_VerticalSize                      Usage_i8(0x32)
+#define Usage_VESAVC_VerticalPincushion                Usage_i8(0x34)
+#define Usage_VESAVC_VerticalPincushionBalance         Usage_i8(0x36)
+#define Usage_VESAVC_VerticalMisconvergence            Usage_i8(0x38)
+#define Usage_VESAVC_VerticalLinearity                 Usage_i8(0x3a)
+#define Usage_VESAVC_VerticalLinearityBalance          Usage_i8(0x3c)
+#define Usage_VESAVC_ParallelogramDistortionKeyBalance Usage_i8(0x40)
+#define Usage_VESAVC_TrapezoidalDistortionKey          Usage_i8(0x42)
+#define Usage_VESAVC_TiltRotation                      Usage_i8(0x44)
+#define Usage_VESAVC_TopCornerDistortionControl        Usage_i8(0x46)
+#define Usage_VESAVC_TopCornerDistortionBalance        Usage_i8(0x48)
+#define Usage_VESAVC_BottomCornerDistortionControl     Usage_i8(0x4a)
+#define Usage_VESAVC_BottomCornerDistortionBalance     Usage_i8(0x4c)
+#define Usage_VESAVC_HorizontalMoiré                   Usage_i8(0x56)
+#define Usage_VESAVC_VerticalMoiré                     Usage_i8(0x58)
+#define Usage_VESAVC_InputLevelSelect                  Usage_i8(0x5e)
+#define Usage_VESAVC_InputSourceSelect                 Usage_i8(0x60)
+#define Usage_VESAVC_RedVideoBlackLevel                Usage_i8(0x6c)
+#define Usage_VESAVC_GreenVideoBlackLevel              Usage_i8(0x6e)
+#define Usage_VESAVC_BlueVideoBlackLevel               Usage_i8(0x70)
+#define Usage_VESAVC_AutoSizeCenter                    Usage_i8(0xa2)
+#define Usage_VESAVC_PolarityHorizontalSynchronization Usage_i8(0xa4)
+#define Usage_VESAVC_PolarityVerticalSynchronization   Usage_i8(0xa6)
+#define Usage_VESAVC_SynchronizationType               Usage_i8(0xa8)
+#define Usage_VESAVC_ScreenOrientation                 Usage_i8(0xaa)
+#define Usage_VESAVC_HorizontalFrequency               Usage_i8(0xac)
+#define Usage_VESAVC_VerticalFrequency                 Usage_i8(0xae)
+#define Usage_VESAVC_Settings                          Usage_i8(0xb0)
+#define Usage_VESAVC_OnScreenDisplay                   Usage_i8(0xca)
+#define Usage_VESAVC_StereoMode                        Usage_i8(0xd4)
+#define Usage_Pow_iName                                Usage_i8(0x1)
+#define Usage_Pow_PresentStatus                        Usage_i8(0x2)
+#define Usage_Pow_ChangedStatus                        Usage_i8(0x3)
+#define Usage_Pow_UPS                                  Usage_i8(0x4)
+#define Usage_Pow_PowerSupply                          Usage_i8(0x5)
+#define Usage_Pow_BatterySystem                        Usage_i8(0x10)
+#define Usage_Pow_BatterySystemId                      Usage_i8(0x11)
+#define Usage_Pow_Battery                              Usage_i8(0x12)
+#define Usage_Pow_BatteryId                            Usage_i8(0x13)
+#define Usage_Pow_Charger                              Usage_i8(0x14)
+#define Usage_Pow_ChargerId                            Usage_i8(0x15)
+#define Usage_Pow_PowerConverter                       Usage_i8(0x16)
+#define Usage_Pow_PowerConverterId                     Usage_i8(0x17)
+#define Usage_Pow_OutletSystem                         Usage_i8(0x18)
+#define Usage_Pow_OutletSystemId                       Usage_i8(0x19)
+#define Usage_Pow_Input                                Usage_i8(0x1a)
+#define Usage_Pow_InputId                              Usage_i8(0x1b)
+#define Usage_Pow_Output                               Usage_i8(0x1c)
+#define Usage_Pow_OutputId                             Usage_i8(0x1d)
+#define Usage_Pow_Flow                                 Usage_i8(0x1e)
+#define Usage_Pow_FlowId                               Usage_i8(0x1f)
+#define Usage_Pow_Outlet                               Usage_i8(0x20)
+#define Usage_Pow_OutletId                             Usage_i8(0x21)
+#define Usage_Pow_Gang                                 Usage_i8(0x22)
+#define Usage_Pow_GangId                               Usage_i8(0x23)
+#define Usage_Pow_PowerSummary                         Usage_i8(0x24)
+#define Usage_Pow_PowerSummaryId                       Usage_i8(0x25)
+#define Usage_Pow_Voltage                              Usage_i8(0x30)
+#define Usage_Pow_Current                              Usage_i8(0x31)
+#define Usage_Pow_Frequency                            Usage_i8(0x32)
+#define Usage_Pow_ApparentPower                        Usage_i8(0x33)
+#define Usage_Pow_ActivePower                          Usage_i8(0x34)
+#define Usage_Pow_PercentLoad                          Usage_i8(0x35)
+#define Usage_Pow_Temperature                          Usage_i8(0x36)
+#define Usage_Pow_Humidity                             Usage_i8(0x37)
+#define Usage_Pow_BadCount                             Usage_i8(0x38)
+#define Usage_Pow_ConfigVoltage                        Usage_i8(0x40)
+#define Usage_Pow_ConfigCurrent                        Usage_i8(0x41)
+#define Usage_Pow_ConfigFrequency                      Usage_i8(0x42)
+#define Usage_Pow_ConfigApparentPower                  Usage_i8(0x43)
+#define Usage_Pow_ConfigActivePower                    Usage_i8(0x44)
+#define Usage_Pow_ConfigPercentLoad                    Usage_i8(0x45)
+#define Usage_Pow_ConfigTemperature                    Usage_i8(0x46)
+#define Usage_Pow_ConfigHumidity                       Usage_i8(0x47)
+#define Usage_Pow_SwitchOnControl                      Usage_i8(0x50)
+#define Usage_Pow_SwitchOffControl                     Usage_i8(0x51)
+#define Usage_Pow_ToggleControl                        Usage_i8(0x52)
+#define Usage_Pow_LowVoltageTransfer                   Usage_i8(0x53)
+#define Usage_Pow_HighVoltageTransfer                  Usage_i8(0x54)
+#define Usage_Pow_DelayBeforeReboot                    Usage_i8(0x55)
+#define Usage_Pow_DelayBeforeStartup                   Usage_i8(0x56)
+#define Usage_Pow_DelayBeforeShutdown                  Usage_i8(0x57)
+#define Usage_Pow_Test                                 Usage_i8(0x58)
+#define Usage_Pow_ModuleReset                          Usage_i8(0x59)
+#define Usage_Pow_AudibleAlarmControl                  Usage_i8(0x5a)
+#define Usage_Pow_Present                              Usage_i8(0x60)
+#define Usage_Pow_Good                                 Usage_i8(0x61)
+#define Usage_Pow_InternalFailure                      Usage_i8(0x62)
+#define Usage_Pow_VoltagOutOfRange                     Usage_i8(0x63)
+#define Usage_Pow_FrequencyOutOfRange                  Usage_i8(0x64)
+#define Usage_Pow_Overload                             Usage_i8(0x65)
+#define Usage_Pow_OverCharged                          Usage_i8(0x66)
+#define Usage_Pow_OverTemperature                      Usage_i8(0x67)
+#define Usage_Pow_ShutdownRequested                    Usage_i8(0x68)
+#define Usage_Pow_ShutdownImminent                     Usage_i8(0x69)
+#define Usage_Pow_SwitchOnOff                          Usage_i8(0x6b)
+#define Usage_Pow_Switchable                           Usage_i8(0x6c)
+#define Usage_Pow_Used                                 Usage_i8(0x6d)
+#define Usage_Pow_Boost                                Usage_i8(0x6e)
+#define Usage_Pow_Buck                                 Usage_i8(0x6f)
+#define Usage_Pow_Initialized                          Usage_i8(0x70)
+#define Usage_Pow_Tested                               Usage_i8(0x71)
+#define Usage_Pow_AwaitingPower                        Usage_i8(0x72)
+#define Usage_Pow_CommunicationLost                    Usage_i8(0x73)
+#define Usage_Pow_iManufacturer                        Usage_i8(0xfd)
+#define Usage_Pow_iProduct                             Usage_i8(0xfe)
+#define Usage_Pow_iSerialNumber                        Usage_i16(0xff)
+#define Usage_BS_SmartBatteryBatteryMode               Usage_i8(0x1)
+#define Usage_BS_SmartBatteryBatteryStatus             Usage_i8(0x2)
+#define Usage_BS_SmartBatteryAlarmWarning              Usage_i8(0x3)
+#define Usage_BS_SmartBatteryChargerMode               Usage_i8(0x4)
+#define Usage_BS_SmartBatteryChargerStatus             Usage_i8(0x5)
+#define Usage_BS_SmartBatteryChargerSpecInfo           Usage_i8(0x6)
+#define Usage_BS_SmartBatterySelectorState             Usage_i8(0x7)
+#define Usage_BS_SmartBatterySelectorPresets           Usage_i8(0x8)
+#define Usage_BS_SmartBatterySelectorInfo              Usage_i8(0x9)
+#define Usage_BS_OptionalMfgFunction1                  Usage_i8(0x10)
+#define Usage_BS_OptionalMfgFunction2                  Usage_i8(0x11)
+#define Usage_BS_OptionalMfgFunction3                  Usage_i8(0x12)
+#define Usage_BS_OptionalMfgFunction4                  Usage_i8(0x13)
+#define Usage_BS_OptionalMfgFunction5                  Usage_i8(0x14)
+#define Usage_BS_ConnectionToSMBus                     Usage_i8(0x15)
+#define Usage_BS_OutputConnection                      Usage_i8(0x16)
+#define Usage_BS_ChargerConnection                     Usage_i8(0x17)
+#define Usage_BS_BatteryInsertion                      Usage_i8(0x18)
+#define Usage_BS_UseNext                               Usage_i8(0x19)
+#define Usage_BS_OKToUse                               Usage_i8(0x1a)
+#define Usage_BS_BatterySupported                      Usage_i8(0x1b)
+#define Usage_BS_SelectorRevision                      Usage_i8(0x1c)
+#define Usage_BS_ChargingIndicator                     Usage_i8(0x1d)
+#define Usage_BS_ManufacturerAccess                    Usage_i8(0x28)
+#define Usage_BS_RemainingCapacityLimit                Usage_i8(0x29)
+#define Usage_BS_RemainingTimeLimit                    Usage_i8(0x2a)
+#define Usage_BS_AtRate                                Usage_i8(0x2b)
+#define Usage_BS_CapacityMode                          Usage_i8(0x2c)
+#define Usage_BS_BroadcastToCharger                    Usage_i8(0x2d)
+#define Usage_BS_PrimaryBattery                        Usage_i8(0x2e)
+#define Usage_BS_ChargeController                      Usage_i8(0x2f)
+#define Usage_BS_TerminateCharge                       Usage_i8(0x40)
+#define Usage_BS_TerminateDischarge                    Usage_i8(0x41)
+#define Usage_BS_BelowRemainingCapacityLimit           Usage_i8(0x42)
+#define Usage_BS_RemainingTimeLimitExpired             Usage_i8(0x43)
+#define Usage_BS_Charging                              Usage_i8(0x44)
+#define Usage_BS_Discharging                           Usage_i8(0x45)
+#define Usage_BS_FullyCharged                          Usage_i8(0x46)
+#define Usage_BS_FullyDischarged                       Usage_i8(0x47)
+#define Usage_BS_ConditioningFlag                      Usage_i8(0x48)
+#define Usage_BS_AtRateOK                              Usage_i8(0x49)
+#define Usage_BS_SmartBatteryErrorCode                 Usage_i8(0x4a)
+#define Usage_BS_NeedReplacement                       Usage_i8(0x4b)
+#define Usage_BS_AtRateTimeToFull                      Usage_i8(0x60)
+#define Usage_BS_AtRateTimeToEmpty                     Usage_i8(0x61)
+#define Usage_BS_AverageCurrent                        Usage_i8(0x62)
+#define Usage_BS_MaxError                              Usage_i8(0x63)
+#define Usage_BS_RelativeStateOfCharge                 Usage_i8(0x64)
+#define Usage_BS_AbsoluteStateOfCharge                 Usage_i8(0x65)
+#define Usage_BS_RemainingCapacity                     Usage_i8(0x66)
+#define Usage_BS_FullChargeCapacity                    Usage_i8(0x67)
+#define Usage_BS_RunTimeToEmpty                        Usage_i8(0x68)
+#define Usage_BS_AverageTimeToEmpty                    Usage_i8(0x69)
+#define Usage_BS_AverageTimeToFull                     Usage_i8(0x6a)
+#define Usage_BS_CycleCount                            Usage_i8(0x6b)
+#define Usage_BS_BatteryPackModelLevel                 Usage_i8(0x80)
+#define Usage_BS_InternalChargeController              Usage_i8(0x81)
+#define Usage_BS_PrimaryBatterySupport                 Usage_i8(0x82)
+#define Usage_BS_DesignCapacity                        Usage_i8(0x83)
+#define Usage_BS_SpecificationInfo                     Usage_i8(0x84)
+#define Usage_BS_ManufactureDate                       Usage_i8(0x85)
+#define Usage_BS_SerialNumber                          Usage_i8(0x86)
+#define Usage_BS_iManufacturerName                     Usage_i8(0x87)
+#define Usage_BS_iDeviceName                           Usage_i8(0x88)
+#define Usage_BS_iDeviceChemistry                      Usage_i8(0x89)
+#define Usage_BS_ManufacturerData                      Usage_i8(0x8a)
+#define Usage_BS_Rechargable                           Usage_i8(0x8b)
+#define Usage_BS_WarningCapacityLimit                  Usage_i8(0x8c)
+#define Usage_BS_CapacityGranularity1                  Usage_i8(0x8d)
+#define Usage_BS_CapacityGranularity2                  Usage_i8(0x8e)
+#define Usage_BS_iOEMInformation                       Usage_i8(0x8f)
+#define Usage_BS_InhibitCharge                         Usage_i8(0xc0)
+#define Usage_BS_EnablePolling                         Usage_i8(0xc1)
+#define Usage_BS_ResetToZero                           Usage_i8(0xc2)
+#define Usage_BS_ACPresent                             Usage_i8(0xd0)
+#define Usage_BS_BatteryPresent                        Usage_i8(0xd1)
+#define Usage_BS_PowerFail                             Usage_i8(0xd2)
+#define Usage_BS_AlarmInhibited                        Usage_i8(0xd3)
+#define Usage_BS_ThermistorUnderRange                  Usage_i8(0xd4)
+#define Usage_BS_ThermistorHot                         Usage_i8(0xd5)
+#define Usage_BS_ThermistorCold                        Usage_i8(0xd6)
+#define Usage_BS_ThermistorOverRange                   Usage_i8(0xd7)
+#define Usage_BS_VoltageOutOfRange                     Usage_i8(0xd8)
+#define Usage_BS_CurrentOutOfRange                     Usage_i8(0xd9)
+#define Usage_BS_CurrentNotRegulated                   Usage_i8(0xda)
+#define Usage_BS_VoltageNotRegulated                   Usage_i8(0xdb)
+#define Usage_BS_MasterMode                            Usage_i8(0xdc)
+#define Usage_BS_ChargerSelectorSupport                Usage_i8(0xf0)
+#define Usage_BS_ChargerSpec                           Usage_i8(0xf1)
+#define Usage_BS_Level2                                Usage_i8(0xf2)
+#define Usage_BS_Level3                                Usage_i8(0xf3)
+#define Usage_BS_BarcodeBadgeReader                    Usage_i8(0x1)
+#define Usage_BS_BarcodeScanner                        Usage_i8(0x2)
+#define Usage_BS_DumbBarCodeScanner                    Usage_i8(0x3)
+#define Usage_BS_CordlessScannerBase                   Usage_i8(0x4)
+#define Usage_BS_BarCodeScannerCradle                  Usage_i8(0x5)
+#define Usage_BS_AttributeReport                       Usage_i8(0x10)
+#define Usage_BS_SettingsReport                        Usage_i8(0x11)
+#define Usage_BS_ScannedDataReport                     Usage_i8(0x12)
+#define Usage_BS_RawScannedDataReport                  Usage_i8(0x13)
+#define Usage_BS_TriggerReport                         Usage_i8(0x14)
+#define Usage_BS_StatusReport                          Usage_i8(0x15)
+#define Usage_BS_UPCEANControlReport                   Usage_i8(0x16)
+#define Usage_BS_EAN23LabelControlReport               Usage_i8(0x17)
+#define Usage_BS_Code39ControlReport                   Usage_i8(0x18)
+#define Usage_BS_Interleaved2of5ControlReport          Usage_i8(0x19)
+#define Usage_BS_Standard2of5ControlReport             Usage_i8(0x1a)
+#define Usage_BS_MSIPlesseyControlReport               Usage_i8(0x1b)
+#define Usage_BS_CodabarControlReport                  Usage_i8(0x1c)
+#define Usage_BS_Code128ControlReport                  Usage_i8(0x1d)
+#define Usage_BS_Misc1DControlReport                   Usage_i8(0x1e)
+#define Usage_BS_TwoDControlReport                     Usage_i8(0x1f)
+#define Usage_BS_AimingPointerMode                     Usage_i8(0x30)
+#define Usage_BS_BarCodePresentSensor                  Usage_i8(0x31)
+#define Usage_BS_Class1ALaser                          Usage_i8(0x32)
+#define Usage_BS_Class2Laser                           Usage_i8(0x33)
+#define Usage_BS_HeaterPresent                         Usage_i8(0x34)
+#define Usage_BS_ContactScanner                        Usage_i8(0x35)
+#define Usage_BS_ElectronicArticleSurveillanceNotification Usage_i8(0x36)
+#define Usage_BS_ConstantElectronicArticleSurveillance Usage_i8(0x37)
+#define Usage_BS_ErrorIndication                       Usage_i8(0x38)
+#define Usage_BS_FixedBeeper                           Usage_i8(0x39)
+#define Usage_BS_GoodDecodeIndication                  Usage_i8(0x3a)
+#define Usage_BS_HandsFreeScanning                     Usage_i8(0x3b)
+#define Usage_BS_IntrinsicallySafe                     Usage_i8(0x3c)
+#define Usage_BS_KlasseEinsLaser                       Usage_i8(0x3d)
+#define Usage_BS_LongRangeScanner                      Usage_i8(0x3e)
+#define Usage_BS_MirrorSpeedControl                    Usage_i8(0x3f)
+#define Usage_BS_NotOnFileIndication                   Usage_i8(0x40)
+#define Usage_BS_ProgrammableBeeper                    Usage_i8(0x41)
+#define Usage_BS_Triggerless                           Usage_i8(0x42)
+#define Usage_BS_Wand                                  Usage_i8(0x43)
+#define Usage_BS_WaterResistant                        Usage_i8(0x44)
+#define Usage_BS_MultiRangeScanner                     Usage_i8(0x45)
+#define Usage_BS_ProximitySensor                       Usage_i8(0x46)
+#define Usage_BS_FragmentDecoding                      Usage_i8(0x4d)
+#define Usage_BS_ScannerReadConfidence                 Usage_i8(0x4e)
+#define Usage_BS_DataPrefix                            Usage_i8(0x4f)
+#define Usage_BS_PrefixAIMI                            Usage_i8(0x50)
+#define Usage_BS_PrefixNone                            Usage_i8(0x51)
+#define Usage_BS_PrefixProprietary                     Usage_i8(0x52)
+#define Usage_BS_ActiveTime                            Usage_i8(0x55)
+#define Usage_BS_AimingLaserPattern                    Usage_i8(0x56)
+#define Usage_BS_BarCodePresent                        Usage_i8(0x57)
+#define Usage_BS_BeeperState                           Usage_i8(0x58)
+#define Usage_BS_LaserOnTime                           Usage_i8(0x59)
+#define Usage_BS_LaserState                            Usage_i8(0x5a)
+#define Usage_BS_LockoutTime                           Usage_i8(0x5b)
+#define Usage_BS_MotorState                            Usage_i8(0x5c)
+#define Usage_BS_MotorTimeout                          Usage_i8(0x5d)
+#define Usage_BS_PowerOnResetScanner                   Usage_i8(0x5e)
+#define Usage_BS_PreventReadofBarcodes                 Usage_i8(0x5f)
+#define Usage_BS_InitiateBarcodeRead                   Usage_i8(0x60)
+#define Usage_BS_TriggerState                          Usage_i8(0x61)
+#define Usage_BS_TriggerMode                           Usage_i8(0x62)
+#define Usage_BS_TriggerModeBlinkingLaserOn            Usage_i8(0x63)
+#define Usage_BS_TriggerModeContinuousLaserOn          Usage_i8(0x64)
+#define Usage_BS_TriggerModeLaseronwhilePulled         Usage_i8(0x65)
+#define Usage_BS_TriggerModeLaserstaysonafterrelease   Usage_i8(0x66)
+#define Usage_BS_CommitParameterstoNVM                 Usage_i8(0x6d)
+#define Usage_BS_ParameterScanning                     Usage_i8(0x6e)
+#define Usage_BS_ParametersChanged                     Usage_i8(0x6f)
+#define Usage_BS_Setparameterdefaultvalues             Usage_i8(0x70)
+#define Usage_BS_ScannerInCradle                       Usage_i8(0x75)
+#define Usage_BS_ScannerInRange                        Usage_i8(0x76)
+#define Usage_BS_AimDuration                           Usage_i8(0x7a)
+#define Usage_BS_GoodReadLampDuration                  Usage_i8(0x7b)
+#define Usage_BS_GoodReadLampIntensity                 Usage_i8(0x7c)
+#define Usage_BS_GoodReadLED                           Usage_i8(0x7d)
+#define Usage_BS_GoodReadToneFrequency                 Usage_i8(0x7e)
+#define Usage_BS_GoodReadToneLength                    Usage_i8(0x7f)
+#define Usage_BS_GoodReadToneVolume                    Usage_i8(0x80)
+#define Usage_BS_NoReadMessage                         Usage_i8(0x82)
+#define Usage_BS_NotonFileVolume                       Usage_i8(0x83)
+#define Usage_BS_PowerupBeep                           Usage_i8(0x84)
+#define Usage_BS_SoundErrorBeep                        Usage_i8(0x85)
+#define Usage_BS_SoundGoodReadBeep                     Usage_i8(0x86)
+#define Usage_BS_SoundNotOnFileBeep                    Usage_i8(0x87)
+#define Usage_BS_GoodReadWhentoWrite                   Usage_i8(0x88)
+#define Usage_BS_GRWTIAfterDecode                      Usage_i8(0x89)
+#define Usage_BS_GRWTIBeepLampaftertransmit            Usage_i8(0x8a)
+#define Usage_BS_GRWTINoBeepLampuseatall               Usage_i8(0x8b)
+#define Usage_BS_BooklandEAN                           Usage_i8(0x91)
+#define Usage_BS_ConvertEAN8to13Type                   Usage_i8(0x92)
+#define Usage_BS_ConvertUPCAtoEAN13                    Usage_i8(0x93)
+#define Usage_BS_ConvertUPCEtoA                        Usage_i8(0x94)
+#define Usage_BS_EAN13                                 Usage_i8(0x95)
+#define Usage_BS_EAN8                                  Usage_i8(0x96)
+#define Usage_BS_EAN99128Mandatory                     Usage_i8(0x97)
+#define Usage_BS_EAN99P5128Optional                    Usage_i8(0x98)
+#define Usage_BS_EnableEANTwoLabel                     Usage_i8(0x99)
+#define Usage_BS_UPCEAN                                Usage_i8(0x9a)
+#define Usage_BS_UPCEANCouponCode                      Usage_i8(0x9b)
+#define Usage_BS_UPCEANPeriodicals                     Usage_i8(0x9c)
+#define Usage_BS_UPCA                                  Usage_i8(0x9d)
+#define Usage_BS_UPCAwith128Mandatory                  Usage_i8(0x9e)
+#define Usage_BS_UPCAwith128Optional                   Usage_i8(0x9f)
+#define Usage_BS_UPCAwithP5Optional                    Usage_i8(0xa0)
+#define Usage_BS_UPCE                                  Usage_i8(0xa1)
+#define Usage_BS_UPCE1                                 Usage_i8(0xa2)
+#define Usage_BS_Periodical                            Usage_i8(0xa9)
+#define Usage_BS_PeriodicalAutoDiscriminatePlus2       Usage_i8(0xaa)
+#define Usage_BS_PeriodicalOnlyDecodewithPlus2         Usage_i8(0xab)
+#define Usage_BS_PeriodicalIgnorePlus2                 Usage_i8(0xac)
+#define Usage_BS_PeriodicalAutoDiscriminatePlus5       Usage_i8(0xad)
+#define Usage_BS_PeriodicalOnlyDecodewithPlus5         Usage_i8(0xae)
+#define Usage_BS_PeriodicalIgnorePlus5                 Usage_i8(0xaf)
+#define Usage_BS_Check                                 Usage_i8(0xb0)
+#define Usage_BS_CheckDisablePrice                     Usage_i8(0xb1)
+#define Usage_BS_CheckEnable4digitPrice                Usage_i8(0xb2)
+#define Usage_BS_CheckEnable5digitPrice                Usage_i8(0xb3)
+#define Usage_BS_CheckEnableEuropean4digitPrice        Usage_i8(0xb4)
+#define Usage_BS_CheckEnableEuropean5digitPrice        Usage_i8(0xb5)
+#define Usage_BS_EANTwoLabel                           Usage_i8(0xb7)
+#define Usage_BS_EANThreeLabel                         Usage_i8(0xb8)
+#define Usage_BS_EAN8FlagDigit1                        Usage_i8(0xb9)
+#define Usage_BS_EAN8FlagDigit2                        Usage_i8(0xba)
+#define Usage_BS_EAN8FlagDigit3                        Usage_i8(0xbb)
+#define Usage_BS_EAN13FlagDigit1                       Usage_i8(0xbc)
+#define Usage_BS_EAN13FlagDigit2                       Usage_i8(0xbd)
+#define Usage_BS_EAN13FlagDigit3                       Usage_i8(0xbe)
+#define Usage_BS_AddEAN23LabelDefinition               Usage_i8(0xbf)
+#define Usage_BS_ClearallEAN23LabelDefinitions         Usage_i8(0xc0)
+#define Usage_BS_Codabar                               Usage_i8(0xc3)
+#define Usage_BS_Code128                               Usage_i8(0xc4)
+#define Usage_BS_Code39                                Usage_i8(0xc7)
+#define Usage_BS_Code93                                Usage_i8(0xc8)
+#define Usage_BS_FullASCIIConversion                   Usage_i8(0xc9)
+#define Usage_BS_Interleaved2of5                       Usage_i8(0xca)
+#define Usage_BS_ItalianPharmacyCode                   Usage_i8(0xcb)
+#define Usage_BS_MSIPlessey                            Usage_i8(0xcc)
+#define Usage_BS_Standard2of5IATA                      Usage_i8(0xcd)
+#define Usage_BS_Standard2of5                          Usage_i8(0xce)
+#define Usage_BS_TransmitStartStop                     Usage_i8(0xd3)
+#define Usage_BS_TriOptic                              Usage_i8(0xd4)
+#define Usage_BS_UCCEAN128                             Usage_i8(0xd5)
+#define Usage_BS_CheckDigit                            Usage_i8(0xd6)
+#define Usage_BS_CheckDigitDisable                     Usage_i8(0xd7)
+#define Usage_BS_CheckDigitEnableInterleaved2of5OPCC   Usage_i8(0xd8)
+#define Usage_BS_CheckDigitEnableInterleaved2of5USS    Usage_i8(0xd9)
+#define Usage_BS_CheckDigitEnableStandard2of5OPCC      Usage_i8(0xda)
+#define Usage_BS_CheckDigitEnableStandard2of5USS       Usage_i8(0xdb)
+#define Usage_BS_CheckDigitEnableOneMSIPlessey         Usage_i8(0xdc)
+#define Usage_BS_CheckDigitEnableTwoMSIPlessey         Usage_i8(0xdd)
+#define Usage_BS_CheckDigitCodabarEnable               Usage_i8(0xde)
+#define Usage_BS_CheckDigitCode39Enable                Usage_i8(0xdf)
+#define Usage_BS_TransmitCheckDigit                    Usage_i8(0xf0)
+#define Usage_BS_DisableCheckDigitTransmit             Usage_i8(0xf1)
+#define Usage_BS_EnableCheckDigitTransmit              Usage_i8(0xf2)
+#define Usage_BS_SymbologyIdentifier1                  Usage_i8(0xfb)
+#define Usage_BS_SymbologyIdentifier2                  Usage_i8(0xfc)
+#define Usage_BS_SymbologyIdentifier3                  Usage_i8(0xfd)
+#define Usage_BS_DecodedData                           Usage_i8(0xfe)
+#define Usage_BS_DecodeDataContinued                   Usage_i16(0xff)
+#define Usage_BS_BarSpaceData                          Usage_i16(0x100)
+#define Usage_BS_ScannerDataAccuracy                   Usage_i16(0x101)
+#define Usage_BS_RawDataPolarity                       Usage_i16(0x102)
+#define Usage_BS_PolarityInvertedBarCode               Usage_i16(0x103)
+#define Usage_BS_PolarityNormalBarCode                 Usage_i16(0x104)
+#define Usage_BS_MinimumLengthtoDecode                 Usage_i16(0x106)
+#define Usage_BS_MaximumLengthtoDecode                 Usage_i16(0x107)
+#define Usage_BS_DiscreteLengthtoDecode1               Usage_i16(0x108)
+#define Usage_BS_DiscreteLengthtoDecode2               Usage_i16(0x109)
+#define Usage_BS_DataLengthMethod                      Usage_i16(0x10a)
+#define Usage_BS_DLMethodReadany                       Usage_i16(0x10b)
+#define Usage_BS_DLMethodCheckinRange                  Usage_i16(0x10c)
+#define Usage_BS_DLMethodCheckforDiscrete              Usage_i16(0x10d)
+#define Usage_BS_AztecCode                             Usage_i16(0x110)
+#define Usage_BS_BC412                                 Usage_i16(0x111)
+#define Usage_BS_ChannelCode                           Usage_i16(0x112)
+#define Usage_BS_Code16                                Usage_i16(0x113)
+#define Usage_BS_Code32                                Usage_i16(0x114)
+#define Usage_BS_Code49                                Usage_i16(0x115)
+#define Usage_BS_CodeOne                               Usage_i16(0x116)
+#define Usage_BS_Colorcode                             Usage_i16(0x117)
+#define Usage_BS_DataMatrix                            Usage_i16(0x118)
+#define Usage_BS_MaxiCode                              Usage_i16(0x119)
+#define Usage_BS_MicroPDF                              Usage_i16(0x11a)
+#define Usage_BS_PDF417                                Usage_i16(0x11b)
+#define Usage_BS_PosiCode                              Usage_i16(0x11c)
+#define Usage_BS_QRCode                                Usage_i16(0x11d)
+#define Usage_BS_SuperCode                             Usage_i16(0x11e)
+#define Usage_BS_UltraCode                             Usage_i16(0x11f)
+#define Usage_BS_USD5SlugCode                          Usage_i16(0x120)
+#define Usage_BS_VeriCode                              Usage_i16(0x121)
+#define Usage_Sca_Scales                               Usage_i8(0x1)
+#define Usage_Sca_ScaleDevice                          Usage_i8(0x20)
+#define Usage_Sca_ScaleClass                           Usage_i8(0x21)
+#define Usage_Sca_ScaleClassIMetric                    Usage_i8(0x22)
+#define Usage_Sca_ScaleClassIIMetric                   Usage_i8(0x23)
+#define Usage_Sca_ScaleClassIIIMetric                  Usage_i8(0x24)
+#define Usage_Sca_ScaleClassIIILMetric                 Usage_i8(0x25)
+#define Usage_Sca_ScaleClassIVMetric                   Usage_i8(0x26)
+#define Usage_Sca_ScaleClassIIIEnglish                 Usage_i8(0x27)
+#define Usage_Sca_ScaleClassIIILEnglish                Usage_i8(0x28)
+#define Usage_Sca_ScaleClassIVEnglish                  Usage_i8(0x29)
+#define Usage_Sca_ScaleClassGeneric                    Usage_i8(0x2a)
+#define Usage_Sca_ScaleAttributeReport                 Usage_i8(0x30)
+#define Usage_Sca_ScaleControlReport                   Usage_i8(0x31)
+#define Usage_Sca_ScaleDataReport                      Usage_i8(0x32)
+#define Usage_Sca_ScaleStatusReport                    Usage_i8(0x33)
+#define Usage_Sca_ScaleWeightLimitReport               Usage_i8(0x34)
+#define Usage_Sca_ScaleStatisticsReport                Usage_i8(0x35)
+#define Usage_Sca_DataWeight                           Usage_i8(0x40)
+#define Usage_Sca_DataScaling                          Usage_i8(0x41)
+#define Usage_Sca_WeightUnit                           Usage_i8(0x50)
+#define Usage_Sca_WeightUnitMilligram                  Usage_i8(0x51)
+#define Usage_Sca_WeightUnitGram                       Usage_i8(0x52)
+#define Usage_Sca_WeightUnitKilogram                   Usage_i8(0x53)
+#define Usage_Sca_WeightUnitCarats                     Usage_i8(0x54)
+#define Usage_Sca_WeightUnitTaels                      Usage_i8(0x55)
+#define Usage_Sca_WeightUnitGrains                     Usage_i8(0x56)
+#define Usage_Sca_WeightUnitPennyweights               Usage_i8(0x57)
+#define Usage_Sca_WeightUnitMetricTon                  Usage_i8(0x58)
+#define Usage_Sca_WeightUnitAvoirTon                   Usage_i8(0x59)
+#define Usage_Sca_WeightUnitTroyOunce                  Usage_i8(0x5a)
+#define Usage_Sca_WeightUnitOunce                      Usage_i8(0x5b)
+#define Usage_Sca_WeightUnitPound                      Usage_i8(0x5c)
+#define Usage_Sca_CalibrationCount                     Usage_i8(0x60)
+#define Usage_Sca_ReZeroCount                          Usage_i8(0x61)
+#define Usage_Sca_ScaleStatus                          Usage_i8(0x70)
+#define Usage_Sca_ScaleStatusFault                     Usage_i8(0x71)
+#define Usage_Sca_ScaleStatusStableatCenterofZero      Usage_i8(0x72)
+#define Usage_Sca_ScaleStatusInMotion                  Usage_i8(0x73)
+#define Usage_Sca_ScaleStatusWeightStable              Usage_i8(0x74)
+#define Usage_Sca_ScaleStatusUnderZero                 Usage_i8(0x75)
+#define Usage_Sca_ScaleStatusOverWeightLimit           Usage_i8(0x76)
+#define Usage_Sca_ScaleStatusRequiresCalibration       Usage_i8(0x77)
+#define Usage_Sca_ScaleStatusRequiresRezeroing         Usage_i8(0x78)
+#define Usage_Sca_ZeroScale                            Usage_i8(0x80)
+#define Usage_Sca_EnforcedZeroReturn                   Usage_i8(0x81)
+#define Usage_MSR_MSRDeviceReadOnly                    Usage_i8(0x1)
+#define Usage_MSR_Track1Length                         Usage_i8(0x11)
+#define Usage_MSR_Track2Length                         Usage_i8(0x12)
+#define Usage_MSR_Track3Length                         Usage_i8(0x13)
+#define Usage_MSR_TrackJISLength                       Usage_i8(0x14)
+#define Usage_MSR_TrackData                            Usage_i8(0x20)
+#define Usage_MSR_Track1Data                           Usage_i8(0x21)
+#define Usage_MSR_Track2Data                           Usage_i8(0x22)
+#define Usage_MSR_Track3Data                           Usage_i8(0x23)
+#define Usage_MSR_TrackJISData                         Usage_i8(0x24)
+#define Usage_CC_CameraAutofocus                       Usage_i8(0x20)
+#define Usage_CC_CameraShutter                         Usage_i8(0x21)
+#define Usage_Arc_GeneralPurposeIOCard                 Usage_i8(0x1)
+#define Usage_Arc_CoinDoor                             Usage_i8(0x2)
+#define Usage_Arc_WatchdogTimer                        Usage_i8(0x3)
+#define Usage_Arc_GeneralPurposeAnalogInputState       Usage_i8(0x30)
+#define Usage_Arc_GeneralPurposeDigitalInputState      Usage_i8(0x31)
+#define Usage_Arc_GeneralPurposeOpticalInputState      Usage_i8(0x32)
+#define Usage_Arc_GeneralPurposeDigitalOutputState     Usage_i8(0x33)
+#define Usage_Arc_NumberofCoinDoors                    Usage_i8(0x34)
+#define Usage_Arc_CoinDrawerDropCount                  Usage_i8(0x35)
+#define Usage_Arc_CoinDrawerStart                      Usage_i8(0x36)
+#define Usage_Arc_CoinDrawerService                    Usage_i8(0x37)
+#define Usage_Arc_CoinDrawerTilt                       Usage_i8(0x38)
+#define Usage_Arc_CoinDoorTest                         Usage_i8(0x39)
+#define Usage_Arc_CoinDoorLockout                      Usage_i8(0x40)
+#define Usage_Arc_WatchdogTimeout                      Usage_i8(0x41)
+#define Usage_Arc_WatchdogAction                       Usage_i8(0x42)
+#define Usage_Arc_WatchdogReboot                       Usage_i8(0x43)
+#define Usage_Arc_WatchdogRestart                      Usage_i8(0x44)
+#define Usage_Arc_AlarmInput                           Usage_i8(0x45)
+#define Usage_Arc_CoinDoorCounter                      Usage_i8(0x46)
+#define Usage_Arc_IODirectionMapping                   Usage_i8(0x47)
+#define Usage_Arc_SetIODirectionMapping                Usage_i8(0x48)
+#define Usage_Arc_ExtendedOpticalInputState            Usage_i8(0x49)
+#define Usage_Arc_PinPadInputState                     Usage_i8(0x4a)
+#define Usage_Arc_PinPadStatus                         Usage_i8(0x4b)
+#define Usage_Arc_PinPadOutput                         Usage_i8(0x4c)
+#define Usage_Arc_PinPadCommand                        Usage_i8(0x4d)
+#define Usage_FIDOA_U2FAuthenticatorDevice             Usage_i8(0x1)
+#define Usage_FIDOA_InputReportData                    Usage_i8(0x20)
+#define Usage_FIDOA_OutputReportData                   Usage_i8(0x21)

-- 
2.44.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/6] HID: bpf: add a driver for the Huion Inspiroy 2S (H641P)
  2024-06-27  9:54 [PATCH 0/6] HID: bpf: import some more fixes from udev-hid-bpf Benjamin Tissoires
  2024-06-27  9:54 ` [PATCH 1/6] HID: bpf: Add a HID report composition helper macros Benjamin Tissoires
@ 2024-06-27  9:54 ` Benjamin Tissoires
  2024-06-28  0:22   ` Peter Hutterer
  2024-06-27  9:54 ` [PATCH 3/6] HID: bpf: move the BIT() macro to hid_bpf_helpers.h Benjamin Tissoires
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 9+ messages in thread
From: Benjamin Tissoires @ 2024-06-27  9:54 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: linux-kernel, linux-input, bpf, Benjamin Tissoires,
	default avatarPeter Hutterer

This is a a driver for the Huion Inspiroy 2S in both modes (firmware mode
and tablet mode). This device has 6 buttons and a wheel, all of which
send key combinations (see the comments for the defaults). Luckily the
device is quite limited in that it only supports one button down at a
time, so with this BPF we can simply remap the 8 possible report IDs to
our own custom-built report descriptor.

If the device is in tablet mode (e.g. using huion-switcher it sends
everything through the vendor report instead). This BPF program converts
both, depending which devices you attach to you get both. Or if you
attach to all hid devices you get a duplicate device but it'll work
either way.

This BPF should be mostly compatible for the M and L as well though they
have more buttons so the rdescs will need some minor rework.

Link: https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/85
Link: https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/109
Signed-off-by: default avatarPeter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
---
 drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c | 534 ++++++++++++++++++++++++
 1 file changed, 534 insertions(+)

diff --git a/drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c b/drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c
new file mode 100644
index 000000000000..b09b80132368
--- /dev/null
+++ b/drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c
@@ -0,0 +1,534 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2024 Red Hat, Inc
+ */
+
+#include "vmlinux.h"
+#include "hid_bpf.h"
+#include "hid_bpf_helpers.h"
+#include "hid_report_helpers.h"
+#include <bpf/bpf_tracing.h>
+
+#define VID_HUION 0x256C
+#define PID_INSPIROY_2_S 0x0066
+
+HID_BPF_CONFIG(
+	HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_HUION, PID_INSPIROY_2_S),
+);
+
+/* Filled in by udev-hid-bpf */
+char UDEV_PROP_HUION_FIRMWARE_ID[64];
+
+/* The prefix of the firmware ID we expect for this device. The full firmware
+ * string has a date suffix, e.g. HUION_T21j_221221
+ */
+char EXPECTED_FIRMWARE_ID[] = "HUION_T21j_";
+
+/* How this BPF program works: the tablet has two modes, firmware mode and
+ * tablet mode. In firmware mode (out of the box) the tablet sends button events
+ * and the dial as keyboard combinations. In tablet mode it uses a vendor specific
+ * hid report to report everything instead.
+ * Depending on the mode some hid reports are never sent and the corresponding
+ * devices are mute.
+ *
+ * To switch the tablet use e.g.  https://github.com/whot/huion-switcher
+ * or one of the tools from the digimend project
+ *
+ * This BPF works for both modes. The huion-switcher tool sets the
+ * HUION_FIRMWARE_ID udev property - if that is set then we disable the firmware
+ * pad and pen reports (by making them vendor collections that are ignored).
+ * If that property is not set we fix all hidraw nodes so the tablet works in
+ * either mode though the drawback is that the device will show up twice if
+ * you bind it to all event nodes
+ *
+ * Default report descriptor for the first exposed hidraw node:
+ *
+ * # HUION Huion Tablet_H641P
+ * # Report descriptor length: 18 bytes
+ * # 0x06, 0x00, 0xff,              // Usage Page (Vendor Defined Page 0xFF00)   0
+ * # 0x09, 0x01,                    // Usage (Vendor Usage 0x01)                 3
+ * # 0xa1, 0x01,                    // Collection (Application)                  5
+ * # 0x85, 0x08,                    //   Report ID (8)                           7
+ * # 0x75, 0x58,                    //   Report Size (88)                        9
+ * # 0x95, 0x01,                    //   Report Count (1)                        11
+ * # 0x09, 0x01,                    //   Usage (Vendor Usage 0x01)               13
+ * # 0x81, 0x02,                    //   Input (Data,Var,Abs)                    15
+ * # 0xc0,                          // End Collection                            17
+ * R: 18 06 00 ff 09 01 a1 01 85 08 75 58 95 01 09 01 81 02 c0
+ *
+ * This rdesc does nothing until the tablet is switched to raw mode, see
+ * https://github.com/whot/huion-switcher
+ *
+ *
+ * Second hidraw node is the Pen. This one sends events until the tablet is
+ * switched to raw mode, then it's mute.
+ *
+ * # Report descriptor length: 93 bytes
+ * # 0x05, 0x0d,          // Usage Page (Digitizers)                   0
+ * # 0x09, 0x02,          // Usage (Pen)                               2
+ * # 0xa1, 0x01,          // Collection (Application)                  4
+ * # 0x85, 0x0a,          //   Report ID (10)                          6
+ * # 0x09, 0x20,          //   Usage (Stylus)                          8
+ * # 0xa1, 0x01,          //   Collection (Application)                10
+ * # 0x09, 0x42,          //     Usage (Tip Switch)                    12
+ * # 0x09, 0x44,          //     Usage (Barrel Switch)                 14
+ * # 0x09, 0x45,          //     Usage (Eraser)                        16
+ * # 0x09, 0x3c,          //     Usage (Invert)                        18 <-- has no Invert eraser
+ * # 0x15, 0x00,          //     Logical Minimum (0)                   20
+ * # 0x25, 0x01,          //     Logical Maximum (1)                   22
+ * # 0x75, 0x01,          //     Report Size (1)                       24
+ * # 0x95, 0x06,          //     Report Count (6)                      26
+ * # 0x81, 0x02,          //     Input (Data,Var,Abs)                  28
+ * # 0x09, 0x32,          //     Usage (In Range)                      30
+ * # 0x75, 0x01,          //     Report Size (1)                       32
+ * # 0x95, 0x01,          //     Report Count (1)                      34
+ * # 0x81, 0x02,          //     Input (Data,Var,Abs)                  36
+ * # 0x81, 0x03,          //     Input (Cnst,Var,Abs)                  38
+ * # 0x05, 0x01,          //     Usage Page (Generic Desktop)          40
+ * # 0x09, 0x30,          //     Usage (X)                             42
+ * # 0x09, 0x31,          //     Usage (Y)                             44
+ * # 0x55, 0x0d,          //     Unit Exponent (-3)                    46 <-- change to -2
+ * # 0x65, 0x33,          //     Unit (EnglishLinear: in³)             48 <-- change in³ to in
+ * # 0x26, 0xff, 0x7f,    //     Logical Maximum (32767)               50
+ * # 0x35, 0x00,          //     Physical Minimum (0)                  53
+ * # 0x46, 0x00, 0x08,    //     Physical Maximum (2048)               55 <-- invalid size
+ * # 0x75, 0x10,          //     Report Size (16)                      58
+ * # 0x95, 0x02,          //     Report Count (2)                      60
+ * # 0x81, 0x02,          //     Input (Data,Var,Abs)                  62
+ * # 0x05, 0x0d,          //     Usage Page (Digitizers)               64
+ * # 0x09, 0x30,          //     Usage (Tip Pressure)                  66
+ * # 0x26, 0xff, 0x1f,    //     Logical Maximum (8191)                68
+ * # 0x75, 0x10,          //     Report Size (16)                      71
+ * # 0x95, 0x01,          //     Report Count (1)                      73
+ * # 0x81, 0x02,          //     Input (Data,Var,Abs)                  75
+ * # 0x09, 0x3d,          //     Usage (X Tilt)                        77 <-- No tilt reported
+ * # 0x09, 0x3e,          //     Usage (Y Tilt)                        79
+ * # 0x15, 0x81,          //     Logical Minimum (-127)                81
+ * # 0x25, 0x7f,          //     Logical Maximum (127)                 83
+ * # 0x75, 0x08,          //     Report Size (8)                       85
+ * # 0x95, 0x02,          //     Report Count (2)                      87
+ * # 0x81, 0x02,          //     Input (Data,Var,Abs)                  89
+ * # 0xc0,                //   End Collection                          91
+ * # 0xc0,                // End Collection                            92
+ * R: 93 05 0d 09 02 a1 01 85 0a 09 20 a1 01 09 42 09 44 09 45 09 3c 15 00 25 01 7501 95 06 81 02 09 32 75 01 95 01 81 02 81 03 05 01 09 30 09 31 55 0d 65 33 26 ff7f 35 00 46 00 08 75 10 95 02 81 02 05 0d 09 30 26 ff 1f 75 10 95 01 81 02 09 3d09 3e 15 81 25 7f 75 08 95 02 81 02 c0 c0
+ *
+ * Third hidraw node is the pad which sends a combination of keyboard shortcuts until
+ * the tablet is switched to raw mode, then it's mute:
+ *
+ * # Report descriptor length: 65 bytes
+ * # 0x05, 0x01,          // Usage Page (Generic Desktop)              0
+ * # 0x09, 0x06,          // Usage (Keyboard)                          2
+ * # 0xa1, 0x01,          // Collection (Application)                  4
+ * # 0x85, 0x03,          //   Report ID (3)                           6
+ * # 0x05, 0x07,          //   Usage Page (Keyboard/Keypad)            8
+ * # 0x19, 0xe0,          //   UsageMinimum (224)                      10
+ * # 0x29, 0xe7,          //   UsageMaximum (231)                      12
+ * # 0x15, 0x00,          //   Logical Minimum (0)                     14
+ * # 0x25, 0x01,          //   Logical Maximum (1)                     16
+ * # 0x75, 0x01,          //   Report Size (1)                         18
+ * # 0x95, 0x08,          //   Report Count (8)                        20
+ * # 0x81, 0x02,          //   Input (Data,Var,Abs)                    22
+ * # 0x05, 0x07,          //   Usage Page (Keyboard/Keypad)            24
+ * # 0x19, 0x00,          //   UsageMinimum (0)                        26
+ * # 0x29, 0xff,          //   UsageMaximum (255)                      28
+ * # 0x26, 0xff, 0x00,    //   Logical Maximum (255)                   30
+ * # 0x75, 0x08,          //   Report Size (8)                         33
+ * # 0x95, 0x06,          //   Report Count (6)                        35
+ * # 0x81, 0x00,          //   Input (Data,Arr,Abs)                    37
+ * # 0xc0,                // End Collection                            39
+ * # 0x05, 0x0c,          // Usage Page (Consumer)                     40
+ * # 0x09, 0x01,          // Usage (Consumer Control)                  42
+ * # 0xa1, 0x01,          // Collection (Application)                  44
+ * # 0x85, 0x04,          //   Report ID (4)                           46
+ * # 0x19, 0x00,          //   UsageMinimum (0)                        48
+ * # 0x2a, 0x3c, 0x02,    //   UsageMaximum (572)                      50
+ * # 0x15, 0x00,          //   Logical Minimum (0)                     53
+ * # 0x26, 0x3c, 0x02,    //   Logical Maximum (572)                   55
+ * # 0x95, 0x01,          //   Report Count (1)                        58
+ * # 0x75, 0x10,          //   Report Size (16)                        60
+ * # 0x81, 0x00,          //   Input (Data,Arr,Abs)                    62
+ * # 0xc0,                // End Collection                            64
+ * R: 65 05 01 09 06 a1 01 85 03 05 07 19 e0 29 e7 15 00 25 01 75 01 95 08 81 02 0507 19 00 29 ff 26 ff 00 75 08 95 06 81 00 c0 05 0c 09 01 a1 01 85 04 19 00 2a 3c02 15 00 26 3c 02 95 01 75 10 81 00 c0
+ * N: HUION Huion Tablet_H641P
+ */
+
+#define PAD_REPORT_DESCRIPTOR_LENGTH 65
+#define PEN_REPORT_DESCRIPTOR_LENGTH 93
+#define VENDOR_REPORT_DESCRIPTOR_LENGTH 18
+#define PAD_REPORT_ID 3
+#define PEN_REPORT_ID 10
+#define VENDOR_REPORT_ID 8
+#define PAD_REPORT_LENGTH 8
+#define PEN_REPORT_LENGTH 10
+#define VENDOR_REPORT_LENGTH 12
+
+
+__u8 last_button_state;
+
+static const __u8 fixed_rdesc_pad[] = {
+	UsagePage_GenericDesktop
+	Usage_GD_Keypad
+	CollectionApplication(
+		// -- Byte 0 in report
+		ReportId(PAD_REPORT_ID)
+		LogicalRange_i8(0, 1)
+		UsagePage_Digitizers
+		Usage_Dig_TabletFunctionKeys
+		CollectionPhysical(
+			// Byte 1 in report - just exists so we get to be a tablet pad
+			Usage_Dig_BarrelSwitch // BTN_STYLUS
+			ReportCount(1)
+			ReportSize(1)
+			Input(Var|Abs)
+			ReportCount(7) // padding
+			Input(Const)
+			// Bytes 2/3 in report - just exists so we get to be a tablet pad
+			UsagePage_GenericDesktop
+			Usage_GD_X
+			Usage_GD_Y
+			ReportCount(2)
+			ReportSize(8)
+			Input(Var|Abs)
+			// Byte 4 in report is the wheel
+			Usage_GD_Wheel
+			LogicalRange_i8(-1, 1)
+			ReportCount(1)
+			ReportSize(8)
+			Input(Var|Rel)
+			// Byte 5 is the button state
+			UsagePage_Button
+			UsageRange_i8(0x01, 0x6)
+			LogicalRange_i8(0x01, 0x6)
+			ReportCount(1)
+			ReportSize(8)
+			Input(Arr|Abs)
+		)
+		// Make sure we match our original report length
+		FixedSizeVendorReport(PAD_REPORT_LENGTH)
+	)
+};
+
+static const __u8 fixed_rdesc_pen[] = {
+	UsagePage_Digitizers
+	Usage_Dig_Pen
+	CollectionApplication(
+		// -- Byte 0 in report
+		ReportId(PEN_REPORT_ID)
+		Usage_Dig_Pen
+		CollectionPhysical(
+			// -- Byte 1 in report
+			Usage_Dig_TipSwitch
+			Usage_Dig_BarrelSwitch
+			Usage_Dig_SecondaryBarrelSwitch // maps eraser to BTN_STYLUS2
+			LogicalRange_i8(0, 1)
+			ReportSize(1)
+			ReportCount(3)
+			Input(Var|Abs)
+			ReportCount(4)  // Padding
+			Input(Const)
+			Usage_Dig_InRange
+			ReportCount(1)
+			Input(Var|Abs)
+			ReportSize(16)
+			ReportCount(1)
+			PushPop(
+				UsagePage_GenericDesktop
+				Unit(cm)
+				UnitExponent(-1)
+				PhysicalRange_i16(0, 160)
+				LogicalRange_i16(0, 32767)
+				Usage_GD_X
+				Input(Var|Abs) // Bytes 2+3
+				PhysicalRange_i16(0, 100)
+				LogicalRange_i16(0, 32767)
+				Usage_GD_Y
+				Input(Var|Abs) // Bytes 4+5
+			)
+			UsagePage_Digitizers
+			Usage_Dig_TipPressure
+			LogicalRange_i16(0, 8191)
+			Input(Var|Abs) // Byte 6+7
+			// Two bytes padding so we don't need to change the report at all
+			ReportSize(8)
+			ReportCount(2)
+			Input(Const) // Byte 6+7
+		)
+	)
+};
+
+static const __u8 fixed_rdesc_vendor[] = {
+	UsagePage_Digitizers
+	Usage_Dig_Pen
+	CollectionApplication(
+		// Byte 0
+		// We leave the pen on the vendor report ID
+		ReportId(VENDOR_REPORT_ID)
+		Usage_Dig_Pen
+		CollectionPhysical(
+			// Byte 1 are the buttons
+			LogicalRange_i8(0, 1)
+			ReportSize(1)
+			Usage_Dig_TipSwitch
+			Usage_Dig_BarrelSwitch
+			Usage_Dig_SecondaryBarrelSwitch
+			ReportCount(3)
+			Input(Var|Abs)
+			ReportCount(4) // Padding
+			Input(Const)
+			Usage_Dig_InRange
+			ReportCount(1)
+			Input(Var|Abs)
+			ReportSize(16)
+			ReportCount(1)
+			PushPop(
+				UsagePage_GenericDesktop
+				Unit(cm)
+				UnitExponent(-1)
+				// Note: reported logical range differs
+				// from the pen report ID for x and y
+				LogicalRange_i16(0, 32000)
+				PhysicalRange_i16(0, 160)
+				// Bytes 2/3 in report
+				Usage_GD_X
+				Input(Var|Abs)
+				LogicalRange_i16(0, 20000)
+				PhysicalRange_i16(0, 100)
+				// Bytes 4/5 in report
+				Usage_GD_Y
+				Input(Var|Abs)
+			)
+			// Bytes 6/7 in report
+			LogicalRange_i16(0, 8192)
+			Usage_Dig_TipPressure
+			Input(Var|Abs)
+		)
+	)
+	UsagePage_GenericDesktop
+	Usage_GD_Keypad
+	CollectionApplication(
+		// Byte 0
+		ReportId(PAD_REPORT_ID)
+		LogicalRange_i8(0, 1)
+		UsagePage_Digitizers
+		Usage_Dig_TabletFunctionKeys
+		CollectionPhysical(
+			// Byte 1 are the buttons
+			Usage_Dig_BarrelSwitch	 // BTN_STYLUS, needed so we get to be a tablet pad
+			ReportCount(1)
+			ReportSize(1)
+			Input(Var|Abs)
+			ReportCount(7) // Padding
+			Input(Const)
+			// Bytes 2/3 - x/y just exist so we get to be a tablet pad
+			UsagePage_GenericDesktop
+			Usage_GD_X
+			Usage_GD_Y
+			ReportCount(2)
+			ReportSize(8)
+			Input(Var|Abs)
+			// Byte 4 is the button state
+			UsagePage_Button
+			UsageRange_i8(0x01, 0x6)
+			LogicalRange_i8(0x0, 0x1)
+			ReportCount(6)
+			ReportSize(1)
+			Input(Var|Abs)
+			ReportCount(2)
+			Input(Const)
+			// Byte 5 is the wheel
+			UsagePage_GenericDesktop
+			Usage_GD_Wheel
+			LogicalRange_i8(-1, 1)
+			ReportCount(1)
+			ReportSize(8)
+			Input(Var|Rel)
+		)
+		// Make sure we match our original report length
+		FixedSizeVendorReport(VENDOR_REPORT_LENGTH)
+	)
+};
+
+static const __u8 disabled_rdesc_pen[] = {
+	FixedSizeVendorReport(PEN_REPORT_LENGTH)
+};
+
+static const __u8 disabled_rdesc_pad[] = {
+	FixedSizeVendorReport(PAD_REPORT_LENGTH)
+};
+
+SEC(HID_BPF_RDESC_FIXUP)
+int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx)
+{
+	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */);
+	__s32 rdesc_size = hctx->size;
+	__u8 have_fw_id;
+
+	if (!data)
+		return 0; /* EPERM check */
+
+	/* If we have a firmware ID and it matches our expected prefix, we
+	 * disable the default pad/pen nodes. They won't send events
+	 * but cause duplicate devices.
+	 */
+	have_fw_id = __builtin_memcmp(UDEV_PROP_HUION_FIRMWARE_ID,
+				      EXPECTED_FIRMWARE_ID,
+				      sizeof(EXPECTED_FIRMWARE_ID) - 1) == 0;
+	if (rdesc_size == PAD_REPORT_DESCRIPTOR_LENGTH) {
+		if (have_fw_id) {
+			__builtin_memcpy(data, disabled_rdesc_pad, sizeof(disabled_rdesc_pad));
+			return sizeof(disabled_rdesc_pad);
+		}
+
+		__builtin_memcpy(data, fixed_rdesc_pad, sizeof(fixed_rdesc_pad));
+		return sizeof(fixed_rdesc_pad);
+	}
+	if (rdesc_size == PEN_REPORT_DESCRIPTOR_LENGTH) {
+		if (have_fw_id) {
+			__builtin_memcpy(data, disabled_rdesc_pen, sizeof(disabled_rdesc_pen));
+			return sizeof(disabled_rdesc_pen);
+		}
+
+		__builtin_memcpy(data, fixed_rdesc_pen, sizeof(fixed_rdesc_pen));
+		return sizeof(fixed_rdesc_pen);
+	}
+	/* Always fix the vendor mode so the tablet will work even if nothing sets
+	 * the udev property (e.g. huion-switcher run manually)
+	 */
+	if (rdesc_size == VENDOR_REPORT_DESCRIPTOR_LENGTH) {
+		__builtin_memcpy(data, fixed_rdesc_vendor, sizeof(fixed_rdesc_vendor));
+		return sizeof(fixed_rdesc_vendor);
+
+	}
+	return 0;
+}
+
+SEC(HID_BPF_DEVICE_EVENT)
+int BPF_PROG(inspiroy_2_fix_events, struct hid_bpf_ctx *hctx)
+{
+	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
+
+	if (!data)
+		return 0; /* EPERM check */
+
+	/* Only sent if tablet is in default mode */
+	if (data[0] == PAD_REPORT_ID) {
+		/* Nicely enough, this device only supports one button down at a time so
+		 * the reports are easy to match. Buttons numbered from the top
+		 *   Button released: 03 00 00 00 00 00 00 00
+		 *   Button 1: 03 00 05 00 00 00 00 00 -> b
+		 *   Button 2: 03 00 0c 00 00 00 00 00 -> i
+		 *   Button 3: 03 00 08 00 00 00 00 00 -> e
+		 *   Button 4: 03 01 16 00 00 00 00 00 -> Ctrl S
+		 *   Button 5: 03 00 2c 00 00 00 00 00 -> space
+		 *   Button 6: 03 05 1d 00 00 00 00 00 -> Ctrl Alt Z
+		 *
+		 *   Wheel down: 03 01 2d 00 00 00 00 00 -> Ctrl -
+		 *   Wheel up:   03 01 2e 00 00 00 00 00 -> Ctrl =
+		 */
+		__u8 button = 0;
+		__u8 wheel = 0;
+
+		switch (data[1] << 8 | data[2]) {
+		case 0x0000:
+			break;
+		case 0x0005:
+			button = 1;
+			break;
+		case 0x000c:
+			button = 2;
+			break;
+		case 0x0008:
+			button = 3;
+			break;
+		case 0x0116:
+			button = 4;
+			break;
+		case 0x002c:
+			button = 5;
+			break;
+		case 0x051d:
+			button = 6;
+			break;
+		case 0x012d:
+			wheel = -1;
+			break;
+		case 0x012e:
+			wheel = 1;
+			break;
+
+		}
+
+		__u8 report[6] = {PAD_REPORT_ID, 0x0, 0x0, 0x0, wheel, button};
+
+		__builtin_memcpy(data, report, sizeof(report));
+		return sizeof(report);
+	}
+
+	/* Nothing to do for the PEN_REPORT_ID, it's already mapped */
+
+	/* Only sent if tablet is in raw mode */
+	if (data[0] == VENDOR_REPORT_ID) {
+		/* Pad reports */
+		if (data[1] & 0x20) {
+			/* See fixed_rdesc_pad */
+			struct pad_report {
+				__u8 report_id;
+				__u8 btn_stylus;
+				__u8 x;
+				__u8 y;
+				__u8 buttons;
+				__u8 wheel;
+			} __attribute__((packed)) *pad_report;
+			__u8 wheel = 0;
+
+			/* Wheel report */
+			if (data[1] == 0xf1) {
+				if (data[5] == 2)
+					wheel = 0xff;
+				else
+					wheel = data[5];
+			} else {
+				/* data[4] are the buttons, mapped correctly */
+				last_button_state = data[4];
+				wheel = 0; // wheel
+			}
+
+			pad_report = (struct pad_report *)data;
+
+			pad_report->report_id = PAD_REPORT_ID;
+			pad_report->btn_stylus = 0;
+			pad_report->x = 0;
+			pad_report->y = 0;
+			pad_report->buttons = last_button_state;
+			pad_report->wheel = wheel;
+
+			return sizeof(struct pad_report);
+		}
+
+		/* Pen reports need nothing done */
+	}
+
+	return 0;
+}
+
+HID_BPF_OPS(inspiroy_2) = {
+	.hid_device_event = (void *)inspiroy_2_fix_events,
+	.hid_rdesc_fixup = (void *)hid_fix_rdesc,
+};
+
+SEC("syscall")
+int probe(struct hid_bpf_probe_args *ctx)
+{
+	switch (ctx->rdesc_size) {
+	case PAD_REPORT_DESCRIPTOR_LENGTH:
+	case PEN_REPORT_DESCRIPTOR_LENGTH:
+	case VENDOR_REPORT_DESCRIPTOR_LENGTH:
+		ctx->retval = 0;
+		break;
+	default:
+		ctx->retval = -EINVAL;
+	}
+
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";

-- 
2.44.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/6] HID: bpf: move the BIT() macro to hid_bpf_helpers.h
  2024-06-27  9:54 [PATCH 0/6] HID: bpf: import some more fixes from udev-hid-bpf Benjamin Tissoires
  2024-06-27  9:54 ` [PATCH 1/6] HID: bpf: Add a HID report composition helper macros Benjamin Tissoires
  2024-06-27  9:54 ` [PATCH 2/6] HID: bpf: add a driver for the Huion Inspiroy 2S (H641P) Benjamin Tissoires
@ 2024-06-27  9:54 ` Benjamin Tissoires
  2024-06-27  9:54 ` [PATCH 4/6] HID: bpf: Add support for the XP-PEN Deco Mini 4 Benjamin Tissoires
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Benjamin Tissoires @ 2024-06-27  9:54 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: linux-kernel, linux-input, bpf, Benjamin Tissoires,
	José Expósito

This macro can be useful in mopre than one place

Link: https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/commit/7970a9c17aa0756bad63e89fccb6ee4f2ec83ccc
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
---
 drivers/hid/bpf/progs/XPPen__Artist24.bpf.c | 2 --
 drivers/hid/bpf/progs/hid_bpf_helpers.h     | 1 +
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c b/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c
index d4d062c3a653..c24fe905c50d 100644
--- a/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c
+++ b/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c
@@ -78,8 +78,6 @@ static const __u8 fixed_rdesc[] = {
 	0xc0,                          // End Collection                      106
 };
 
-#define BIT(n) (1UL << n)
-
 #define TIP_SWITCH		BIT(0)
 #define BARREL_SWITCH		BIT(1)
 #define ERASER			BIT(2)
diff --git a/drivers/hid/bpf/progs/hid_bpf_helpers.h b/drivers/hid/bpf/progs/hid_bpf_helpers.h
index 8f226f6e886b..3ba24d125a08 100644
--- a/drivers/hid/bpf/progs/hid_bpf_helpers.h
+++ b/drivers/hid/bpf/progs/hid_bpf_helpers.h
@@ -66,6 +66,7 @@ extern int hid_bpf_hw_request(struct hid_bpf_ctx *ctx,
 #define HID_VID_ANY				0x0000
 #define HID_PID_ANY				0x0000
 
+#define BIT(n) (1UL << (n))
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
 
 /* Helper macro to convert (foo, __LINE__)  into foo134 so we can use __LINE__ for

-- 
2.44.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/6] HID: bpf: Add support for the XP-PEN Deco Mini 4
  2024-06-27  9:54 [PATCH 0/6] HID: bpf: import some more fixes from udev-hid-bpf Benjamin Tissoires
                   ` (2 preceding siblings ...)
  2024-06-27  9:54 ` [PATCH 3/6] HID: bpf: move the BIT() macro to hid_bpf_helpers.h Benjamin Tissoires
@ 2024-06-27  9:54 ` Benjamin Tissoires
  2024-06-27  9:54 ` [PATCH 5/6] HID: bpf: Add Huion Dial 2 bpf fixup Benjamin Tissoires
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Benjamin Tissoires @ 2024-06-27  9:54 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: linux-kernel, linux-input, bpf, Benjamin Tissoires,
	José Expósito

The XP-PEN Deco Mini 4 is a UGEE device with a frame with 6 buttons.
Its pen has 2 buttons and supports pressure reporting.

Fix their report descriptors and transform the frame button events to
support it.

Link: https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/88
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
---
 drivers/hid/bpf/progs/XPPen__DecoMini4.bpf.c | 231 +++++++++++++++++++++++++++
 1 file changed, 231 insertions(+)

diff --git a/drivers/hid/bpf/progs/XPPen__DecoMini4.bpf.c b/drivers/hid/bpf/progs/XPPen__DecoMini4.bpf.c
new file mode 100644
index 000000000000..46d5c459d0c9
--- /dev/null
+++ b/drivers/hid/bpf/progs/XPPen__DecoMini4.bpf.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2024 José Expósito
+ */
+
+#include "vmlinux.h"
+#include "hid_bpf.h"
+#include "hid_bpf_helpers.h"
+#include <bpf/bpf_tracing.h>
+
+#define VID_UGEE	0x28BD
+#define PID_DECO_MINI_4	0x0929
+#define RDESC_SIZE_PAD	177
+#define RDESC_SIZE_PEN	109
+#define PAD_REPORT_ID	0x06
+
+/*
+ * XP-Pen devices return a descriptor with the values the driver should use when
+ * one of its interfaces is queried. For this device the descriptor is:
+ *
+ * 0E 03 60 4F 88 3B 06 00 FF 1F D8 13
+ *       ----- -----       ----- -----
+ *         |     |           |     |
+ *         |     |           |     `- Resolution: 5080 (13d8)
+ *         |     |           `- Maximum pressure: 8191 (1FFF)
+ *         |     `- Logical maximum Y: 15240 (3B88)
+ *         `- Logical maximum X: 20320 (4F60)
+ *
+ * The physical maximum is calculated as (logical_max * 1000) / resolution.
+ */
+#define LOGICAL_MAX_X	0x60, 0x4F
+#define LOGICAL_MAX_Y	0x88, 0x3B
+#define PHYSICAL_MAX_X	0xA0, 0x0F
+#define PHYSICAL_MAX_Y	0xB8, 0x0B
+#define PRESSURE_MAX	0xFF, 0x1F
+
+HID_BPF_CONFIG(
+	HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_UGEE, PID_DECO_MINI_4)
+);
+
+/*
+ * The tablet send these values when the pad buttons are pressed individually:
+ *
+ *   Buttons released: 06 00 00 00 00 00 00 00
+ *   Button 1:         06 00 05 00 00 00 00 00 -> b
+ *   Button 2:         06 00 08 00 00 00 00 00 -> e
+ *   Button 3:         06 04 00 00 00 00 00 00 -> LAlt
+ *   Button 4:         06 00 2c 00 00 00 00 00 -> Space
+ *   Button 5:         06 01 16 00 00 00 00 00 -> LControl + s
+ *   Button 6:         06 01 1d 00 00 00 00 00 -> LControl + z
+ *
+ * When multiple buttons are pressed at the same time, the values used to
+ * identify the buttons are identical, but they appear in different bytes of the
+ * record. For example, when button 2 (0x08) and button 1 (0x05) are pressed,
+ * this is the report:
+ *
+ *   Buttons 2 and 1:  06 00 08 05 00 00 00 00 -> e + b
+ *
+ * Buttons 1, 2, 4, 5 and 6 can be matched by finding their values in the
+ * report.
+ *
+ * Button 3 is pressed when the 3rd bit is 1. For example, pressing buttons 3
+ * and 5 generates this report:
+ *
+ *   Buttons 3 and 5:  06 05 16 00 00 00 00 00 -> LControl + LAlt + s
+ *                        -- --
+ *                         |  |
+ *                         |  `- Button 5 (0x16)
+ *                         `- 0x05 = 0101. Button 3 is pressed
+ *                                    ^
+ *
+ * pad_buttons contains a list of buttons that can be matched in
+ * HID_BPF_DEVICE_EVENT. Button 3 as it has a dedicated bit.
+ */
+static const __u8 pad_buttons[] = { 0x05, 0x08, 0x00, 0x2C, 0x16, 0x1D };
+
+static const __u8 fixed_pad_rdesc[] = {
+	0x05, 0x01,           /*  Usage Page (Desktop),                   */
+	0x09, 0x07,           /*  Usage (Keypad),                         */
+	0xA1, 0x01,           /*  Collection (Application),               */
+	0x85, 0x06,           /*      Report ID (6),                      */
+	0x05, 0x0D,           /*      Usage Page (Digitizer),             */
+	0x09, 0x39,           /*      Usage (Tablet Function Keys),       */
+	0xA0,                 /*      Collection (Physical),              */
+	0x05, 0x09,           /*          Usage Page (Button),            */
+	0x75, 0x01,           /*          Report Size (1),                */
+	0x95, 0x06,           /*          Report Count (6),               */
+	0x19, 0x01,           /*          Usage Minimum (01h),            */
+	0x29, 0x06,           /*          Usage Maximum (06h),            */
+	0x14,                 /*          Logical Minimum (0),            */
+	0x25, 0x01,           /*          Logical Maximum (1),            */
+	0x81, 0x02,           /*          Input (Variable),               */
+	0x95, 0x32,           /*          Report Count (50),              */
+	0x81, 0x01,           /*          Input (Constant),               */
+	0xC0,                 /*      End Collection,                     */
+	0xC0                  /*  End Collection                          */
+};
+
+static const __u8 fixed_pen_rdesc[] = {
+	0x05, 0x0d,           /*  Usage Page (Digitizers),                */
+	0x09, 0x01,           /*  Usage (Digitizer),                      */
+	0xa1, 0x01,           /*  Collection (Application),               */
+	0x85, 0x07,           /*      Report ID (7),                      */
+	0x09, 0x20,           /*      Usage (Stylus),                     */
+	0xa1, 0x00,           /*      Collection (Physical),              */
+	0x09, 0x42,           /*          Usage (Tip Switch),             */
+	0x09, 0x44,           /*          Usage (Barrel Switch),          */
+	0x09, 0x46,           /*          Usage (Tablet Pick),            */
+	0x75, 0x01,           /*          Report Size (1),                */
+	0x95, 0x03,           /*          Report Count (3),               */
+	0x14,                 /*          Logical Minimum (0),            */
+	0x25, 0x01,           /*          Logical Maximum (1),            */
+	0x81, 0x02,           /*          Input (Variable),               */
+	0x95, 0x02,           /*          Report Count (2),               */
+	0x81, 0x03,           /*          Input (Constant, Variable),     */
+	0x09, 0x32,           /*          Usage (In Range),               */
+	0x95, 0x01,           /*          Report Count (1),               */
+	0x81, 0x02,           /*          Input (Variable),               */
+	0x95, 0x02,           /*          Report Count (2),               */
+	0x81, 0x03,           /*          Input (Constant, Variable),     */
+	0x75, 0x10,           /*          Report Size (16),               */
+	0x95, 0x01,           /*          Report Count (1),               */
+	0x35, 0x00,           /*          Physical Minimum (0),           */
+	0xa4,                 /*          Push,                           */
+	0x05, 0x01,           /*          Usage Page (Desktop),           */
+	0x09, 0x30,           /*          Usage (X),                      */
+	0x65, 0x13,           /*          Unit (Inch),                    */
+	0x55, 0x0d,           /*          Unit Exponent (-3),             */
+	0x26, LOGICAL_MAX_X,  /*          Logical Maximum,                */
+	0x46, PHYSICAL_MAX_X, /*          Physical Maximum,               */
+	0x81, 0x02,           /*          Input (Variable),               */
+	0x09, 0x31,           /*          Usage (Y),                      */
+	0x26, LOGICAL_MAX_Y,  /*          Logical Maximum,                */
+	0x46, PHYSICAL_MAX_Y, /*          Physical Maximum,               */
+	0x81, 0x02,           /*          Input (Variable),               */
+	0xb4,                 /*          Pop,                            */
+	0x09, 0x30,           /*          Usage (Tip Pressure),           */
+	0x45, 0x00,           /*          Physical Maximum (0),           */
+	0x26, PRESSURE_MAX,   /*          Logical Maximum,                */
+	0x75, 0x0D,           /*          Report Size (13),               */
+	0x95, 0x01,           /*          Report Count (1),               */
+	0x81, 0x02,           /*          Input (Variable),               */
+	0x75, 0x01,           /*          Report Size (1),                */
+	0x95, 0x13,           /*          Report Count (19),              */
+	0x81, 0x01,           /*          Input (Constant),               */
+	0xc0,                 /*      End Collection,                     */
+	0xc0,                 /*  End Collection                          */
+};
+
+static const size_t fixed_pad_rdesc_size = sizeof(fixed_pad_rdesc);
+static const size_t fixed_pen_rdesc_size = sizeof(fixed_pen_rdesc);
+
+SEC(HID_BPF_RDESC_FIXUP)
+int BPF_PROG(hid_rdesc_fixup_xppen_deco_mini_4, struct hid_bpf_ctx *hctx)
+{
+	__u8 *data = hid_bpf_get_data(hctx, 0, HID_MAX_DESCRIPTOR_SIZE);
+
+	if (!data)
+		return 0; /* EPERM check */
+
+	if (hctx->size == RDESC_SIZE_PAD) {
+		__builtin_memcpy(data, fixed_pad_rdesc, fixed_pad_rdesc_size);
+		return fixed_pad_rdesc_size;
+	} else if (hctx->size == RDESC_SIZE_PEN) {
+		__builtin_memcpy(data, fixed_pen_rdesc, fixed_pen_rdesc_size);
+		return fixed_pen_rdesc_size;
+	}
+
+	return 0;
+}
+
+SEC(HID_BPF_DEVICE_EVENT)
+int BPF_PROG(hid_device_event_xppen_deco_mini_4, struct hid_bpf_ctx *hctx)
+{
+	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 8 /* size */);
+	__u8 button_mask = 0;
+	int d, b;
+
+	if (!data)
+		return 0; /* EPERM check */
+
+	if (data[0] != PAD_REPORT_ID)
+		return 0;
+
+	/* data[1] stores the status of BTN_2 in the 3rd bit*/
+	if (data[1] & BIT(2))
+		button_mask |= BIT(2);
+
+	/* The rest of the descriptor stores the buttons as in pad_buttons */
+	for (d = 2; d < 8; d++) {
+		for (b = 0; b < sizeof(pad_buttons); b++) {
+			if (data[d] != 0 && data[d] == pad_buttons[b])
+				button_mask |= BIT(b);
+		}
+	}
+
+	__u8 report[8] = {PAD_REPORT_ID, button_mask, 0x00};
+
+	__builtin_memcpy(data, report, sizeof(report));
+
+	return 0;
+}
+
+HID_BPF_OPS(deco_mini_4) = {
+	.hid_device_event = (void *)hid_device_event_xppen_deco_mini_4,
+	.hid_rdesc_fixup = (void *)hid_rdesc_fixup_xppen_deco_mini_4,
+};
+
+SEC("syscall")
+int probe(struct hid_bpf_probe_args *ctx)
+{
+	/*
+	 * The device has 2 modes: The compatibility mode, enabled by default,
+	 * and the raw mode, that can be activated by sending a buffer of magic
+	 * data to a certain USB endpoint.
+	 *
+	 * Depending on the mode, different interfaces of the device are used:
+	 * - First interface:  Pad in compatibility mode
+	 * - Second interface: Pen in compatibility mode
+	 * - Third interface:  Only used in raw mode
+	 *
+	 * We'll use the device in compatibility mode.
+	 */
+	ctx->retval = ctx->rdesc_size != RDESC_SIZE_PAD &&
+		      ctx->rdesc_size != RDESC_SIZE_PEN;
+	if (ctx->retval)
+		ctx->retval = -EINVAL;
+
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";

-- 
2.44.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 5/6] HID: bpf: Add Huion Dial 2 bpf fixup
  2024-06-27  9:54 [PATCH 0/6] HID: bpf: import some more fixes from udev-hid-bpf Benjamin Tissoires
                   ` (3 preceding siblings ...)
  2024-06-27  9:54 ` [PATCH 4/6] HID: bpf: Add support for the XP-PEN Deco Mini 4 Benjamin Tissoires
@ 2024-06-27  9:54 ` Benjamin Tissoires
  2024-06-27  9:54 ` [PATCH 6/6] HID: bpf: Thrustmaster TCA Yoke Boeing joystick fix Benjamin Tissoires
  2024-07-01 13:46 ` [PATCH 0/6] HID: bpf: import some more fixes from udev-hid-bpf Benjamin Tissoires
  6 siblings, 0 replies; 9+ messages in thread
From: Benjamin Tissoires @ 2024-06-27  9:54 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: linux-kernel, linux-input, bpf, Benjamin Tissoires

Pretty much similar to the Inspiroy 2, but with 2 wheels and 8 buttons.

This bpf also works in both normal and vendor mode. If the device is
switched into vendor mode by huion-switcher, a udev property is set
which is then retrieved by this bpf object. This allows to hide the now
unused normal collections.

Link: https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/103
Link: https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/104
Link: https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/111
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
---
 drivers/hid/bpf/progs/Huion__Dial-2.bpf.c | 614 ++++++++++++++++++++++++++++++
 drivers/hid/bpf/progs/hid_bpf.h           |   1 +
 2 files changed, 615 insertions(+)

diff --git a/drivers/hid/bpf/progs/Huion__Dial-2.bpf.c b/drivers/hid/bpf/progs/Huion__Dial-2.bpf.c
new file mode 100644
index 000000000000..2411dec6db08
--- /dev/null
+++ b/drivers/hid/bpf/progs/Huion__Dial-2.bpf.c
@@ -0,0 +1,614 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2024 Red Hat, Inc
+ */
+
+#include "vmlinux.h"
+#include "hid_bpf.h"
+#include "hid_bpf_helpers.h"
+#include "hid_report_helpers.h"
+#include <bpf/bpf_tracing.h>
+
+#define VID_HUION 0x256C
+#define PID_DIAL_2 0x0060
+
+
+HID_BPF_CONFIG(
+	HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_HUION, PID_DIAL_2),
+);
+
+/* Filled in by udev-hid-bpf */
+char UDEV_PROP_HUION_FIRMWARE_ID[64];
+
+/* The prefix of the firmware ID we expect for this device. The full firmware
+ * string has a date suffix, e.g. HUION_T21j_221221
+ */
+char EXPECTED_FIRMWARE_ID[] = "HUION_T216_";
+
+/* How this BPF program works: the tablet has two modes, firmware mode and
+ * tablet mode. In firmware mode (out of the box) the tablet sends button events
+ * and the dial as keyboard combinations. In tablet mode it uses a vendor specific
+ * hid report to report everything instead.
+ * Depending on the mode some hid reports are never sent and the corresponding
+ * devices are mute.
+ *
+ * To switch the tablet use e.g.  https://github.com/whot/huion-switcher
+ * or one of the tools from the digimend project
+ *
+ * This BPF works for both modes. The huion-switcher tool sets the
+ * HUION_FIRMWARE_ID udev property - if that is set then we disable the firmware
+ * pad and pen reports (by making them vendor collections that are ignored).
+ * If that property is not set we fix all hidraw nodes so the tablet works in
+ * either mode though the drawback is that the device will show up twice if
+ * you bind it to all event nodes
+ *
+ * Default report descriptor for the first exposed hidraw node:
+ *
+ * # HUION Huion Tablet_Q630M
+ * # 0x06, 0x00, 0xff,              // Usage Page (Vendor Defined Page 1)  0
+ * # 0x09, 0x01,                    // Usage (Vendor Usage 1)              3
+ * # 0xa1, 0x01,                    // Collection (Application)            5
+ * # 0x85, 0x08,                    //  Report ID (8)                      7
+ * # 0x75, 0x58,                    //  Report Size (88)                   9
+ * # 0x95, 0x01,                    //  Report Count (1)                   11
+ * # 0x09, 0x01,                    //  Usage (Vendor Usage 1)             13
+ * # 0x81, 0x02,                    //  Input (Data,Var,Abs)               15
+ * # 0xc0,                          // End Collection                      17
+ * R: 18 06 00 ff 09 01 a1 01 85 08 75 58 95 01 09 01 81 02 c0
+ *
+ * This rdesc does nothing until the tablet is switched to raw mode, see
+ * https://github.com/whot/huion-switcher
+ *
+ *
+ * Second hidraw node is the Pen. This one sends events until the tablet is
+ * switched to raw mode, then it's mute.
+ *
+ * # Report descriptor length: 93 bytes
+ * # HUION Huion Tablet_Q630M
+ * # 0x05, 0x0d,                    // Usage Page (Digitizers)             0
+ * # 0x09, 0x02,                    // Usage (Pen)                         2
+ * # 0xa1, 0x01,                    // Collection (Application)            4
+ * # 0x85, 0x0a,                    //  Report ID (10)                     6
+ * # 0x09, 0x20,                    //  Usage (Stylus)                     8
+ * # 0xa1, 0x01,                    //  Collection (Application)           10
+ * # 0x09, 0x42,                    //   Usage (Tip Switch)                12
+ * # 0x09, 0x44,                    //   Usage (Barrel Switch)             14
+ * # 0x09, 0x45,                    //   Usage (Eraser)                    16
+ * # 0x09, 0x3c,                    //   Usage (Invert)                    18
+ * # 0x15, 0x00,                    //   Logical Minimum (0)               20
+ * # 0x25, 0x01,                    //   Logical Maximum (1)               22
+ * # 0x75, 0x01,                    //   Report Size (1)                   24
+ * # 0x95, 0x06,                    //   Report Count (6)                  26
+ * # 0x81, 0x02,                    //   Input (Data,Var,Abs)              28
+ * # 0x09, 0x32,                    //   Usage (In Range)                  30
+ * # 0x75, 0x01,                    //   Report Size (1)                   32
+ * # 0x95, 0x01,                    //   Report Count (1)                  34
+ * # 0x81, 0x02,                    //   Input (Data,Var,Abs)              36
+ * # 0x81, 0x03,                    //   Input (Cnst,Var,Abs)              38
+ * # 0x05, 0x01,                    //   Usage Page (Generic Desktop)      40
+ * # 0x09, 0x30,                    //   Usage (X)                         42
+ * # 0x09, 0x31,                    //   Usage (Y)                         44
+ * # 0x55, 0x0d,                    //   Unit Exponent (-3)                46
+ * # 0x65, 0x33,                    //   Unit (EnglishLinear: in³)         48
+ * # 0x26, 0xff, 0x7f,              //   Logical Maximum (32767)           50
+ * # 0x35, 0x00,                    //   Physical Minimum (0)              53
+ * # 0x46, 0x00, 0x08,              //   Physical Maximum (2048)           55
+ * # 0x75, 0x10,                    //   Report Size (16)                  58
+ * # 0x95, 0x02,                    //   Report Count (2)                  60
+ * # 0x81, 0x02,                    //   Input (Data,Var,Abs)              62
+ * # 0x05, 0x0d,                    //   Usage Page (Digitizers)           64
+ * # 0x09, 0x30,                    //   Usage (Tip Pressure)              66
+ * # 0x26, 0xff, 0x1f,              //   Logical Maximum (8191)            68
+ * # 0x75, 0x10,                    //   Report Size (16)                  71
+ * # 0x95, 0x01,                    //   Report Count (1)                  73
+ * # 0x81, 0x02,                    //   Input (Data,Var,Abs)              75
+ * # 0x09, 0x3d,                    //   Usage (X Tilt)                    77
+ * # 0x09, 0x3e,                    //   Usage (Y Tilt)                    79
+ * # 0x15, 0x81,                    //   Logical Minimum (-127)            81
+ * # 0x25, 0x7f,                    //   Logical Maximum (127)             83
+ * # 0x75, 0x08,                    //   Report Size (8)                   85
+ * # 0x95, 0x02,                    //   Report Count (2)                  87
+ * # 0x81, 0x02,                    //   Input (Data,Var,Abs)              89
+ * # 0xc0,                          //  End Collection                     91
+ * # 0xc0,                          // End Collection                      92
+ * R: 93 05 0d 09 02 a1 01 85 0a 09 20 a1 01 09 42 09 44 09 45 09 3c 15 00 25 01 75 01 95 06 81 02 09 32 75 01 95 01 81 02 81 03 05 01 09 30 09 31 55 0d 65 33 26 ff 7f 35 00 46 00 08 75 10 95 02 81 02 05 0d 09 30 26 ff 1f 75 10 95 01 81 02 09 3d 09 3e 15 81 25 7f 75 08 95 02 81 02 c0 c0
+ *
+ * Third hidraw node is the pad which sends a combination of keyboard shortcuts until
+ * the tablet is switched to raw mode, then it's mute:
+ *
+ * # Report descriptor length: 148 bytes
+ * # HUION Huion Tablet_Q630M
+ * # 0x05, 0x01,                    // Usage Page (Generic Desktop)        0
+ * # 0x09, 0x0e,                    // Usage (System Multi-Axis Controller) 2
+ * # 0xa1, 0x01,                    // Collection (Application)            4
+ * # 0x85, 0x11,                    //  Report ID (17)                     6
+ * # 0x05, 0x0d,                    //  Usage Page (Digitizers)            8
+ * # 0x09, 0x21,                    //  Usage (Puck)                       10
+ * # 0xa1, 0x02,                    //  Collection (Logical)               12
+ * # 0x15, 0x00,                    //   Logical Minimum (0)               14
+ * # 0x25, 0x01,                    //   Logical Maximum (1)               16
+ * # 0x75, 0x01,                    //   Report Size (1)                   18
+ * # 0x95, 0x01,                    //   Report Count (1)                  20
+ * # 0xa1, 0x00,                    //   Collection (Physical)             22
+ * # 0x05, 0x09,                    //    Usage Page (Button)              24
+ * # 0x09, 0x01,                    //    Usage (Vendor Usage 0x01)        26
+ * # 0x81, 0x02,                    //    Input (Data,Var,Abs)             28
+ * # 0x05, 0x0d,                    //    Usage Page (Digitizers)          30
+ * # 0x09, 0x33,                    //    Usage (Touch)                    32
+ * # 0x81, 0x02,                    //    Input (Data,Var,Abs)             34
+ * # 0x95, 0x06,                    //    Report Count (6)                 36
+ * # 0x81, 0x03,                    //    Input (Cnst,Var,Abs)             38
+ * # 0xa1, 0x02,                    //    Collection (Logical)             40
+ * # 0x05, 0x01,                    //     Usage Page (Generic Desktop)    42
+ * # 0x09, 0x37,                    //     Usage (Dial)                    44
+ * # 0x16, 0x00, 0x80,              //     Logical Minimum (-32768)        46
+ * # 0x26, 0xff, 0x7f,              //     Logical Maximum (32767)         49
+ * # 0x75, 0x10,                    //     Report Size (16)                52
+ * # 0x95, 0x01,                    //     Report Count (1)                54
+ * # 0x81, 0x06,                    //     Input (Data,Var,Rel)            56
+ * # 0x35, 0x00,                    //     Physical Minimum (0)            58
+ * # 0x46, 0x10, 0x0e,              //     Physical Maximum (3600)         60
+ * # 0x15, 0x00,                    //     Logical Minimum (0)             63
+ * # 0x26, 0x10, 0x0e,              //     Logical Maximum (3600)          65
+ * # 0x09, 0x48,                    //     Usage (Resolution Multiplier)   68
+ * # 0xb1, 0x02,                    //     Feature (Data,Var,Abs)          70
+ * # 0x45, 0x00,                    //     Physical Maximum (0)            72
+ * # 0xc0,                          //    End Collection                   74
+ * # 0x75, 0x08,                    //    Report Size (8)                  75
+ * # 0x95, 0x01,                    //    Report Count (1)                 77
+ * # 0x81, 0x01,                    //    Input (Cnst,Arr,Abs)             79
+ * # 0x75, 0x08,                    //    Report Size (8)                  81
+ * # 0x95, 0x01,                    //    Report Count (1)                 83
+ * # 0x81, 0x01,                    //    Input (Cnst,Arr,Abs)             85
+ * # 0x75, 0x08,                    //    Report Size (8)                  87
+ * # 0x95, 0x01,                    //    Report Count (1)                 89
+ * # 0x81, 0x01,                    //    Input (Cnst,Arr,Abs)             91
+ * # 0x75, 0x08,                    //    Report Size (8)                  93
+ * # 0x95, 0x01,                    //    Report Count (1)                 95
+ * # 0x81, 0x01,                    //    Input (Cnst,Arr,Abs)             97
+ * # 0x75, 0x08,                    //    Report Size (8)                  99
+ * # 0x95, 0x01,                    //    Report Count (1)                 101
+ * # 0x81, 0x01,                    //    Input (Cnst,Arr,Abs)             103
+ * # 0xc0,                          //   End Collection                    105
+ * # 0xc0,                          //  End Collection                     106
+ * # 0xc0,                          // End Collection                      107
+ * # 0x05, 0x01,                    // Usage Page (Generic Desktop)        108
+ * # 0x09, 0x06,                    // Usage (Keyboard)                    110
+ * # 0xa1, 0x01,                    // Collection (Application)            112
+ * # 0x85, 0x03,                    //  Report ID (3)                      114
+ * # 0x05, 0x07,                    //  Usage Page (Keyboard)              116
+ * # 0x19, 0xe0,                    //  Usage Minimum (224)                118
+ * # 0x29, 0xe7,                    //  Usage Maximum (231)                120
+ * # 0x15, 0x00,                    //  Logical Minimum (0)                122
+ * # 0x25, 0x01,                    //  Logical Maximum (1)                124
+ * # 0x75, 0x01,                    //  Report Size (1)                    126
+ * # 0x95, 0x08,                    //  Report Count (8)                   128
+ * # 0x81, 0x02,                    //  Input (Data,Var,Abs)               130
+ * # 0x05, 0x07,                    //  Usage Page (Keyboard)              132
+ * # 0x19, 0x00,                    //  Usage Minimum (0)                  134
+ * # 0x29, 0xff,                    //  Usage Maximum (255)                136
+ * # 0x26, 0xff, 0x00,              //  Logical Maximum (255)              138
+ * # 0x75, 0x08,                    //  Report Size (8)                    141
+ * # 0x95, 0x06,                    //  Report Count (6)                   143
+ * # 0x81, 0x00,                    //  Input (Data,Arr,Abs)               145
+ * # 0xc0,                          // End Collection                      147
+ * R: 148 05 01 09 0e a1 01 85 11 05 0d 09 21 a1 02 15 00 25 01 75 01 95 01 a1 00 05 09 09 01 81 02 05 0d 09 33 81 02 95 06 81 03 a1 02 05 01 09 37 16 00 80 26 ff 7f 75 10 95 01 81 06 35 00 46 10 0e 15 00 26 10 0e 09 48 b1 02 45 00 c0 75 08 95 01 81 01 75 08 95 01 81 01 75 08 95 01 81 01 75 08 95 01 81 01 75 08 95 01 81 01 c0 c0 c0 05 01 09 06 a1 01 85 03 05 07 19 e0 29 e7 15 00 25 01 75 01 95 08 81 02 05 07 19 00 29 ff 26 ff 00 75 08 95 06 81 00 c0
+ */
+
+#define PAD_REPORT_DESCRIPTOR_LENGTH 148
+#define PEN_REPORT_DESCRIPTOR_LENGTH 93
+#define VENDOR_REPORT_DESCRIPTOR_LENGTH 18
+#define PAD_REPORT_ID 3
+#define DIAL_REPORT_ID 17
+#define PEN_REPORT_ID 10
+#define VENDOR_REPORT_ID 8
+#define PAD_REPORT_LENGTH 9
+#define PEN_REPORT_LENGTH 10
+#define VENDOR_REPORT_LENGTH 12
+
+
+__u8 last_button_state;
+
+static const __u8 fixed_rdesc_pad[] = {
+	UsagePage_GenericDesktop
+	Usage_GD_Keypad
+	CollectionApplication(
+		// -- Byte 0 in report
+		ReportId(PAD_REPORT_ID)
+		LogicalRange_i8(0, 1)
+		UsagePage_Digitizers
+		Usage_Dig_TabletFunctionKeys
+		CollectionPhysical(
+			// Byte 1 in report - just exists so we get to be a tablet pad
+			Usage_Dig_BarrelSwitch // BTN_STYLUS
+			ReportCount(1)
+			ReportSize(1)
+			Input(Var|Abs)
+			ReportCount(7) // padding
+			Input(Const)
+			// Bytes 2/3 in report - just exists so we get to be a tablet pad
+			UsagePage_GenericDesktop
+			Usage_GD_X
+			Usage_GD_Y
+			ReportCount(2)
+			ReportSize(8)
+			Input(Var|Abs)
+			// Byte 4 in report is the dial
+			Usage_GD_Wheel
+			LogicalRange_i8(-1, 1)
+			ReportCount(1)
+			ReportSize(8)
+			Input(Var|Rel)
+			// Byte 5 is the button state
+			UsagePage_Button
+			UsageRange_i8(0x01, 0x8)
+			LogicalRange_i8(0x0, 0x1)
+			ReportCount(7)
+			ReportSize(1)
+			Input(Var|Abs)
+			ReportCount(1) // padding
+			Input(Const)
+		)
+		// Make sure we match our original report length
+		FixedSizeVendorReport(PAD_REPORT_LENGTH)
+	)
+};
+
+static const __u8 fixed_rdesc_pen[] = {
+	UsagePage_Digitizers
+	Usage_Dig_Pen
+	CollectionApplication(
+		// -- Byte 0 in report
+		ReportId(PEN_REPORT_ID)
+		Usage_Dig_Pen
+		CollectionPhysical(
+			// -- Byte 1 in report
+			Usage_Dig_TipSwitch
+			Usage_Dig_BarrelSwitch
+			Usage_Dig_SecondaryBarrelSwitch // maps eraser to BTN_STYLUS2
+			LogicalRange_i8(0, 1)
+			ReportSize(1)
+			ReportCount(3)
+			Input(Var|Abs)
+			ReportCount(4)  // Padding
+			Input(Const)
+			Usage_Dig_InRange
+			ReportCount(1)
+			Input(Var|Abs)
+			ReportSize(16)
+			ReportCount(1)
+			PushPop(
+				UsagePage_GenericDesktop
+				Unit(cm)
+				UnitExponent(-1)
+				PhysicalRange_i16(0, 266)
+				LogicalRange_i16(0, 32767)
+				Usage_GD_X
+				Input(Var|Abs) // Bytes 2+3
+				PhysicalRange_i16(0, 166)
+				LogicalRange_i16(0, 32767)
+				Usage_GD_Y
+				Input(Var|Abs) // Bytes 4+5
+			)
+			UsagePage_Digitizers
+			Usage_Dig_TipPressure
+			LogicalRange_i16(0, 8191)
+			Input(Var|Abs) // Byte 6+7
+			ReportSize(8)
+			ReportCount(2)
+			LogicalRange_i8(-60, 60)
+			Usage_Dig_XTilt
+			Usage_Dig_YTilt
+			Input(Var|Abs) // Byte 8+9
+		)
+	)
+};
+
+static const __u8 fixed_rdesc_vendor[] = {
+	UsagePage_Digitizers
+	Usage_Dig_Pen
+	CollectionApplication(
+		// Byte 0
+		// We leave the pen on the vendor report ID
+		ReportId(VENDOR_REPORT_ID)
+		Usage_Dig_Pen
+		CollectionPhysical(
+			// Byte 1 are the buttons
+			LogicalRange_i8(0, 1)
+			ReportSize(1)
+			Usage_Dig_TipSwitch
+			Usage_Dig_BarrelSwitch
+			Usage_Dig_SecondaryBarrelSwitch
+			ReportCount(3)
+			Input(Var|Abs)
+			ReportCount(4) // Padding
+			Input(Const)
+			Usage_Dig_InRange
+			ReportCount(1)
+			Input(Var|Abs)
+			ReportSize(16)
+			ReportCount(1)
+			PushPop(
+				UsagePage_GenericDesktop
+				Unit(cm)
+				UnitExponent(-1)
+				// Note: reported logical range differs
+				// from the pen report ID for x and y
+				LogicalRange_i16(0, 53340)
+				PhysicalRange_i16(0, 266)
+				// Bytes 2/3 in report
+				Usage_GD_X
+				Input(Var|Abs)
+				LogicalRange_i16(0, 33340)
+				PhysicalRange_i16(0, 166)
+				// Bytes 4/5 in report
+				Usage_GD_Y
+				Input(Var|Abs)
+			)
+			// Bytes 6/7 in report
+			LogicalRange_i16(0, 8191)
+			Usage_Dig_TipPressure
+			Input(Var|Abs)
+			// Bytes 8/9 in report
+			ReportCount(1) // Padding
+			Input(Const)
+			LogicalRange_i8(-60, 60)
+			// Byte 10 in report
+			Usage_Dig_XTilt
+			// Byte 11 in report
+			Usage_Dig_YTilt
+			ReportSize(8)
+			ReportCount(2)
+			Input(Var|Abs)
+		)
+	)
+	UsagePage_GenericDesktop
+	Usage_GD_Keypad
+	CollectionApplication(
+		// Byte 0
+		ReportId(PAD_REPORT_ID)
+		LogicalRange_i8(0, 1)
+		UsagePage_Digitizers
+		Usage_Dig_TabletFunctionKeys
+		CollectionPhysical(
+			// Byte 1 are the buttons
+			Usage_Dig_BarrelSwitch	 // BTN_STYLUS, needed so we get to be a tablet pad
+			ReportCount(1)
+			ReportSize(1)
+			Input(Var|Abs)
+			ReportCount(7) // Padding
+			Input(Const)
+			// Bytes 2/3 - x/y just exist so we get to be a tablet pad
+			UsagePage_GenericDesktop
+			Usage_GD_X
+			Usage_GD_Y
+			ReportCount(2)
+			ReportSize(8)
+			Input(Var|Abs)
+			// Byte 4 is the button state
+			UsagePage_Button
+			UsageRange_i8(0x01, 0x8)
+			LogicalRange_i8(0x0, 0x1)
+			ReportCount(8)
+			ReportSize(1)
+			Input(Var|Abs)
+			// Byte 5 is the top dial
+			UsagePage_GenericDesktop
+			Usage_GD_Wheel
+			LogicalRange_i8(-1, 1)
+			ReportCount(1)
+			ReportSize(8)
+			Input(Var|Rel)
+			// Byte 6 is the bottom dial
+			UsagePage_Consumer
+			Usage_Con_ACPan
+			Input(Var|Rel)
+		)
+		// Make sure we match our original report length
+		FixedSizeVendorReport(VENDOR_REPORT_LENGTH)
+	)
+};
+
+static const __u8 disabled_rdesc_pen[] = {
+	FixedSizeVendorReport(PEN_REPORT_LENGTH)
+};
+
+static const __u8 disabled_rdesc_pad[] = {
+	FixedSizeVendorReport(PAD_REPORT_LENGTH)
+};
+
+SEC(HID_BPF_RDESC_FIXUP)
+int BPF_PROG(dial_2_fix_rdesc, struct hid_bpf_ctx *hctx)
+{
+	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */);
+	__s32 rdesc_size = hctx->size;
+	__u8 have_fw_id;
+
+	if (!data)
+		return 0; /* EPERM check */
+
+	/* If we have a firmware ID and it matches our expected prefix, we
+	 * disable the default pad/pen nodes. They won't send events
+	 * but cause duplicate devices.
+	 */
+	have_fw_id = __builtin_memcmp(UDEV_PROP_HUION_FIRMWARE_ID,
+				      EXPECTED_FIRMWARE_ID,
+				      sizeof(EXPECTED_FIRMWARE_ID) - 1) == 0;
+	if (rdesc_size == PAD_REPORT_DESCRIPTOR_LENGTH) {
+		if (have_fw_id) {
+			__builtin_memcpy(data, disabled_rdesc_pad, sizeof(disabled_rdesc_pad));
+			return sizeof(disabled_rdesc_pad);
+		}
+
+		__builtin_memcpy(data, fixed_rdesc_pad, sizeof(fixed_rdesc_pad));
+		return sizeof(fixed_rdesc_pad);
+	}
+	if (rdesc_size == PEN_REPORT_DESCRIPTOR_LENGTH) {
+		if (have_fw_id) {
+			__builtin_memcpy(data, disabled_rdesc_pen, sizeof(disabled_rdesc_pen));
+			return sizeof(disabled_rdesc_pen);
+		}
+
+		__builtin_memcpy(data, fixed_rdesc_pen, sizeof(fixed_rdesc_pen));
+		return sizeof(fixed_rdesc_pen);
+	}
+	/* Always fix the vendor mode so the tablet will work even if nothing sets
+	 * the udev property (e.g. huion-switcher run manually)
+	 */
+	if (rdesc_size == VENDOR_REPORT_DESCRIPTOR_LENGTH) {
+		__builtin_memcpy(data, fixed_rdesc_vendor, sizeof(fixed_rdesc_vendor));
+		return sizeof(fixed_rdesc_vendor);
+
+	}
+	return 0;
+}
+
+SEC(HID_BPF_DEVICE_EVENT)
+int BPF_PROG(dial_2_fix_events, struct hid_bpf_ctx *hctx)
+{
+	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 16 /* size */);
+	static __u8 button;
+
+	if (!data)
+		return 0; /* EPERM check */
+
+	/* Only sent if tablet is in default mode */
+	if (data[0] == PAD_REPORT_ID) {
+		/* Nicely enough, this device only supports one button down at a time so
+		 * the reports are easy to match. Buttons numbered from the top
+		 *   Button released: 03 00 00 00 00 00 00 00
+		 *   Button 1: 03 00 05 00 00 00 00 00 -> b
+		 *   Button 2: 03 00 08 00 00 00 00 00 -> e
+		 *   Button 3: 03 00 0c 00 00 00 00 00 -> i
+		 *   Button 4: 03 00 e0 16 00 00 00 00 -> Ctrl S
+		 *   Button 5: 03 00 2c 00 00 00 00 00 -> space
+		 *   Button 6: 03 00 e0 e2 1d 00 00 00 -> Ctrl Alt Z
+		 */
+		button &= 0xc0;
+
+		switch ((data[2] << 16) | (data[3] << 8) | data[4]) {
+		case 0x000000:
+			break;
+		case 0x050000:
+			button |= BIT(0);
+			break;
+		case 0x080000:
+			button |= BIT(1);
+			break;
+		case 0x0c0000:
+			button |= BIT(2);
+			break;
+		case 0xe01600:
+			button |= BIT(3);
+			break;
+		case 0x2c0000:
+			button |= BIT(4);
+			break;
+		case 0xe0e21d:
+			button |= BIT(5);
+			break;
+		}
+
+		__u8 report[8] = {PAD_REPORT_ID, 0x0, 0x0, 0x0, 0x00, button};
+
+		__builtin_memcpy(data, report, sizeof(report));
+		return sizeof(report);
+	}
+
+	/* Only sent if tablet is in default mode */
+	if (data[0] == DIAL_REPORT_ID) {
+		/*
+		 * In default mode, both dials are merged together:
+		 *
+		 *   Dial down: 11 00 ff ff 00 00 00 00 00 -> Dial -1
+		 *   Dial up:   11 00 01 00 00 00 00 00 00 -> Dial 1
+		 */
+		__u16 dial = data[3] << 8 | data[2];
+
+		button &= 0x3f;
+		button |= !!data[1] << 6;
+
+		__u8 report[] = {PAD_REPORT_ID, 0x0, 0x0, 0x0, dial, button};
+
+		__builtin_memcpy(data, report, sizeof(report));
+		return sizeof(report);
+	}
+
+	/* Nothing to do for the PEN_REPORT_ID, it's already mapped */
+
+	/* Only sent if tablet is in raw mode */
+	if (data[0] == VENDOR_REPORT_ID) {
+		/* Pad reports */
+		if (data[1] & 0x20) {
+			/* See fixed_rdesc_pad */
+			struct pad_report {
+				__u8 report_id;
+				__u8 btn_stylus;
+				__u8 x;
+				__u8 y;
+				__u8 buttons;
+				__u8 dial_1;
+				__u8 dial_2;
+			} __attribute__((packed)) *pad_report;
+			__u8 dial_1 = 0, dial_2 = 0;
+
+			/* Dial report */
+			if (data[1] == 0xf1) {
+				__u8 d = 0;
+
+				if (data[5] == 2)
+					d = 0xff;
+				else
+					d = data[5];
+
+				if (data[3] == 1)
+					dial_1 = d;
+				else
+					dial_2 = d;
+			} else {
+				/* data[4] are the buttons, mapped correctly */
+				last_button_state = data[4];
+				dial_1 = 0; // dial
+				dial_2 = 0;
+			}
+
+			pad_report = (struct pad_report *)data;
+
+			pad_report->report_id = PAD_REPORT_ID;
+			pad_report->btn_stylus = 0;
+			pad_report->x = 0;
+			pad_report->y = 0;
+			pad_report->buttons = last_button_state;
+			pad_report->dial_1 = dial_1;
+			pad_report->dial_2 = dial_2;
+
+			return sizeof(struct pad_report);
+		}
+
+		/* Pen reports need nothing done */
+	}
+
+	return 0;
+}
+
+HID_BPF_OPS(inspiroy_dial2) = {
+	.hid_device_event = (void *)dial_2_fix_events,
+	.hid_rdesc_fixup = (void *)dial_2_fix_rdesc,
+};
+
+SEC("syscall")
+int probe(struct hid_bpf_probe_args *ctx)
+{
+	switch (ctx->rdesc_size) {
+	case PAD_REPORT_DESCRIPTOR_LENGTH:
+	case PEN_REPORT_DESCRIPTOR_LENGTH:
+	case VENDOR_REPORT_DESCRIPTOR_LENGTH:
+		ctx->retval = 0;
+		break;
+	default:
+		ctx->retval = -EINVAL;
+	}
+
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/drivers/hid/bpf/progs/hid_bpf.h b/drivers/hid/bpf/progs/hid_bpf.h
index 8c1cd9e25bc3..7cabd1b2e837 100644
--- a/drivers/hid/bpf/progs/hid_bpf.h
+++ b/drivers/hid/bpf/progs/hid_bpf.h
@@ -9,6 +9,7 @@
 #define HID_BPF_RDESC_FIXUP  "struct_ops/hid_rdesc_fixup"
 #define HID_BPF_OPS(name) SEC(".struct_ops.link") \
 	struct hid_bpf_ops name
+#define hid_set_name(_hdev, _name) __builtin_memcpy(_hdev->name, _name, sizeof(_name))
 
 struct hid_bpf_probe_args {
 	unsigned int hid;

-- 
2.44.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 6/6] HID: bpf: Thrustmaster TCA Yoke Boeing joystick fix
  2024-06-27  9:54 [PATCH 0/6] HID: bpf: import some more fixes from udev-hid-bpf Benjamin Tissoires
                   ` (4 preceding siblings ...)
  2024-06-27  9:54 ` [PATCH 5/6] HID: bpf: Add Huion Dial 2 bpf fixup Benjamin Tissoires
@ 2024-06-27  9:54 ` Benjamin Tissoires
  2024-07-01 13:46 ` [PATCH 0/6] HID: bpf: import some more fixes from udev-hid-bpf Benjamin Tissoires
  6 siblings, 0 replies; 9+ messages in thread
From: Benjamin Tissoires @ 2024-06-27  9:54 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: linux-kernel, linux-input, bpf, Benjamin Tissoires, K S Iyer

This joystick's original HID descriptor is wrong & it shows a
ABS_MISC axis in Linux that doesn't exist on the hardware.

Link: https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/82
Signed-off-by: K S Iyer <kumar.s.iyer65@gmail.com>
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
---
 .../bpf/progs/Thrustmaster__TCA-Yoke-Boeing.bpf.c  | 144 +++++++++++++++++++++
 1 file changed, 144 insertions(+)

diff --git a/drivers/hid/bpf/progs/Thrustmaster__TCA-Yoke-Boeing.bpf.c b/drivers/hid/bpf/progs/Thrustmaster__TCA-Yoke-Boeing.bpf.c
new file mode 100644
index 000000000000..ecf775a99346
--- /dev/null
+++ b/drivers/hid/bpf/progs/Thrustmaster__TCA-Yoke-Boeing.bpf.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2024 Kumar Swarnam Iyer (kumar.s.iyer65@gmail.com)
+ */
+
+#include "vmlinux.h"
+#include "hid_bpf.h"
+#include "hid_bpf_helpers.h"
+#include <bpf/bpf_tracing.h>
+
+#define VID_THRUSTMASTER 0x044F
+#define PID_TCA_YOKE_BOEING 0x0409
+
+HID_BPF_CONFIG(
+	HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_THRUSTMASTER, PID_TCA_YOKE_BOEING)
+);
+
+/*  The original HID descriptor of the Thrustmaster TCA Yoke Boeing joystick contains
+ *  an Input field that shows up as an axis, ABS_MISC in Linux. But it is not possible
+ *  to assign an actual physical control to this axis as they're all taken up. There
+ *  are 2 vendor-defined inputs where the Input type appears to be defined wrongly.
+ *  This bpf attempts to fix this by changing the Inputs so that it doesn't show up in
+ *  Linux at all.
+ *  This version is the short version fix that only changes 2 fields in the descriptor
+ *  instead of the whole report descriptor.
+ *  For reference, this is the original report descriptor:
+ *
+ *  0x05, 0x01,                    // Usage Page (Generic Desktop)        0
+ *  0x09, 0x04,                    // Usage (Joystick)                    2
+ *  0xa1, 0x01,                    // Collection (Application)            4
+ *  0x85, 0x01,                    //  Report ID (1)                      6
+ *  0x09, 0x39,                    //  Usage (Hat switch)                 8
+ *  0x15, 0x00,                    //  Logical Minimum (0)                10
+ *  0x25, 0x07,                    //  Logical Maximum (7)                12
+ *  0x35, 0x00,                    //  Physical Minimum (0)               14
+ *  0x46, 0x3b, 0x01,              //  Physical Maximum (315)             16
+ *  0x65, 0x14,                    //  Unit (EnglishRotation: deg)        19
+ *  0x75, 0x04,                    //  Report Size (4)                    21
+ *  0x95, 0x01,                    //  Report Count (1)                   23
+ *  0x81, 0x42,                    //  Input (Data,Var,Abs,Null)          25
+ *  0x65, 0x00,                    //  Unit (None)                        27
+ *  0x05, 0x09,                    //  Usage Page (Button)                29
+ *  0x19, 0x01,                    //  Usage Minimum (1)                  31
+ *  0x29, 0x12,                    //  Usage Maximum (18)                 33
+ *  0x15, 0x00,                    //  Logical Minimum (0)                35
+ *  0x25, 0x01,                    //  Logical Maximum (1)                37
+ *  0x75, 0x01,                    //  Report Size (1)                    39
+ *  0x95, 0x12,                    //  Report Count (18)                  41
+ *  0x81, 0x02,                    //  Input (Data,Var,Abs)               43
+ *  0x95, 0x02,                    //  Report Count (2)                   45
+ *  0x81, 0x03,                    //  Input (Cnst,Var,Abs)               47
+ *  0x05, 0x01,                    //  Usage Page (Generic Desktop)       49
+ *  0x09, 0x31,                    //  Usage (Y)                          51
+ *  0x09, 0x30,                    //  Usage (X)                          53
+ *  0x09, 0x32,                    //  Usage (Z)                          55
+ *  0x09, 0x34,                    //  Usage (Ry)                         57
+ *  0x09, 0x33,                    //  Usage (Rx)                         59
+ *  0x09, 0x35,                    //  Usage (Rz)                         61
+ *  0x15, 0x00,                    //  Logical Minimum (0)                63
+ *  0x27, 0xff, 0xff, 0x00, 0x00,  //  Logical Maximum (65535)            65
+ *  0x75, 0x10,                    //  Report Size (16)                   70
+ *  0x95, 0x06,                    //  Report Count (6)                   72
+ *  0x81, 0x02,                    //  Input (Data,Var,Abs)               74
+ *  0x06, 0xf0, 0xff,              //  Usage Page (Vendor Usage Page 0xfff0) 76
+ *  0x09, 0x59,                    //  Usage (Vendor Usage 0x59)          79
+ *  0x15, 0x00,                    //  Logical Minimum (0)                81
+ *  0x26, 0xff, 0x00,              //  Logical Maximum (255)              83
+ *  0x75, 0x08,                    //  Report Size (8)                    86
+ *  0x95, 0x01,                    //  Report Count (1)                   88
+ *  0x81, 0x02,                    //  Input (Data,Var,Abs)               90 --> Needs to be changed
+ *  0x09, 0x51,                    //  Usage (Vendor Usage 0x51)          92
+ *  0x15, 0x00,                    //  Logical Minimum (0)                94
+ *  0x26, 0xff, 0x00,              //  Logical Maximum (255)              96
+ *  0x75, 0x08,                    //  Report Size (8)                    99
+ *  0x95, 0x20,                    //  Report Count (32)                  101 --> Needs to be changed
+ *  0x81, 0x02,                    //  Input (Data,Var,Abs)               103
+ *  0x09, 0x50,                    //  Usage (Vendor Usage 0x50)          105
+ *  0x15, 0x00,                    //  Logical Minimum (0)                107
+ *  0x26, 0xff, 0x00,              //  Logical Maximum (255)              109
+ *  0x75, 0x08,                    //  Report Size (8)                    112
+ *  0x95, 0x0f,                    //  Report Count (15)                  114
+ *  0x81, 0x03,                    //  Input (Cnst,Var,Abs)               116
+ *  0x09, 0x47,                    //  Usage (Vendor Usage 0x47)          118
+ *  0x85, 0xf2,                    //  Report ID (242)                    120
+ *  0x15, 0x00,                    //  Logical Minimum (0)                122
+ *  0x26, 0xff, 0x00,              //  Logical Maximum (255)              124
+ *  0x75, 0x08,                    //  Report Size (8)                    127
+ *  0x95, 0x3f,                    //  Report Count (63)                  129
+ *  0xb1, 0x02,                    //  Feature (Data,Var,Abs)             131
+ *  0x09, 0x48,                    //  Usage (Vendor Usage 0x48)          133
+ *  0x85, 0xf3,                    //  Report ID (243)                    135
+ *  0x15, 0x00,                    //  Logical Minimum (0)                137
+ *  0x26, 0xff, 0x00,              //  Logical Maximum (255)              139
+ *  0x75, 0x08,                    //  Report Size (8)                    142
+ *  0x95, 0x3f,                    //  Report Count (63)                  144
+ *  0xb1, 0x02,                    //  Feature (Data,Var,Abs)             146
+ *  0xc0,                          // End Collection                      148
+ */
+
+SEC(HID_BPF_RDESC_FIXUP)
+int BPF_PROG(hid_fix_rdesc_tca_yoke, struct hid_bpf_ctx *hctx)
+{
+	const int expected_length = 148;
+
+	if (hctx->size != expected_length)
+		return 0;
+
+	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */);
+
+	if (!data)
+		return 0; /* EPERM */
+
+	/* Safety check, our probe() should take care of this though */
+	if (data[1] != 0x01 /* Generic Desktop */ || data[3] != 0x04 /* Joystick */)
+		return 0;
+
+	/* The report descriptor sets incorrect Input items in 2 places, resulting in a
+	 * non-existing axis showing up.
+	 * This change sets the correct Input which prevents the axis from showing up in Linux.
+	 */
+
+	if (data[90] == 0x81 && /* Input */
+	    data[103] == 0x81) { /* Input */
+		data[91] = 0x03; /* Input set to 0x03 Constant, Variable Absolute */
+		data[104] = 0x03; /* Input set to 0X03 Constant, Variable Absolute */
+	}
+
+	return 0;
+}
+
+HID_BPF_OPS(tca_yoke) = {
+	.hid_rdesc_fixup = (void *)hid_fix_rdesc_tca_yoke,
+};
+
+SEC("syscall")
+int probe(struct hid_bpf_probe_args *ctx)
+{
+	/* ensure the kernel isn't fixed already */
+	if (ctx->rdesc[91] != 0x02) /* Input for 0x59 Usage type has changed */
+		ctx->retval = -EINVAL;
+
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";

-- 
2.44.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/6] HID: bpf: add a driver for the Huion Inspiroy 2S (H641P)
  2024-06-27  9:54 ` [PATCH 2/6] HID: bpf: add a driver for the Huion Inspiroy 2S (H641P) Benjamin Tissoires
@ 2024-06-28  0:22   ` Peter Hutterer
  0 siblings, 0 replies; 9+ messages in thread
From: Peter Hutterer @ 2024-06-28  0:22 UTC (permalink / raw)
  To: Benjamin Tissoires; +Cc: Jiri Kosina, linux-kernel, linux-input, bpf

On Thu, Jun 27, 2024 at 11:54:18AM +0200, Benjamin Tissoires wrote:
> This is a a driver for the Huion Inspiroy 2S in both modes (firmware mode
> and tablet mode). This device has 6 buttons and a wheel, all of which
> send key combinations (see the comments for the defaults). Luckily the
> device is quite limited in that it only supports one button down at a
> time, so with this BPF we can simply remap the 8 possible report IDs to
> our own custom-built report descriptor.
> 
> If the device is in tablet mode (e.g. using huion-switcher it sends
> everything through the vendor report instead). This BPF program converts
> both, depending which devices you attach to you get both. Or if you
> attach to all hid devices you get a duplicate device but it'll work
> either way.
> 
> This BPF should be mostly compatible for the M and L as well though they
> have more buttons so the rdescs will need some minor rework.
> 
> Link: https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/85
> Link: https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/109
> Signed-off-by: default avatarPeter Hutterer <peter.hutterer@who-t.net>

That looks like a copy-paste gone wrong :)

Cheers,
  Peter

> Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
> ---
>  drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c | 534 ++++++++++++++++++++++++
>  1 file changed, 534 insertions(+)
> 
> diff --git a/drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c b/drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c
> new file mode 100644
> index 000000000000..b09b80132368
> --- /dev/null
> +++ b/drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c
> @@ -0,0 +1,534 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/* Copyright (c) 2024 Red Hat, Inc
> + */
> +
> +#include "vmlinux.h"
> +#include "hid_bpf.h"
> +#include "hid_bpf_helpers.h"
> +#include "hid_report_helpers.h"
> +#include <bpf/bpf_tracing.h>
> +
> +#define VID_HUION 0x256C
> +#define PID_INSPIROY_2_S 0x0066
> +
> +HID_BPF_CONFIG(
> +	HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_HUION, PID_INSPIROY_2_S),
> +);
> +
> +/* Filled in by udev-hid-bpf */
> +char UDEV_PROP_HUION_FIRMWARE_ID[64];
> +
> +/* The prefix of the firmware ID we expect for this device. The full firmware
> + * string has a date suffix, e.g. HUION_T21j_221221
> + */
> +char EXPECTED_FIRMWARE_ID[] = "HUION_T21j_";
> +
> +/* How this BPF program works: the tablet has two modes, firmware mode and
> + * tablet mode. In firmware mode (out of the box) the tablet sends button events
> + * and the dial as keyboard combinations. In tablet mode it uses a vendor specific
> + * hid report to report everything instead.
> + * Depending on the mode some hid reports are never sent and the corresponding
> + * devices are mute.
> + *
> + * To switch the tablet use e.g.  https://github.com/whot/huion-switcher
> + * or one of the tools from the digimend project
> + *
> + * This BPF works for both modes. The huion-switcher tool sets the
> + * HUION_FIRMWARE_ID udev property - if that is set then we disable the firmware
> + * pad and pen reports (by making them vendor collections that are ignored).
> + * If that property is not set we fix all hidraw nodes so the tablet works in
> + * either mode though the drawback is that the device will show up twice if
> + * you bind it to all event nodes
> + *
> + * Default report descriptor for the first exposed hidraw node:
> + *
> + * # HUION Huion Tablet_H641P
> + * # Report descriptor length: 18 bytes
> + * # 0x06, 0x00, 0xff,              // Usage Page (Vendor Defined Page 0xFF00)   0
> + * # 0x09, 0x01,                    // Usage (Vendor Usage 0x01)                 3
> + * # 0xa1, 0x01,                    // Collection (Application)                  5
> + * # 0x85, 0x08,                    //   Report ID (8)                           7
> + * # 0x75, 0x58,                    //   Report Size (88)                        9
> + * # 0x95, 0x01,                    //   Report Count (1)                        11
> + * # 0x09, 0x01,                    //   Usage (Vendor Usage 0x01)               13
> + * # 0x81, 0x02,                    //   Input (Data,Var,Abs)                    15
> + * # 0xc0,                          // End Collection                            17
> + * R: 18 06 00 ff 09 01 a1 01 85 08 75 58 95 01 09 01 81 02 c0
> + *
> + * This rdesc does nothing until the tablet is switched to raw mode, see
> + * https://github.com/whot/huion-switcher
> + *
> + *
> + * Second hidraw node is the Pen. This one sends events until the tablet is
> + * switched to raw mode, then it's mute.
> + *
> + * # Report descriptor length: 93 bytes
> + * # 0x05, 0x0d,          // Usage Page (Digitizers)                   0
> + * # 0x09, 0x02,          // Usage (Pen)                               2
> + * # 0xa1, 0x01,          // Collection (Application)                  4
> + * # 0x85, 0x0a,          //   Report ID (10)                          6
> + * # 0x09, 0x20,          //   Usage (Stylus)                          8
> + * # 0xa1, 0x01,          //   Collection (Application)                10
> + * # 0x09, 0x42,          //     Usage (Tip Switch)                    12
> + * # 0x09, 0x44,          //     Usage (Barrel Switch)                 14
> + * # 0x09, 0x45,          //     Usage (Eraser)                        16
> + * # 0x09, 0x3c,          //     Usage (Invert)                        18 <-- has no Invert eraser
> + * # 0x15, 0x00,          //     Logical Minimum (0)                   20
> + * # 0x25, 0x01,          //     Logical Maximum (1)                   22
> + * # 0x75, 0x01,          //     Report Size (1)                       24
> + * # 0x95, 0x06,          //     Report Count (6)                      26
> + * # 0x81, 0x02,          //     Input (Data,Var,Abs)                  28
> + * # 0x09, 0x32,          //     Usage (In Range)                      30
> + * # 0x75, 0x01,          //     Report Size (1)                       32
> + * # 0x95, 0x01,          //     Report Count (1)                      34
> + * # 0x81, 0x02,          //     Input (Data,Var,Abs)                  36
> + * # 0x81, 0x03,          //     Input (Cnst,Var,Abs)                  38
> + * # 0x05, 0x01,          //     Usage Page (Generic Desktop)          40
> + * # 0x09, 0x30,          //     Usage (X)                             42
> + * # 0x09, 0x31,          //     Usage (Y)                             44
> + * # 0x55, 0x0d,          //     Unit Exponent (-3)                    46 <-- change to -2
> + * # 0x65, 0x33,          //     Unit (EnglishLinear: in³)             48 <-- change in³ to in
> + * # 0x26, 0xff, 0x7f,    //     Logical Maximum (32767)               50
> + * # 0x35, 0x00,          //     Physical Minimum (0)                  53
> + * # 0x46, 0x00, 0x08,    //     Physical Maximum (2048)               55 <-- invalid size
> + * # 0x75, 0x10,          //     Report Size (16)                      58
> + * # 0x95, 0x02,          //     Report Count (2)                      60
> + * # 0x81, 0x02,          //     Input (Data,Var,Abs)                  62
> + * # 0x05, 0x0d,          //     Usage Page (Digitizers)               64
> + * # 0x09, 0x30,          //     Usage (Tip Pressure)                  66
> + * # 0x26, 0xff, 0x1f,    //     Logical Maximum (8191)                68
> + * # 0x75, 0x10,          //     Report Size (16)                      71
> + * # 0x95, 0x01,          //     Report Count (1)                      73
> + * # 0x81, 0x02,          //     Input (Data,Var,Abs)                  75
> + * # 0x09, 0x3d,          //     Usage (X Tilt)                        77 <-- No tilt reported
> + * # 0x09, 0x3e,          //     Usage (Y Tilt)                        79
> + * # 0x15, 0x81,          //     Logical Minimum (-127)                81
> + * # 0x25, 0x7f,          //     Logical Maximum (127)                 83
> + * # 0x75, 0x08,          //     Report Size (8)                       85
> + * # 0x95, 0x02,          //     Report Count (2)                      87
> + * # 0x81, 0x02,          //     Input (Data,Var,Abs)                  89
> + * # 0xc0,                //   End Collection                          91
> + * # 0xc0,                // End Collection                            92
> + * R: 93 05 0d 09 02 a1 01 85 0a 09 20 a1 01 09 42 09 44 09 45 09 3c 15 00 25 01 7501 95 06 81 02 09 32 75 01 95 01 81 02 81 03 05 01 09 30 09 31 55 0d 65 33 26 ff7f 35 00 46 00 08 75 10 95 02 81 02 05 0d 09 30 26 ff 1f 75 10 95 01 81 02 09 3d09 3e 15 81 25 7f 75 08 95 02 81 02 c0 c0
> + *
> + * Third hidraw node is the pad which sends a combination of keyboard shortcuts until
> + * the tablet is switched to raw mode, then it's mute:
> + *
> + * # Report descriptor length: 65 bytes
> + * # 0x05, 0x01,          // Usage Page (Generic Desktop)              0
> + * # 0x09, 0x06,          // Usage (Keyboard)                          2
> + * # 0xa1, 0x01,          // Collection (Application)                  4
> + * # 0x85, 0x03,          //   Report ID (3)                           6
> + * # 0x05, 0x07,          //   Usage Page (Keyboard/Keypad)            8
> + * # 0x19, 0xe0,          //   UsageMinimum (224)                      10
> + * # 0x29, 0xe7,          //   UsageMaximum (231)                      12
> + * # 0x15, 0x00,          //   Logical Minimum (0)                     14
> + * # 0x25, 0x01,          //   Logical Maximum (1)                     16
> + * # 0x75, 0x01,          //   Report Size (1)                         18
> + * # 0x95, 0x08,          //   Report Count (8)                        20
> + * # 0x81, 0x02,          //   Input (Data,Var,Abs)                    22
> + * # 0x05, 0x07,          //   Usage Page (Keyboard/Keypad)            24
> + * # 0x19, 0x00,          //   UsageMinimum (0)                        26
> + * # 0x29, 0xff,          //   UsageMaximum (255)                      28
> + * # 0x26, 0xff, 0x00,    //   Logical Maximum (255)                   30
> + * # 0x75, 0x08,          //   Report Size (8)                         33
> + * # 0x95, 0x06,          //   Report Count (6)                        35
> + * # 0x81, 0x00,          //   Input (Data,Arr,Abs)                    37
> + * # 0xc0,                // End Collection                            39
> + * # 0x05, 0x0c,          // Usage Page (Consumer)                     40
> + * # 0x09, 0x01,          // Usage (Consumer Control)                  42
> + * # 0xa1, 0x01,          // Collection (Application)                  44
> + * # 0x85, 0x04,          //   Report ID (4)                           46
> + * # 0x19, 0x00,          //   UsageMinimum (0)                        48
> + * # 0x2a, 0x3c, 0x02,    //   UsageMaximum (572)                      50
> + * # 0x15, 0x00,          //   Logical Minimum (0)                     53
> + * # 0x26, 0x3c, 0x02,    //   Logical Maximum (572)                   55
> + * # 0x95, 0x01,          //   Report Count (1)                        58
> + * # 0x75, 0x10,          //   Report Size (16)                        60
> + * # 0x81, 0x00,          //   Input (Data,Arr,Abs)                    62
> + * # 0xc0,                // End Collection                            64
> + * R: 65 05 01 09 06 a1 01 85 03 05 07 19 e0 29 e7 15 00 25 01 75 01 95 08 81 02 0507 19 00 29 ff 26 ff 00 75 08 95 06 81 00 c0 05 0c 09 01 a1 01 85 04 19 00 2a 3c02 15 00 26 3c 02 95 01 75 10 81 00 c0
> + * N: HUION Huion Tablet_H641P
> + */
> +
> +#define PAD_REPORT_DESCRIPTOR_LENGTH 65
> +#define PEN_REPORT_DESCRIPTOR_LENGTH 93
> +#define VENDOR_REPORT_DESCRIPTOR_LENGTH 18
> +#define PAD_REPORT_ID 3
> +#define PEN_REPORT_ID 10
> +#define VENDOR_REPORT_ID 8
> +#define PAD_REPORT_LENGTH 8
> +#define PEN_REPORT_LENGTH 10
> +#define VENDOR_REPORT_LENGTH 12
> +
> +
> +__u8 last_button_state;
> +
> +static const __u8 fixed_rdesc_pad[] = {
> +	UsagePage_GenericDesktop
> +	Usage_GD_Keypad
> +	CollectionApplication(
> +		// -- Byte 0 in report
> +		ReportId(PAD_REPORT_ID)
> +		LogicalRange_i8(0, 1)
> +		UsagePage_Digitizers
> +		Usage_Dig_TabletFunctionKeys
> +		CollectionPhysical(
> +			// Byte 1 in report - just exists so we get to be a tablet pad
> +			Usage_Dig_BarrelSwitch // BTN_STYLUS
> +			ReportCount(1)
> +			ReportSize(1)
> +			Input(Var|Abs)
> +			ReportCount(7) // padding
> +			Input(Const)
> +			// Bytes 2/3 in report - just exists so we get to be a tablet pad
> +			UsagePage_GenericDesktop
> +			Usage_GD_X
> +			Usage_GD_Y
> +			ReportCount(2)
> +			ReportSize(8)
> +			Input(Var|Abs)
> +			// Byte 4 in report is the wheel
> +			Usage_GD_Wheel
> +			LogicalRange_i8(-1, 1)
> +			ReportCount(1)
> +			ReportSize(8)
> +			Input(Var|Rel)
> +			// Byte 5 is the button state
> +			UsagePage_Button
> +			UsageRange_i8(0x01, 0x6)
> +			LogicalRange_i8(0x01, 0x6)
> +			ReportCount(1)
> +			ReportSize(8)
> +			Input(Arr|Abs)
> +		)
> +		// Make sure we match our original report length
> +		FixedSizeVendorReport(PAD_REPORT_LENGTH)
> +	)
> +};
> +
> +static const __u8 fixed_rdesc_pen[] = {
> +	UsagePage_Digitizers
> +	Usage_Dig_Pen
> +	CollectionApplication(
> +		// -- Byte 0 in report
> +		ReportId(PEN_REPORT_ID)
> +		Usage_Dig_Pen
> +		CollectionPhysical(
> +			// -- Byte 1 in report
> +			Usage_Dig_TipSwitch
> +			Usage_Dig_BarrelSwitch
> +			Usage_Dig_SecondaryBarrelSwitch // maps eraser to BTN_STYLUS2
> +			LogicalRange_i8(0, 1)
> +			ReportSize(1)
> +			ReportCount(3)
> +			Input(Var|Abs)
> +			ReportCount(4)  // Padding
> +			Input(Const)
> +			Usage_Dig_InRange
> +			ReportCount(1)
> +			Input(Var|Abs)
> +			ReportSize(16)
> +			ReportCount(1)
> +			PushPop(
> +				UsagePage_GenericDesktop
> +				Unit(cm)
> +				UnitExponent(-1)
> +				PhysicalRange_i16(0, 160)
> +				LogicalRange_i16(0, 32767)
> +				Usage_GD_X
> +				Input(Var|Abs) // Bytes 2+3
> +				PhysicalRange_i16(0, 100)
> +				LogicalRange_i16(0, 32767)
> +				Usage_GD_Y
> +				Input(Var|Abs) // Bytes 4+5
> +			)
> +			UsagePage_Digitizers
> +			Usage_Dig_TipPressure
> +			LogicalRange_i16(0, 8191)
> +			Input(Var|Abs) // Byte 6+7
> +			// Two bytes padding so we don't need to change the report at all
> +			ReportSize(8)
> +			ReportCount(2)
> +			Input(Const) // Byte 6+7
> +		)
> +	)
> +};
> +
> +static const __u8 fixed_rdesc_vendor[] = {
> +	UsagePage_Digitizers
> +	Usage_Dig_Pen
> +	CollectionApplication(
> +		// Byte 0
> +		// We leave the pen on the vendor report ID
> +		ReportId(VENDOR_REPORT_ID)
> +		Usage_Dig_Pen
> +		CollectionPhysical(
> +			// Byte 1 are the buttons
> +			LogicalRange_i8(0, 1)
> +			ReportSize(1)
> +			Usage_Dig_TipSwitch
> +			Usage_Dig_BarrelSwitch
> +			Usage_Dig_SecondaryBarrelSwitch
> +			ReportCount(3)
> +			Input(Var|Abs)
> +			ReportCount(4) // Padding
> +			Input(Const)
> +			Usage_Dig_InRange
> +			ReportCount(1)
> +			Input(Var|Abs)
> +			ReportSize(16)
> +			ReportCount(1)
> +			PushPop(
> +				UsagePage_GenericDesktop
> +				Unit(cm)
> +				UnitExponent(-1)
> +				// Note: reported logical range differs
> +				// from the pen report ID for x and y
> +				LogicalRange_i16(0, 32000)
> +				PhysicalRange_i16(0, 160)
> +				// Bytes 2/3 in report
> +				Usage_GD_X
> +				Input(Var|Abs)
> +				LogicalRange_i16(0, 20000)
> +				PhysicalRange_i16(0, 100)
> +				// Bytes 4/5 in report
> +				Usage_GD_Y
> +				Input(Var|Abs)
> +			)
> +			// Bytes 6/7 in report
> +			LogicalRange_i16(0, 8192)
> +			Usage_Dig_TipPressure
> +			Input(Var|Abs)
> +		)
> +	)
> +	UsagePage_GenericDesktop
> +	Usage_GD_Keypad
> +	CollectionApplication(
> +		// Byte 0
> +		ReportId(PAD_REPORT_ID)
> +		LogicalRange_i8(0, 1)
> +		UsagePage_Digitizers
> +		Usage_Dig_TabletFunctionKeys
> +		CollectionPhysical(
> +			// Byte 1 are the buttons
> +			Usage_Dig_BarrelSwitch	 // BTN_STYLUS, needed so we get to be a tablet pad
> +			ReportCount(1)
> +			ReportSize(1)
> +			Input(Var|Abs)
> +			ReportCount(7) // Padding
> +			Input(Const)
> +			// Bytes 2/3 - x/y just exist so we get to be a tablet pad
> +			UsagePage_GenericDesktop
> +			Usage_GD_X
> +			Usage_GD_Y
> +			ReportCount(2)
> +			ReportSize(8)
> +			Input(Var|Abs)
> +			// Byte 4 is the button state
> +			UsagePage_Button
> +			UsageRange_i8(0x01, 0x6)
> +			LogicalRange_i8(0x0, 0x1)
> +			ReportCount(6)
> +			ReportSize(1)
> +			Input(Var|Abs)
> +			ReportCount(2)
> +			Input(Const)
> +			// Byte 5 is the wheel
> +			UsagePage_GenericDesktop
> +			Usage_GD_Wheel
> +			LogicalRange_i8(-1, 1)
> +			ReportCount(1)
> +			ReportSize(8)
> +			Input(Var|Rel)
> +		)
> +		// Make sure we match our original report length
> +		FixedSizeVendorReport(VENDOR_REPORT_LENGTH)
> +	)
> +};
> +
> +static const __u8 disabled_rdesc_pen[] = {
> +	FixedSizeVendorReport(PEN_REPORT_LENGTH)
> +};
> +
> +static const __u8 disabled_rdesc_pad[] = {
> +	FixedSizeVendorReport(PAD_REPORT_LENGTH)
> +};
> +
> +SEC(HID_BPF_RDESC_FIXUP)
> +int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx)
> +{
> +	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */);
> +	__s32 rdesc_size = hctx->size;
> +	__u8 have_fw_id;
> +
> +	if (!data)
> +		return 0; /* EPERM check */
> +
> +	/* If we have a firmware ID and it matches our expected prefix, we
> +	 * disable the default pad/pen nodes. They won't send events
> +	 * but cause duplicate devices.
> +	 */
> +	have_fw_id = __builtin_memcmp(UDEV_PROP_HUION_FIRMWARE_ID,
> +				      EXPECTED_FIRMWARE_ID,
> +				      sizeof(EXPECTED_FIRMWARE_ID) - 1) == 0;
> +	if (rdesc_size == PAD_REPORT_DESCRIPTOR_LENGTH) {
> +		if (have_fw_id) {
> +			__builtin_memcpy(data, disabled_rdesc_pad, sizeof(disabled_rdesc_pad));
> +			return sizeof(disabled_rdesc_pad);
> +		}
> +
> +		__builtin_memcpy(data, fixed_rdesc_pad, sizeof(fixed_rdesc_pad));
> +		return sizeof(fixed_rdesc_pad);
> +	}
> +	if (rdesc_size == PEN_REPORT_DESCRIPTOR_LENGTH) {
> +		if (have_fw_id) {
> +			__builtin_memcpy(data, disabled_rdesc_pen, sizeof(disabled_rdesc_pen));
> +			return sizeof(disabled_rdesc_pen);
> +		}
> +
> +		__builtin_memcpy(data, fixed_rdesc_pen, sizeof(fixed_rdesc_pen));
> +		return sizeof(fixed_rdesc_pen);
> +	}
> +	/* Always fix the vendor mode so the tablet will work even if nothing sets
> +	 * the udev property (e.g. huion-switcher run manually)
> +	 */
> +	if (rdesc_size == VENDOR_REPORT_DESCRIPTOR_LENGTH) {
> +		__builtin_memcpy(data, fixed_rdesc_vendor, sizeof(fixed_rdesc_vendor));
> +		return sizeof(fixed_rdesc_vendor);
> +
> +	}
> +	return 0;
> +}
> +
> +SEC(HID_BPF_DEVICE_EVENT)
> +int BPF_PROG(inspiroy_2_fix_events, struct hid_bpf_ctx *hctx)
> +{
> +	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
> +
> +	if (!data)
> +		return 0; /* EPERM check */
> +
> +	/* Only sent if tablet is in default mode */
> +	if (data[0] == PAD_REPORT_ID) {
> +		/* Nicely enough, this device only supports one button down at a time so
> +		 * the reports are easy to match. Buttons numbered from the top
> +		 *   Button released: 03 00 00 00 00 00 00 00
> +		 *   Button 1: 03 00 05 00 00 00 00 00 -> b
> +		 *   Button 2: 03 00 0c 00 00 00 00 00 -> i
> +		 *   Button 3: 03 00 08 00 00 00 00 00 -> e
> +		 *   Button 4: 03 01 16 00 00 00 00 00 -> Ctrl S
> +		 *   Button 5: 03 00 2c 00 00 00 00 00 -> space
> +		 *   Button 6: 03 05 1d 00 00 00 00 00 -> Ctrl Alt Z
> +		 *
> +		 *   Wheel down: 03 01 2d 00 00 00 00 00 -> Ctrl -
> +		 *   Wheel up:   03 01 2e 00 00 00 00 00 -> Ctrl =
> +		 */
> +		__u8 button = 0;
> +		__u8 wheel = 0;
> +
> +		switch (data[1] << 8 | data[2]) {
> +		case 0x0000:
> +			break;
> +		case 0x0005:
> +			button = 1;
> +			break;
> +		case 0x000c:
> +			button = 2;
> +			break;
> +		case 0x0008:
> +			button = 3;
> +			break;
> +		case 0x0116:
> +			button = 4;
> +			break;
> +		case 0x002c:
> +			button = 5;
> +			break;
> +		case 0x051d:
> +			button = 6;
> +			break;
> +		case 0x012d:
> +			wheel = -1;
> +			break;
> +		case 0x012e:
> +			wheel = 1;
> +			break;
> +
> +		}
> +
> +		__u8 report[6] = {PAD_REPORT_ID, 0x0, 0x0, 0x0, wheel, button};
> +
> +		__builtin_memcpy(data, report, sizeof(report));
> +		return sizeof(report);
> +	}
> +
> +	/* Nothing to do for the PEN_REPORT_ID, it's already mapped */
> +
> +	/* Only sent if tablet is in raw mode */
> +	if (data[0] == VENDOR_REPORT_ID) {
> +		/* Pad reports */
> +		if (data[1] & 0x20) {
> +			/* See fixed_rdesc_pad */
> +			struct pad_report {
> +				__u8 report_id;
> +				__u8 btn_stylus;
> +				__u8 x;
> +				__u8 y;
> +				__u8 buttons;
> +				__u8 wheel;
> +			} __attribute__((packed)) *pad_report;
> +			__u8 wheel = 0;
> +
> +			/* Wheel report */
> +			if (data[1] == 0xf1) {
> +				if (data[5] == 2)
> +					wheel = 0xff;
> +				else
> +					wheel = data[5];
> +			} else {
> +				/* data[4] are the buttons, mapped correctly */
> +				last_button_state = data[4];
> +				wheel = 0; // wheel
> +			}
> +
> +			pad_report = (struct pad_report *)data;
> +
> +			pad_report->report_id = PAD_REPORT_ID;
> +			pad_report->btn_stylus = 0;
> +			pad_report->x = 0;
> +			pad_report->y = 0;
> +			pad_report->buttons = last_button_state;
> +			pad_report->wheel = wheel;
> +
> +			return sizeof(struct pad_report);
> +		}
> +
> +		/* Pen reports need nothing done */
> +	}
> +
> +	return 0;
> +}
> +
> +HID_BPF_OPS(inspiroy_2) = {
> +	.hid_device_event = (void *)inspiroy_2_fix_events,
> +	.hid_rdesc_fixup = (void *)hid_fix_rdesc,
> +};
> +
> +SEC("syscall")
> +int probe(struct hid_bpf_probe_args *ctx)
> +{
> +	switch (ctx->rdesc_size) {
> +	case PAD_REPORT_DESCRIPTOR_LENGTH:
> +	case PEN_REPORT_DESCRIPTOR_LENGTH:
> +	case VENDOR_REPORT_DESCRIPTOR_LENGTH:
> +		ctx->retval = 0;
> +		break;
> +	default:
> +		ctx->retval = -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +char _license[] SEC("license") = "GPL";
> 
> -- 
> 2.44.0
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/6] HID: bpf: import some more fixes from udev-hid-bpf
  2024-06-27  9:54 [PATCH 0/6] HID: bpf: import some more fixes from udev-hid-bpf Benjamin Tissoires
                   ` (5 preceding siblings ...)
  2024-06-27  9:54 ` [PATCH 6/6] HID: bpf: Thrustmaster TCA Yoke Boeing joystick fix Benjamin Tissoires
@ 2024-07-01 13:46 ` Benjamin Tissoires
  6 siblings, 0 replies; 9+ messages in thread
From: Benjamin Tissoires @ 2024-07-01 13:46 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires
  Cc: linux-kernel, linux-input, bpf, Peter Hutterer,
	José Expósito, K S Iyer

On Thu, 27 Jun 2024 11:54:16 +0200, Benjamin Tissoires wrote:
> This is a batch update to sync up the testing directory of udev-hid-bpf
> and the kernel. The development happens there, and once we are happy,
> we merge the bpf there, and then sync up with the kernel.
> 
> I've added all of the signed-off by from the various authors, as we
> require them there as well.
> 
> [...]

Applied to hid/hid.git (for-6.11/bpf), thanks!

[1/6] HID: bpf: Add a HID report composition helper macros
      https://git.kernel.org/hid/hid/c/8a89db51873c
[2/6] HID: bpf: add a driver for the Huion Inspiroy 2S (H641P)
      https://git.kernel.org/hid/hid/c/09c555faedb8
[3/6] HID: bpf: move the BIT() macro to hid_bpf_helpers.h
      https://git.kernel.org/hid/hid/c/c4015aa7d8fa
[4/6] HID: bpf: Add support for the XP-PEN Deco Mini 4
      https://git.kernel.org/hid/hid/c/f03741540dba
[5/6] HID: bpf: Add Huion Dial 2 bpf fixup
      https://git.kernel.org/hid/hid/c/9b52d81115db
[6/6] HID: bpf: Thrustmaster TCA Yoke Boeing joystick fix
      https://git.kernel.org/hid/hid/c/f58e7f404da4

Cheers,
-- 
Benjamin Tissoires <bentiss@kernel.org>


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2024-07-01 13:46 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-27  9:54 [PATCH 0/6] HID: bpf: import some more fixes from udev-hid-bpf Benjamin Tissoires
2024-06-27  9:54 ` [PATCH 1/6] HID: bpf: Add a HID report composition helper macros Benjamin Tissoires
2024-06-27  9:54 ` [PATCH 2/6] HID: bpf: add a driver for the Huion Inspiroy 2S (H641P) Benjamin Tissoires
2024-06-28  0:22   ` Peter Hutterer
2024-06-27  9:54 ` [PATCH 3/6] HID: bpf: move the BIT() macro to hid_bpf_helpers.h Benjamin Tissoires
2024-06-27  9:54 ` [PATCH 4/6] HID: bpf: Add support for the XP-PEN Deco Mini 4 Benjamin Tissoires
2024-06-27  9:54 ` [PATCH 5/6] HID: bpf: Add Huion Dial 2 bpf fixup Benjamin Tissoires
2024-06-27  9:54 ` [PATCH 6/6] HID: bpf: Thrustmaster TCA Yoke Boeing joystick fix Benjamin Tissoires
2024-07-01 13:46 ` [PATCH 0/6] HID: bpf: import some more fixes from udev-hid-bpf Benjamin Tissoires

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).