summaryrefslogtreecommitdiffstats
path: root/drivers/hid/bpf
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/bpf')
-rw-r--r--drivers/hid/bpf/Kconfig2
-rw-r--r--drivers/hid/bpf/Makefile2
-rw-r--r--drivers/hid/bpf/entrypoints/Makefile93
-rw-r--r--drivers/hid/bpf/entrypoints/README4
-rw-r--r--drivers/hid/bpf/entrypoints/entrypoints.bpf.c25
-rw-r--r--drivers/hid/bpf/entrypoints/entrypoints.lskel.h248
-rw-r--r--drivers/hid/bpf/hid_bpf_dispatch.c425
-rw-r--r--drivers/hid/bpf/hid_bpf_dispatch.h13
-rw-r--r--drivers/hid/bpf/hid_bpf_jmp_table.c565
-rw-r--r--drivers/hid/bpf/hid_bpf_struct_ops.c326
-rw-r--r--drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c9
-rw-r--r--drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c6
-rw-r--r--drivers/hid/bpf/progs/Huion__Dial-2.bpf.c614
-rw-r--r--drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c534
-rw-r--r--drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c9
-rw-r--r--drivers/hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c6
-rw-r--r--drivers/hid/bpf/progs/Makefile2
-rw-r--r--drivers/hid/bpf/progs/Microsoft__Xbox-Elite-2.bpf.c (renamed from drivers/hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c)21
-rw-r--r--drivers/hid/bpf/progs/Thrustmaster__TCA-Yoke-Boeing.bpf.c144
-rw-r--r--drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c6
-rw-r--r--drivers/hid/bpf/progs/XPPen__Artist24.bpf.c12
-rw-r--r--drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c24
-rw-r--r--drivers/hid/bpf/progs/XPPen__DecoMini4.bpf.c231
-rw-r--r--drivers/hid/bpf/progs/hid_bpf.h6
-rw-r--r--drivers/hid/bpf/progs/hid_bpf_helpers.h1
-rw-r--r--drivers/hid/bpf/progs/hid_report_helpers.h2960
26 files changed, 5103 insertions, 1185 deletions
diff --git a/drivers/hid/bpf/Kconfig b/drivers/hid/bpf/Kconfig
index 83214bae6768..d65482e02a6c 100644
--- a/drivers/hid/bpf/Kconfig
+++ b/drivers/hid/bpf/Kconfig
@@ -3,7 +3,7 @@ menu "HID-BPF support"
config HID_BPF
bool "HID-BPF support"
- depends on BPF
+ depends on BPF_JIT
depends on BPF_SYSCALL
depends on DYNAMIC_FTRACE_WITH_DIRECT_CALLS
help
diff --git a/drivers/hid/bpf/Makefile b/drivers/hid/bpf/Makefile
index cf55120cf7d6..d1f2b81788ca 100644
--- a/drivers/hid/bpf/Makefile
+++ b/drivers/hid/bpf/Makefile
@@ -8,4 +8,4 @@ LIBBPF_INCLUDE = $(srctree)/tools/lib
obj-$(CONFIG_HID_BPF) += hid_bpf.o
CFLAGS_hid_bpf_dispatch.o += -I$(LIBBPF_INCLUDE)
CFLAGS_hid_bpf_jmp_table.o += -I$(LIBBPF_INCLUDE)
-hid_bpf-objs += hid_bpf_dispatch.o hid_bpf_jmp_table.o
+hid_bpf-objs += hid_bpf_dispatch.o hid_bpf_struct_ops.o
diff --git a/drivers/hid/bpf/entrypoints/Makefile b/drivers/hid/bpf/entrypoints/Makefile
deleted file mode 100644
index 43b99b5575cf..000000000000
--- a/drivers/hid/bpf/entrypoints/Makefile
+++ /dev/null
@@ -1,93 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-OUTPUT := .output
-abs_out := $(abspath $(OUTPUT))
-
-CLANG ?= clang
-LLC ?= llc
-LLVM_STRIP ?= llvm-strip
-
-TOOLS_PATH := $(abspath ../../../../tools)
-BPFTOOL_SRC := $(TOOLS_PATH)/bpf/bpftool
-BPFTOOL_OUTPUT := $(abs_out)/bpftool
-DEFAULT_BPFTOOL := $(BPFTOOL_OUTPUT)/bootstrap/bpftool
-BPFTOOL ?= $(DEFAULT_BPFTOOL)
-
-LIBBPF_SRC := $(TOOLS_PATH)/lib/bpf
-LIBBPF_OUTPUT := $(abs_out)/libbpf
-LIBBPF_DESTDIR := $(LIBBPF_OUTPUT)
-LIBBPF_INCLUDE := $(LIBBPF_DESTDIR)/include
-BPFOBJ := $(LIBBPF_OUTPUT)/libbpf.a
-
-INCLUDES := -I$(OUTPUT) -I$(LIBBPF_INCLUDE) -I$(TOOLS_PATH)/include/uapi
-CFLAGS := -g -Wall
-
-VMLINUX_BTF_PATHS ?= $(if $(O),$(O)/vmlinux) \
- $(if $(KBUILD_OUTPUT),$(KBUILD_OUTPUT)/vmlinux) \
- ../../../../vmlinux \
- /sys/kernel/btf/vmlinux \
- /boot/vmlinux-$(shell uname -r)
-VMLINUX_BTF ?= $(abspath $(firstword $(wildcard $(VMLINUX_BTF_PATHS))))
-ifeq ($(VMLINUX_BTF),)
-$(error Cannot find a vmlinux for VMLINUX_BTF at any of "$(VMLINUX_BTF_PATHS)")
-endif
-
-ifeq ($(V),1)
-Q =
-msg =
-else
-Q = @
-msg = @printf ' %-8s %s%s\n' "$(1)" "$(notdir $(2))" "$(if $(3), $(3))";
-MAKEFLAGS += --no-print-directory
-submake_extras := feature_display=0
-endif
-
-.DELETE_ON_ERROR:
-
-.PHONY: all clean
-
-all: entrypoints.lskel.h
-
-clean:
- $(call msg,CLEAN)
- $(Q)rm -rf $(OUTPUT) entrypoints
-
-entrypoints.lskel.h: $(OUTPUT)/entrypoints.bpf.o | $(BPFTOOL)
- $(call msg,GEN-SKEL,$@)
- $(Q)$(BPFTOOL) gen skeleton -L $< > $@
-
-
-$(OUTPUT)/entrypoints.bpf.o: entrypoints.bpf.c $(OUTPUT)/vmlinux.h $(BPFOBJ) | $(OUTPUT)
- $(call msg,BPF,$@)
- $(Q)$(CLANG) -g -O2 --target=bpf $(INCLUDES) \
- -c $(filter %.c,$^) -o $@ && \
- $(LLVM_STRIP) -g $@
-
-$(OUTPUT)/vmlinux.h: $(VMLINUX_BTF) $(BPFTOOL) | $(INCLUDE_DIR)
-ifeq ($(VMLINUX_H),)
- $(call msg,GEN,,$@)
- $(Q)$(BPFTOOL) btf dump file $(VMLINUX_BTF) format c > $@
-else
- $(call msg,CP,,$@)
- $(Q)cp "$(VMLINUX_H)" $@
-endif
-
-$(OUTPUT) $(LIBBPF_OUTPUT) $(BPFTOOL_OUTPUT):
- $(call msg,MKDIR,$@)
- $(Q)mkdir -p $@
-
-$(BPFOBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(LIBBPF_OUTPUT)
- $(Q)$(MAKE) $(submake_extras) -C $(LIBBPF_SRC) \
- OUTPUT=$(abspath $(dir $@))/ prefix= \
- DESTDIR=$(LIBBPF_DESTDIR) $(abspath $@) install_headers
-
-ifeq ($(CROSS_COMPILE),)
-$(DEFAULT_BPFTOOL): $(BPFOBJ) | $(BPFTOOL_OUTPUT)
- $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOL_SRC) \
- OUTPUT=$(BPFTOOL_OUTPUT)/ \
- LIBBPF_BOOTSTRAP_OUTPUT=$(LIBBPF_OUTPUT)/ \
- LIBBPF_BOOTSTRAP_DESTDIR=$(LIBBPF_DESTDIR)/ bootstrap
-else
-$(DEFAULT_BPFTOOL): | $(BPFTOOL_OUTPUT)
- $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOL_SRC) \
- OUTPUT=$(BPFTOOL_OUTPUT)/ bootstrap
-endif
diff --git a/drivers/hid/bpf/entrypoints/README b/drivers/hid/bpf/entrypoints/README
deleted file mode 100644
index 147e0d41509f..000000000000
--- a/drivers/hid/bpf/entrypoints/README
+++ /dev/null
@@ -1,4 +0,0 @@
-WARNING:
-If you change "entrypoints.bpf.c" do "make -j" in this directory to rebuild "entrypoints.skel.h".
-Make sure to have clang 10 installed.
-See Documentation/bpf/bpf_devel_QA.rst
diff --git a/drivers/hid/bpf/entrypoints/entrypoints.bpf.c b/drivers/hid/bpf/entrypoints/entrypoints.bpf.c
deleted file mode 100644
index c22921125a1a..000000000000
--- a/drivers/hid/bpf/entrypoints/entrypoints.bpf.c
+++ /dev/null
@@ -1,25 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2022 Benjamin Tissoires */
-
-#include ".output/vmlinux.h"
-#include <bpf/bpf_helpers.h>
-#include <bpf/bpf_tracing.h>
-
-#define HID_BPF_MAX_PROGS 1024
-
-struct {
- __uint(type, BPF_MAP_TYPE_PROG_ARRAY);
- __uint(max_entries, HID_BPF_MAX_PROGS);
- __uint(key_size, sizeof(__u32));
- __uint(value_size, sizeof(__u32));
-} hid_jmp_table SEC(".maps");
-
-SEC("fmod_ret/__hid_bpf_tail_call")
-int BPF_PROG(hid_tail_call, struct hid_bpf_ctx *hctx)
-{
- bpf_tail_call(ctx, &hid_jmp_table, hctx->index);
-
- return 0;
-}
-
-char LICENSE[] SEC("license") = "GPL";
diff --git a/drivers/hid/bpf/entrypoints/entrypoints.lskel.h b/drivers/hid/bpf/entrypoints/entrypoints.lskel.h
deleted file mode 100644
index 35618051598c..000000000000
--- a/drivers/hid/bpf/entrypoints/entrypoints.lskel.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
-/* THIS FILE IS AUTOGENERATED BY BPFTOOL! */
-#ifndef __ENTRYPOINTS_BPF_SKEL_H__
-#define __ENTRYPOINTS_BPF_SKEL_H__
-
-#include <bpf/skel_internal.h>
-
-struct entrypoints_bpf {
- struct bpf_loader_ctx ctx;
- struct {
- struct bpf_map_desc hid_jmp_table;
- } maps;
- struct {
- struct bpf_prog_desc hid_tail_call;
- } progs;
- struct {
- int hid_tail_call_fd;
- } links;
-};
-
-static inline int
-entrypoints_bpf__hid_tail_call__attach(struct entrypoints_bpf *skel)
-{
- int prog_fd = skel->progs.hid_tail_call.prog_fd;
- int fd = skel_raw_tracepoint_open(NULL, prog_fd);
-
- if (fd > 0)
- skel->links.hid_tail_call_fd = fd;
- return fd;
-}
-
-static inline int
-entrypoints_bpf__attach(struct entrypoints_bpf *skel)
-{
- int ret = 0;
-
- ret = ret < 0 ? ret : entrypoints_bpf__hid_tail_call__attach(skel);
- return ret < 0 ? ret : 0;
-}
-
-static inline void
-entrypoints_bpf__detach(struct entrypoints_bpf *skel)
-{
- skel_closenz(skel->links.hid_tail_call_fd);
-}
-static void
-entrypoints_bpf__destroy(struct entrypoints_bpf *skel)
-{
- if (!skel)
- return;
- entrypoints_bpf__detach(skel);
- skel_closenz(skel->progs.hid_tail_call.prog_fd);
- skel_closenz(skel->maps.hid_jmp_table.map_fd);
- skel_free(skel);
-}
-static inline struct entrypoints_bpf *
-entrypoints_bpf__open(void)
-{
- struct entrypoints_bpf *skel;
-
- skel = skel_alloc(sizeof(*skel));
- if (!skel)
- goto cleanup;
- skel->ctx.sz = (void *)&skel->links - (void *)skel;
- return skel;
-cleanup:
- entrypoints_bpf__destroy(skel);
- return NULL;
-}
-
-static inline int
-entrypoints_bpf__load(struct entrypoints_bpf *skel)
-{
- struct bpf_load_and_run_opts opts = {};
- int err;
-
- opts.ctx = (struct bpf_loader_ctx *)skel;
- opts.data_sz = 2856;
- opts.data = (void *)"\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x9f\xeb\x01\0\
-\x18\0\0\0\0\0\0\0\x60\x02\0\0\x60\x02\0\0\x12\x02\0\0\0\0\0\0\0\0\0\x02\x03\0\
-\0\0\x01\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\x01\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\
-\0\0\x04\0\0\0\x03\0\0\0\x05\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\0\0\0\0\0\0\0\0\
-\x02\x06\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\0\x04\0\0\0\0\0\0\
-\0\0\0\x02\x08\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x04\0\0\0\0\
-\0\0\0\x04\0\0\x04\x20\0\0\0\x19\0\0\0\x01\0\0\0\0\0\0\0\x1e\0\0\0\x05\0\0\0\
-\x40\0\0\0\x2a\0\0\0\x07\0\0\0\x80\0\0\0\x33\0\0\0\x07\0\0\0\xc0\0\0\0\x3e\0\0\
-\0\0\0\0\x0e\x09\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\x02\x0c\0\0\0\x4c\0\0\0\0\0\0\
-\x01\x08\0\0\0\x40\0\0\0\0\0\0\0\x01\0\0\x0d\x02\0\0\0\x5f\0\0\0\x0b\0\0\0\x63\
-\0\0\0\x01\0\0\x0c\x0d\0\0\0\x09\x01\0\0\x05\0\0\x04\x20\0\0\0\x15\x01\0\0\x10\
-\0\0\0\0\0\0\0\x1b\x01\0\0\x12\0\0\0\x40\0\0\0\x1f\x01\0\0\x10\0\0\0\x80\0\0\0\
-\x2e\x01\0\0\x14\0\0\0\xa0\0\0\0\0\0\0\0\x15\0\0\0\xc0\0\0\0\x3a\x01\0\0\0\0\0\
-\x08\x11\0\0\0\x40\x01\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\0\0\0\0\0\0\0\0\x02\x13\
-\0\0\0\0\0\0\0\0\0\0\x0a\x1c\0\0\0\x4d\x01\0\0\x04\0\0\x06\x04\0\0\0\x5d\x01\0\
-\0\0\0\0\0\x6e\x01\0\0\x01\0\0\0\x80\x01\0\0\x02\0\0\0\x93\x01\0\0\x03\0\0\0\0\
-\0\0\0\x02\0\0\x05\x04\0\0\0\xa4\x01\0\0\x16\0\0\0\0\0\0\0\xab\x01\0\0\x16\0\0\
-\0\0\0\0\0\xb0\x01\0\0\0\0\0\x08\x02\0\0\0\xec\x01\0\0\0\0\0\x01\x01\0\0\0\x08\
-\0\0\x01\0\0\0\0\0\0\0\x03\0\0\0\0\x17\0\0\0\x04\0\0\0\x04\0\0\0\xf1\x01\0\0\0\
-\0\0\x0e\x18\0\0\0\x01\0\0\0\xf9\x01\0\0\x01\0\0\x0f\x20\0\0\0\x0a\0\0\0\0\0\0\
-\0\x20\0\0\0\xff\x01\0\0\x01\0\0\x0f\x04\0\0\0\x19\0\0\0\0\0\0\0\x04\0\0\0\x07\
-\x02\0\0\0\0\0\x07\0\0\0\0\0\x69\x6e\x74\0\x5f\x5f\x41\x52\x52\x41\x59\x5f\x53\
-\x49\x5a\x45\x5f\x54\x59\x50\x45\x5f\x5f\0\x74\x79\x70\x65\0\x6d\x61\x78\x5f\
-\x65\x6e\x74\x72\x69\x65\x73\0\x6b\x65\x79\x5f\x73\x69\x7a\x65\0\x76\x61\x6c\
-\x75\x65\x5f\x73\x69\x7a\x65\0\x68\x69\x64\x5f\x6a\x6d\x70\x5f\x74\x61\x62\x6c\
-\x65\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e\x67\
-\0\x63\x74\x78\0\x68\x69\x64\x5f\x74\x61\x69\x6c\x5f\x63\x61\x6c\x6c\0\x66\x6d\
-\x6f\x64\x5f\x72\x65\x74\x2f\x5f\x5f\x68\x69\x64\x5f\x62\x70\x66\x5f\x74\x61\
-\x69\x6c\x5f\x63\x61\x6c\x6c\0\x2f\x68\x6f\x6d\x65\x2f\x62\x74\x69\x73\x73\x6f\
-\x69\x72\x2f\x53\x72\x63\x2f\x68\x69\x64\x2f\x64\x72\x69\x76\x65\x72\x73\x2f\
-\x68\x69\x64\x2f\x62\x70\x66\x2f\x65\x6e\x74\x72\x79\x70\x6f\x69\x6e\x74\x73\
-\x2f\x65\x6e\x74\x72\x79\x70\x6f\x69\x6e\x74\x73\x2e\x62\x70\x66\x2e\x63\0\x69\
-\x6e\x74\x20\x42\x50\x46\x5f\x50\x52\x4f\x47\x28\x68\x69\x64\x5f\x74\x61\x69\
-\x6c\x5f\x63\x61\x6c\x6c\x2c\x20\x73\x74\x72\x75\x63\x74\x20\x68\x69\x64\x5f\
-\x62\x70\x66\x5f\x63\x74\x78\x20\x2a\x68\x63\x74\x78\x29\0\x68\x69\x64\x5f\x62\
-\x70\x66\x5f\x63\x74\x78\0\x69\x6e\x64\x65\x78\0\x68\x69\x64\0\x61\x6c\x6c\x6f\
-\x63\x61\x74\x65\x64\x5f\x73\x69\x7a\x65\0\x72\x65\x70\x6f\x72\x74\x5f\x74\x79\
-\x70\x65\0\x5f\x5f\x75\x33\x32\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\
-\x74\0\x68\x69\x64\x5f\x72\x65\x70\x6f\x72\x74\x5f\x74\x79\x70\x65\0\x48\x49\
-\x44\x5f\x49\x4e\x50\x55\x54\x5f\x52\x45\x50\x4f\x52\x54\0\x48\x49\x44\x5f\x4f\
-\x55\x54\x50\x55\x54\x5f\x52\x45\x50\x4f\x52\x54\0\x48\x49\x44\x5f\x46\x45\x41\
-\x54\x55\x52\x45\x5f\x52\x45\x50\x4f\x52\x54\0\x48\x49\x44\x5f\x52\x45\x50\x4f\
-\x52\x54\x5f\x54\x59\x50\x45\x53\0\x72\x65\x74\x76\x61\x6c\0\x73\x69\x7a\x65\0\
-\x5f\x5f\x73\x33\x32\0\x30\x3a\x30\0\x09\x62\x70\x66\x5f\x74\x61\x69\x6c\x5f\
-\x63\x61\x6c\x6c\x28\x63\x74\x78\x2c\x20\x26\x68\x69\x64\x5f\x6a\x6d\x70\x5f\
-\x74\x61\x62\x6c\x65\x2c\x20\x68\x63\x74\x78\x2d\x3e\x69\x6e\x64\x65\x78\x29\
-\x3b\0\x63\x68\x61\x72\0\x4c\x49\x43\x45\x4e\x53\x45\0\x2e\x6d\x61\x70\x73\0\
-\x6c\x69\x63\x65\x6e\x73\x65\0\x68\x69\x64\x5f\x64\x65\x76\x69\x63\x65\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x8a\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\
-\0\0\0\x04\0\0\0\x04\0\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x68\x69\x64\x5f\
-\x6a\x6d\x70\x5f\x74\x61\x62\x6c\x65\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\x47\x50\x4c\0\0\0\0\0\x79\x12\0\0\0\0\0\0\x61\x23\0\0\0\0\
-\0\0\x18\x52\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x85\0\0\0\x0c\0\0\0\xb7\0\0\0\0\0\0\0\
-\x95\0\0\0\0\0\0\0\0\0\0\0\x0e\0\0\0\0\0\0\0\x8e\0\0\0\xd3\0\0\0\x05\x48\0\0\
-\x01\0\0\0\x8e\0\0\0\xba\x01\0\0\x02\x50\0\0\x05\0\0\0\x8e\0\0\0\xd3\0\0\0\x05\
-\x48\0\0\x08\0\0\0\x0f\0\0\0\xb6\x01\0\0\0\0\0\0\x1a\0\0\0\x07\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x68\x69\
-\x64\x5f\x74\x61\x69\x6c\x5f\x63\x61\x6c\x6c\0\0\0\0\0\0\0\x1a\0\0\0\0\0\0\0\
-\x08\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\x10\0\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\x01\0\
-\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\x5f\
-\x5f\x68\x69\x64\x5f\x62\x70\x66\x5f\x74\x61\x69\x6c\x5f\x63\x61\x6c\x6c\0\0\0\
-\0\0";
- opts.insns_sz = 1192;
- opts.insns = (void *)"\
-\xbf\x16\0\0\0\0\0\0\xbf\xa1\0\0\0\0\0\0\x07\x01\0\0\x78\xff\xff\xff\xb7\x02\0\
-\0\x88\0\0\0\xb7\x03\0\0\0\0\0\0\x85\0\0\0\x71\0\0\0\x05\0\x11\0\0\0\0\0\x61\
-\xa1\x78\xff\0\0\0\0\xd5\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa1\x7c\xff\
-\0\0\0\0\xd5\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa1\x80\xff\0\0\0\0\xd5\
-\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x61\
-\x01\0\0\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\
-\xbf\x70\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\x61\x60\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\
-\0\0\0\0\0\xa8\x09\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x0c\0\0\0\0\0\x18\x61\0\0\0\
-\0\0\0\0\0\0\0\xa4\x09\0\0\x63\x01\0\0\0\0\0\0\x79\x60\x10\0\0\0\0\0\x18\x61\0\
-\0\0\0\0\0\0\0\0\0\x98\x09\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\
-\0\x05\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x90\x09\0\0\x7b\x01\0\0\0\0\0\0\xb7\x01\
-\0\0\x12\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x90\x09\0\0\xb7\x03\0\0\x1c\0\0\0\
-\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\xd7\xff\0\0\0\0\x63\x7a\x78\
-\xff\0\0\0\0\x61\x60\x1c\0\0\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\
-\0\0\xbc\x09\0\0\x63\x01\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x18\x62\0\0\0\0\0\0\0\
-\0\0\0\xb0\x09\0\0\xb7\x03\0\0\x48\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\
-\0\xc5\x07\xca\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x63\x71\0\0\0\0\
-\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xf8\x09\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x90\
-\x0a\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\x0a\0\0\x18\x61\0\0\
-\0\0\0\0\0\0\0\0\x88\x0a\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\
-\x38\x0a\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xd0\x0a\0\0\x7b\x01\0\0\0\0\0\0\x18\
-\x60\0\0\0\0\0\0\0\0\0\0\x40\x0a\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xe0\x0a\0\0\
-\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x70\x0a\0\0\x18\x61\0\0\0\0\0\
-\0\0\0\0\0\0\x0b\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\x18\x61\0\0\0\0\0\0\0\0\0\0\xf8\x0a\0\0\x7b\x01\0\0\0\0\0\0\x61\x60\x08\0\0\0\
-\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x98\x0a\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x0c\0\
-\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x9c\x0a\0\0\x63\x01\0\0\0\0\0\0\x79\x60\
-\x10\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xa0\x0a\0\0\x7b\x01\0\0\0\0\0\0\x61\
-\xa0\x78\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xc8\x0a\0\0\x63\x01\0\0\0\0\0\
-\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x10\x0b\0\0\xb7\x02\0\0\x14\0\0\0\xb7\x03\0\0\
-\x0c\0\0\0\xb7\x04\0\0\0\0\0\0\x85\0\0\0\xa7\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\
-\x91\xff\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x80\x0a\0\0\x63\x70\x6c\0\0\0\0\0\
-\x77\x07\0\0\x20\0\0\0\x63\x70\x70\0\0\0\0\0\xb7\x01\0\0\x05\0\0\0\x18\x62\0\0\
-\0\0\0\0\0\0\0\0\x80\x0a\0\0\xb7\x03\0\0\x8c\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\
-\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xf0\x0a\0\0\x61\x01\0\0\0\0\0\0\xd5\
-\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\xc5\x07\x7f\xff\0\0\
-\0\0\x63\x7a\x80\xff\0\0\0\0\x61\xa1\x78\xff\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\
-\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa0\x80\xff\0\0\0\0\x63\x06\x28\0\0\0\
-\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x61\x10\0\0\0\0\0\0\x63\x06\x18\0\0\0\
-\0\0\xb7\0\0\0\0\0\0\0\x95\0\0\0\0\0\0\0";
- err = bpf_load_and_run(&opts);
- if (err < 0)
- return err;
- return 0;
-}
-
-static inline struct entrypoints_bpf *
-entrypoints_bpf__open_and_load(void)
-{
- struct entrypoints_bpf *skel;
-
- skel = entrypoints_bpf__open();
- if (!skel)
- return NULL;
- if (entrypoints_bpf__load(skel)) {
- entrypoints_bpf__destroy(skel);
- return NULL;
- }
- return skel;
-}
-
-__attribute__((unused)) static void
-entrypoints_bpf__assert(struct entrypoints_bpf *s __attribute__((unused)))
-{
-#ifdef __cplusplus
-#define _Static_assert static_assert
-#endif
-#ifdef __cplusplus
-#undef _Static_assert
-#endif
-}
-
-#endif /* __ENTRYPOINTS_BPF_SKEL_H__ */
diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c
index 10289f44d0cc..8420c227e21b 100644
--- a/drivers/hid/bpf/hid_bpf_dispatch.c
+++ b/drivers/hid/bpf/hid_bpf_dispatch.c
@@ -3,7 +3,7 @@
/*
* HID-BPF support for Linux
*
- * Copyright (c) 2022 Benjamin Tissoires
+ * Copyright (c) 2022-2024 Benjamin Tissoires
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -17,47 +17,25 @@
#include <linux/kfifo.h>
#include <linux/minmax.h>
#include <linux/module.h>
-#include <linux/workqueue.h>
#include "hid_bpf_dispatch.h"
-#include "entrypoints/entrypoints.lskel.h"
-struct hid_bpf_ops *hid_bpf_ops;
-EXPORT_SYMBOL(hid_bpf_ops);
-
-/**
- * hid_bpf_device_event - Called whenever an event is coming in from the device
- *
- * @ctx: The HID-BPF context
- *
- * @return %0 on success and keep processing; a positive value to change the
- * incoming size buffer; a negative error code to interrupt the processing
- * of this event
- *
- * Declare an %fmod_ret tracing bpf program to this function and attach this
- * program through hid_bpf_attach_prog() to have this helper called for
- * any incoming event from the device itself.
- *
- * The function is called while on IRQ context, so we can not sleep.
- */
-/* never used by the kernel but declared so we can load and attach a tracepoint */
-__weak noinline int hid_bpf_device_event(struct hid_bpf_ctx *ctx)
-{
- return 0;
-}
+struct hid_ops *hid_ops;
+EXPORT_SYMBOL(hid_ops);
u8 *
dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type, u8 *data,
- u32 *size, int interrupt)
+ u32 *size, int interrupt, u64 source, bool from_bpf)
{
struct hid_bpf_ctx_kern ctx_kern = {
.ctx = {
.hid = hdev,
- .report_type = type,
.allocated_size = hdev->bpf.allocated_data,
.size = *size,
},
.data = hdev->bpf.device_data,
+ .from_bpf = from_bpf,
};
+ struct hid_bpf_ops *e;
int ret;
if (type >= HID_REPORT_TYPES)
@@ -70,10 +48,22 @@ dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type
memset(ctx_kern.data, 0, hdev->bpf.allocated_data);
memcpy(ctx_kern.data, data, *size);
- ret = hid_bpf_prog_run(hdev, HID_BPF_PROG_TYPE_DEVICE_EVENT, &ctx_kern);
- if (ret < 0)
- return ERR_PTR(ret);
+ rcu_read_lock();
+ list_for_each_entry_rcu(e, &hdev->bpf.prog_list, list) {
+ if (e->hid_device_event) {
+ ret = e->hid_device_event(&ctx_kern.ctx, type, source);
+ if (ret < 0) {
+ rcu_read_unlock();
+ return ERR_PTR(ret);
+ }
+
+ if (ret)
+ ctx_kern.ctx.size = ret;
+ }
+ }
+ rcu_read_unlock();
+ ret = ctx_kern.ctx.size;
if (ret) {
if (ret > ctx_kern.ctx.allocated_size)
return ERR_PTR(-EINVAL);
@@ -85,27 +75,80 @@ dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type
}
EXPORT_SYMBOL_GPL(dispatch_hid_bpf_device_event);
-/**
- * hid_bpf_rdesc_fixup - Called when the probe function parses the report
- * descriptor of the HID device
- *
- * @ctx: The HID-BPF context
- *
- * @return 0 on success and keep processing; a positive value to change the
- * incoming size buffer; a negative error code to interrupt the processing
- * of this event
- *
- * Declare an %fmod_ret tracing bpf program to this function and attach this
- * program through hid_bpf_attach_prog() to have this helper called before any
- * parsing of the report descriptor by HID.
- */
-/* never used by the kernel but declared so we can load and attach a tracepoint */
-__weak noinline int hid_bpf_rdesc_fixup(struct hid_bpf_ctx *ctx)
+int dispatch_hid_bpf_raw_requests(struct hid_device *hdev,
+ unsigned char reportnum, u8 *buf,
+ u32 size, enum hid_report_type rtype,
+ enum hid_class_request reqtype,
+ u64 source, bool from_bpf)
{
- return 0;
+ struct hid_bpf_ctx_kern ctx_kern = {
+ .ctx = {
+ .hid = hdev,
+ .allocated_size = size,
+ .size = size,
+ },
+ .data = buf,
+ .from_bpf = from_bpf,
+ };
+ struct hid_bpf_ops *e;
+ int ret, idx;
+
+ if (rtype >= HID_REPORT_TYPES)
+ return -EINVAL;
+
+ idx = srcu_read_lock(&hdev->bpf.srcu);
+ list_for_each_entry_srcu(e, &hdev->bpf.prog_list, list,
+ srcu_read_lock_held(&hdev->bpf.srcu)) {
+ if (!e->hid_hw_request)
+ continue;
+
+ ret = e->hid_hw_request(&ctx_kern.ctx, reportnum, rtype, reqtype, source);
+ if (ret)
+ goto out;
+ }
+ ret = 0;
+
+out:
+ srcu_read_unlock(&hdev->bpf.srcu, idx);
+ return ret;
}
+EXPORT_SYMBOL_GPL(dispatch_hid_bpf_raw_requests);
-u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *size)
+int dispatch_hid_bpf_output_report(struct hid_device *hdev,
+ __u8 *buf, u32 size, u64 source,
+ bool from_bpf)
+{
+ struct hid_bpf_ctx_kern ctx_kern = {
+ .ctx = {
+ .hid = hdev,
+ .allocated_size = size,
+ .size = size,
+ },
+ .data = buf,
+ .from_bpf = from_bpf,
+ };
+ struct hid_bpf_ops *e;
+ int ret, idx;
+
+ idx = srcu_read_lock(&hdev->bpf.srcu);
+ list_for_each_entry_srcu(e, &hdev->bpf.prog_list, list,
+ srcu_read_lock_held(&hdev->bpf.srcu)) {
+ if (!e->hid_hw_output_report)
+ continue;
+
+ ret = e->hid_hw_output_report(&ctx_kern.ctx, source);
+ if (ret)
+ goto out;
+ }
+ ret = 0;
+
+out:
+ srcu_read_unlock(&hdev->bpf.srcu, idx);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dispatch_hid_bpf_output_report);
+
+u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, const u8 *rdesc, unsigned int *size)
{
int ret;
struct hid_bpf_ctx_kern ctx_kern = {
@@ -116,13 +159,16 @@ u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *s
},
};
+ if (!hdev->bpf.rdesc_ops)
+ goto ignore_bpf;
+
ctx_kern.data = kzalloc(ctx_kern.ctx.allocated_size, GFP_KERNEL);
if (!ctx_kern.data)
goto ignore_bpf;
memcpy(ctx_kern.data, rdesc, min_t(unsigned int, *size, HID_MAX_DESCRIPTOR_SIZE));
- ret = hid_bpf_prog_run(hdev, HID_BPF_PROG_TYPE_RDESC_FIXUP, &ctx_kern);
+ ret = hdev->bpf.rdesc_ops->hid_rdesc_fixup(&ctx_kern.ctx);
if (ret < 0)
goto ignore_bpf;
@@ -133,9 +179,7 @@ u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *s
*size = ret;
}
- rdesc = krealloc(ctx_kern.data, *size, GFP_KERNEL);
-
- return rdesc;
+ return krealloc(ctx_kern.data, *size, GFP_KERNEL);
ignore_bpf:
kfree(ctx_kern.data);
@@ -150,6 +194,25 @@ static int device_match_id(struct device *dev, const void *id)
return hdev->id == *(int *)id;
}
+struct hid_device *hid_get_device(unsigned int hid_id)
+{
+ struct device *dev;
+
+ if (!hid_ops)
+ return ERR_PTR(-EINVAL);
+
+ dev = bus_find_device(hid_ops->bus_type, NULL, &hid_id, device_match_id);
+ if (!dev)
+ return ERR_PTR(-EINVAL);
+
+ return to_hid_device(dev);
+}
+
+void hid_put_device(struct hid_device *hid)
+{
+ put_device(&hid->dev);
+}
+
static int __hid_bpf_allocate_data(struct hid_device *hdev, u8 **data, u32 *size)
{
u8 *alloc_data;
@@ -186,7 +249,7 @@ static int __hid_bpf_allocate_data(struct hid_device *hdev, u8 **data, u32 *size
return 0;
}
-static int hid_bpf_allocate_event_data(struct hid_device *hdev)
+int hid_bpf_allocate_event_data(struct hid_device *hdev)
{
/* hdev->bpf.device_data is already allocated, abort */
if (hdev->bpf.device_data)
@@ -203,39 +266,6 @@ int hid_bpf_reconnect(struct hid_device *hdev)
return 0;
}
-static int do_hid_bpf_attach_prog(struct hid_device *hdev, int prog_fd, struct bpf_prog *prog,
- __u32 flags)
-{
- int fd, err, prog_type;
-
- prog_type = hid_bpf_get_prog_attach_type(prog);
- if (prog_type < 0)
- return prog_type;
-
- if (prog_type >= HID_BPF_PROG_TYPE_MAX)
- return -EINVAL;
-
- if (prog_type == HID_BPF_PROG_TYPE_DEVICE_EVENT) {
- err = hid_bpf_allocate_event_data(hdev);
- if (err)
- return err;
- }
-
- fd = __hid_bpf_attach_prog(hdev, prog_type, prog_fd, prog, flags);
- if (fd < 0)
- return fd;
-
- if (prog_type == HID_BPF_PROG_TYPE_RDESC_FIXUP) {
- err = hid_bpf_reconnect(hdev);
- if (err) {
- close_fd(fd);
- return err;
- }
- }
-
- return fd;
-}
-
/* Disables missing prototype warnings */
__bpf_kfunc_start_defs();
@@ -265,63 +295,6 @@ hid_bpf_get_data(struct hid_bpf_ctx *ctx, unsigned int offset, const size_t rdwr
}
/**
- * hid_bpf_attach_prog - Attach the given @prog_fd to the given HID device
- *
- * @hid_id: the system unique identifier of the HID device
- * @prog_fd: an fd in the user process representing the program to attach
- * @flags: any logical OR combination of &enum hid_bpf_attach_flags
- *
- * @returns an fd of a bpf_link object on success (> %0), an error code otherwise.
- * Closing this fd will detach the program from the HID device (unless the bpf_link
- * is pinned to the BPF file system).
- */
-/* called from syscall */
-__bpf_kfunc int
-hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags)
-{
- struct hid_device *hdev;
- struct bpf_prog *prog;
- struct device *dev;
- int err, fd;
-
- if (!hid_bpf_ops)
- return -EINVAL;
-
- if ((flags & ~HID_BPF_FLAG_MASK))
- return -EINVAL;
-
- dev = bus_find_device(hid_bpf_ops->bus_type, NULL, &hid_id, device_match_id);
- if (!dev)
- return -EINVAL;
-
- hdev = to_hid_device(dev);
-
- /*
- * take a ref on the prog itself, it will be released
- * on errors or when it'll be detached
- */
- prog = bpf_prog_get(prog_fd);
- if (IS_ERR(prog)) {
- err = PTR_ERR(prog);
- goto out_dev_put;
- }
-
- fd = do_hid_bpf_attach_prog(hdev, prog_fd, prog, flags);
- if (fd < 0) {
- err = fd;
- goto out_prog_put;
- }
-
- return fd;
-
- out_prog_put:
- bpf_prog_put(prog);
- out_dev_put:
- put_device(dev);
- return err;
-}
-
-/**
* hid_bpf_allocate_context - Allocate a context to the given HID device
*
* @hid_id: the system unique identifier of the HID device
@@ -333,20 +306,14 @@ hid_bpf_allocate_context(unsigned int hid_id)
{
struct hid_device *hdev;
struct hid_bpf_ctx_kern *ctx_kern = NULL;
- struct device *dev;
- if (!hid_bpf_ops)
+ hdev = hid_get_device(hid_id);
+ if (IS_ERR(hdev))
return NULL;
- dev = bus_find_device(hid_bpf_ops->bus_type, NULL, &hid_id, device_match_id);
- if (!dev)
- return NULL;
-
- hdev = to_hid_device(dev);
-
ctx_kern = kzalloc(sizeof(*ctx_kern), GFP_KERNEL);
if (!ctx_kern) {
- put_device(dev);
+ hid_put_device(hdev);
return NULL;
}
@@ -373,7 +340,7 @@ hid_bpf_release_context(struct hid_bpf_ctx *ctx)
kfree(ctx_kern);
/* get_device() is called by bus_find_device() */
- put_device(&hid->dev);
+ hid_put_device(hid);
}
static int
@@ -386,7 +353,7 @@ __hid_bpf_hw_check_params(struct hid_bpf_ctx *ctx, __u8 *buf, size_t *buf__sz,
u32 report_len;
/* check arguments */
- if (!ctx || !hid_bpf_ops || !buf)
+ if (!ctx || !hid_ops || !buf)
return -EINVAL;
switch (rtype) {
@@ -404,7 +371,7 @@ __hid_bpf_hw_check_params(struct hid_bpf_ctx *ctx, __u8 *buf, size_t *buf__sz,
hdev = (struct hid_device *)ctx->hid; /* discard const */
report_enum = hdev->report_enum + rtype;
- report = hid_bpf_ops->hid_get_report(report_enum, buf);
+ report = hid_ops->hid_get_report(report_enum, buf);
if (!report)
return -EINVAL;
@@ -431,11 +398,17 @@ __bpf_kfunc int
hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
enum hid_report_type rtype, enum hid_class_request reqtype)
{
+ struct hid_bpf_ctx_kern *ctx_kern;
struct hid_device *hdev;
size_t size = buf__sz;
u8 *dma_data;
int ret;
+ ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
+
+ if (ctx_kern->from_bpf)
+ return -EDEADLOCK;
+
/* check arguments */
ret = __hid_bpf_hw_check_params(ctx, buf, &size, rtype);
if (ret)
@@ -459,12 +432,14 @@ hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
if (!dma_data)
return -ENOMEM;
- ret = hid_bpf_ops->hid_hw_raw_request(hdev,
+ ret = hid_ops->hid_hw_raw_request(hdev,
dma_data[0],
dma_data,
size,
rtype,
- reqtype);
+ reqtype,
+ (u64)(long)ctx,
+ true); /* prevent infinite recursions */
if (ret > 0)
memcpy(buf, dma_data, ret);
@@ -485,11 +460,16 @@ hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
__bpf_kfunc int
hid_bpf_hw_output_report(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz)
{
+ struct hid_bpf_ctx_kern *ctx_kern;
struct hid_device *hdev;
size_t size = buf__sz;
u8 *dma_data;
int ret;
+ ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
+ if (ctx_kern->from_bpf)
+ return -EDEADLOCK;
+
/* check arguments */
ret = __hid_bpf_hw_check_params(ctx, buf, &size, HID_OUTPUT_REPORT);
if (ret)
@@ -501,14 +481,56 @@ hid_bpf_hw_output_report(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz)
if (!dma_data)
return -ENOMEM;
- ret = hid_bpf_ops->hid_hw_output_report(hdev,
- dma_data,
- size);
+ ret = hid_ops->hid_hw_output_report(hdev, dma_data, size, (u64)(long)ctx, true);
kfree(dma_data);
return ret;
}
+static int
+__hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf,
+ size_t size, bool lock_already_taken)
+{
+ struct hid_bpf_ctx_kern *ctx_kern;
+ int ret;
+
+ ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
+ if (ctx_kern->from_bpf)
+ return -EDEADLOCK;
+
+ /* check arguments */
+ ret = __hid_bpf_hw_check_params(ctx, buf, &size, type);
+ if (ret)
+ return ret;
+
+ return hid_ops->hid_input_report(ctx->hid, type, buf, size, 0, (u64)(long)ctx, true,
+ lock_already_taken);
+}
+
+/**
+ * hid_bpf_try_input_report - Inject a HID report in the kernel from a HID device
+ *
+ * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
+ * @type: the type of the report (%HID_INPUT_REPORT, %HID_FEATURE_REPORT, %HID_OUTPUT_REPORT)
+ * @buf: a %PTR_TO_MEM buffer
+ * @buf__sz: the size of the data to transfer
+ *
+ * Returns %0 on success, a negative error code otherwise. This function will immediately
+ * fail if the device is not available, thus can be safely used in IRQ context.
+ */
+__bpf_kfunc int
+hid_bpf_try_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf,
+ const size_t buf__sz)
+{
+ struct hid_bpf_ctx_kern *ctx_kern;
+ bool from_hid_event_hook;
+
+ ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
+ from_hid_event_hook = ctx_kern->data && ctx_kern->data == ctx->hid->bpf.device_data;
+
+ return __hid_bpf_input_report(ctx, type, buf, buf__sz, from_hid_event_hook);
+}
+
/**
* hid_bpf_input_report - Inject a HID report in the kernel from a HID device
*
@@ -517,24 +539,26 @@ hid_bpf_hw_output_report(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz)
* @buf: a %PTR_TO_MEM buffer
* @buf__sz: the size of the data to transfer
*
- * Returns %0 on success, a negative error code otherwise.
+ * Returns %0 on success, a negative error code otherwise. This function will wait for the
+ * device to be available before injecting the event, thus needs to be called in sleepable
+ * context.
*/
__bpf_kfunc int
hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf,
const size_t buf__sz)
{
- struct hid_device *hdev;
- size_t size = buf__sz;
int ret;
- /* check arguments */
- ret = __hid_bpf_hw_check_params(ctx, buf, &size, type);
+ ret = down_interruptible(&ctx->hid->driver_input_lock);
if (ret)
return ret;
- hdev = (struct hid_device *)ctx->hid; /* discard const */
+ /* check arguments */
+ ret = __hid_bpf_input_report(ctx, type, buf, buf__sz, true /* lock_already_taken */);
- return hid_bpf_ops->hid_input_report(hdev, type, buf, size, 0);
+ up(&ctx->hid->driver_input_lock);
+
+ return ret;
}
__bpf_kfunc_end_defs();
@@ -549,6 +573,7 @@ BTF_ID_FLAGS(func, hid_bpf_release_context, KF_RELEASE | KF_SLEEPABLE)
BTF_ID_FLAGS(func, hid_bpf_hw_request, KF_SLEEPABLE)
BTF_ID_FLAGS(func, hid_bpf_hw_output_report, KF_SLEEPABLE)
BTF_ID_FLAGS(func, hid_bpf_input_report, KF_SLEEPABLE)
+BTF_ID_FLAGS(func, hid_bpf_try_input_report)
BTF_KFUNCS_END(hid_bpf_kfunc_ids)
static const struct btf_kfunc_id_set hid_bpf_kfunc_set = {
@@ -556,21 +581,8 @@ static const struct btf_kfunc_id_set hid_bpf_kfunc_set = {
.set = &hid_bpf_kfunc_ids,
};
-/* our HID-BPF entrypoints */
-BTF_SET8_START(hid_bpf_fmodret_ids)
-BTF_ID_FLAGS(func, hid_bpf_device_event)
-BTF_ID_FLAGS(func, hid_bpf_rdesc_fixup)
-BTF_ID_FLAGS(func, __hid_bpf_tail_call)
-BTF_SET8_END(hid_bpf_fmodret_ids)
-
-static const struct btf_kfunc_id_set hid_bpf_fmodret_set = {
- .owner = THIS_MODULE,
- .set = &hid_bpf_fmodret_ids,
-};
-
/* for syscall HID-BPF */
BTF_KFUNCS_START(hid_bpf_syscall_kfunc_ids)
-BTF_ID_FLAGS(func, hid_bpf_attach_prog)
BTF_ID_FLAGS(func, hid_bpf_allocate_context, KF_ACQUIRE | KF_RET_NULL)
BTF_ID_FLAGS(func, hid_bpf_release_context, KF_RELEASE)
BTF_ID_FLAGS(func, hid_bpf_hw_request)
@@ -585,14 +597,20 @@ static const struct btf_kfunc_id_set hid_bpf_syscall_kfunc_set = {
int hid_bpf_connect_device(struct hid_device *hdev)
{
- struct hid_bpf_prog_list *prog_list;
+ bool need_to_allocate = false;
+ struct hid_bpf_ops *e;
rcu_read_lock();
- prog_list = rcu_dereference(hdev->bpf.progs[HID_BPF_PROG_TYPE_DEVICE_EVENT]);
+ list_for_each_entry_rcu(e, &hdev->bpf.prog_list, list) {
+ if (e->hid_device_event) {
+ need_to_allocate = true;
+ break;
+ }
+ }
rcu_read_unlock();
/* only allocate BPF data if there are programs attached */
- if (!prog_list)
+ if (!need_to_allocate)
return 0;
return hid_bpf_allocate_event_data(hdev);
@@ -615,13 +633,18 @@ void hid_bpf_destroy_device(struct hid_device *hdev)
/* mark the device as destroyed in bpf so we don't reattach it */
hdev->bpf.destroyed = true;
- __hid_bpf_destroy_device(hdev);
+ __hid_bpf_ops_destroy_device(hdev);
+
+ synchronize_srcu(&hdev->bpf.srcu);
+ cleanup_srcu_struct(&hdev->bpf.srcu);
}
EXPORT_SYMBOL_GPL(hid_bpf_destroy_device);
-void hid_bpf_device_init(struct hid_device *hdev)
+int hid_bpf_device_init(struct hid_device *hdev)
{
- spin_lock_init(&hdev->bpf.progs_lock);
+ INIT_LIST_HEAD(&hdev->bpf.prog_list);
+ mutex_init(&hdev->bpf.prog_list_lock);
+ return init_srcu_struct(&hdev->bpf.srcu);
}
EXPORT_SYMBOL_GPL(hid_bpf_device_init);
@@ -632,30 +655,15 @@ static int __init hid_bpf_init(void)
/* Note: if we exit with an error any time here, we would entirely break HID, which
* is probably not something we want. So we log an error and return success.
*
- * This is not a big deal: the syscall allowing to attach a BPF program to a HID device
- * will not be available, so nobody will be able to use the functionality.
+ * This is not a big deal: nobody will be able to use the functionality.
*/
- err = register_btf_fmodret_id_set(&hid_bpf_fmodret_set);
- if (err) {
- pr_warn("error while registering fmodret entrypoints: %d", err);
- return 0;
- }
-
- err = hid_bpf_preload_skel();
- if (err) {
- pr_warn("error while preloading HID BPF dispatcher: %d", err);
- return 0;
- }
-
- /* register tracing kfuncs after we are sure we can load our preloaded bpf program */
- err = register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &hid_bpf_kfunc_set);
+ err = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, &hid_bpf_kfunc_set);
if (err) {
pr_warn("error while setting HID BPF tracing kfuncs: %d", err);
return 0;
}
- /* register syscalls after we are sure we can load our preloaded bpf program */
err = register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &hid_bpf_syscall_kfunc_set);
if (err) {
pr_warn("error while setting HID BPF syscall kfuncs: %d", err);
@@ -665,15 +673,6 @@ static int __init hid_bpf_init(void)
return 0;
}
-static void __exit hid_bpf_exit(void)
-{
- /* HID depends on us, so if we hit that code, we are guaranteed that hid
- * has been removed and thus we do not need to clear the HID devices
- */
- hid_bpf_free_links_and_skel();
-}
-
late_initcall(hid_bpf_init);
-module_exit(hid_bpf_exit);
MODULE_AUTHOR("Benjamin Tissoires");
MODULE_LICENSE("GPL");
diff --git a/drivers/hid/bpf/hid_bpf_dispatch.h b/drivers/hid/bpf/hid_bpf_dispatch.h
index fbe0639d09f2..44c6ea22233f 100644
--- a/drivers/hid/bpf/hid_bpf_dispatch.h
+++ b/drivers/hid/bpf/hid_bpf_dispatch.h
@@ -8,16 +8,13 @@
struct hid_bpf_ctx_kern {
struct hid_bpf_ctx ctx;
u8 *data;
+ bool from_bpf;
};
-int hid_bpf_preload_skel(void);
-void hid_bpf_free_links_and_skel(void);
-int hid_bpf_get_prog_attach_type(struct bpf_prog *prog);
-int __hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type, int prog_fd,
- struct bpf_prog *prog, __u32 flags);
-void __hid_bpf_destroy_device(struct hid_device *hdev);
-int hid_bpf_prog_run(struct hid_device *hdev, enum hid_bpf_prog_type type,
- struct hid_bpf_ctx_kern *ctx_kern);
+struct hid_device *hid_get_device(unsigned int hid_id);
+void hid_put_device(struct hid_device *hid);
+int hid_bpf_allocate_event_data(struct hid_device *hdev);
+void __hid_bpf_ops_destroy_device(struct hid_device *hdev);
int hid_bpf_reconnect(struct hid_device *hdev);
struct bpf_prog;
diff --git a/drivers/hid/bpf/hid_bpf_jmp_table.c b/drivers/hid/bpf/hid_bpf_jmp_table.c
deleted file mode 100644
index aa8e1c79cdf5..000000000000
--- a/drivers/hid/bpf/hid_bpf_jmp_table.c
+++ /dev/null
@@ -1,565 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-
-/*
- * HID-BPF support for Linux
- *
- * Copyright (c) 2022 Benjamin Tissoires
- */
-
-#include <linux/bitops.h>
-#include <linux/btf.h>
-#include <linux/btf_ids.h>
-#include <linux/circ_buf.h>
-#include <linux/filter.h>
-#include <linux/hid.h>
-#include <linux/hid_bpf.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/workqueue.h>
-#include "hid_bpf_dispatch.h"
-#include "entrypoints/entrypoints.lskel.h"
-
-#define HID_BPF_MAX_PROGS 1024 /* keep this in sync with preloaded bpf,
- * needs to be a power of 2 as we use it as
- * a circular buffer
- */
-
-#define NEXT(idx) (((idx) + 1) & (HID_BPF_MAX_PROGS - 1))
-#define PREV(idx) (((idx) - 1) & (HID_BPF_MAX_PROGS - 1))
-
-/*
- * represents one attached program stored in the hid jump table
- */
-struct hid_bpf_prog_entry {
- struct bpf_prog *prog;
- struct hid_device *hdev;
- enum hid_bpf_prog_type type;
- u16 idx;
-};
-
-struct hid_bpf_jmp_table {
- struct bpf_map *map;
- struct hid_bpf_prog_entry entries[HID_BPF_MAX_PROGS]; /* compacted list, circular buffer */
- int tail, head;
- struct bpf_prog *progs[HID_BPF_MAX_PROGS]; /* idx -> progs mapping */
- unsigned long enabled[BITS_TO_LONGS(HID_BPF_MAX_PROGS)];
-};
-
-#define FOR_ENTRIES(__i, __start, __end) \
- for (__i = __start; CIRC_CNT(__end, __i, HID_BPF_MAX_PROGS); __i = NEXT(__i))
-
-static struct hid_bpf_jmp_table jmp_table;
-
-static DEFINE_MUTEX(hid_bpf_attach_lock); /* held when attaching/detaching programs */
-
-static void hid_bpf_release_progs(struct work_struct *work);
-
-static DECLARE_WORK(release_work, hid_bpf_release_progs);
-
-BTF_ID_LIST(hid_bpf_btf_ids)
-BTF_ID(func, hid_bpf_device_event) /* HID_BPF_PROG_TYPE_DEVICE_EVENT */
-BTF_ID(func, hid_bpf_rdesc_fixup) /* HID_BPF_PROG_TYPE_RDESC_FIXUP */
-
-static int hid_bpf_max_programs(enum hid_bpf_prog_type type)
-{
- switch (type) {
- case HID_BPF_PROG_TYPE_DEVICE_EVENT:
- return HID_BPF_MAX_PROGS_PER_DEV;
- case HID_BPF_PROG_TYPE_RDESC_FIXUP:
- return 1;
- default:
- return -EINVAL;
- }
-}
-
-static int hid_bpf_program_count(struct hid_device *hdev,
- struct bpf_prog *prog,
- enum hid_bpf_prog_type type)
-{
- int i, n = 0;
-
- if (type >= HID_BPF_PROG_TYPE_MAX)
- return -EINVAL;
-
- FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) {
- struct hid_bpf_prog_entry *entry = &jmp_table.entries[i];
-
- if (type != HID_BPF_PROG_TYPE_UNDEF && entry->type != type)
- continue;
-
- if (hdev && entry->hdev != hdev)
- continue;
-
- if (prog && entry->prog != prog)
- continue;
-
- n++;
- }
-
- return n;
-}
-
-__weak noinline int __hid_bpf_tail_call(struct hid_bpf_ctx *ctx)
-{
- return 0;
-}
-
-int hid_bpf_prog_run(struct hid_device *hdev, enum hid_bpf_prog_type type,
- struct hid_bpf_ctx_kern *ctx_kern)
-{
- struct hid_bpf_prog_list *prog_list;
- int i, idx, err = 0;
-
- rcu_read_lock();
- prog_list = rcu_dereference(hdev->bpf.progs[type]);
-
- if (!prog_list)
- goto out_unlock;
-
- for (i = 0; i < prog_list->prog_cnt; i++) {
- idx = prog_list->prog_idx[i];
-
- if (!test_bit(idx, jmp_table.enabled))
- continue;
-
- ctx_kern->ctx.index = idx;
- err = __hid_bpf_tail_call(&ctx_kern->ctx);
- if (err < 0)
- break;
- if (err)
- ctx_kern->ctx.retval = err;
- }
-
- out_unlock:
- rcu_read_unlock();
-
- return err;
-}
-
-/*
- * assign the list of programs attached to a given hid device.
- */
-static void __hid_bpf_set_hdev_progs(struct hid_device *hdev, struct hid_bpf_prog_list *new_list,
- enum hid_bpf_prog_type type)
-{
- struct hid_bpf_prog_list *old_list;
-
- spin_lock(&hdev->bpf.progs_lock);
- old_list = rcu_dereference_protected(hdev->bpf.progs[type],
- lockdep_is_held(&hdev->bpf.progs_lock));
- rcu_assign_pointer(hdev->bpf.progs[type], new_list);
- spin_unlock(&hdev->bpf.progs_lock);
- synchronize_rcu();
-
- kfree(old_list);
-}
-
-/*
- * allocate and populate the list of programs attached to a given hid device.
- *
- * Must be called under lock.
- */
-static int hid_bpf_populate_hdev(struct hid_device *hdev, enum hid_bpf_prog_type type)
-{
- struct hid_bpf_prog_list *new_list;
- int i;
-
- if (type >= HID_BPF_PROG_TYPE_MAX || !hdev)
- return -EINVAL;
-
- if (hdev->bpf.destroyed)
- return 0;
-
- new_list = kzalloc(sizeof(*new_list), GFP_KERNEL);
- if (!new_list)
- return -ENOMEM;
-
- FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) {
- struct hid_bpf_prog_entry *entry = &jmp_table.entries[i];
-
- if (entry->type == type && entry->hdev == hdev &&
- test_bit(entry->idx, jmp_table.enabled))
- new_list->prog_idx[new_list->prog_cnt++] = entry->idx;
- }
-
- __hid_bpf_set_hdev_progs(hdev, new_list, type);
-
- return 0;
-}
-
-static void __hid_bpf_do_release_prog(int map_fd, unsigned int idx)
-{
- skel_map_delete_elem(map_fd, &idx);
- jmp_table.progs[idx] = NULL;
-}
-
-static void hid_bpf_release_progs(struct work_struct *work)
-{
- int i, j, n, map_fd = -1;
- bool hdev_destroyed;
-
- if (!jmp_table.map)
- return;
-
- /* retrieve a fd of our prog_array map in BPF */
- map_fd = skel_map_get_fd_by_id(jmp_table.map->id);
- if (map_fd < 0)
- return;
-
- mutex_lock(&hid_bpf_attach_lock); /* protects against attaching new programs */
-
- /* detach unused progs from HID devices */
- FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) {
- struct hid_bpf_prog_entry *entry = &jmp_table.entries[i];
- enum hid_bpf_prog_type type;
- struct hid_device *hdev;
-
- if (test_bit(entry->idx, jmp_table.enabled))
- continue;
-
- /* we have an attached prog */
- if (entry->hdev) {
- hdev = entry->hdev;
- type = entry->type;
- /*
- * hdev is still valid, even if we are called after hid_destroy_device():
- * when hid_bpf_attach() gets called, it takes a ref on the dev through
- * bus_find_device()
- */
- hdev_destroyed = hdev->bpf.destroyed;
-
- hid_bpf_populate_hdev(hdev, type);
-
- /* mark all other disabled progs from hdev of the given type as detached */
- FOR_ENTRIES(j, i, jmp_table.head) {
- struct hid_bpf_prog_entry *next;
-
- next = &jmp_table.entries[j];
-
- if (test_bit(next->idx, jmp_table.enabled))
- continue;
-
- if (next->hdev == hdev && next->type == type) {
- /*
- * clear the hdev reference and decrement the device ref
- * that was taken during bus_find_device() while calling
- * hid_bpf_attach()
- */
- next->hdev = NULL;
- put_device(&hdev->dev);
- }
- }
-
- /* if type was rdesc fixup and the device is not gone, reconnect device */
- if (type == HID_BPF_PROG_TYPE_RDESC_FIXUP && !hdev_destroyed)
- hid_bpf_reconnect(hdev);
- }
- }
-
- /* remove all unused progs from the jump table */
- FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) {
- struct hid_bpf_prog_entry *entry = &jmp_table.entries[i];
-
- if (test_bit(entry->idx, jmp_table.enabled))
- continue;
-
- if (entry->prog)
- __hid_bpf_do_release_prog(map_fd, entry->idx);
- }
-
- /* compact the entry list */
- n = jmp_table.tail;
- FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) {
- struct hid_bpf_prog_entry *entry = &jmp_table.entries[i];
-
- if (!test_bit(entry->idx, jmp_table.enabled))
- continue;
-
- jmp_table.entries[n] = jmp_table.entries[i];
- n = NEXT(n);
- }
-
- jmp_table.head = n;
-
- mutex_unlock(&hid_bpf_attach_lock);
-
- if (map_fd >= 0)
- close_fd(map_fd);
-}
-
-static void hid_bpf_release_prog_at(int idx)
-{
- int map_fd = -1;
-
- /* retrieve a fd of our prog_array map in BPF */
- map_fd = skel_map_get_fd_by_id(jmp_table.map->id);
- if (map_fd < 0)
- return;
-
- __hid_bpf_do_release_prog(map_fd, idx);
-
- close(map_fd);
-}
-
-/*
- * Insert the given BPF program represented by its fd in the jmp table.
- * Returns the index in the jump table or a negative error.
- */
-static int hid_bpf_insert_prog(int prog_fd, struct bpf_prog *prog)
-{
- int i, index = -1, map_fd = -1, err = -EINVAL;
-
- /* retrieve a fd of our prog_array map in BPF */
- map_fd = skel_map_get_fd_by_id(jmp_table.map->id);
-
- if (map_fd < 0) {
- err = -EINVAL;
- goto out;
- }
-
- /* find the first available index in the jmp_table */
- for (i = 0; i < HID_BPF_MAX_PROGS; i++) {
- if (!jmp_table.progs[i] && index < 0) {
- /* mark the index as used */
- jmp_table.progs[i] = prog;
- index = i;
- __set_bit(i, jmp_table.enabled);
- }
- }
- if (index < 0) {
- err = -ENOMEM;
- goto out;
- }
-
- /* insert the program in the jump table */
- err = skel_map_update_elem(map_fd, &index, &prog_fd, 0);
- if (err)
- goto out;
-
- /* return the index */
- err = index;
-
- out:
- if (err < 0)
- __hid_bpf_do_release_prog(map_fd, index);
- if (map_fd >= 0)
- close_fd(map_fd);
- return err;
-}
-
-int hid_bpf_get_prog_attach_type(struct bpf_prog *prog)
-{
- int prog_type = HID_BPF_PROG_TYPE_UNDEF;
- int i;
-
- for (i = 0; i < HID_BPF_PROG_TYPE_MAX; i++) {
- if (hid_bpf_btf_ids[i] == prog->aux->attach_btf_id) {
- prog_type = i;
- break;
- }
- }
-
- return prog_type;
-}
-
-static void hid_bpf_link_release(struct bpf_link *link)
-{
- struct hid_bpf_link *hid_link =
- container_of(link, struct hid_bpf_link, link);
-
- __clear_bit(hid_link->hid_table_index, jmp_table.enabled);
- schedule_work(&release_work);
-}
-
-static void hid_bpf_link_dealloc(struct bpf_link *link)
-{
- struct hid_bpf_link *hid_link =
- container_of(link, struct hid_bpf_link, link);
-
- kfree(hid_link);
-}
-
-static void hid_bpf_link_show_fdinfo(const struct bpf_link *link,
- struct seq_file *seq)
-{
- seq_printf(seq,
- "attach_type:\tHID-BPF\n");
-}
-
-static const struct bpf_link_ops hid_bpf_link_lops = {
- .release = hid_bpf_link_release,
- .dealloc = hid_bpf_link_dealloc,
- .show_fdinfo = hid_bpf_link_show_fdinfo,
-};
-
-/* called from syscall */
-noinline int
-__hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type,
- int prog_fd, struct bpf_prog *prog, __u32 flags)
-{
- struct bpf_link_primer link_primer;
- struct hid_bpf_link *link;
- struct hid_bpf_prog_entry *prog_entry;
- int cnt, err = -EINVAL, prog_table_idx = -1;
-
- mutex_lock(&hid_bpf_attach_lock);
-
- link = kzalloc(sizeof(*link), GFP_USER);
- if (!link) {
- err = -ENOMEM;
- goto err_unlock;
- }
-
- bpf_link_init(&link->link, BPF_LINK_TYPE_UNSPEC,
- &hid_bpf_link_lops, prog);
-
- /* do not attach too many programs to a given HID device */
- cnt = hid_bpf_program_count(hdev, NULL, prog_type);
- if (cnt < 0) {
- err = cnt;
- goto err_unlock;
- }
-
- if (cnt >= hid_bpf_max_programs(prog_type)) {
- err = -E2BIG;
- goto err_unlock;
- }
-
- prog_table_idx = hid_bpf_insert_prog(prog_fd, prog);
- /* if the jmp table is full, abort */
- if (prog_table_idx < 0) {
- err = prog_table_idx;
- goto err_unlock;
- }
-
- if (flags & HID_BPF_FLAG_INSERT_HEAD) {
- /* take the previous prog_entry slot */
- jmp_table.tail = PREV(jmp_table.tail);
- prog_entry = &jmp_table.entries[jmp_table.tail];
- } else {
- /* take the next prog_entry slot */
- prog_entry = &jmp_table.entries[jmp_table.head];
- jmp_table.head = NEXT(jmp_table.head);
- }
-
- /* we steal the ref here */
- prog_entry->prog = prog;
- prog_entry->idx = prog_table_idx;
- prog_entry->hdev = hdev;
- prog_entry->type = prog_type;
-
- /* finally store the index in the device list */
- err = hid_bpf_populate_hdev(hdev, prog_type);
- if (err) {
- hid_bpf_release_prog_at(prog_table_idx);
- goto err_unlock;
- }
-
- link->hid_table_index = prog_table_idx;
-
- err = bpf_link_prime(&link->link, &link_primer);
- if (err)
- goto err_unlock;
-
- mutex_unlock(&hid_bpf_attach_lock);
-
- return bpf_link_settle(&link_primer);
-
- err_unlock:
- mutex_unlock(&hid_bpf_attach_lock);
-
- kfree(link);
-
- return err;
-}
-
-void __hid_bpf_destroy_device(struct hid_device *hdev)
-{
- int type, i;
- struct hid_bpf_prog_list *prog_list;
-
- rcu_read_lock();
-
- for (type = 0; type < HID_BPF_PROG_TYPE_MAX; type++) {
- prog_list = rcu_dereference(hdev->bpf.progs[type]);
-
- if (!prog_list)
- continue;
-
- for (i = 0; i < prog_list->prog_cnt; i++)
- __clear_bit(prog_list->prog_idx[i], jmp_table.enabled);
- }
-
- rcu_read_unlock();
-
- for (type = 0; type < HID_BPF_PROG_TYPE_MAX; type++)
- __hid_bpf_set_hdev_progs(hdev, NULL, type);
-
- /* schedule release of all detached progs */
- schedule_work(&release_work);
-}
-
-#define HID_BPF_PROGS_COUNT 1
-
-static struct bpf_link *links[HID_BPF_PROGS_COUNT];
-static struct entrypoints_bpf *skel;
-
-void hid_bpf_free_links_and_skel(void)
-{
- int i;
-
- /* the following is enough to release all programs attached to hid */
- if (jmp_table.map)
- bpf_map_put_with_uref(jmp_table.map);
-
- for (i = 0; i < ARRAY_SIZE(links); i++) {
- if (!IS_ERR_OR_NULL(links[i]))
- bpf_link_put(links[i]);
- }
- entrypoints_bpf__destroy(skel);
-}
-
-#define ATTACH_AND_STORE_LINK(__name) do { \
- err = entrypoints_bpf__##__name##__attach(skel); \
- if (err) \
- goto out; \
- \
- links[idx] = bpf_link_get_from_fd(skel->links.__name##_fd); \
- if (IS_ERR(links[idx])) { \
- err = PTR_ERR(links[idx]); \
- goto out; \
- } \
- \
- /* Avoid taking over stdin/stdout/stderr of init process. Zeroing out \
- * makes skel_closenz() a no-op later in iterators_bpf__destroy(). \
- */ \
- close_fd(skel->links.__name##_fd); \
- skel->links.__name##_fd = 0; \
- idx++; \
-} while (0)
-
-int hid_bpf_preload_skel(void)
-{
- int err, idx = 0;
-
- skel = entrypoints_bpf__open();
- if (!skel)
- return -ENOMEM;
-
- err = entrypoints_bpf__load(skel);
- if (err)
- goto out;
-
- jmp_table.map = bpf_map_get_with_uref(skel->maps.hid_jmp_table.map_fd);
- if (IS_ERR(jmp_table.map)) {
- err = PTR_ERR(jmp_table.map);
- goto out;
- }
-
- ATTACH_AND_STORE_LINK(hid_tail_call);
-
- return 0;
-out:
- hid_bpf_free_links_and_skel();
- return err;
-}
diff --git a/drivers/hid/bpf/hid_bpf_struct_ops.c b/drivers/hid/bpf/hid_bpf_struct_ops.c
new file mode 100644
index 000000000000..702c22fae136
--- /dev/null
+++ b/drivers/hid/bpf/hid_bpf_struct_ops.c
@@ -0,0 +1,326 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * HID-BPF support for Linux
+ *
+ * Copyright (c) 2024 Benjamin Tissoires
+ */
+
+#include <linux/bitops.h>
+#include <linux/bpf_verifier.h>
+#include <linux/bpf.h>
+#include <linux/btf.h>
+#include <linux/btf_ids.h>
+#include <linux/filter.h>
+#include <linux/hid.h>
+#include <linux/hid_bpf.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/stddef.h>
+#include <linux/workqueue.h>
+#include "hid_bpf_dispatch.h"
+
+static struct btf *hid_bpf_ops_btf;
+
+static int hid_bpf_ops_init(struct btf *btf)
+{
+ hid_bpf_ops_btf = btf;
+ return 0;
+}
+
+static bool hid_bpf_ops_is_valid_access(int off, int size,
+ enum bpf_access_type type,
+ const struct bpf_prog *prog,
+ struct bpf_insn_access_aux *info)
+{
+ return bpf_tracing_btf_ctx_access(off, size, type, prog, info);
+}
+
+static int hid_bpf_ops_check_member(const struct btf_type *t,
+ const struct btf_member *member,
+ const struct bpf_prog *prog)
+{
+ u32 moff = __btf_member_bit_offset(t, member) / 8;
+
+ switch (moff) {
+ case offsetof(struct hid_bpf_ops, hid_rdesc_fixup):
+ case offsetof(struct hid_bpf_ops, hid_hw_request):
+ case offsetof(struct hid_bpf_ops, hid_hw_output_report):
+ break;
+ default:
+ if (prog->sleepable)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+struct hid_bpf_offset_write_range {
+ const char *struct_name;
+ u32 struct_length;
+ u32 start;
+ u32 end;
+};
+
+static int hid_bpf_ops_btf_struct_access(struct bpf_verifier_log *log,
+ const struct bpf_reg_state *reg,
+ int off, int size)
+{
+#define WRITE_RANGE(_name, _field, _is_string) \
+ { \
+ .struct_name = #_name, \
+ .struct_length = sizeof(struct _name), \
+ .start = offsetof(struct _name, _field), \
+ .end = offsetofend(struct _name, _field) - !!(_is_string), \
+ }
+
+ const struct hid_bpf_offset_write_range write_ranges[] = {
+ WRITE_RANGE(hid_bpf_ctx, retval, false),
+ WRITE_RANGE(hid_device, name, true),
+ WRITE_RANGE(hid_device, uniq, true),
+ WRITE_RANGE(hid_device, phys, true),
+ };
+#undef WRITE_RANGE
+ const struct btf_type *state = NULL;
+ const struct btf_type *t;
+ const char *cur = NULL;
+ int i;
+
+ t = btf_type_by_id(reg->btf, reg->btf_id);
+
+ for (i = 0; i < ARRAY_SIZE(write_ranges); i++) {
+ const struct hid_bpf_offset_write_range *write_range = &write_ranges[i];
+ s32 type_id;
+
+ /* we already found a writeable struct, but there is a
+ * new one, let's break the loop.
+ */
+ if (t == state && write_range->struct_name != cur)
+ break;
+
+ /* new struct to look for */
+ if (write_range->struct_name != cur) {
+ type_id = btf_find_by_name_kind(reg->btf, write_range->struct_name,
+ BTF_KIND_STRUCT);
+ if (type_id < 0)
+ return -EINVAL;
+
+ state = btf_type_by_id(reg->btf, type_id);
+ }
+
+ /* this is not the struct we are looking for */
+ if (t != state) {
+ cur = write_range->struct_name;
+ continue;
+ }
+
+ /* first time we see this struct, check for out of bounds */
+ if (cur != write_range->struct_name &&
+ off + size > write_range->struct_length) {
+ bpf_log(log, "write access for struct %s at off %d with size %d\n",
+ write_range->struct_name, off, size);
+ return -EACCES;
+ }
+
+ /* now check if we are in our boundaries */
+ if (off >= write_range->start && off + size <= write_range->end)
+ return NOT_INIT;
+
+ cur = write_range->struct_name;
+ }
+
+
+ if (t != state)
+ bpf_log(log, "write access to this struct is not supported\n");
+ else
+ bpf_log(log,
+ "write access at off %d with size %d on read-only part of %s\n",
+ off, size, cur);
+
+ return -EACCES;
+}
+
+static const struct bpf_verifier_ops hid_bpf_verifier_ops = {
+ .get_func_proto = bpf_base_func_proto,
+ .is_valid_access = hid_bpf_ops_is_valid_access,
+ .btf_struct_access = hid_bpf_ops_btf_struct_access,
+};
+
+static int hid_bpf_ops_init_member(const struct btf_type *t,
+ const struct btf_member *member,
+ void *kdata, const void *udata)
+{
+ const struct hid_bpf_ops *uhid_bpf_ops;
+ struct hid_bpf_ops *khid_bpf_ops;
+ u32 moff;
+
+ uhid_bpf_ops = (const struct hid_bpf_ops *)udata;
+ khid_bpf_ops = (struct hid_bpf_ops *)kdata;
+
+ moff = __btf_member_bit_offset(t, member) / 8;
+
+ switch (moff) {
+ case offsetof(struct hid_bpf_ops, hid_id):
+ /* For hid_id and flags fields, this function has to copy it
+ * and return 1 to indicate that the data has been handled by
+ * the struct_ops type, or the verifier will reject the map if
+ * the value of those fields is not zero.
+ */
+ khid_bpf_ops->hid_id = uhid_bpf_ops->hid_id;
+ return 1;
+ case offsetof(struct hid_bpf_ops, flags):
+ if (uhid_bpf_ops->flags & ~BPF_F_BEFORE)
+ return -EINVAL;
+ khid_bpf_ops->flags = uhid_bpf_ops->flags;
+ return 1;
+ }
+ return 0;
+}
+
+static int hid_bpf_reg(void *kdata, struct bpf_link *link)
+{
+ struct hid_bpf_ops *ops = kdata;
+ struct hid_device *hdev;
+ int count, err = 0;
+
+ /* prevent multiple attach of the same struct_ops */
+ if (ops->hdev)
+ return -EINVAL;
+
+ hdev = hid_get_device(ops->hid_id);
+ if (IS_ERR(hdev))
+ return PTR_ERR(hdev);
+
+ ops->hdev = hdev;
+
+ mutex_lock(&hdev->bpf.prog_list_lock);
+
+ count = list_count_nodes(&hdev->bpf.prog_list);
+ if (count >= HID_BPF_MAX_PROGS_PER_DEV) {
+ err = -E2BIG;
+ goto out_unlock;
+ }
+
+ if (ops->hid_rdesc_fixup) {
+ if (hdev->bpf.rdesc_ops) {
+ err = -EINVAL;
+ goto out_unlock;
+ }
+
+ hdev->bpf.rdesc_ops = ops;
+ }
+
+ if (ops->hid_device_event) {
+ err = hid_bpf_allocate_event_data(hdev);
+ if (err)
+ goto out_unlock;
+ }
+
+ if (ops->flags & BPF_F_BEFORE)
+ list_add_rcu(&ops->list, &hdev->bpf.prog_list);
+ else
+ list_add_tail_rcu(&ops->list, &hdev->bpf.prog_list);
+ synchronize_srcu(&hdev->bpf.srcu);
+
+out_unlock:
+ mutex_unlock(&hdev->bpf.prog_list_lock);
+
+ if (err) {
+ if (hdev->bpf.rdesc_ops == ops)
+ hdev->bpf.rdesc_ops = NULL;
+ hid_put_device(hdev);
+ } else if (ops->hid_rdesc_fixup) {
+ hid_bpf_reconnect(hdev);
+ }
+
+ return err;
+}
+
+static void hid_bpf_unreg(void *kdata, struct bpf_link *link)
+{
+ struct hid_bpf_ops *ops = kdata;
+ struct hid_device *hdev;
+ bool reconnect = false;
+
+ hdev = ops->hdev;
+
+ /* check if __hid_bpf_ops_destroy_device() has been called */
+ if (!hdev)
+ return;
+
+ mutex_lock(&hdev->bpf.prog_list_lock);
+
+ list_del_rcu(&ops->list);
+ synchronize_srcu(&hdev->bpf.srcu);
+ ops->hdev = NULL;
+
+ reconnect = hdev->bpf.rdesc_ops == ops;
+ if (reconnect)
+ hdev->bpf.rdesc_ops = NULL;
+
+ mutex_unlock(&hdev->bpf.prog_list_lock);
+
+ if (reconnect)
+ hid_bpf_reconnect(hdev);
+
+ hid_put_device(hdev);
+}
+
+static int __hid_bpf_device_event(struct hid_bpf_ctx *ctx, enum hid_report_type type, u64 source)
+{
+ return 0;
+}
+
+static int __hid_bpf_rdesc_fixup(struct hid_bpf_ctx *ctx)
+{
+ return 0;
+}
+
+static int __hid_bpf_hw_request(struct hid_bpf_ctx *ctx, unsigned char reportnum,
+ enum hid_report_type rtype, enum hid_class_request reqtype,
+ u64 source)
+{
+ return 0;
+}
+
+static int __hid_bpf_hw_output_report(struct hid_bpf_ctx *ctx, u64 source)
+{
+ return 0;
+}
+
+static struct hid_bpf_ops __bpf_hid_bpf_ops = {
+ .hid_device_event = __hid_bpf_device_event,
+ .hid_rdesc_fixup = __hid_bpf_rdesc_fixup,
+ .hid_hw_request = __hid_bpf_hw_request,
+ .hid_hw_output_report = __hid_bpf_hw_output_report,
+};
+
+static struct bpf_struct_ops bpf_hid_bpf_ops = {
+ .verifier_ops = &hid_bpf_verifier_ops,
+ .init = hid_bpf_ops_init,
+ .check_member = hid_bpf_ops_check_member,
+ .init_member = hid_bpf_ops_init_member,
+ .reg = hid_bpf_reg,
+ .unreg = hid_bpf_unreg,
+ .name = "hid_bpf_ops",
+ .cfi_stubs = &__bpf_hid_bpf_ops,
+ .owner = THIS_MODULE,
+};
+
+void __hid_bpf_ops_destroy_device(struct hid_device *hdev)
+{
+ struct hid_bpf_ops *e;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(e, &hdev->bpf.prog_list, list) {
+ hid_put_device(hdev);
+ e->hdev = NULL;
+ }
+ rcu_read_unlock();
+}
+
+static int __init hid_bpf_struct_ops_init(void)
+{
+ return register_bpf_struct_ops(&bpf_hid_bpf_ops, hid_bpf_ops);
+}
+late_initcall(hid_bpf_struct_ops_init);
diff --git a/drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c b/drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c
index dc26a7677d36..caec91391d32 100644
--- a/drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c
+++ b/drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c
@@ -133,7 +133,7 @@ HID_BPF_CONFIG(
* integer. We thus divide it by 30 to match what other joysticks are
* doing
*/
-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC(HID_BPF_RDESC_FIXUP)
int BPF_PROG(hid_fix_rdesc_raptor_mach_2, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */);
@@ -152,7 +152,7 @@ int BPF_PROG(hid_fix_rdesc_raptor_mach_2, struct hid_bpf_ctx *hctx)
* divide it by 30.
* Byte 34 is always null, so it is ignored.
*/
-SEC("fmod_ret/hid_bpf_device_event")
+SEC(HID_BPF_DEVICE_EVENT)
int BPF_PROG(raptor_mach_2_fix_hat_switch, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 64 /* size */);
@@ -168,6 +168,11 @@ int BPF_PROG(raptor_mach_2_fix_hat_switch, struct hid_bpf_ctx *hctx)
return 0;
}
+HID_BPF_OPS(raptor_mach_2) = {
+ .hid_rdesc_fixup = (void *)hid_fix_rdesc_raptor_mach_2,
+ .hid_device_event = (void *)raptor_mach_2_fix_hat_switch,
+};
+
SEC("syscall")
int probe(struct hid_bpf_probe_args *ctx)
{
diff --git a/drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c b/drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c
index 3d14bbb6f276..c2413fa80543 100644
--- a/drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c
+++ b/drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c
@@ -30,7 +30,7 @@ HID_BPF_CONFIG(
* pointer.
*/
-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+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 */, 4096 /* size */);
@@ -45,6 +45,10 @@ int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx)
return 0;
}
+HID_BPF_OPS(hp_elite_presenter) = {
+ .hid_rdesc_fixup = (void *)hid_fix_rdesc,
+};
+
SEC("syscall")
int probe(struct hid_bpf_probe_args *ctx)
{
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/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";
diff --git a/drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c b/drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c
index ff759f2276f9..a4a4f324aedd 100644
--- a/drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c
+++ b/drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c
@@ -191,7 +191,7 @@ static const __u8 fixed_rdesc[] = {
0xc0, // End Collection 327
};
-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC(HID_BPF_RDESC_FIXUP)
int BPF_PROG(hid_fix_rdesc_huion_kamvas_pro_19, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */);
@@ -215,7 +215,7 @@ int BPF_PROG(hid_fix_rdesc_huion_kamvas_pro_19, struct hid_bpf_ctx *hctx)
* - if there was this out-of-proximity event, we are entering
* eraser mode, and we will until the next out-of-proximity.
*/
-SEC("fmod_ret/hid_bpf_device_event")
+SEC(HID_BPF_DEVICE_EVENT)
int BPF_PROG(kamvas_pro_19_fix_3rd_button, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
@@ -255,6 +255,11 @@ int BPF_PROG(kamvas_pro_19_fix_3rd_button, struct hid_bpf_ctx *hctx)
return 0;
}
+HID_BPF_OPS(huion_Kamvas_pro_19) = {
+ .hid_rdesc_fixup = (void *)hid_fix_rdesc_huion_kamvas_pro_19,
+ .hid_device_event = (void *)kamvas_pro_19_fix_3rd_button,
+};
+
SEC("syscall")
int probe(struct hid_bpf_probe_args *ctx)
{
diff --git a/drivers/hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c b/drivers/hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c
index 225cbefdbf0e..82f1950445dd 100644
--- a/drivers/hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c
+++ b/drivers/hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c
@@ -21,7 +21,7 @@ HID_BPF_CONFIG(
* We just fix the report descriptor to enable those missing 7 buttons.
*/
-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC(HID_BPF_RDESC_FIXUP)
int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx)
{
const u8 offsets[] = {84, 112, 140};
@@ -45,6 +45,10 @@ int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx)
return 0;
}
+HID_BPF_OPS(iogear_kaliber_momentum) = {
+ .hid_rdesc_fixup = (void *)hid_fix_rdesc,
+};
+
SEC("syscall")
int probe(struct hid_bpf_probe_args *ctx)
{
diff --git a/drivers/hid/bpf/progs/Makefile b/drivers/hid/bpf/progs/Makefile
index 63ed7e02adf1..ec1fc642fd63 100644
--- a/drivers/hid/bpf/progs/Makefile
+++ b/drivers/hid/bpf/progs/Makefile
@@ -56,7 +56,7 @@ clean:
%.bpf.o: %.bpf.c vmlinux.h $(BPFOBJ) | $(OUTPUT)
$(call msg,BPF,$@)
- $(Q)$(CLANG) -g -O2 --target=bpf $(INCLUDES) \
+ $(Q)$(CLANG) -g -O2 --target=bpf -Wall -Werror $(INCLUDES) \
-c $(filter %.c,$^) -o $@ && \
$(LLVM_STRIP) -g $@
diff --git a/drivers/hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c b/drivers/hid/bpf/progs/Microsoft__Xbox-Elite-2.bpf.c
index c04abecab8ee..382bba735a2c 100644
--- a/drivers/hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c
+++ b/drivers/hid/bpf/progs/Microsoft__Xbox-Elite-2.bpf.c
@@ -15,20 +15,19 @@ HID_BPF_CONFIG(
);
/*
- * When using the XBox Wireless Controller Elite 2 over Bluetooth,
- * the device exports the paddle on the back of the device as a single
+ * When using the Xbox Wireless Controller Elite 2 over Bluetooth,
+ * the device exports the paddles on the back of the device as a single
* bitfield value of usage "Assign Selection".
*
- * The kernel doesn't process those usages properly and report KEY_UNKNOWN
- * for it.
+ * The kernel doesn't process the paddles usage properly and reports KEY_UNKNOWN.
*
- * SDL doesn't know how to interprete that KEY_UNKNOWN and thus ignores the paddles.
+ * SDL doesn't know how to interpret KEY_UNKNOWN and thus ignores the paddles.
*
* Given that over USB the kernel uses BTN_TRIGGER_HAPPY[5-8], we
- * can tweak the report descriptor to make the kernel interprete it properly:
- * - we need an application collection of gamepad (so we have to close the current
+ * can tweak the report descriptor to make the kernel interpret it properly:
+ * - We need an application collection of gamepad (so we have to close the current
* Consumer Control one)
- * - we need to change the usage to be buttons from 0x15 to 0x18
+ * - We need to change the usage to be buttons from 0x15 to 0x18
*/
#define OFFSET_ASSIGN_SELECTION 211
@@ -93,7 +92,7 @@ _Static_assert(sizeof(rdesc_assign_selection) == sizeof(fixed_rdesc_assign_selec
_Static_assert(sizeof(rdesc_assign_selection) + OFFSET_ASSIGN_SELECTION < ORIGINAL_RDESC_SIZE,
"Rdesc at given offset is too big");
-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+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 */, 4096 /* size */);
@@ -114,6 +113,10 @@ int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx)
return 0;
}
+HID_BPF_OPS(xbox_elite_2) = {
+ .hid_rdesc_fixup = (void *)hid_fix_rdesc,
+};
+
SEC("syscall")
int probe(struct hid_bpf_probe_args *ctx)
{
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";
diff --git a/drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c b/drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c
index dc05aa48faa7..2da680bc4e11 100644
--- a/drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c
+++ b/drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c
@@ -101,7 +101,7 @@ static inline __u8 *get_u8(__u8 *data, unsigned int offset)
return (__u8 *)get_bits(data, offset);
}
-SEC("fmod_ret/hid_bpf_device_event")
+SEC(HID_BPF_DEVICE_EVENT)
int BPF_PROG(artpen_pressure_interpolate, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, PEN_REPORT_LEN /* size */);
@@ -139,6 +139,10 @@ int BPF_PROG(artpen_pressure_interpolate, struct hid_bpf_ctx *hctx)
return 0;
}
+HID_BPF_OPS(wacom_artpen) = {
+ .hid_device_event = (void *)artpen_pressure_interpolate,
+};
+
SEC("syscall")
int probe(struct hid_bpf_probe_args *ctx)
{
diff --git a/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c b/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c
index e1be6a12bb75..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)
@@ -91,7 +89,7 @@ static const __u8 fixed_rdesc[] = {
#define U16(index) (data[index] | (data[index + 1] << 8))
-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC(HID_BPF_RDESC_FIXUP)
int BPF_PROG(hid_fix_rdesc_xppen_artist24, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
@@ -152,13 +150,12 @@ static __u8 prev_state = 0;
* E: TipSwitch InRange
*
*/
-SEC("fmod_ret/hid_bpf_device_event")
+SEC(HID_BPF_DEVICE_EVENT)
int BPF_PROG(xppen_24_fix_eraser, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
__u8 current_state, changed_state;
bool prev_tip;
- __u16 tilt;
if (!data)
return 0; /* EPERM check */
@@ -209,6 +206,11 @@ int BPF_PROG(xppen_24_fix_eraser, struct hid_bpf_ctx *hctx)
return 0;
}
+HID_BPF_OPS(xppen_artist_24) = {
+ .hid_rdesc_fixup = (void *)hid_fix_rdesc_xppen_artist24,
+ .hid_device_event = (void *)xppen_24_fix_eraser,
+};
+
SEC("syscall")
int probe(struct hid_bpf_probe_args *ctx)
{
diff --git a/drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c b/drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c
index 65ef10036126..a669525691aa 100644
--- a/drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c
+++ b/drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c
@@ -82,7 +82,7 @@ static const __u8 fixed_rdesc[] = {
0xc0, // End Collection 112
};
-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC(HID_BPF_RDESC_FIXUP)
int BPF_PROG(hid_fix_rdesc_xppen_artistpro16gen2, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
@@ -105,8 +105,7 @@ int BPF_PROG(hid_fix_rdesc_xppen_artistpro16gen2, struct hid_bpf_ctx *hctx)
return sizeof(fixed_rdesc);
}
-SEC("fmod_ret/hid_bpf_device_event")
-int BPF_PROG(xppen_16_fix_eraser, struct hid_bpf_ctx *hctx)
+static int xppen_16_fix_eraser(struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
@@ -207,8 +206,7 @@ static void compensate_coordinates_by_tilt(__u8 *data, const __u8 idx,
data[idx+1] = coords >> 8;
}
-SEC("fmod_ret/hid_bpf_device_event")
-int BPF_PROG(xppen_16_fix_angle_offset, struct hid_bpf_ctx *hctx)
+static int xppen_16_fix_angle_offset(struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
@@ -254,6 +252,22 @@ int BPF_PROG(xppen_16_fix_angle_offset, struct hid_bpf_ctx *hctx)
return 0;
}
+SEC(HID_BPF_DEVICE_EVENT)
+int BPF_PROG(xppen_artist_pro_16_device_event, struct hid_bpf_ctx *hctx)
+{
+ int ret = xppen_16_fix_angle_offset(hctx);
+
+ if (ret)
+ return ret;
+
+ return xppen_16_fix_eraser(hctx);
+}
+
+HID_BPF_OPS(xppen_artist_pro_16) = {
+ .hid_rdesc_fixup = (void *)hid_fix_rdesc_xppen_artistpro16gen2,
+ .hid_device_event = (void *)xppen_artist_pro_16_device_event,
+};
+
SEC("syscall")
int probe(struct hid_bpf_probe_args *ctx)
{
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";
diff --git a/drivers/hid/bpf/progs/hid_bpf.h b/drivers/hid/bpf/progs/hid_bpf.h
index 7ee371cac2e1..7cabd1b2e837 100644
--- a/drivers/hid/bpf/progs/hid_bpf.h
+++ b/drivers/hid/bpf/progs/hid_bpf.h
@@ -5,6 +5,12 @@
#ifndef ____HID_BPF__H
#define ____HID_BPF__H
+#define HID_BPF_DEVICE_EVENT "struct_ops/hid_device_event"
+#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;
unsigned int rdesc_size;
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
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)