Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'for-linus-2024071601' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid

Pull HID updates from Benjamin Tissoires:

- rewrite of the HID-BPF internal implementation to use bpf struct_ops
instead of a tracing endpoint (Benjamin Tissoires)

- add two new HID-BPF hooks to be able to intercept userspace calls
targeting a HID device and filtering them (Benjamin Tissoires)

- add support for various new devices through HID-BPF filters (Benjamin
Tissoires)

- add support for the magic keyboard backlight (Orlando Chamberlain)

- add the missing MODULE_DESCRIPTION() macros in HID drivers (Jeff
Johnson)

- use of kvzalloc in case memory gets too fragmented (Hailong Liu)

- retrieve the device firmware node in the child HID device (Danny
Kaehn)

- some hid-uclogic improvements (José Expósito)

- some more typos, trivial fixes, kernel doctext and unused functions
cleanups

* tag 'for-linus-2024071601' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (60 commits)
HID: hid-steam: Fix typo in goto label
HID: mcp2221: Remove unnecessary semicolon
HID: Fix spelling mistakes "Kensigton" -> "Kensington"
HID: add more missing MODULE_DESCRIPTION() macros
HID: samples: fix the 2 struct_ops definitions
HID: fix for amples in for-6.11/bpf
HID: apple: Add support for magic keyboard backlight on T2 Macs
HID: bpf: Thrustmaster TCA Yoke Boeing joystick fix
HID: bpf: Add Huion Dial 2 bpf fixup
HID: bpf: Add support for the XP-PEN Deco Mini 4
HID: bpf: move the BIT() macro to hid_bpf_helpers.h
HID: bpf: add a driver for the Huion Inspiroy 2S (H641P)
HID: bpf: Add a HID report composition helper macros
HID: bpf: doc fixes for hid_hw_request() hooks
HID: bpf: doc fixes for hid_hw_request() hooks
HID: bpf: fix gcc warning and unify __u64 into u64
selftests/hid: ensure CKI can compile our new tests on old kernels
selftests/hid: add an infinite loop test for hid_bpf_try_input_report
selftests/hid: add another test for injecting an event from an event hook
HID: bpf: allow hid_device_event hooks to inject input reports on self
...

+6443 -1579
+89 -84
Documentation/hid/hid-bpf.rst
··· 129 129 protocol, and rely on the HID kernel processing to translate the HID data into 130 130 input events. 131 131 132 + In-tree HID-BPF programs and ``udev-hid-bpf`` 133 + ============================================= 134 + 135 + Official device fixes are shipped in the kernel tree as source in the 136 + ``drivers/hid/bpf/progs`` directory. This allows to add selftests to them in 137 + ``tools/testing/selftests/hid``. 138 + 139 + However, the compilation of these objects is not part of a regular kernel compilation 140 + given that they need an external tool to be loaded. This tool is currently 141 + `udev-hid-bpf <https://libevdev.pages.freedesktop.org/udev-hid-bpf/index.html>`_. 142 + 143 + For convenience, that external repository duplicates the files from here in 144 + ``drivers/hid/bpf/progs`` into its own ``src/bpf/stable`` directory. This allows 145 + distributions to not have to pull the entire kernel source tree to ship and package 146 + those HID-BPF fixes. ``udev-hid-bpf`` also has capabilities of handling multiple 147 + objects files depending on the kernel the user is running. 148 + 132 149 Available types of programs 133 150 =========================== 134 151 135 - HID-BPF is built "on top" of BPF, meaning that we use tracing method to 152 + HID-BPF is built "on top" of BPF, meaning that we use bpf struct_ops method to 136 153 declare our programs. 137 154 138 155 HID-BPF has the following attachment types available: 139 156 140 - 1. event processing/filtering with ``SEC("fmod_ret/hid_bpf_device_event")`` in libbpf 157 + 1. event processing/filtering with ``SEC("struct_ops/hid_device_event")`` in libbpf 141 158 2. actions coming from userspace with ``SEC("syscall")`` in libbpf 142 - 3. change of the report descriptor with ``SEC("fmod_ret/hid_bpf_rdesc_fixup")`` in libbpf 159 + 3. change of the report descriptor with ``SEC("struct_ops/hid_rdesc_fixup")`` or 160 + ``SEC("struct_ops.s/hid_rdesc_fixup")`` in libbpf 143 161 144 - A ``hid_bpf_device_event`` is calling a BPF program when an event is received from 162 + A ``hid_device_event`` is calling a BPF program when an event is received from 145 163 the device. Thus we are in IRQ context and can act on the data or notify userspace. 146 164 And given that we are in IRQ context, we can not talk back to the device. 147 165 ··· 167 149 This time, we can do any operations allowed by HID-BPF, and talking to the device is 168 150 allowed. 169 151 170 - Last, ``hid_bpf_rdesc_fixup`` is different from the others as there can be only one 152 + Last, ``hid_rdesc_fixup`` is different from the others as there can be only one 171 153 BPF program of this type. This is called on ``probe`` from the driver and allows to 172 - change the report descriptor from the BPF program. Once a ``hid_bpf_rdesc_fixup`` 154 + change the report descriptor from the BPF program. Once a ``hid_rdesc_fixup`` 173 155 program has been loaded, it is not possible to overwrite it unless the program which 174 156 inserted it allows us by pinning the program and closing all of its fds pointing to it. 175 157 158 + Note that ``hid_rdesc_fixup`` can be declared as sleepable (``SEC("struct_ops.s/hid_rdesc_fixup")``). 159 + 160 + 176 161 Developer API: 177 162 ============== 163 + 164 + Available ``struct_ops`` for HID-BPF: 165 + ------------------------------------- 166 + 167 + .. kernel-doc:: include/linux/hid_bpf.h 168 + :identifiers: hid_bpf_ops 169 + 178 170 179 171 User API data structures available in programs: 180 172 ----------------------------------------------- 181 173 182 174 .. kernel-doc:: include/linux/hid_bpf.h 175 + :identifiers: hid_bpf_ctx 183 176 184 - Available tracing functions to attach a HID-BPF program: 185 - -------------------------------------------------------- 186 - 187 - .. kernel-doc:: drivers/hid/bpf/hid_bpf_dispatch.c 188 - :functions: hid_bpf_device_event hid_bpf_rdesc_fixup 189 - 190 - Available API that can be used in all HID-BPF programs: 191 - ------------------------------------------------------- 177 + Available API that can be used in all HID-BPF struct_ops programs: 178 + ------------------------------------------------------------------ 192 179 193 180 .. kernel-doc:: drivers/hid/bpf/hid_bpf_dispatch.c 194 - :functions: hid_bpf_get_data 181 + :identifiers: hid_bpf_get_data 195 182 196 - Available API that can be used in syscall HID-BPF programs: 197 - ----------------------------------------------------------- 183 + Available API that can be used in syscall HID-BPF programs or in sleepable HID-BPF struct_ops programs: 184 + ------------------------------------------------------------------------------------------------------- 198 185 199 186 .. kernel-doc:: drivers/hid/bpf/hid_bpf_dispatch.c 200 - :functions: hid_bpf_attach_prog hid_bpf_hw_request hid_bpf_hw_output_report hid_bpf_input_report hid_bpf_allocate_context hid_bpf_release_context 187 + :identifiers: hid_bpf_hw_request hid_bpf_hw_output_report hid_bpf_input_report hid_bpf_try_input_report hid_bpf_allocate_context hid_bpf_release_context 201 188 202 189 General overview of a HID-BPF program 203 190 ===================================== ··· 245 222 Effect of a HID-BPF program 246 223 --------------------------- 247 224 248 - For all HID-BPF attachment types except for :c:func:`hid_bpf_rdesc_fixup`, several eBPF 249 - programs can be attached to the same device. 225 + For all HID-BPF attachment types except for :c:func:`hid_rdesc_fixup`, several eBPF 226 + programs can be attached to the same device. If a HID-BPF struct_ops has a 227 + :c:func:`hid_rdesc_fixup` while another is already attached to the device, the 228 + kernel will return `-EINVAL` when attaching the struct_ops. 250 229 251 - Unless ``HID_BPF_FLAG_INSERT_HEAD`` is added to the flags while attaching the 252 - program, the new program is appended at the end of the list. 253 - ``HID_BPF_FLAG_INSERT_HEAD`` will insert the new program at the beginning of the 254 - list which is useful for e.g. tracing where we need to get the unprocessed events 255 - from the device. 230 + Unless ``BPF_F_BEFORE`` is added to the flags while attaching the program, the new 231 + program is appended at the end of the list. 232 + ``BPF_F_BEFORE`` will insert the new program at the beginning of the list which is 233 + useful for e.g. tracing where we need to get the unprocessed events from the device. 256 234 257 - Note that if there are multiple programs using the ``HID_BPF_FLAG_INSERT_HEAD`` flag, 235 + Note that if there are multiple programs using the ``BPF_F_BEFORE`` flag, 258 236 only the most recently loaded one is actually the first in the list. 259 237 260 - ``SEC("fmod_ret/hid_bpf_device_event")`` 261 - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 238 + ``SEC("struct_ops/hid_device_event")`` 239 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 262 240 263 241 Whenever a matching event is raised, the eBPF programs are called one after the other 264 242 and are working on the same data buffer. ··· 282 258 in the sysfs path: ``/sys/bus/hid/devices/xxxx:yyyy:zzzz:0000``). 283 259 284 260 To retrieve a context associated with the device, the program must call 285 - :c:func:`hid_bpf_allocate_context` and must release it with :c:func:`hid_bpf_release_context` 261 + hid_bpf_allocate_context() and must release it with hid_bpf_release_context() 286 262 before returning. 287 263 Once the context is retrieved, one can also request a pointer to kernel memory with 288 - :c:func:`hid_bpf_get_data`. This memory is big enough to support all input/output/feature 264 + hid_bpf_get_data(). This memory is big enough to support all input/output/feature 289 265 reports of the given device. 290 266 291 - ``SEC("fmod_ret/hid_bpf_rdesc_fixup")`` 292 - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 267 + ``SEC("struct_ops/hid_rdesc_fixup")`` 268 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 293 269 294 - The ``hid_bpf_rdesc_fixup`` program works in a similar manner to 295 - ``.report_fixup`` of ``struct hid_driver``. 270 + The ``hid_rdesc_fixup`` program works in a similar manner to ``.report_fixup`` 271 + of ``struct hid_driver``. 296 272 297 273 When the device is probed, the kernel sets the data buffer of the context with the 298 274 content of the report descriptor. The memory associated with that buffer is ··· 301 277 The eBPF program can modify the data buffer at-will and the kernel uses the 302 278 modified content and size as the report descriptor. 303 279 304 - Whenever a ``SEC("fmod_ret/hid_bpf_rdesc_fixup")`` program is attached (if no 305 - program was attached before), the kernel immediately disconnects the HID device 306 - and does a reprobe. 280 + Whenever a struct_ops containing a ``SEC("struct_ops/hid_rdesc_fixup")`` program 281 + is attached (if no program was attached before), the kernel immediately disconnects 282 + the HID device and does a reprobe. 307 283 308 - In the same way, when the ``SEC("fmod_ret/hid_bpf_rdesc_fixup")`` program is 309 - detached, the kernel issues a disconnect on the device. 284 + In the same way, when this struct_ops is detached, the kernel issues a disconnect 285 + on the device. 310 286 311 287 There is no ``detach`` facility in HID-BPF. Detaching a program happens when 312 - all the user space file descriptors pointing at a program are closed. 288 + all the user space file descriptors pointing at a HID-BPF struct_ops link are closed. 313 289 Thus, if we need to replace a report descriptor fixup, some cooperation is 314 290 required from the owner of the original report descriptor fixup. 315 - The previous owner will likely pin the program in the bpffs, and we can then 291 + The previous owner will likely pin the struct_ops link in the bpffs, and we can then 316 292 replace it through normal bpf operations. 317 293 318 294 Attaching a bpf program to a device 319 295 =================================== 320 296 321 - ``libbpf`` does not export any helper to attach a HID-BPF program. 322 - Users need to use a dedicated ``syscall`` program which will call 323 - ``hid_bpf_attach_prog(hid_id, program_fd, flags)``. 297 + We now use standard struct_ops attachment through ``bpf_map__attach_struct_ops()``. 298 + But given that we need to attach a struct_ops to a dedicated HID device, the caller 299 + must set ``hid_id`` in the struct_ops map before loading the program in the kernel. 324 300 325 301 ``hid_id`` is the unique system ID of the HID device (the last 4 numbers in the 326 302 sysfs path: ``/sys/bus/hid/devices/xxxx:yyyy:zzzz:0000``) 327 303 328 - ``progam_fd`` is the opened file descriptor of the program to attach. 329 - 330 - ``flags`` is of type ``enum hid_bpf_attach_flags``. 304 + One can also set ``flags``, which is of type ``enum hid_bpf_attach_flags``. 331 305 332 306 We can not rely on hidraw to bind a BPF program to a HID device. hidraw is an 333 307 artefact of the processing of the HID device, and is not stable. Some drivers ··· 380 358 extern __u8 *hid_bpf_get_data(struct hid_bpf_ctx *ctx, 381 359 unsigned int offset, 382 360 const size_t __sz) __ksym; 383 - extern int hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, u32 flags) __ksym; 384 361 385 362 struct { 386 363 __uint(type, BPF_MAP_TYPE_RINGBUF); 387 364 __uint(max_entries, 4096 * 64); 388 365 } ringbuf SEC(".maps"); 389 366 390 - struct attach_prog_args { 391 - int prog_fd; 392 - unsigned int hid; 393 - unsigned int flags; 394 - int retval; 395 - }; 396 - 397 - SEC("syscall") 398 - int attach_prog(struct attach_prog_args *ctx) 399 - { 400 - ctx->retval = hid_bpf_attach_prog(ctx->hid, 401 - ctx->prog_fd, 402 - ctx->flags); 403 - return 0; 404 - } 405 - 406 367 __u8 current_value = 0; 407 368 408 - SEC("?fmod_ret/hid_bpf_device_event") 369 + SEC("struct_ops/hid_device_event") 409 370 int BPF_PROG(filter_switch, struct hid_bpf_ctx *hid_ctx) 410 371 { 411 372 __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 192 /* size */); ··· 412 407 return 0; 413 408 } 414 409 415 - To attach ``filter_switch``, userspace needs to call the ``attach_prog`` syscall 416 - program first:: 410 + SEC(".struct_ops.link") 411 + struct hid_bpf_ops haptic_tablet = { 412 + .hid_device_event = (void *)filter_switch, 413 + }; 414 + 415 + 416 + To attach ``haptic_tablet``, userspace needs to set ``hid_id`` first:: 417 417 418 418 static int attach_filter(struct hid *hid_skel, int hid_id) 419 419 { 420 - int err, prog_fd; 421 - int ret = -1; 422 - struct attach_prog_args args = { 423 - .hid = hid_id, 424 - }; 425 - DECLARE_LIBBPF_OPTS(bpf_test_run_opts, tattrs, 426 - .ctx_in = &args, 427 - .ctx_size_in = sizeof(args), 428 - ); 420 + int err, link_fd; 429 421 430 - args.prog_fd = bpf_program__fd(hid_skel->progs.filter_switch); 422 + hid_skel->struct_ops.haptic_tablet->hid_id = hid_id; 423 + err = hid__load(skel); 424 + if (err) 425 + return err; 431 426 432 - prog_fd = bpf_program__fd(hid_skel->progs.attach_prog); 427 + link_fd = bpf_map__attach_struct_ops(hid_skel->maps.haptic_tablet); 428 + if (!link_fd) { 429 + fprintf(stderr, "can not attach HID-BPF program: %m\n"); 430 + return -1; 431 + } 433 432 434 - err = bpf_prog_test_run_opts(prog_fd, &tattrs); 435 - if (err) 436 - return err; 437 - 438 - return args.retval; /* the fd of the created bpf_link */ 433 + return link_fd; /* the fd of the created bpf_link */ 439 434 } 440 435 441 436 Our userspace program can now listen to notifications on the ring buffer, and 442 437 is awaken only when the value changes. 443 438 444 439 When the userspace program doesn't need to listen to events anymore, it can just 445 - close the returned fd from :c:func:`attach_filter`, which will tell the kernel to 440 + close the returned bpf link from :c:func:`attach_filter`, which will tell the kernel to 446 441 detach the program from the HID device. 447 442 448 443 Of course, in other use cases, the userspace program can also pin the fd to the
+2 -4
drivers/hid/Makefile
··· 154 154 obj-$(CONFIG_HID_SENSOR_HUB) += hid-sensor-hub.o 155 155 obj-$(CONFIG_HID_SENSOR_CUSTOM_SENSOR) += hid-sensor-custom.o 156 156 157 - hid-uclogic-test-objs := hid-uclogic-rdesc.o \ 158 - hid-uclogic-params.o \ 159 - hid-uclogic-rdesc-test.o 160 - obj-$(CONFIG_HID_KUNIT_TEST) += hid-uclogic-test.o 157 + hid-uclogic-test-objs := hid-uclogic-rdesc-test.o 158 + obj-$(CONFIG_HID_KUNIT_TEST) += hid-uclogic.o hid-uclogic-test.o 161 159 162 160 obj-$(CONFIG_USB_HID) += usbhid/ 163 161 obj-$(CONFIG_USB_MOUSE) += usbhid/
+1 -1
drivers/hid/bpf/Makefile
··· 8 8 obj-$(CONFIG_HID_BPF) += hid_bpf.o 9 9 CFLAGS_hid_bpf_dispatch.o += -I$(LIBBPF_INCLUDE) 10 10 CFLAGS_hid_bpf_jmp_table.o += -I$(LIBBPF_INCLUDE) 11 - hid_bpf-objs += hid_bpf_dispatch.o hid_bpf_jmp_table.o 11 + hid_bpf-objs += hid_bpf_dispatch.o hid_bpf_struct_ops.o
-93
drivers/hid/bpf/entrypoints/Makefile
··· 1 - # SPDX-License-Identifier: GPL-2.0 2 - OUTPUT := .output 3 - abs_out := $(abspath $(OUTPUT)) 4 - 5 - CLANG ?= clang 6 - LLC ?= llc 7 - LLVM_STRIP ?= llvm-strip 8 - 9 - TOOLS_PATH := $(abspath ../../../../tools) 10 - BPFTOOL_SRC := $(TOOLS_PATH)/bpf/bpftool 11 - BPFTOOL_OUTPUT := $(abs_out)/bpftool 12 - DEFAULT_BPFTOOL := $(BPFTOOL_OUTPUT)/bootstrap/bpftool 13 - BPFTOOL ?= $(DEFAULT_BPFTOOL) 14 - 15 - LIBBPF_SRC := $(TOOLS_PATH)/lib/bpf 16 - LIBBPF_OUTPUT := $(abs_out)/libbpf 17 - LIBBPF_DESTDIR := $(LIBBPF_OUTPUT) 18 - LIBBPF_INCLUDE := $(LIBBPF_DESTDIR)/include 19 - BPFOBJ := $(LIBBPF_OUTPUT)/libbpf.a 20 - 21 - INCLUDES := -I$(OUTPUT) -I$(LIBBPF_INCLUDE) -I$(TOOLS_PATH)/include/uapi 22 - CFLAGS := -g -Wall 23 - 24 - VMLINUX_BTF_PATHS ?= $(if $(O),$(O)/vmlinux) \ 25 - $(if $(KBUILD_OUTPUT),$(KBUILD_OUTPUT)/vmlinux) \ 26 - ../../../../vmlinux \ 27 - /sys/kernel/btf/vmlinux \ 28 - /boot/vmlinux-$(shell uname -r) 29 - VMLINUX_BTF ?= $(abspath $(firstword $(wildcard $(VMLINUX_BTF_PATHS)))) 30 - ifeq ($(VMLINUX_BTF),) 31 - $(error Cannot find a vmlinux for VMLINUX_BTF at any of "$(VMLINUX_BTF_PATHS)") 32 - endif 33 - 34 - ifeq ($(V),1) 35 - Q = 36 - msg = 37 - else 38 - Q = @ 39 - msg = @printf ' %-8s %s%s\n' "$(1)" "$(notdir $(2))" "$(if $(3), $(3))"; 40 - MAKEFLAGS += --no-print-directory 41 - submake_extras := feature_display=0 42 - endif 43 - 44 - .DELETE_ON_ERROR: 45 - 46 - .PHONY: all clean 47 - 48 - all: entrypoints.lskel.h 49 - 50 - clean: 51 - $(call msg,CLEAN) 52 - $(Q)rm -rf $(OUTPUT) entrypoints 53 - 54 - entrypoints.lskel.h: $(OUTPUT)/entrypoints.bpf.o | $(BPFTOOL) 55 - $(call msg,GEN-SKEL,$@) 56 - $(Q)$(BPFTOOL) gen skeleton -L $< > $@ 57 - 58 - 59 - $(OUTPUT)/entrypoints.bpf.o: entrypoints.bpf.c $(OUTPUT)/vmlinux.h $(BPFOBJ) | $(OUTPUT) 60 - $(call msg,BPF,$@) 61 - $(Q)$(CLANG) -g -O2 --target=bpf $(INCLUDES) \ 62 - -c $(filter %.c,$^) -o $@ && \ 63 - $(LLVM_STRIP) -g $@ 64 - 65 - $(OUTPUT)/vmlinux.h: $(VMLINUX_BTF) $(BPFTOOL) | $(INCLUDE_DIR) 66 - ifeq ($(VMLINUX_H),) 67 - $(call msg,GEN,,$@) 68 - $(Q)$(BPFTOOL) btf dump file $(VMLINUX_BTF) format c > $@ 69 - else 70 - $(call msg,CP,,$@) 71 - $(Q)cp "$(VMLINUX_H)" $@ 72 - endif 73 - 74 - $(OUTPUT) $(LIBBPF_OUTPUT) $(BPFTOOL_OUTPUT): 75 - $(call msg,MKDIR,$@) 76 - $(Q)mkdir -p $@ 77 - 78 - $(BPFOBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(LIBBPF_OUTPUT) 79 - $(Q)$(MAKE) $(submake_extras) -C $(LIBBPF_SRC) \ 80 - OUTPUT=$(abspath $(dir $@))/ prefix= \ 81 - DESTDIR=$(LIBBPF_DESTDIR) $(abspath $@) install_headers 82 - 83 - ifeq ($(CROSS_COMPILE),) 84 - $(DEFAULT_BPFTOOL): $(BPFOBJ) | $(BPFTOOL_OUTPUT) 85 - $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOL_SRC) \ 86 - OUTPUT=$(BPFTOOL_OUTPUT)/ \ 87 - LIBBPF_BOOTSTRAP_OUTPUT=$(LIBBPF_OUTPUT)/ \ 88 - LIBBPF_BOOTSTRAP_DESTDIR=$(LIBBPF_DESTDIR)/ bootstrap 89 - else 90 - $(DEFAULT_BPFTOOL): | $(BPFTOOL_OUTPUT) 91 - $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOL_SRC) \ 92 - OUTPUT=$(BPFTOOL_OUTPUT)/ bootstrap 93 - endif
-4
drivers/hid/bpf/entrypoints/README
··· 1 - WARNING: 2 - If you change "entrypoints.bpf.c" do "make -j" in this directory to rebuild "entrypoints.skel.h". 3 - Make sure to have clang 10 installed. 4 - See Documentation/bpf/bpf_devel_QA.rst
-25
drivers/hid/bpf/entrypoints/entrypoints.bpf.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* Copyright (c) 2022 Benjamin Tissoires */ 3 - 4 - #include ".output/vmlinux.h" 5 - #include <bpf/bpf_helpers.h> 6 - #include <bpf/bpf_tracing.h> 7 - 8 - #define HID_BPF_MAX_PROGS 1024 9 - 10 - struct { 11 - __uint(type, BPF_MAP_TYPE_PROG_ARRAY); 12 - __uint(max_entries, HID_BPF_MAX_PROGS); 13 - __uint(key_size, sizeof(__u32)); 14 - __uint(value_size, sizeof(__u32)); 15 - } hid_jmp_table SEC(".maps"); 16 - 17 - SEC("fmod_ret/__hid_bpf_tail_call") 18 - int BPF_PROG(hid_tail_call, struct hid_bpf_ctx *hctx) 19 - { 20 - bpf_tail_call(ctx, &hid_jmp_table, hctx->index); 21 - 22 - return 0; 23 - } 24 - 25 - char LICENSE[] SEC("license") = "GPL";
-248
drivers/hid/bpf/entrypoints/entrypoints.lskel.h
··· 1 - /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 - /* THIS FILE IS AUTOGENERATED BY BPFTOOL! */ 3 - #ifndef __ENTRYPOINTS_BPF_SKEL_H__ 4 - #define __ENTRYPOINTS_BPF_SKEL_H__ 5 - 6 - #include <bpf/skel_internal.h> 7 - 8 - struct entrypoints_bpf { 9 - struct bpf_loader_ctx ctx; 10 - struct { 11 - struct bpf_map_desc hid_jmp_table; 12 - } maps; 13 - struct { 14 - struct bpf_prog_desc hid_tail_call; 15 - } progs; 16 - struct { 17 - int hid_tail_call_fd; 18 - } links; 19 - }; 20 - 21 - static inline int 22 - entrypoints_bpf__hid_tail_call__attach(struct entrypoints_bpf *skel) 23 - { 24 - int prog_fd = skel->progs.hid_tail_call.prog_fd; 25 - int fd = skel_raw_tracepoint_open(NULL, prog_fd); 26 - 27 - if (fd > 0) 28 - skel->links.hid_tail_call_fd = fd; 29 - return fd; 30 - } 31 - 32 - static inline int 33 - entrypoints_bpf__attach(struct entrypoints_bpf *skel) 34 - { 35 - int ret = 0; 36 - 37 - ret = ret < 0 ? ret : entrypoints_bpf__hid_tail_call__attach(skel); 38 - return ret < 0 ? ret : 0; 39 - } 40 - 41 - static inline void 42 - entrypoints_bpf__detach(struct entrypoints_bpf *skel) 43 - { 44 - skel_closenz(skel->links.hid_tail_call_fd); 45 - } 46 - static void 47 - entrypoints_bpf__destroy(struct entrypoints_bpf *skel) 48 - { 49 - if (!skel) 50 - return; 51 - entrypoints_bpf__detach(skel); 52 - skel_closenz(skel->progs.hid_tail_call.prog_fd); 53 - skel_closenz(skel->maps.hid_jmp_table.map_fd); 54 - skel_free(skel); 55 - } 56 - static inline struct entrypoints_bpf * 57 - entrypoints_bpf__open(void) 58 - { 59 - struct entrypoints_bpf *skel; 60 - 61 - skel = skel_alloc(sizeof(*skel)); 62 - if (!skel) 63 - goto cleanup; 64 - skel->ctx.sz = (void *)&skel->links - (void *)skel; 65 - return skel; 66 - cleanup: 67 - entrypoints_bpf__destroy(skel); 68 - return NULL; 69 - } 70 - 71 - static inline int 72 - entrypoints_bpf__load(struct entrypoints_bpf *skel) 73 - { 74 - struct bpf_load_and_run_opts opts = {}; 75 - int err; 76 - 77 - opts.ctx = (struct bpf_loader_ctx *)skel; 78 - opts.data_sz = 2856; 79 - opts.data = (void *)"\ 80 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 81 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 82 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 83 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 84 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 85 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 86 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 87 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 88 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 89 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 90 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 91 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 92 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 93 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 94 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 95 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 96 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 97 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 98 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 99 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 100 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 101 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 102 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 103 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 104 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 105 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 106 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 107 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 108 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 109 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 110 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 111 - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 112 - \0\0\0\0\0\0\0\0\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\ 113 - \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\ 114 - \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\ 115 - \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\ 116 - \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\ 117 - \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\ 118 - \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\ 119 - \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\ 120 - \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\ 121 - \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\ 122 - \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\ 123 - \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\ 124 - \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\ 125 - \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\ 126 - \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\ 127 - \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\ 128 - \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\ 129 - \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\ 130 - \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\ 131 - \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\ 132 - \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\ 133 - \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\ 134 - \x49\x5a\x45\x5f\x54\x59\x50\x45\x5f\x5f\0\x74\x79\x70\x65\0\x6d\x61\x78\x5f\ 135 - \x65\x6e\x74\x72\x69\x65\x73\0\x6b\x65\x79\x5f\x73\x69\x7a\x65\0\x76\x61\x6c\ 136 - \x75\x65\x5f\x73\x69\x7a\x65\0\x68\x69\x64\x5f\x6a\x6d\x70\x5f\x74\x61\x62\x6c\ 137 - \x65\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e\x67\ 138 - \0\x63\x74\x78\0\x68\x69\x64\x5f\x74\x61\x69\x6c\x5f\x63\x61\x6c\x6c\0\x66\x6d\ 139 - \x6f\x64\x5f\x72\x65\x74\x2f\x5f\x5f\x68\x69\x64\x5f\x62\x70\x66\x5f\x74\x61\ 140 - \x69\x6c\x5f\x63\x61\x6c\x6c\0\x2f\x68\x6f\x6d\x65\x2f\x62\x74\x69\x73\x73\x6f\ 141 - \x69\x72\x2f\x53\x72\x63\x2f\x68\x69\x64\x2f\x64\x72\x69\x76\x65\x72\x73\x2f\ 142 - \x68\x69\x64\x2f\x62\x70\x66\x2f\x65\x6e\x74\x72\x79\x70\x6f\x69\x6e\x74\x73\ 143 - \x2f\x65\x6e\x74\x72\x79\x70\x6f\x69\x6e\x74\x73\x2e\x62\x70\x66\x2e\x63\0\x69\ 144 - \x6e\x74\x20\x42\x50\x46\x5f\x50\x52\x4f\x47\x28\x68\x69\x64\x5f\x74\x61\x69\ 145 - \x6c\x5f\x63\x61\x6c\x6c\x2c\x20\x73\x74\x72\x75\x63\x74\x20\x68\x69\x64\x5f\ 146 - \x62\x70\x66\x5f\x63\x74\x78\x20\x2a\x68\x63\x74\x78\x29\0\x68\x69\x64\x5f\x62\ 147 - \x70\x66\x5f\x63\x74\x78\0\x69\x6e\x64\x65\x78\0\x68\x69\x64\0\x61\x6c\x6c\x6f\ 148 - \x63\x61\x74\x65\x64\x5f\x73\x69\x7a\x65\0\x72\x65\x70\x6f\x72\x74\x5f\x74\x79\ 149 - \x70\x65\0\x5f\x5f\x75\x33\x32\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\ 150 - \x74\0\x68\x69\x64\x5f\x72\x65\x70\x6f\x72\x74\x5f\x74\x79\x70\x65\0\x48\x49\ 151 - \x44\x5f\x49\x4e\x50\x55\x54\x5f\x52\x45\x50\x4f\x52\x54\0\x48\x49\x44\x5f\x4f\ 152 - \x55\x54\x50\x55\x54\x5f\x52\x45\x50\x4f\x52\x54\0\x48\x49\x44\x5f\x46\x45\x41\ 153 - \x54\x55\x52\x45\x5f\x52\x45\x50\x4f\x52\x54\0\x48\x49\x44\x5f\x52\x45\x50\x4f\ 154 - \x52\x54\x5f\x54\x59\x50\x45\x53\0\x72\x65\x74\x76\x61\x6c\0\x73\x69\x7a\x65\0\ 155 - \x5f\x5f\x73\x33\x32\0\x30\x3a\x30\0\x09\x62\x70\x66\x5f\x74\x61\x69\x6c\x5f\ 156 - \x63\x61\x6c\x6c\x28\x63\x74\x78\x2c\x20\x26\x68\x69\x64\x5f\x6a\x6d\x70\x5f\ 157 - \x74\x61\x62\x6c\x65\x2c\x20\x68\x63\x74\x78\x2d\x3e\x69\x6e\x64\x65\x78\x29\ 158 - \x3b\0\x63\x68\x61\x72\0\x4c\x49\x43\x45\x4e\x53\x45\0\x2e\x6d\x61\x70\x73\0\ 159 - \x6c\x69\x63\x65\x6e\x73\x65\0\x68\x69\x64\x5f\x64\x65\x76\x69\x63\x65\0\0\0\0\ 160 - \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\ 161 - \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\ 162 - \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\ 163 - \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\ 164 - \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\ 165 - \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\ 166 - \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\ 167 - \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\ 168 - \0\0\0\0\0\0\0\0\0\0\0\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\ 169 - \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\ 170 - \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\ 171 - \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\ 172 - \x5f\x68\x69\x64\x5f\x62\x70\x66\x5f\x74\x61\x69\x6c\x5f\x63\x61\x6c\x6c\0\0\0\ 173 - \0\0"; 174 - opts.insns_sz = 1192; 175 - opts.insns = (void *)"\ 176 - \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\ 177 - \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\ 178 - \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\ 179 - \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\ 180 - \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\ 181 - \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\ 182 - \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\ 183 - \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\ 184 - \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\ 185 - \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\ 186 - \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\ 187 - \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\ 188 - \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\ 189 - \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\ 190 - \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\ 191 - \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\ 192 - \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\ 193 - \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\ 194 - \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\ 195 - \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\ 196 - \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\ 197 - \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\ 198 - \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\ 199 - \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\ 200 - \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\ 201 - \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\ 202 - \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\ 203 - \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\ 204 - \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\ 205 - \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\ 206 - \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\ 207 - \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\ 208 - \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\ 209 - \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\ 210 - \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\ 211 - \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\ 212 - \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\ 213 - \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\ 214 - \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\ 215 - \0\0\xb7\0\0\0\0\0\0\0\x95\0\0\0\0\0\0\0"; 216 - err = bpf_load_and_run(&opts); 217 - if (err < 0) 218 - return err; 219 - return 0; 220 - } 221 - 222 - static inline struct entrypoints_bpf * 223 - entrypoints_bpf__open_and_load(void) 224 - { 225 - struct entrypoints_bpf *skel; 226 - 227 - skel = entrypoints_bpf__open(); 228 - if (!skel) 229 - return NULL; 230 - if (entrypoints_bpf__load(skel)) { 231 - entrypoints_bpf__destroy(skel); 232 - return NULL; 233 - } 234 - return skel; 235 - } 236 - 237 - __attribute__((unused)) static void 238 - entrypoints_bpf__assert(struct entrypoints_bpf *s __attribute__((unused))) 239 - { 240 - #ifdef __cplusplus 241 - #define _Static_assert static_assert 242 - #endif 243 - #ifdef __cplusplus 244 - #undef _Static_assert 245 - #endif 246 - } 247 - 248 - #endif /* __ENTRYPOINTS_BPF_SKEL_H__ */
+210 -209
drivers/hid/bpf/hid_bpf_dispatch.c
··· 3 3 /* 4 4 * HID-BPF support for Linux 5 5 * 6 - * Copyright (c) 2022 Benjamin Tissoires 6 + * Copyright (c) 2022-2024 Benjamin Tissoires 7 7 */ 8 8 9 9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ··· 17 17 #include <linux/kfifo.h> 18 18 #include <linux/minmax.h> 19 19 #include <linux/module.h> 20 - #include <linux/workqueue.h> 21 20 #include "hid_bpf_dispatch.h" 22 - #include "entrypoints/entrypoints.lskel.h" 23 21 24 - struct hid_bpf_ops *hid_bpf_ops; 25 - EXPORT_SYMBOL(hid_bpf_ops); 26 - 27 - /** 28 - * hid_bpf_device_event - Called whenever an event is coming in from the device 29 - * 30 - * @ctx: The HID-BPF context 31 - * 32 - * @return %0 on success and keep processing; a positive value to change the 33 - * incoming size buffer; a negative error code to interrupt the processing 34 - * of this event 35 - * 36 - * Declare an %fmod_ret tracing bpf program to this function and attach this 37 - * program through hid_bpf_attach_prog() to have this helper called for 38 - * any incoming event from the device itself. 39 - * 40 - * The function is called while on IRQ context, so we can not sleep. 41 - */ 42 - /* never used by the kernel but declared so we can load and attach a tracepoint */ 43 - __weak noinline int hid_bpf_device_event(struct hid_bpf_ctx *ctx) 44 - { 45 - return 0; 46 - } 22 + struct hid_ops *hid_ops; 23 + EXPORT_SYMBOL(hid_ops); 47 24 48 25 u8 * 49 26 dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type, u8 *data, 50 - u32 *size, int interrupt) 27 + u32 *size, int interrupt, u64 source, bool from_bpf) 51 28 { 52 29 struct hid_bpf_ctx_kern ctx_kern = { 53 30 .ctx = { 54 31 .hid = hdev, 55 - .report_type = type, 56 32 .allocated_size = hdev->bpf.allocated_data, 57 33 .size = *size, 58 34 }, 59 35 .data = hdev->bpf.device_data, 36 + .from_bpf = from_bpf, 60 37 }; 38 + struct hid_bpf_ops *e; 61 39 int ret; 62 40 63 41 if (type >= HID_REPORT_TYPES) ··· 48 70 memset(ctx_kern.data, 0, hdev->bpf.allocated_data); 49 71 memcpy(ctx_kern.data, data, *size); 50 72 51 - ret = hid_bpf_prog_run(hdev, HID_BPF_PROG_TYPE_DEVICE_EVENT, &ctx_kern); 52 - if (ret < 0) 53 - return ERR_PTR(ret); 73 + rcu_read_lock(); 74 + list_for_each_entry_rcu(e, &hdev->bpf.prog_list, list) { 75 + if (e->hid_device_event) { 76 + ret = e->hid_device_event(&ctx_kern.ctx, type, source); 77 + if (ret < 0) { 78 + rcu_read_unlock(); 79 + return ERR_PTR(ret); 80 + } 54 81 82 + if (ret) 83 + ctx_kern.ctx.size = ret; 84 + } 85 + } 86 + rcu_read_unlock(); 87 + 88 + ret = ctx_kern.ctx.size; 55 89 if (ret) { 56 90 if (ret > ctx_kern.ctx.allocated_size) 57 91 return ERR_PTR(-EINVAL); ··· 75 85 } 76 86 EXPORT_SYMBOL_GPL(dispatch_hid_bpf_device_event); 77 87 78 - /** 79 - * hid_bpf_rdesc_fixup - Called when the probe function parses the report 80 - * descriptor of the HID device 81 - * 82 - * @ctx: The HID-BPF context 83 - * 84 - * @return 0 on success and keep processing; a positive value to change the 85 - * incoming size buffer; a negative error code to interrupt the processing 86 - * of this event 87 - * 88 - * Declare an %fmod_ret tracing bpf program to this function and attach this 89 - * program through hid_bpf_attach_prog() to have this helper called before any 90 - * parsing of the report descriptor by HID. 91 - */ 92 - /* never used by the kernel but declared so we can load and attach a tracepoint */ 93 - __weak noinline int hid_bpf_rdesc_fixup(struct hid_bpf_ctx *ctx) 88 + int dispatch_hid_bpf_raw_requests(struct hid_device *hdev, 89 + unsigned char reportnum, u8 *buf, 90 + u32 size, enum hid_report_type rtype, 91 + enum hid_class_request reqtype, 92 + u64 source, bool from_bpf) 94 93 { 95 - return 0; 94 + struct hid_bpf_ctx_kern ctx_kern = { 95 + .ctx = { 96 + .hid = hdev, 97 + .allocated_size = size, 98 + .size = size, 99 + }, 100 + .data = buf, 101 + .from_bpf = from_bpf, 102 + }; 103 + struct hid_bpf_ops *e; 104 + int ret, idx; 105 + 106 + if (rtype >= HID_REPORT_TYPES) 107 + return -EINVAL; 108 + 109 + idx = srcu_read_lock(&hdev->bpf.srcu); 110 + list_for_each_entry_srcu(e, &hdev->bpf.prog_list, list, 111 + srcu_read_lock_held(&hdev->bpf.srcu)) { 112 + if (!e->hid_hw_request) 113 + continue; 114 + 115 + ret = e->hid_hw_request(&ctx_kern.ctx, reportnum, rtype, reqtype, source); 116 + if (ret) 117 + goto out; 118 + } 119 + ret = 0; 120 + 121 + out: 122 + srcu_read_unlock(&hdev->bpf.srcu, idx); 123 + return ret; 96 124 } 125 + EXPORT_SYMBOL_GPL(dispatch_hid_bpf_raw_requests); 126 + 127 + int dispatch_hid_bpf_output_report(struct hid_device *hdev, 128 + __u8 *buf, u32 size, u64 source, 129 + bool from_bpf) 130 + { 131 + struct hid_bpf_ctx_kern ctx_kern = { 132 + .ctx = { 133 + .hid = hdev, 134 + .allocated_size = size, 135 + .size = size, 136 + }, 137 + .data = buf, 138 + .from_bpf = from_bpf, 139 + }; 140 + struct hid_bpf_ops *e; 141 + int ret, idx; 142 + 143 + idx = srcu_read_lock(&hdev->bpf.srcu); 144 + list_for_each_entry_srcu(e, &hdev->bpf.prog_list, list, 145 + srcu_read_lock_held(&hdev->bpf.srcu)) { 146 + if (!e->hid_hw_output_report) 147 + continue; 148 + 149 + ret = e->hid_hw_output_report(&ctx_kern.ctx, source); 150 + if (ret) 151 + goto out; 152 + } 153 + ret = 0; 154 + 155 + out: 156 + srcu_read_unlock(&hdev->bpf.srcu, idx); 157 + return ret; 158 + } 159 + EXPORT_SYMBOL_GPL(dispatch_hid_bpf_output_report); 97 160 98 161 u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *size) 99 162 { ··· 159 116 }, 160 117 }; 161 118 119 + if (!hdev->bpf.rdesc_ops) 120 + goto ignore_bpf; 121 + 162 122 ctx_kern.data = kzalloc(ctx_kern.ctx.allocated_size, GFP_KERNEL); 163 123 if (!ctx_kern.data) 164 124 goto ignore_bpf; 165 125 166 126 memcpy(ctx_kern.data, rdesc, min_t(unsigned int, *size, HID_MAX_DESCRIPTOR_SIZE)); 167 127 168 - ret = hid_bpf_prog_run(hdev, HID_BPF_PROG_TYPE_RDESC_FIXUP, &ctx_kern); 128 + ret = hdev->bpf.rdesc_ops->hid_rdesc_fixup(&ctx_kern.ctx); 169 129 if (ret < 0) 170 130 goto ignore_bpf; 171 131 ··· 194 148 struct hid_device *hdev = to_hid_device(dev); 195 149 196 150 return hdev->id == *(int *)id; 151 + } 152 + 153 + struct hid_device *hid_get_device(unsigned int hid_id) 154 + { 155 + struct device *dev; 156 + 157 + if (!hid_ops) 158 + return ERR_PTR(-EINVAL); 159 + 160 + dev = bus_find_device(hid_ops->bus_type, NULL, &hid_id, device_match_id); 161 + if (!dev) 162 + return ERR_PTR(-EINVAL); 163 + 164 + return to_hid_device(dev); 165 + } 166 + 167 + void hid_put_device(struct hid_device *hid) 168 + { 169 + put_device(&hid->dev); 197 170 } 198 171 199 172 static int __hid_bpf_allocate_data(struct hid_device *hdev, u8 **data, u32 *size) ··· 251 186 return 0; 252 187 } 253 188 254 - static int hid_bpf_allocate_event_data(struct hid_device *hdev) 189 + int hid_bpf_allocate_event_data(struct hid_device *hdev) 255 190 { 256 191 /* hdev->bpf.device_data is already allocated, abort */ 257 192 if (hdev->bpf.device_data) ··· 266 201 return device_reprobe(&hdev->dev); 267 202 268 203 return 0; 269 - } 270 - 271 - static int do_hid_bpf_attach_prog(struct hid_device *hdev, int prog_fd, struct bpf_prog *prog, 272 - __u32 flags) 273 - { 274 - int fd, err, prog_type; 275 - 276 - prog_type = hid_bpf_get_prog_attach_type(prog); 277 - if (prog_type < 0) 278 - return prog_type; 279 - 280 - if (prog_type >= HID_BPF_PROG_TYPE_MAX) 281 - return -EINVAL; 282 - 283 - if (prog_type == HID_BPF_PROG_TYPE_DEVICE_EVENT) { 284 - err = hid_bpf_allocate_event_data(hdev); 285 - if (err) 286 - return err; 287 - } 288 - 289 - fd = __hid_bpf_attach_prog(hdev, prog_type, prog_fd, prog, flags); 290 - if (fd < 0) 291 - return fd; 292 - 293 - if (prog_type == HID_BPF_PROG_TYPE_RDESC_FIXUP) { 294 - err = hid_bpf_reconnect(hdev); 295 - if (err) { 296 - close_fd(fd); 297 - return err; 298 - } 299 - } 300 - 301 - return fd; 302 204 } 303 205 304 206 /* Disables missing prototype warnings */ ··· 297 265 } 298 266 299 267 /** 300 - * hid_bpf_attach_prog - Attach the given @prog_fd to the given HID device 301 - * 302 - * @hid_id: the system unique identifier of the HID device 303 - * @prog_fd: an fd in the user process representing the program to attach 304 - * @flags: any logical OR combination of &enum hid_bpf_attach_flags 305 - * 306 - * @returns an fd of a bpf_link object on success (> %0), an error code otherwise. 307 - * Closing this fd will detach the program from the HID device (unless the bpf_link 308 - * is pinned to the BPF file system). 309 - */ 310 - /* called from syscall */ 311 - __bpf_kfunc int 312 - hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags) 313 - { 314 - struct hid_device *hdev; 315 - struct bpf_prog *prog; 316 - struct device *dev; 317 - int err, fd; 318 - 319 - if (!hid_bpf_ops) 320 - return -EINVAL; 321 - 322 - if ((flags & ~HID_BPF_FLAG_MASK)) 323 - return -EINVAL; 324 - 325 - dev = bus_find_device(hid_bpf_ops->bus_type, NULL, &hid_id, device_match_id); 326 - if (!dev) 327 - return -EINVAL; 328 - 329 - hdev = to_hid_device(dev); 330 - 331 - /* 332 - * take a ref on the prog itself, it will be released 333 - * on errors or when it'll be detached 334 - */ 335 - prog = bpf_prog_get(prog_fd); 336 - if (IS_ERR(prog)) { 337 - err = PTR_ERR(prog); 338 - goto out_dev_put; 339 - } 340 - 341 - fd = do_hid_bpf_attach_prog(hdev, prog_fd, prog, flags); 342 - if (fd < 0) { 343 - err = fd; 344 - goto out_prog_put; 345 - } 346 - 347 - return fd; 348 - 349 - out_prog_put: 350 - bpf_prog_put(prog); 351 - out_dev_put: 352 - put_device(dev); 353 - return err; 354 - } 355 - 356 - /** 357 268 * hid_bpf_allocate_context - Allocate a context to the given HID device 358 269 * 359 270 * @hid_id: the system unique identifier of the HID device ··· 308 333 { 309 334 struct hid_device *hdev; 310 335 struct hid_bpf_ctx_kern *ctx_kern = NULL; 311 - struct device *dev; 312 336 313 - if (!hid_bpf_ops) 337 + hdev = hid_get_device(hid_id); 338 + if (IS_ERR(hdev)) 314 339 return NULL; 315 - 316 - dev = bus_find_device(hid_bpf_ops->bus_type, NULL, &hid_id, device_match_id); 317 - if (!dev) 318 - return NULL; 319 - 320 - hdev = to_hid_device(dev); 321 340 322 341 ctx_kern = kzalloc(sizeof(*ctx_kern), GFP_KERNEL); 323 342 if (!ctx_kern) { 324 - put_device(dev); 343 + hid_put_device(hdev); 325 344 return NULL; 326 345 } 327 346 ··· 342 373 kfree(ctx_kern); 343 374 344 375 /* get_device() is called by bus_find_device() */ 345 - put_device(&hid->dev); 376 + hid_put_device(hid); 346 377 } 347 378 348 379 static int ··· 355 386 u32 report_len; 356 387 357 388 /* check arguments */ 358 - if (!ctx || !hid_bpf_ops || !buf) 389 + if (!ctx || !hid_ops || !buf) 359 390 return -EINVAL; 360 391 361 392 switch (rtype) { ··· 373 404 hdev = (struct hid_device *)ctx->hid; /* discard const */ 374 405 375 406 report_enum = hdev->report_enum + rtype; 376 - report = hid_bpf_ops->hid_get_report(report_enum, buf); 407 + report = hid_ops->hid_get_report(report_enum, buf); 377 408 if (!report) 378 409 return -EINVAL; 379 410 ··· 400 431 hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz, 401 432 enum hid_report_type rtype, enum hid_class_request reqtype) 402 433 { 434 + struct hid_bpf_ctx_kern *ctx_kern; 403 435 struct hid_device *hdev; 404 436 size_t size = buf__sz; 405 437 u8 *dma_data; 406 438 int ret; 439 + 440 + ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx); 441 + 442 + if (ctx_kern->from_bpf) 443 + return -EDEADLOCK; 407 444 408 445 /* check arguments */ 409 446 ret = __hid_bpf_hw_check_params(ctx, buf, &size, rtype); ··· 434 459 if (!dma_data) 435 460 return -ENOMEM; 436 461 437 - ret = hid_bpf_ops->hid_hw_raw_request(hdev, 462 + ret = hid_ops->hid_hw_raw_request(hdev, 438 463 dma_data[0], 439 464 dma_data, 440 465 size, 441 466 rtype, 442 - reqtype); 467 + reqtype, 468 + (u64)(long)ctx, 469 + true); /* prevent infinite recursions */ 443 470 444 471 if (ret > 0) 445 472 memcpy(buf, dma_data, ret); ··· 462 485 __bpf_kfunc int 463 486 hid_bpf_hw_output_report(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz) 464 487 { 488 + struct hid_bpf_ctx_kern *ctx_kern; 465 489 struct hid_device *hdev; 466 490 size_t size = buf__sz; 467 491 u8 *dma_data; 468 492 int ret; 493 + 494 + ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx); 495 + if (ctx_kern->from_bpf) 496 + return -EDEADLOCK; 469 497 470 498 /* check arguments */ 471 499 ret = __hid_bpf_hw_check_params(ctx, buf, &size, HID_OUTPUT_REPORT); ··· 483 501 if (!dma_data) 484 502 return -ENOMEM; 485 503 486 - ret = hid_bpf_ops->hid_hw_output_report(hdev, 487 - dma_data, 488 - size); 504 + ret = hid_ops->hid_hw_output_report(hdev, dma_data, size, (u64)(long)ctx, true); 489 505 490 506 kfree(dma_data); 491 507 return ret; 508 + } 509 + 510 + static int 511 + __hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf, 512 + size_t size, bool lock_already_taken) 513 + { 514 + struct hid_bpf_ctx_kern *ctx_kern; 515 + int ret; 516 + 517 + ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx); 518 + if (ctx_kern->from_bpf) 519 + return -EDEADLOCK; 520 + 521 + /* check arguments */ 522 + ret = __hid_bpf_hw_check_params(ctx, buf, &size, type); 523 + if (ret) 524 + return ret; 525 + 526 + return hid_ops->hid_input_report(ctx->hid, type, buf, size, 0, (u64)(long)ctx, true, 527 + lock_already_taken); 528 + } 529 + 530 + /** 531 + * hid_bpf_try_input_report - Inject a HID report in the kernel from a HID device 532 + * 533 + * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context() 534 + * @type: the type of the report (%HID_INPUT_REPORT, %HID_FEATURE_REPORT, %HID_OUTPUT_REPORT) 535 + * @buf: a %PTR_TO_MEM buffer 536 + * @buf__sz: the size of the data to transfer 537 + * 538 + * Returns %0 on success, a negative error code otherwise. This function will immediately 539 + * fail if the device is not available, thus can be safely used in IRQ context. 540 + */ 541 + __bpf_kfunc int 542 + hid_bpf_try_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf, 543 + const size_t buf__sz) 544 + { 545 + struct hid_bpf_ctx_kern *ctx_kern; 546 + bool from_hid_event_hook; 547 + 548 + ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx); 549 + from_hid_event_hook = ctx_kern->data && ctx_kern->data == ctx->hid->bpf.device_data; 550 + 551 + return __hid_bpf_input_report(ctx, type, buf, buf__sz, from_hid_event_hook); 492 552 } 493 553 494 554 /** ··· 541 517 * @buf: a %PTR_TO_MEM buffer 542 518 * @buf__sz: the size of the data to transfer 543 519 * 544 - * Returns %0 on success, a negative error code otherwise. 520 + * Returns %0 on success, a negative error code otherwise. This function will wait for the 521 + * device to be available before injecting the event, thus needs to be called in sleepable 522 + * context. 545 523 */ 546 524 __bpf_kfunc int 547 525 hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf, 548 526 const size_t buf__sz) 549 527 { 550 - struct hid_device *hdev; 551 - size_t size = buf__sz; 552 528 int ret; 553 529 554 - /* check arguments */ 555 - ret = __hid_bpf_hw_check_params(ctx, buf, &size, type); 530 + ret = down_interruptible(&ctx->hid->driver_input_lock); 556 531 if (ret) 557 532 return ret; 558 533 559 - hdev = (struct hid_device *)ctx->hid; /* discard const */ 534 + /* check arguments */ 535 + ret = __hid_bpf_input_report(ctx, type, buf, buf__sz, true /* lock_already_taken */); 560 536 561 - return hid_bpf_ops->hid_input_report(hdev, type, buf, size, 0); 537 + up(&ctx->hid->driver_input_lock); 538 + 539 + return ret; 562 540 } 563 541 __bpf_kfunc_end_defs(); 564 542 ··· 575 549 BTF_ID_FLAGS(func, hid_bpf_hw_request, KF_SLEEPABLE) 576 550 BTF_ID_FLAGS(func, hid_bpf_hw_output_report, KF_SLEEPABLE) 577 551 BTF_ID_FLAGS(func, hid_bpf_input_report, KF_SLEEPABLE) 552 + BTF_ID_FLAGS(func, hid_bpf_try_input_report) 578 553 BTF_KFUNCS_END(hid_bpf_kfunc_ids) 579 554 580 555 static const struct btf_kfunc_id_set hid_bpf_kfunc_set = { ··· 583 556 .set = &hid_bpf_kfunc_ids, 584 557 }; 585 558 586 - /* our HID-BPF entrypoints */ 587 - BTF_SET8_START(hid_bpf_fmodret_ids) 588 - BTF_ID_FLAGS(func, hid_bpf_device_event) 589 - BTF_ID_FLAGS(func, hid_bpf_rdesc_fixup) 590 - BTF_ID_FLAGS(func, __hid_bpf_tail_call) 591 - BTF_SET8_END(hid_bpf_fmodret_ids) 592 - 593 - static const struct btf_kfunc_id_set hid_bpf_fmodret_set = { 594 - .owner = THIS_MODULE, 595 - .set = &hid_bpf_fmodret_ids, 596 - }; 597 - 598 559 /* for syscall HID-BPF */ 599 560 BTF_KFUNCS_START(hid_bpf_syscall_kfunc_ids) 600 - BTF_ID_FLAGS(func, hid_bpf_attach_prog) 601 561 BTF_ID_FLAGS(func, hid_bpf_allocate_context, KF_ACQUIRE | KF_RET_NULL) 602 562 BTF_ID_FLAGS(func, hid_bpf_release_context, KF_RELEASE) 603 563 BTF_ID_FLAGS(func, hid_bpf_hw_request) ··· 599 585 600 586 int hid_bpf_connect_device(struct hid_device *hdev) 601 587 { 602 - struct hid_bpf_prog_list *prog_list; 588 + bool need_to_allocate = false; 589 + struct hid_bpf_ops *e; 603 590 604 591 rcu_read_lock(); 605 - prog_list = rcu_dereference(hdev->bpf.progs[HID_BPF_PROG_TYPE_DEVICE_EVENT]); 592 + list_for_each_entry_rcu(e, &hdev->bpf.prog_list, list) { 593 + if (e->hid_device_event) { 594 + need_to_allocate = true; 595 + break; 596 + } 597 + } 606 598 rcu_read_unlock(); 607 599 608 600 /* only allocate BPF data if there are programs attached */ 609 - if (!prog_list) 601 + if (!need_to_allocate) 610 602 return 0; 611 603 612 604 return hid_bpf_allocate_event_data(hdev); ··· 635 615 /* mark the device as destroyed in bpf so we don't reattach it */ 636 616 hdev->bpf.destroyed = true; 637 617 638 - __hid_bpf_destroy_device(hdev); 618 + __hid_bpf_ops_destroy_device(hdev); 619 + 620 + synchronize_srcu(&hdev->bpf.srcu); 621 + cleanup_srcu_struct(&hdev->bpf.srcu); 639 622 } 640 623 EXPORT_SYMBOL_GPL(hid_bpf_destroy_device); 641 624 642 - void hid_bpf_device_init(struct hid_device *hdev) 625 + int hid_bpf_device_init(struct hid_device *hdev) 643 626 { 644 - spin_lock_init(&hdev->bpf.progs_lock); 627 + INIT_LIST_HEAD(&hdev->bpf.prog_list); 628 + mutex_init(&hdev->bpf.prog_list_lock); 629 + return init_srcu_struct(&hdev->bpf.srcu); 645 630 } 646 631 EXPORT_SYMBOL_GPL(hid_bpf_device_init); 647 632 ··· 657 632 /* Note: if we exit with an error any time here, we would entirely break HID, which 658 633 * is probably not something we want. So we log an error and return success. 659 634 * 660 - * This is not a big deal: the syscall allowing to attach a BPF program to a HID device 661 - * will not be available, so nobody will be able to use the functionality. 635 + * This is not a big deal: nobody will be able to use the functionality. 662 636 */ 663 637 664 - err = register_btf_fmodret_id_set(&hid_bpf_fmodret_set); 665 - if (err) { 666 - pr_warn("error while registering fmodret entrypoints: %d", err); 667 - return 0; 668 - } 669 - 670 - err = hid_bpf_preload_skel(); 671 - if (err) { 672 - pr_warn("error while preloading HID BPF dispatcher: %d", err); 673 - return 0; 674 - } 675 - 676 - /* register tracing kfuncs after we are sure we can load our preloaded bpf program */ 677 - err = register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &hid_bpf_kfunc_set); 638 + err = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, &hid_bpf_kfunc_set); 678 639 if (err) { 679 640 pr_warn("error while setting HID BPF tracing kfuncs: %d", err); 680 641 return 0; 681 642 } 682 643 683 - /* register syscalls after we are sure we can load our preloaded bpf program */ 684 644 err = register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &hid_bpf_syscall_kfunc_set); 685 645 if (err) { 686 646 pr_warn("error while setting HID BPF syscall kfuncs: %d", err); ··· 675 665 return 0; 676 666 } 677 667 678 - static void __exit hid_bpf_exit(void) 679 - { 680 - /* HID depends on us, so if we hit that code, we are guaranteed that hid 681 - * has been removed and thus we do not need to clear the HID devices 682 - */ 683 - hid_bpf_free_links_and_skel(); 684 - } 685 - 686 668 late_initcall(hid_bpf_init); 687 - module_exit(hid_bpf_exit); 688 669 MODULE_AUTHOR("Benjamin Tissoires"); 689 670 MODULE_LICENSE("GPL");
+5 -8
drivers/hid/bpf/hid_bpf_dispatch.h
··· 8 8 struct hid_bpf_ctx_kern { 9 9 struct hid_bpf_ctx ctx; 10 10 u8 *data; 11 + bool from_bpf; 11 12 }; 12 13 13 - int hid_bpf_preload_skel(void); 14 - void hid_bpf_free_links_and_skel(void); 15 - int hid_bpf_get_prog_attach_type(struct bpf_prog *prog); 16 - int __hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type, int prog_fd, 17 - struct bpf_prog *prog, __u32 flags); 18 - void __hid_bpf_destroy_device(struct hid_device *hdev); 19 - int hid_bpf_prog_run(struct hid_device *hdev, enum hid_bpf_prog_type type, 20 - struct hid_bpf_ctx_kern *ctx_kern); 14 + struct hid_device *hid_get_device(unsigned int hid_id); 15 + void hid_put_device(struct hid_device *hid); 16 + int hid_bpf_allocate_event_data(struct hid_device *hdev); 17 + void __hid_bpf_ops_destroy_device(struct hid_device *hdev); 21 18 int hid_bpf_reconnect(struct hid_device *hdev); 22 19 23 20 struct bpf_prog;
-565
drivers/hid/bpf/hid_bpf_jmp_table.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - 3 - /* 4 - * HID-BPF support for Linux 5 - * 6 - * Copyright (c) 2022 Benjamin Tissoires 7 - */ 8 - 9 - #include <linux/bitops.h> 10 - #include <linux/btf.h> 11 - #include <linux/btf_ids.h> 12 - #include <linux/circ_buf.h> 13 - #include <linux/filter.h> 14 - #include <linux/hid.h> 15 - #include <linux/hid_bpf.h> 16 - #include <linux/init.h> 17 - #include <linux/module.h> 18 - #include <linux/workqueue.h> 19 - #include "hid_bpf_dispatch.h" 20 - #include "entrypoints/entrypoints.lskel.h" 21 - 22 - #define HID_BPF_MAX_PROGS 1024 /* keep this in sync with preloaded bpf, 23 - * needs to be a power of 2 as we use it as 24 - * a circular buffer 25 - */ 26 - 27 - #define NEXT(idx) (((idx) + 1) & (HID_BPF_MAX_PROGS - 1)) 28 - #define PREV(idx) (((idx) - 1) & (HID_BPF_MAX_PROGS - 1)) 29 - 30 - /* 31 - * represents one attached program stored in the hid jump table 32 - */ 33 - struct hid_bpf_prog_entry { 34 - struct bpf_prog *prog; 35 - struct hid_device *hdev; 36 - enum hid_bpf_prog_type type; 37 - u16 idx; 38 - }; 39 - 40 - struct hid_bpf_jmp_table { 41 - struct bpf_map *map; 42 - struct hid_bpf_prog_entry entries[HID_BPF_MAX_PROGS]; /* compacted list, circular buffer */ 43 - int tail, head; 44 - struct bpf_prog *progs[HID_BPF_MAX_PROGS]; /* idx -> progs mapping */ 45 - unsigned long enabled[BITS_TO_LONGS(HID_BPF_MAX_PROGS)]; 46 - }; 47 - 48 - #define FOR_ENTRIES(__i, __start, __end) \ 49 - for (__i = __start; CIRC_CNT(__end, __i, HID_BPF_MAX_PROGS); __i = NEXT(__i)) 50 - 51 - static struct hid_bpf_jmp_table jmp_table; 52 - 53 - static DEFINE_MUTEX(hid_bpf_attach_lock); /* held when attaching/detaching programs */ 54 - 55 - static void hid_bpf_release_progs(struct work_struct *work); 56 - 57 - static DECLARE_WORK(release_work, hid_bpf_release_progs); 58 - 59 - BTF_ID_LIST(hid_bpf_btf_ids) 60 - BTF_ID(func, hid_bpf_device_event) /* HID_BPF_PROG_TYPE_DEVICE_EVENT */ 61 - BTF_ID(func, hid_bpf_rdesc_fixup) /* HID_BPF_PROG_TYPE_RDESC_FIXUP */ 62 - 63 - static int hid_bpf_max_programs(enum hid_bpf_prog_type type) 64 - { 65 - switch (type) { 66 - case HID_BPF_PROG_TYPE_DEVICE_EVENT: 67 - return HID_BPF_MAX_PROGS_PER_DEV; 68 - case HID_BPF_PROG_TYPE_RDESC_FIXUP: 69 - return 1; 70 - default: 71 - return -EINVAL; 72 - } 73 - } 74 - 75 - static int hid_bpf_program_count(struct hid_device *hdev, 76 - struct bpf_prog *prog, 77 - enum hid_bpf_prog_type type) 78 - { 79 - int i, n = 0; 80 - 81 - if (type >= HID_BPF_PROG_TYPE_MAX) 82 - return -EINVAL; 83 - 84 - FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) { 85 - struct hid_bpf_prog_entry *entry = &jmp_table.entries[i]; 86 - 87 - if (type != HID_BPF_PROG_TYPE_UNDEF && entry->type != type) 88 - continue; 89 - 90 - if (hdev && entry->hdev != hdev) 91 - continue; 92 - 93 - if (prog && entry->prog != prog) 94 - continue; 95 - 96 - n++; 97 - } 98 - 99 - return n; 100 - } 101 - 102 - __weak noinline int __hid_bpf_tail_call(struct hid_bpf_ctx *ctx) 103 - { 104 - return 0; 105 - } 106 - 107 - int hid_bpf_prog_run(struct hid_device *hdev, enum hid_bpf_prog_type type, 108 - struct hid_bpf_ctx_kern *ctx_kern) 109 - { 110 - struct hid_bpf_prog_list *prog_list; 111 - int i, idx, err = 0; 112 - 113 - rcu_read_lock(); 114 - prog_list = rcu_dereference(hdev->bpf.progs[type]); 115 - 116 - if (!prog_list) 117 - goto out_unlock; 118 - 119 - for (i = 0; i < prog_list->prog_cnt; i++) { 120 - idx = prog_list->prog_idx[i]; 121 - 122 - if (!test_bit(idx, jmp_table.enabled)) 123 - continue; 124 - 125 - ctx_kern->ctx.index = idx; 126 - err = __hid_bpf_tail_call(&ctx_kern->ctx); 127 - if (err < 0) 128 - break; 129 - if (err) 130 - ctx_kern->ctx.retval = err; 131 - } 132 - 133 - out_unlock: 134 - rcu_read_unlock(); 135 - 136 - return err; 137 - } 138 - 139 - /* 140 - * assign the list of programs attached to a given hid device. 141 - */ 142 - static void __hid_bpf_set_hdev_progs(struct hid_device *hdev, struct hid_bpf_prog_list *new_list, 143 - enum hid_bpf_prog_type type) 144 - { 145 - struct hid_bpf_prog_list *old_list; 146 - 147 - spin_lock(&hdev->bpf.progs_lock); 148 - old_list = rcu_dereference_protected(hdev->bpf.progs[type], 149 - lockdep_is_held(&hdev->bpf.progs_lock)); 150 - rcu_assign_pointer(hdev->bpf.progs[type], new_list); 151 - spin_unlock(&hdev->bpf.progs_lock); 152 - synchronize_rcu(); 153 - 154 - kfree(old_list); 155 - } 156 - 157 - /* 158 - * allocate and populate the list of programs attached to a given hid device. 159 - * 160 - * Must be called under lock. 161 - */ 162 - static int hid_bpf_populate_hdev(struct hid_device *hdev, enum hid_bpf_prog_type type) 163 - { 164 - struct hid_bpf_prog_list *new_list; 165 - int i; 166 - 167 - if (type >= HID_BPF_PROG_TYPE_MAX || !hdev) 168 - return -EINVAL; 169 - 170 - if (hdev->bpf.destroyed) 171 - return 0; 172 - 173 - new_list = kzalloc(sizeof(*new_list), GFP_KERNEL); 174 - if (!new_list) 175 - return -ENOMEM; 176 - 177 - FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) { 178 - struct hid_bpf_prog_entry *entry = &jmp_table.entries[i]; 179 - 180 - if (entry->type == type && entry->hdev == hdev && 181 - test_bit(entry->idx, jmp_table.enabled)) 182 - new_list->prog_idx[new_list->prog_cnt++] = entry->idx; 183 - } 184 - 185 - __hid_bpf_set_hdev_progs(hdev, new_list, type); 186 - 187 - return 0; 188 - } 189 - 190 - static void __hid_bpf_do_release_prog(int map_fd, unsigned int idx) 191 - { 192 - skel_map_delete_elem(map_fd, &idx); 193 - jmp_table.progs[idx] = NULL; 194 - } 195 - 196 - static void hid_bpf_release_progs(struct work_struct *work) 197 - { 198 - int i, j, n, map_fd = -1; 199 - bool hdev_destroyed; 200 - 201 - if (!jmp_table.map) 202 - return; 203 - 204 - /* retrieve a fd of our prog_array map in BPF */ 205 - map_fd = skel_map_get_fd_by_id(jmp_table.map->id); 206 - if (map_fd < 0) 207 - return; 208 - 209 - mutex_lock(&hid_bpf_attach_lock); /* protects against attaching new programs */ 210 - 211 - /* detach unused progs from HID devices */ 212 - FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) { 213 - struct hid_bpf_prog_entry *entry = &jmp_table.entries[i]; 214 - enum hid_bpf_prog_type type; 215 - struct hid_device *hdev; 216 - 217 - if (test_bit(entry->idx, jmp_table.enabled)) 218 - continue; 219 - 220 - /* we have an attached prog */ 221 - if (entry->hdev) { 222 - hdev = entry->hdev; 223 - type = entry->type; 224 - /* 225 - * hdev is still valid, even if we are called after hid_destroy_device(): 226 - * when hid_bpf_attach() gets called, it takes a ref on the dev through 227 - * bus_find_device() 228 - */ 229 - hdev_destroyed = hdev->bpf.destroyed; 230 - 231 - hid_bpf_populate_hdev(hdev, type); 232 - 233 - /* mark all other disabled progs from hdev of the given type as detached */ 234 - FOR_ENTRIES(j, i, jmp_table.head) { 235 - struct hid_bpf_prog_entry *next; 236 - 237 - next = &jmp_table.entries[j]; 238 - 239 - if (test_bit(next->idx, jmp_table.enabled)) 240 - continue; 241 - 242 - if (next->hdev == hdev && next->type == type) { 243 - /* 244 - * clear the hdev reference and decrement the device ref 245 - * that was taken during bus_find_device() while calling 246 - * hid_bpf_attach() 247 - */ 248 - next->hdev = NULL; 249 - put_device(&hdev->dev); 250 - } 251 - } 252 - 253 - /* if type was rdesc fixup and the device is not gone, reconnect device */ 254 - if (type == HID_BPF_PROG_TYPE_RDESC_FIXUP && !hdev_destroyed) 255 - hid_bpf_reconnect(hdev); 256 - } 257 - } 258 - 259 - /* remove all unused progs from the jump table */ 260 - FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) { 261 - struct hid_bpf_prog_entry *entry = &jmp_table.entries[i]; 262 - 263 - if (test_bit(entry->idx, jmp_table.enabled)) 264 - continue; 265 - 266 - if (entry->prog) 267 - __hid_bpf_do_release_prog(map_fd, entry->idx); 268 - } 269 - 270 - /* compact the entry list */ 271 - n = jmp_table.tail; 272 - FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) { 273 - struct hid_bpf_prog_entry *entry = &jmp_table.entries[i]; 274 - 275 - if (!test_bit(entry->idx, jmp_table.enabled)) 276 - continue; 277 - 278 - jmp_table.entries[n] = jmp_table.entries[i]; 279 - n = NEXT(n); 280 - } 281 - 282 - jmp_table.head = n; 283 - 284 - mutex_unlock(&hid_bpf_attach_lock); 285 - 286 - if (map_fd >= 0) 287 - close_fd(map_fd); 288 - } 289 - 290 - static void hid_bpf_release_prog_at(int idx) 291 - { 292 - int map_fd = -1; 293 - 294 - /* retrieve a fd of our prog_array map in BPF */ 295 - map_fd = skel_map_get_fd_by_id(jmp_table.map->id); 296 - if (map_fd < 0) 297 - return; 298 - 299 - __hid_bpf_do_release_prog(map_fd, idx); 300 - 301 - close(map_fd); 302 - } 303 - 304 - /* 305 - * Insert the given BPF program represented by its fd in the jmp table. 306 - * Returns the index in the jump table or a negative error. 307 - */ 308 - static int hid_bpf_insert_prog(int prog_fd, struct bpf_prog *prog) 309 - { 310 - int i, index = -1, map_fd = -1, err = -EINVAL; 311 - 312 - /* retrieve a fd of our prog_array map in BPF */ 313 - map_fd = skel_map_get_fd_by_id(jmp_table.map->id); 314 - 315 - if (map_fd < 0) { 316 - err = -EINVAL; 317 - goto out; 318 - } 319 - 320 - /* find the first available index in the jmp_table */ 321 - for (i = 0; i < HID_BPF_MAX_PROGS; i++) { 322 - if (!jmp_table.progs[i] && index < 0) { 323 - /* mark the index as used */ 324 - jmp_table.progs[i] = prog; 325 - index = i; 326 - __set_bit(i, jmp_table.enabled); 327 - } 328 - } 329 - if (index < 0) { 330 - err = -ENOMEM; 331 - goto out; 332 - } 333 - 334 - /* insert the program in the jump table */ 335 - err = skel_map_update_elem(map_fd, &index, &prog_fd, 0); 336 - if (err) 337 - goto out; 338 - 339 - /* return the index */ 340 - err = index; 341 - 342 - out: 343 - if (err < 0) 344 - __hid_bpf_do_release_prog(map_fd, index); 345 - if (map_fd >= 0) 346 - close_fd(map_fd); 347 - return err; 348 - } 349 - 350 - int hid_bpf_get_prog_attach_type(struct bpf_prog *prog) 351 - { 352 - int prog_type = HID_BPF_PROG_TYPE_UNDEF; 353 - int i; 354 - 355 - for (i = 0; i < HID_BPF_PROG_TYPE_MAX; i++) { 356 - if (hid_bpf_btf_ids[i] == prog->aux->attach_btf_id) { 357 - prog_type = i; 358 - break; 359 - } 360 - } 361 - 362 - return prog_type; 363 - } 364 - 365 - static void hid_bpf_link_release(struct bpf_link *link) 366 - { 367 - struct hid_bpf_link *hid_link = 368 - container_of(link, struct hid_bpf_link, link); 369 - 370 - __clear_bit(hid_link->hid_table_index, jmp_table.enabled); 371 - schedule_work(&release_work); 372 - } 373 - 374 - static void hid_bpf_link_dealloc(struct bpf_link *link) 375 - { 376 - struct hid_bpf_link *hid_link = 377 - container_of(link, struct hid_bpf_link, link); 378 - 379 - kfree(hid_link); 380 - } 381 - 382 - static void hid_bpf_link_show_fdinfo(const struct bpf_link *link, 383 - struct seq_file *seq) 384 - { 385 - seq_printf(seq, 386 - "attach_type:\tHID-BPF\n"); 387 - } 388 - 389 - static const struct bpf_link_ops hid_bpf_link_lops = { 390 - .release = hid_bpf_link_release, 391 - .dealloc = hid_bpf_link_dealloc, 392 - .show_fdinfo = hid_bpf_link_show_fdinfo, 393 - }; 394 - 395 - /* called from syscall */ 396 - noinline int 397 - __hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type, 398 - int prog_fd, struct bpf_prog *prog, __u32 flags) 399 - { 400 - struct bpf_link_primer link_primer; 401 - struct hid_bpf_link *link; 402 - struct hid_bpf_prog_entry *prog_entry; 403 - int cnt, err = -EINVAL, prog_table_idx = -1; 404 - 405 - mutex_lock(&hid_bpf_attach_lock); 406 - 407 - link = kzalloc(sizeof(*link), GFP_USER); 408 - if (!link) { 409 - err = -ENOMEM; 410 - goto err_unlock; 411 - } 412 - 413 - bpf_link_init(&link->link, BPF_LINK_TYPE_UNSPEC, 414 - &hid_bpf_link_lops, prog); 415 - 416 - /* do not attach too many programs to a given HID device */ 417 - cnt = hid_bpf_program_count(hdev, NULL, prog_type); 418 - if (cnt < 0) { 419 - err = cnt; 420 - goto err_unlock; 421 - } 422 - 423 - if (cnt >= hid_bpf_max_programs(prog_type)) { 424 - err = -E2BIG; 425 - goto err_unlock; 426 - } 427 - 428 - prog_table_idx = hid_bpf_insert_prog(prog_fd, prog); 429 - /* if the jmp table is full, abort */ 430 - if (prog_table_idx < 0) { 431 - err = prog_table_idx; 432 - goto err_unlock; 433 - } 434 - 435 - if (flags & HID_BPF_FLAG_INSERT_HEAD) { 436 - /* take the previous prog_entry slot */ 437 - jmp_table.tail = PREV(jmp_table.tail); 438 - prog_entry = &jmp_table.entries[jmp_table.tail]; 439 - } else { 440 - /* take the next prog_entry slot */ 441 - prog_entry = &jmp_table.entries[jmp_table.head]; 442 - jmp_table.head = NEXT(jmp_table.head); 443 - } 444 - 445 - /* we steal the ref here */ 446 - prog_entry->prog = prog; 447 - prog_entry->idx = prog_table_idx; 448 - prog_entry->hdev = hdev; 449 - prog_entry->type = prog_type; 450 - 451 - /* finally store the index in the device list */ 452 - err = hid_bpf_populate_hdev(hdev, prog_type); 453 - if (err) { 454 - hid_bpf_release_prog_at(prog_table_idx); 455 - goto err_unlock; 456 - } 457 - 458 - link->hid_table_index = prog_table_idx; 459 - 460 - err = bpf_link_prime(&link->link, &link_primer); 461 - if (err) 462 - goto err_unlock; 463 - 464 - mutex_unlock(&hid_bpf_attach_lock); 465 - 466 - return bpf_link_settle(&link_primer); 467 - 468 - err_unlock: 469 - mutex_unlock(&hid_bpf_attach_lock); 470 - 471 - kfree(link); 472 - 473 - return err; 474 - } 475 - 476 - void __hid_bpf_destroy_device(struct hid_device *hdev) 477 - { 478 - int type, i; 479 - struct hid_bpf_prog_list *prog_list; 480 - 481 - rcu_read_lock(); 482 - 483 - for (type = 0; type < HID_BPF_PROG_TYPE_MAX; type++) { 484 - prog_list = rcu_dereference(hdev->bpf.progs[type]); 485 - 486 - if (!prog_list) 487 - continue; 488 - 489 - for (i = 0; i < prog_list->prog_cnt; i++) 490 - __clear_bit(prog_list->prog_idx[i], jmp_table.enabled); 491 - } 492 - 493 - rcu_read_unlock(); 494 - 495 - for (type = 0; type < HID_BPF_PROG_TYPE_MAX; type++) 496 - __hid_bpf_set_hdev_progs(hdev, NULL, type); 497 - 498 - /* schedule release of all detached progs */ 499 - schedule_work(&release_work); 500 - } 501 - 502 - #define HID_BPF_PROGS_COUNT 1 503 - 504 - static struct bpf_link *links[HID_BPF_PROGS_COUNT]; 505 - static struct entrypoints_bpf *skel; 506 - 507 - void hid_bpf_free_links_and_skel(void) 508 - { 509 - int i; 510 - 511 - /* the following is enough to release all programs attached to hid */ 512 - if (jmp_table.map) 513 - bpf_map_put_with_uref(jmp_table.map); 514 - 515 - for (i = 0; i < ARRAY_SIZE(links); i++) { 516 - if (!IS_ERR_OR_NULL(links[i])) 517 - bpf_link_put(links[i]); 518 - } 519 - entrypoints_bpf__destroy(skel); 520 - } 521 - 522 - #define ATTACH_AND_STORE_LINK(__name) do { \ 523 - err = entrypoints_bpf__##__name##__attach(skel); \ 524 - if (err) \ 525 - goto out; \ 526 - \ 527 - links[idx] = bpf_link_get_from_fd(skel->links.__name##_fd); \ 528 - if (IS_ERR(links[idx])) { \ 529 - err = PTR_ERR(links[idx]); \ 530 - goto out; \ 531 - } \ 532 - \ 533 - /* Avoid taking over stdin/stdout/stderr of init process. Zeroing out \ 534 - * makes skel_closenz() a no-op later in iterators_bpf__destroy(). \ 535 - */ \ 536 - close_fd(skel->links.__name##_fd); \ 537 - skel->links.__name##_fd = 0; \ 538 - idx++; \ 539 - } while (0) 540 - 541 - int hid_bpf_preload_skel(void) 542 - { 543 - int err, idx = 0; 544 - 545 - skel = entrypoints_bpf__open(); 546 - if (!skel) 547 - return -ENOMEM; 548 - 549 - err = entrypoints_bpf__load(skel); 550 - if (err) 551 - goto out; 552 - 553 - jmp_table.map = bpf_map_get_with_uref(skel->maps.hid_jmp_table.map_fd); 554 - if (IS_ERR(jmp_table.map)) { 555 - err = PTR_ERR(jmp_table.map); 556 - goto out; 557 - } 558 - 559 - ATTACH_AND_STORE_LINK(hid_tail_call); 560 - 561 - return 0; 562 - out: 563 - hid_bpf_free_links_and_skel(); 564 - return err; 565 - }
+307
drivers/hid/bpf/hid_bpf_struct_ops.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + /* 4 + * HID-BPF support for Linux 5 + * 6 + * Copyright (c) 2024 Benjamin Tissoires 7 + */ 8 + 9 + #include <linux/bitops.h> 10 + #include <linux/bpf_verifier.h> 11 + #include <linux/bpf.h> 12 + #include <linux/btf.h> 13 + #include <linux/btf_ids.h> 14 + #include <linux/filter.h> 15 + #include <linux/hid.h> 16 + #include <linux/hid_bpf.h> 17 + #include <linux/init.h> 18 + #include <linux/module.h> 19 + #include <linux/stddef.h> 20 + #include <linux/workqueue.h> 21 + #include "hid_bpf_dispatch.h" 22 + 23 + static struct btf *hid_bpf_ops_btf; 24 + 25 + static int hid_bpf_ops_init(struct btf *btf) 26 + { 27 + hid_bpf_ops_btf = btf; 28 + return 0; 29 + } 30 + 31 + static bool hid_bpf_ops_is_valid_access(int off, int size, 32 + enum bpf_access_type type, 33 + const struct bpf_prog *prog, 34 + struct bpf_insn_access_aux *info) 35 + { 36 + return bpf_tracing_btf_ctx_access(off, size, type, prog, info); 37 + } 38 + 39 + static int hid_bpf_ops_check_member(const struct btf_type *t, 40 + const struct btf_member *member, 41 + const struct bpf_prog *prog) 42 + { 43 + u32 moff = __btf_member_bit_offset(t, member) / 8; 44 + 45 + switch (moff) { 46 + case offsetof(struct hid_bpf_ops, hid_rdesc_fixup): 47 + case offsetof(struct hid_bpf_ops, hid_hw_request): 48 + case offsetof(struct hid_bpf_ops, hid_hw_output_report): 49 + break; 50 + default: 51 + if (prog->sleepable) 52 + return -EINVAL; 53 + } 54 + 55 + return 0; 56 + } 57 + 58 + struct hid_bpf_offset_write_range { 59 + const char *struct_name; 60 + u32 struct_length; 61 + u32 start; 62 + u32 end; 63 + }; 64 + 65 + static int hid_bpf_ops_btf_struct_access(struct bpf_verifier_log *log, 66 + const struct bpf_reg_state *reg, 67 + int off, int size) 68 + { 69 + #define WRITE_RANGE(_name, _field, _is_string) \ 70 + { \ 71 + .struct_name = #_name, \ 72 + .struct_length = sizeof(struct _name), \ 73 + .start = offsetof(struct _name, _field), \ 74 + .end = offsetofend(struct _name, _field) - !!(_is_string), \ 75 + } 76 + 77 + const struct hid_bpf_offset_write_range write_ranges[] = { 78 + WRITE_RANGE(hid_bpf_ctx, retval, false), 79 + WRITE_RANGE(hid_device, name, true), 80 + WRITE_RANGE(hid_device, uniq, true), 81 + WRITE_RANGE(hid_device, phys, true), 82 + }; 83 + #undef WRITE_RANGE 84 + const struct btf_type *state = NULL; 85 + const struct btf_type *t; 86 + const char *cur = NULL; 87 + int i; 88 + 89 + t = btf_type_by_id(reg->btf, reg->btf_id); 90 + 91 + for (i = 0; i < ARRAY_SIZE(write_ranges); i++) { 92 + const struct hid_bpf_offset_write_range *write_range = &write_ranges[i]; 93 + s32 type_id; 94 + 95 + /* we already found a writeable struct, but there is a 96 + * new one, let's break the loop. 97 + */ 98 + if (t == state && write_range->struct_name != cur) 99 + break; 100 + 101 + /* new struct to look for */ 102 + if (write_range->struct_name != cur) { 103 + type_id = btf_find_by_name_kind(reg->btf, write_range->struct_name, 104 + BTF_KIND_STRUCT); 105 + if (type_id < 0) 106 + return -EINVAL; 107 + 108 + state = btf_type_by_id(reg->btf, type_id); 109 + } 110 + 111 + /* this is not the struct we are looking for */ 112 + if (t != state) { 113 + cur = write_range->struct_name; 114 + continue; 115 + } 116 + 117 + /* first time we see this struct, check for out of bounds */ 118 + if (cur != write_range->struct_name && 119 + off + size > write_range->struct_length) { 120 + bpf_log(log, "write access for struct %s at off %d with size %d\n", 121 + write_range->struct_name, off, size); 122 + return -EACCES; 123 + } 124 + 125 + /* now check if we are in our boundaries */ 126 + if (off >= write_range->start && off + size <= write_range->end) 127 + return NOT_INIT; 128 + 129 + cur = write_range->struct_name; 130 + } 131 + 132 + 133 + if (t != state) 134 + bpf_log(log, "write access to this struct is not supported\n"); 135 + else 136 + bpf_log(log, 137 + "write access at off %d with size %d on read-only part of %s\n", 138 + off, size, cur); 139 + 140 + return -EACCES; 141 + } 142 + 143 + static const struct bpf_verifier_ops hid_bpf_verifier_ops = { 144 + .get_func_proto = bpf_base_func_proto, 145 + .is_valid_access = hid_bpf_ops_is_valid_access, 146 + .btf_struct_access = hid_bpf_ops_btf_struct_access, 147 + }; 148 + 149 + static int hid_bpf_ops_init_member(const struct btf_type *t, 150 + const struct btf_member *member, 151 + void *kdata, const void *udata) 152 + { 153 + const struct hid_bpf_ops *uhid_bpf_ops; 154 + struct hid_bpf_ops *khid_bpf_ops; 155 + u32 moff; 156 + 157 + uhid_bpf_ops = (const struct hid_bpf_ops *)udata; 158 + khid_bpf_ops = (struct hid_bpf_ops *)kdata; 159 + 160 + moff = __btf_member_bit_offset(t, member) / 8; 161 + 162 + switch (moff) { 163 + case offsetof(struct hid_bpf_ops, hid_id): 164 + /* For hid_id and flags fields, this function has to copy it 165 + * and return 1 to indicate that the data has been handled by 166 + * the struct_ops type, or the verifier will reject the map if 167 + * the value of those fields is not zero. 168 + */ 169 + khid_bpf_ops->hid_id = uhid_bpf_ops->hid_id; 170 + return 1; 171 + case offsetof(struct hid_bpf_ops, flags): 172 + if (uhid_bpf_ops->flags & ~BPF_F_BEFORE) 173 + return -EINVAL; 174 + khid_bpf_ops->flags = uhid_bpf_ops->flags; 175 + return 1; 176 + } 177 + return 0; 178 + } 179 + 180 + static int hid_bpf_reg(void *kdata, struct bpf_link *link) 181 + { 182 + struct hid_bpf_ops *ops = kdata; 183 + struct hid_device *hdev; 184 + int count, err = 0; 185 + 186 + hdev = hid_get_device(ops->hid_id); 187 + if (IS_ERR(hdev)) 188 + return PTR_ERR(hdev); 189 + 190 + ops->hdev = hdev; 191 + 192 + mutex_lock(&hdev->bpf.prog_list_lock); 193 + 194 + count = list_count_nodes(&hdev->bpf.prog_list); 195 + if (count >= HID_BPF_MAX_PROGS_PER_DEV) { 196 + err = -E2BIG; 197 + goto out_unlock; 198 + } 199 + 200 + if (ops->hid_rdesc_fixup) { 201 + if (hdev->bpf.rdesc_ops) { 202 + err = -EINVAL; 203 + goto out_unlock; 204 + } 205 + 206 + hdev->bpf.rdesc_ops = ops; 207 + } 208 + 209 + if (ops->hid_device_event) { 210 + err = hid_bpf_allocate_event_data(hdev); 211 + if (err) 212 + goto out_unlock; 213 + } 214 + 215 + if (ops->flags & BPF_F_BEFORE) 216 + list_add_rcu(&ops->list, &hdev->bpf.prog_list); 217 + else 218 + list_add_tail_rcu(&ops->list, &hdev->bpf.prog_list); 219 + synchronize_srcu(&hdev->bpf.srcu); 220 + 221 + out_unlock: 222 + mutex_unlock(&hdev->bpf.prog_list_lock); 223 + 224 + if (err) { 225 + if (hdev->bpf.rdesc_ops == ops) 226 + hdev->bpf.rdesc_ops = NULL; 227 + hid_put_device(hdev); 228 + } else if (ops->hid_rdesc_fixup) { 229 + hid_bpf_reconnect(hdev); 230 + } 231 + 232 + return err; 233 + } 234 + 235 + static void hid_bpf_unreg(void *kdata, struct bpf_link *link) 236 + { 237 + struct hid_bpf_ops *ops = kdata; 238 + struct hid_device *hdev; 239 + bool reconnect = false; 240 + 241 + hdev = ops->hdev; 242 + 243 + /* check if __hid_bpf_ops_destroy_device() has been called */ 244 + if (!hdev) 245 + return; 246 + 247 + mutex_lock(&hdev->bpf.prog_list_lock); 248 + 249 + list_del_rcu(&ops->list); 250 + synchronize_srcu(&hdev->bpf.srcu); 251 + 252 + reconnect = hdev->bpf.rdesc_ops == ops; 253 + if (reconnect) 254 + hdev->bpf.rdesc_ops = NULL; 255 + 256 + mutex_unlock(&hdev->bpf.prog_list_lock); 257 + 258 + if (reconnect) 259 + hid_bpf_reconnect(hdev); 260 + 261 + hid_put_device(hdev); 262 + } 263 + 264 + static int __hid_bpf_device_event(struct hid_bpf_ctx *ctx, enum hid_report_type type, u64 source) 265 + { 266 + return 0; 267 + } 268 + 269 + static int __hid_bpf_rdesc_fixup(struct hid_bpf_ctx *ctx) 270 + { 271 + return 0; 272 + } 273 + 274 + static struct hid_bpf_ops __bpf_hid_bpf_ops = { 275 + .hid_device_event = __hid_bpf_device_event, 276 + .hid_rdesc_fixup = __hid_bpf_rdesc_fixup, 277 + }; 278 + 279 + static struct bpf_struct_ops bpf_hid_bpf_ops = { 280 + .verifier_ops = &hid_bpf_verifier_ops, 281 + .init = hid_bpf_ops_init, 282 + .check_member = hid_bpf_ops_check_member, 283 + .init_member = hid_bpf_ops_init_member, 284 + .reg = hid_bpf_reg, 285 + .unreg = hid_bpf_unreg, 286 + .name = "hid_bpf_ops", 287 + .cfi_stubs = &__bpf_hid_bpf_ops, 288 + .owner = THIS_MODULE, 289 + }; 290 + 291 + void __hid_bpf_ops_destroy_device(struct hid_device *hdev) 292 + { 293 + struct hid_bpf_ops *e; 294 + 295 + rcu_read_lock(); 296 + list_for_each_entry_rcu(e, &hdev->bpf.prog_list, list) { 297 + hid_put_device(hdev); 298 + e->hdev = NULL; 299 + } 300 + rcu_read_unlock(); 301 + } 302 + 303 + static int __init hid_bpf_struct_ops_init(void) 304 + { 305 + return register_bpf_struct_ops(&bpf_hid_bpf_ops, hid_bpf_ops); 306 + } 307 + late_initcall(hid_bpf_struct_ops_init);
+7 -2
drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c
··· 133 133 * integer. We thus divide it by 30 to match what other joysticks are 134 134 * doing 135 135 */ 136 - SEC("fmod_ret/hid_bpf_rdesc_fixup") 136 + SEC(HID_BPF_RDESC_FIXUP) 137 137 int BPF_PROG(hid_fix_rdesc_raptor_mach_2, struct hid_bpf_ctx *hctx) 138 138 { 139 139 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */); ··· 152 152 * divide it by 30. 153 153 * Byte 34 is always null, so it is ignored. 154 154 */ 155 - SEC("fmod_ret/hid_bpf_device_event") 155 + SEC(HID_BPF_DEVICE_EVENT) 156 156 int BPF_PROG(raptor_mach_2_fix_hat_switch, struct hid_bpf_ctx *hctx) 157 157 { 158 158 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 64 /* size */); ··· 167 167 168 168 return 0; 169 169 } 170 + 171 + HID_BPF_OPS(raptor_mach_2) = { 172 + .hid_rdesc_fixup = (void *)hid_fix_rdesc_raptor_mach_2, 173 + .hid_device_event = (void *)raptor_mach_2_fix_hat_switch, 174 + }; 170 175 171 176 SEC("syscall") 172 177 int probe(struct hid_bpf_probe_args *ctx)
+5 -1
drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c
··· 30 30 * pointer. 31 31 */ 32 32 33 - SEC("fmod_ret/hid_bpf_rdesc_fixup") 33 + SEC(HID_BPF_RDESC_FIXUP) 34 34 int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx) 35 35 { 36 36 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */); ··· 44 44 45 45 return 0; 46 46 } 47 + 48 + HID_BPF_OPS(hp_elite_presenter) = { 49 + .hid_rdesc_fixup = (void *)hid_fix_rdesc, 50 + }; 47 51 48 52 SEC("syscall") 49 53 int probe(struct hid_bpf_probe_args *ctx)
+614
drivers/hid/bpf/progs/Huion__Dial-2.bpf.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Copyright (c) 2024 Red Hat, Inc 3 + */ 4 + 5 + #include "vmlinux.h" 6 + #include "hid_bpf.h" 7 + #include "hid_bpf_helpers.h" 8 + #include "hid_report_helpers.h" 9 + #include <bpf/bpf_tracing.h> 10 + 11 + #define VID_HUION 0x256C 12 + #define PID_DIAL_2 0x0060 13 + 14 + 15 + HID_BPF_CONFIG( 16 + HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_HUION, PID_DIAL_2), 17 + ); 18 + 19 + /* Filled in by udev-hid-bpf */ 20 + char UDEV_PROP_HUION_FIRMWARE_ID[64]; 21 + 22 + /* The prefix of the firmware ID we expect for this device. The full firmware 23 + * string has a date suffix, e.g. HUION_T21j_221221 24 + */ 25 + char EXPECTED_FIRMWARE_ID[] = "HUION_T216_"; 26 + 27 + /* How this BPF program works: the tablet has two modes, firmware mode and 28 + * tablet mode. In firmware mode (out of the box) the tablet sends button events 29 + * and the dial as keyboard combinations. In tablet mode it uses a vendor specific 30 + * hid report to report everything instead. 31 + * Depending on the mode some hid reports are never sent and the corresponding 32 + * devices are mute. 33 + * 34 + * To switch the tablet use e.g. https://github.com/whot/huion-switcher 35 + * or one of the tools from the digimend project 36 + * 37 + * This BPF works for both modes. The huion-switcher tool sets the 38 + * HUION_FIRMWARE_ID udev property - if that is set then we disable the firmware 39 + * pad and pen reports (by making them vendor collections that are ignored). 40 + * If that property is not set we fix all hidraw nodes so the tablet works in 41 + * either mode though the drawback is that the device will show up twice if 42 + * you bind it to all event nodes 43 + * 44 + * Default report descriptor for the first exposed hidraw node: 45 + * 46 + * # HUION Huion Tablet_Q630M 47 + * # 0x06, 0x00, 0xff, // Usage Page (Vendor Defined Page 1) 0 48 + * # 0x09, 0x01, // Usage (Vendor Usage 1) 3 49 + * # 0xa1, 0x01, // Collection (Application) 5 50 + * # 0x85, 0x08, // Report ID (8) 7 51 + * # 0x75, 0x58, // Report Size (88) 9 52 + * # 0x95, 0x01, // Report Count (1) 11 53 + * # 0x09, 0x01, // Usage (Vendor Usage 1) 13 54 + * # 0x81, 0x02, // Input (Data,Var,Abs) 15 55 + * # 0xc0, // End Collection 17 56 + * R: 18 06 00 ff 09 01 a1 01 85 08 75 58 95 01 09 01 81 02 c0 57 + * 58 + * This rdesc does nothing until the tablet is switched to raw mode, see 59 + * https://github.com/whot/huion-switcher 60 + * 61 + * 62 + * Second hidraw node is the Pen. This one sends events until the tablet is 63 + * switched to raw mode, then it's mute. 64 + * 65 + * # Report descriptor length: 93 bytes 66 + * # HUION Huion Tablet_Q630M 67 + * # 0x05, 0x0d, // Usage Page (Digitizers) 0 68 + * # 0x09, 0x02, // Usage (Pen) 2 69 + * # 0xa1, 0x01, // Collection (Application) 4 70 + * # 0x85, 0x0a, // Report ID (10) 6 71 + * # 0x09, 0x20, // Usage (Stylus) 8 72 + * # 0xa1, 0x01, // Collection (Application) 10 73 + * # 0x09, 0x42, // Usage (Tip Switch) 12 74 + * # 0x09, 0x44, // Usage (Barrel Switch) 14 75 + * # 0x09, 0x45, // Usage (Eraser) 16 76 + * # 0x09, 0x3c, // Usage (Invert) 18 77 + * # 0x15, 0x00, // Logical Minimum (0) 20 78 + * # 0x25, 0x01, // Logical Maximum (1) 22 79 + * # 0x75, 0x01, // Report Size (1) 24 80 + * # 0x95, 0x06, // Report Count (6) 26 81 + * # 0x81, 0x02, // Input (Data,Var,Abs) 28 82 + * # 0x09, 0x32, // Usage (In Range) 30 83 + * # 0x75, 0x01, // Report Size (1) 32 84 + * # 0x95, 0x01, // Report Count (1) 34 85 + * # 0x81, 0x02, // Input (Data,Var,Abs) 36 86 + * # 0x81, 0x03, // Input (Cnst,Var,Abs) 38 87 + * # 0x05, 0x01, // Usage Page (Generic Desktop) 40 88 + * # 0x09, 0x30, // Usage (X) 42 89 + * # 0x09, 0x31, // Usage (Y) 44 90 + * # 0x55, 0x0d, // Unit Exponent (-3) 46 91 + * # 0x65, 0x33, // Unit (EnglishLinear: in³) 48 92 + * # 0x26, 0xff, 0x7f, // Logical Maximum (32767) 50 93 + * # 0x35, 0x00, // Physical Minimum (0) 53 94 + * # 0x46, 0x00, 0x08, // Physical Maximum (2048) 55 95 + * # 0x75, 0x10, // Report Size (16) 58 96 + * # 0x95, 0x02, // Report Count (2) 60 97 + * # 0x81, 0x02, // Input (Data,Var,Abs) 62 98 + * # 0x05, 0x0d, // Usage Page (Digitizers) 64 99 + * # 0x09, 0x30, // Usage (Tip Pressure) 66 100 + * # 0x26, 0xff, 0x1f, // Logical Maximum (8191) 68 101 + * # 0x75, 0x10, // Report Size (16) 71 102 + * # 0x95, 0x01, // Report Count (1) 73 103 + * # 0x81, 0x02, // Input (Data,Var,Abs) 75 104 + * # 0x09, 0x3d, // Usage (X Tilt) 77 105 + * # 0x09, 0x3e, // Usage (Y Tilt) 79 106 + * # 0x15, 0x81, // Logical Minimum (-127) 81 107 + * # 0x25, 0x7f, // Logical Maximum (127) 83 108 + * # 0x75, 0x08, // Report Size (8) 85 109 + * # 0x95, 0x02, // Report Count (2) 87 110 + * # 0x81, 0x02, // Input (Data,Var,Abs) 89 111 + * # 0xc0, // End Collection 91 112 + * # 0xc0, // End Collection 92 113 + * 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 114 + * 115 + * Third hidraw node is the pad which sends a combination of keyboard shortcuts until 116 + * the tablet is switched to raw mode, then it's mute: 117 + * 118 + * # Report descriptor length: 148 bytes 119 + * # HUION Huion Tablet_Q630M 120 + * # 0x05, 0x01, // Usage Page (Generic Desktop) 0 121 + * # 0x09, 0x0e, // Usage (System Multi-Axis Controller) 2 122 + * # 0xa1, 0x01, // Collection (Application) 4 123 + * # 0x85, 0x11, // Report ID (17) 6 124 + * # 0x05, 0x0d, // Usage Page (Digitizers) 8 125 + * # 0x09, 0x21, // Usage (Puck) 10 126 + * # 0xa1, 0x02, // Collection (Logical) 12 127 + * # 0x15, 0x00, // Logical Minimum (0) 14 128 + * # 0x25, 0x01, // Logical Maximum (1) 16 129 + * # 0x75, 0x01, // Report Size (1) 18 130 + * # 0x95, 0x01, // Report Count (1) 20 131 + * # 0xa1, 0x00, // Collection (Physical) 22 132 + * # 0x05, 0x09, // Usage Page (Button) 24 133 + * # 0x09, 0x01, // Usage (Vendor Usage 0x01) 26 134 + * # 0x81, 0x02, // Input (Data,Var,Abs) 28 135 + * # 0x05, 0x0d, // Usage Page (Digitizers) 30 136 + * # 0x09, 0x33, // Usage (Touch) 32 137 + * # 0x81, 0x02, // Input (Data,Var,Abs) 34 138 + * # 0x95, 0x06, // Report Count (6) 36 139 + * # 0x81, 0x03, // Input (Cnst,Var,Abs) 38 140 + * # 0xa1, 0x02, // Collection (Logical) 40 141 + * # 0x05, 0x01, // Usage Page (Generic Desktop) 42 142 + * # 0x09, 0x37, // Usage (Dial) 44 143 + * # 0x16, 0x00, 0x80, // Logical Minimum (-32768) 46 144 + * # 0x26, 0xff, 0x7f, // Logical Maximum (32767) 49 145 + * # 0x75, 0x10, // Report Size (16) 52 146 + * # 0x95, 0x01, // Report Count (1) 54 147 + * # 0x81, 0x06, // Input (Data,Var,Rel) 56 148 + * # 0x35, 0x00, // Physical Minimum (0) 58 149 + * # 0x46, 0x10, 0x0e, // Physical Maximum (3600) 60 150 + * # 0x15, 0x00, // Logical Minimum (0) 63 151 + * # 0x26, 0x10, 0x0e, // Logical Maximum (3600) 65 152 + * # 0x09, 0x48, // Usage (Resolution Multiplier) 68 153 + * # 0xb1, 0x02, // Feature (Data,Var,Abs) 70 154 + * # 0x45, 0x00, // Physical Maximum (0) 72 155 + * # 0xc0, // End Collection 74 156 + * # 0x75, 0x08, // Report Size (8) 75 157 + * # 0x95, 0x01, // Report Count (1) 77 158 + * # 0x81, 0x01, // Input (Cnst,Arr,Abs) 79 159 + * # 0x75, 0x08, // Report Size (8) 81 160 + * # 0x95, 0x01, // Report Count (1) 83 161 + * # 0x81, 0x01, // Input (Cnst,Arr,Abs) 85 162 + * # 0x75, 0x08, // Report Size (8) 87 163 + * # 0x95, 0x01, // Report Count (1) 89 164 + * # 0x81, 0x01, // Input (Cnst,Arr,Abs) 91 165 + * # 0x75, 0x08, // Report Size (8) 93 166 + * # 0x95, 0x01, // Report Count (1) 95 167 + * # 0x81, 0x01, // Input (Cnst,Arr,Abs) 97 168 + * # 0x75, 0x08, // Report Size (8) 99 169 + * # 0x95, 0x01, // Report Count (1) 101 170 + * # 0x81, 0x01, // Input (Cnst,Arr,Abs) 103 171 + * # 0xc0, // End Collection 105 172 + * # 0xc0, // End Collection 106 173 + * # 0xc0, // End Collection 107 174 + * # 0x05, 0x01, // Usage Page (Generic Desktop) 108 175 + * # 0x09, 0x06, // Usage (Keyboard) 110 176 + * # 0xa1, 0x01, // Collection (Application) 112 177 + * # 0x85, 0x03, // Report ID (3) 114 178 + * # 0x05, 0x07, // Usage Page (Keyboard) 116 179 + * # 0x19, 0xe0, // Usage Minimum (224) 118 180 + * # 0x29, 0xe7, // Usage Maximum (231) 120 181 + * # 0x15, 0x00, // Logical Minimum (0) 122 182 + * # 0x25, 0x01, // Logical Maximum (1) 124 183 + * # 0x75, 0x01, // Report Size (1) 126 184 + * # 0x95, 0x08, // Report Count (8) 128 185 + * # 0x81, 0x02, // Input (Data,Var,Abs) 130 186 + * # 0x05, 0x07, // Usage Page (Keyboard) 132 187 + * # 0x19, 0x00, // Usage Minimum (0) 134 188 + * # 0x29, 0xff, // Usage Maximum (255) 136 189 + * # 0x26, 0xff, 0x00, // Logical Maximum (255) 138 190 + * # 0x75, 0x08, // Report Size (8) 141 191 + * # 0x95, 0x06, // Report Count (6) 143 192 + * # 0x81, 0x00, // Input (Data,Arr,Abs) 145 193 + * # 0xc0, // End Collection 147 194 + * 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 195 + */ 196 + 197 + #define PAD_REPORT_DESCRIPTOR_LENGTH 148 198 + #define PEN_REPORT_DESCRIPTOR_LENGTH 93 199 + #define VENDOR_REPORT_DESCRIPTOR_LENGTH 18 200 + #define PAD_REPORT_ID 3 201 + #define DIAL_REPORT_ID 17 202 + #define PEN_REPORT_ID 10 203 + #define VENDOR_REPORT_ID 8 204 + #define PAD_REPORT_LENGTH 9 205 + #define PEN_REPORT_LENGTH 10 206 + #define VENDOR_REPORT_LENGTH 12 207 + 208 + 209 + __u8 last_button_state; 210 + 211 + static const __u8 fixed_rdesc_pad[] = { 212 + UsagePage_GenericDesktop 213 + Usage_GD_Keypad 214 + CollectionApplication( 215 + // -- Byte 0 in report 216 + ReportId(PAD_REPORT_ID) 217 + LogicalRange_i8(0, 1) 218 + UsagePage_Digitizers 219 + Usage_Dig_TabletFunctionKeys 220 + CollectionPhysical( 221 + // Byte 1 in report - just exists so we get to be a tablet pad 222 + Usage_Dig_BarrelSwitch // BTN_STYLUS 223 + ReportCount(1) 224 + ReportSize(1) 225 + Input(Var|Abs) 226 + ReportCount(7) // padding 227 + Input(Const) 228 + // Bytes 2/3 in report - just exists so we get to be a tablet pad 229 + UsagePage_GenericDesktop 230 + Usage_GD_X 231 + Usage_GD_Y 232 + ReportCount(2) 233 + ReportSize(8) 234 + Input(Var|Abs) 235 + // Byte 4 in report is the dial 236 + Usage_GD_Wheel 237 + LogicalRange_i8(-1, 1) 238 + ReportCount(1) 239 + ReportSize(8) 240 + Input(Var|Rel) 241 + // Byte 5 is the button state 242 + UsagePage_Button 243 + UsageRange_i8(0x01, 0x8) 244 + LogicalRange_i8(0x0, 0x1) 245 + ReportCount(7) 246 + ReportSize(1) 247 + Input(Var|Abs) 248 + ReportCount(1) // padding 249 + Input(Const) 250 + ) 251 + // Make sure we match our original report length 252 + FixedSizeVendorReport(PAD_REPORT_LENGTH) 253 + ) 254 + }; 255 + 256 + static const __u8 fixed_rdesc_pen[] = { 257 + UsagePage_Digitizers 258 + Usage_Dig_Pen 259 + CollectionApplication( 260 + // -- Byte 0 in report 261 + ReportId(PEN_REPORT_ID) 262 + Usage_Dig_Pen 263 + CollectionPhysical( 264 + // -- Byte 1 in report 265 + Usage_Dig_TipSwitch 266 + Usage_Dig_BarrelSwitch 267 + Usage_Dig_SecondaryBarrelSwitch // maps eraser to BTN_STYLUS2 268 + LogicalRange_i8(0, 1) 269 + ReportSize(1) 270 + ReportCount(3) 271 + Input(Var|Abs) 272 + ReportCount(4) // Padding 273 + Input(Const) 274 + Usage_Dig_InRange 275 + ReportCount(1) 276 + Input(Var|Abs) 277 + ReportSize(16) 278 + ReportCount(1) 279 + PushPop( 280 + UsagePage_GenericDesktop 281 + Unit(cm) 282 + UnitExponent(-1) 283 + PhysicalRange_i16(0, 266) 284 + LogicalRange_i16(0, 32767) 285 + Usage_GD_X 286 + Input(Var|Abs) // Bytes 2+3 287 + PhysicalRange_i16(0, 166) 288 + LogicalRange_i16(0, 32767) 289 + Usage_GD_Y 290 + Input(Var|Abs) // Bytes 4+5 291 + ) 292 + UsagePage_Digitizers 293 + Usage_Dig_TipPressure 294 + LogicalRange_i16(0, 8191) 295 + Input(Var|Abs) // Byte 6+7 296 + ReportSize(8) 297 + ReportCount(2) 298 + LogicalRange_i8(-60, 60) 299 + Usage_Dig_XTilt 300 + Usage_Dig_YTilt 301 + Input(Var|Abs) // Byte 8+9 302 + ) 303 + ) 304 + }; 305 + 306 + static const __u8 fixed_rdesc_vendor[] = { 307 + UsagePage_Digitizers 308 + Usage_Dig_Pen 309 + CollectionApplication( 310 + // Byte 0 311 + // We leave the pen on the vendor report ID 312 + ReportId(VENDOR_REPORT_ID) 313 + Usage_Dig_Pen 314 + CollectionPhysical( 315 + // Byte 1 are the buttons 316 + LogicalRange_i8(0, 1) 317 + ReportSize(1) 318 + Usage_Dig_TipSwitch 319 + Usage_Dig_BarrelSwitch 320 + Usage_Dig_SecondaryBarrelSwitch 321 + ReportCount(3) 322 + Input(Var|Abs) 323 + ReportCount(4) // Padding 324 + Input(Const) 325 + Usage_Dig_InRange 326 + ReportCount(1) 327 + Input(Var|Abs) 328 + ReportSize(16) 329 + ReportCount(1) 330 + PushPop( 331 + UsagePage_GenericDesktop 332 + Unit(cm) 333 + UnitExponent(-1) 334 + // Note: reported logical range differs 335 + // from the pen report ID for x and y 336 + LogicalRange_i16(0, 53340) 337 + PhysicalRange_i16(0, 266) 338 + // Bytes 2/3 in report 339 + Usage_GD_X 340 + Input(Var|Abs) 341 + LogicalRange_i16(0, 33340) 342 + PhysicalRange_i16(0, 166) 343 + // Bytes 4/5 in report 344 + Usage_GD_Y 345 + Input(Var|Abs) 346 + ) 347 + // Bytes 6/7 in report 348 + LogicalRange_i16(0, 8191) 349 + Usage_Dig_TipPressure 350 + Input(Var|Abs) 351 + // Bytes 8/9 in report 352 + ReportCount(1) // Padding 353 + Input(Const) 354 + LogicalRange_i8(-60, 60) 355 + // Byte 10 in report 356 + Usage_Dig_XTilt 357 + // Byte 11 in report 358 + Usage_Dig_YTilt 359 + ReportSize(8) 360 + ReportCount(2) 361 + Input(Var|Abs) 362 + ) 363 + ) 364 + UsagePage_GenericDesktop 365 + Usage_GD_Keypad 366 + CollectionApplication( 367 + // Byte 0 368 + ReportId(PAD_REPORT_ID) 369 + LogicalRange_i8(0, 1) 370 + UsagePage_Digitizers 371 + Usage_Dig_TabletFunctionKeys 372 + CollectionPhysical( 373 + // Byte 1 are the buttons 374 + Usage_Dig_BarrelSwitch // BTN_STYLUS, needed so we get to be a tablet pad 375 + ReportCount(1) 376 + ReportSize(1) 377 + Input(Var|Abs) 378 + ReportCount(7) // Padding 379 + Input(Const) 380 + // Bytes 2/3 - x/y just exist so we get to be a tablet pad 381 + UsagePage_GenericDesktop 382 + Usage_GD_X 383 + Usage_GD_Y 384 + ReportCount(2) 385 + ReportSize(8) 386 + Input(Var|Abs) 387 + // Byte 4 is the button state 388 + UsagePage_Button 389 + UsageRange_i8(0x01, 0x8) 390 + LogicalRange_i8(0x0, 0x1) 391 + ReportCount(8) 392 + ReportSize(1) 393 + Input(Var|Abs) 394 + // Byte 5 is the top dial 395 + UsagePage_GenericDesktop 396 + Usage_GD_Wheel 397 + LogicalRange_i8(-1, 1) 398 + ReportCount(1) 399 + ReportSize(8) 400 + Input(Var|Rel) 401 + // Byte 6 is the bottom dial 402 + UsagePage_Consumer 403 + Usage_Con_ACPan 404 + Input(Var|Rel) 405 + ) 406 + // Make sure we match our original report length 407 + FixedSizeVendorReport(VENDOR_REPORT_LENGTH) 408 + ) 409 + }; 410 + 411 + static const __u8 disabled_rdesc_pen[] = { 412 + FixedSizeVendorReport(PEN_REPORT_LENGTH) 413 + }; 414 + 415 + static const __u8 disabled_rdesc_pad[] = { 416 + FixedSizeVendorReport(PAD_REPORT_LENGTH) 417 + }; 418 + 419 + SEC(HID_BPF_RDESC_FIXUP) 420 + int BPF_PROG(dial_2_fix_rdesc, struct hid_bpf_ctx *hctx) 421 + { 422 + __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */); 423 + __s32 rdesc_size = hctx->size; 424 + __u8 have_fw_id; 425 + 426 + if (!data) 427 + return 0; /* EPERM check */ 428 + 429 + /* If we have a firmware ID and it matches our expected prefix, we 430 + * disable the default pad/pen nodes. They won't send events 431 + * but cause duplicate devices. 432 + */ 433 + have_fw_id = __builtin_memcmp(UDEV_PROP_HUION_FIRMWARE_ID, 434 + EXPECTED_FIRMWARE_ID, 435 + sizeof(EXPECTED_FIRMWARE_ID) - 1) == 0; 436 + if (rdesc_size == PAD_REPORT_DESCRIPTOR_LENGTH) { 437 + if (have_fw_id) { 438 + __builtin_memcpy(data, disabled_rdesc_pad, sizeof(disabled_rdesc_pad)); 439 + return sizeof(disabled_rdesc_pad); 440 + } 441 + 442 + __builtin_memcpy(data, fixed_rdesc_pad, sizeof(fixed_rdesc_pad)); 443 + return sizeof(fixed_rdesc_pad); 444 + } 445 + if (rdesc_size == PEN_REPORT_DESCRIPTOR_LENGTH) { 446 + if (have_fw_id) { 447 + __builtin_memcpy(data, disabled_rdesc_pen, sizeof(disabled_rdesc_pen)); 448 + return sizeof(disabled_rdesc_pen); 449 + } 450 + 451 + __builtin_memcpy(data, fixed_rdesc_pen, sizeof(fixed_rdesc_pen)); 452 + return sizeof(fixed_rdesc_pen); 453 + } 454 + /* Always fix the vendor mode so the tablet will work even if nothing sets 455 + * the udev property (e.g. huion-switcher run manually) 456 + */ 457 + if (rdesc_size == VENDOR_REPORT_DESCRIPTOR_LENGTH) { 458 + __builtin_memcpy(data, fixed_rdesc_vendor, sizeof(fixed_rdesc_vendor)); 459 + return sizeof(fixed_rdesc_vendor); 460 + 461 + } 462 + return 0; 463 + } 464 + 465 + SEC(HID_BPF_DEVICE_EVENT) 466 + int BPF_PROG(dial_2_fix_events, struct hid_bpf_ctx *hctx) 467 + { 468 + __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 16 /* size */); 469 + static __u8 button; 470 + 471 + if (!data) 472 + return 0; /* EPERM check */ 473 + 474 + /* Only sent if tablet is in default mode */ 475 + if (data[0] == PAD_REPORT_ID) { 476 + /* Nicely enough, this device only supports one button down at a time so 477 + * the reports are easy to match. Buttons numbered from the top 478 + * Button released: 03 00 00 00 00 00 00 00 479 + * Button 1: 03 00 05 00 00 00 00 00 -> b 480 + * Button 2: 03 00 08 00 00 00 00 00 -> e 481 + * Button 3: 03 00 0c 00 00 00 00 00 -> i 482 + * Button 4: 03 00 e0 16 00 00 00 00 -> Ctrl S 483 + * Button 5: 03 00 2c 00 00 00 00 00 -> space 484 + * Button 6: 03 00 e0 e2 1d 00 00 00 -> Ctrl Alt Z 485 + */ 486 + button &= 0xc0; 487 + 488 + switch ((data[2] << 16) | (data[3] << 8) | data[4]) { 489 + case 0x000000: 490 + break; 491 + case 0x050000: 492 + button |= BIT(0); 493 + break; 494 + case 0x080000: 495 + button |= BIT(1); 496 + break; 497 + case 0x0c0000: 498 + button |= BIT(2); 499 + break; 500 + case 0xe01600: 501 + button |= BIT(3); 502 + break; 503 + case 0x2c0000: 504 + button |= BIT(4); 505 + break; 506 + case 0xe0e21d: 507 + button |= BIT(5); 508 + break; 509 + } 510 + 511 + __u8 report[8] = {PAD_REPORT_ID, 0x0, 0x0, 0x0, 0x00, button}; 512 + 513 + __builtin_memcpy(data, report, sizeof(report)); 514 + return sizeof(report); 515 + } 516 + 517 + /* Only sent if tablet is in default mode */ 518 + if (data[0] == DIAL_REPORT_ID) { 519 + /* 520 + * In default mode, both dials are merged together: 521 + * 522 + * Dial down: 11 00 ff ff 00 00 00 00 00 -> Dial -1 523 + * Dial up: 11 00 01 00 00 00 00 00 00 -> Dial 1 524 + */ 525 + __u16 dial = data[3] << 8 | data[2]; 526 + 527 + button &= 0x3f; 528 + button |= !!data[1] << 6; 529 + 530 + __u8 report[] = {PAD_REPORT_ID, 0x0, 0x0, 0x0, dial, button}; 531 + 532 + __builtin_memcpy(data, report, sizeof(report)); 533 + return sizeof(report); 534 + } 535 + 536 + /* Nothing to do for the PEN_REPORT_ID, it's already mapped */ 537 + 538 + /* Only sent if tablet is in raw mode */ 539 + if (data[0] == VENDOR_REPORT_ID) { 540 + /* Pad reports */ 541 + if (data[1] & 0x20) { 542 + /* See fixed_rdesc_pad */ 543 + struct pad_report { 544 + __u8 report_id; 545 + __u8 btn_stylus; 546 + __u8 x; 547 + __u8 y; 548 + __u8 buttons; 549 + __u8 dial_1; 550 + __u8 dial_2; 551 + } __attribute__((packed)) *pad_report; 552 + __u8 dial_1 = 0, dial_2 = 0; 553 + 554 + /* Dial report */ 555 + if (data[1] == 0xf1) { 556 + __u8 d = 0; 557 + 558 + if (data[5] == 2) 559 + d = 0xff; 560 + else 561 + d = data[5]; 562 + 563 + if (data[3] == 1) 564 + dial_1 = d; 565 + else 566 + dial_2 = d; 567 + } else { 568 + /* data[4] are the buttons, mapped correctly */ 569 + last_button_state = data[4]; 570 + dial_1 = 0; // dial 571 + dial_2 = 0; 572 + } 573 + 574 + pad_report = (struct pad_report *)data; 575 + 576 + pad_report->report_id = PAD_REPORT_ID; 577 + pad_report->btn_stylus = 0; 578 + pad_report->x = 0; 579 + pad_report->y = 0; 580 + pad_report->buttons = last_button_state; 581 + pad_report->dial_1 = dial_1; 582 + pad_report->dial_2 = dial_2; 583 + 584 + return sizeof(struct pad_report); 585 + } 586 + 587 + /* Pen reports need nothing done */ 588 + } 589 + 590 + return 0; 591 + } 592 + 593 + HID_BPF_OPS(inspiroy_dial2) = { 594 + .hid_device_event = (void *)dial_2_fix_events, 595 + .hid_rdesc_fixup = (void *)dial_2_fix_rdesc, 596 + }; 597 + 598 + SEC("syscall") 599 + int probe(struct hid_bpf_probe_args *ctx) 600 + { 601 + switch (ctx->rdesc_size) { 602 + case PAD_REPORT_DESCRIPTOR_LENGTH: 603 + case PEN_REPORT_DESCRIPTOR_LENGTH: 604 + case VENDOR_REPORT_DESCRIPTOR_LENGTH: 605 + ctx->retval = 0; 606 + break; 607 + default: 608 + ctx->retval = -EINVAL; 609 + } 610 + 611 + return 0; 612 + } 613 + 614 + char _license[] SEC("license") = "GPL";
+534
drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Copyright (c) 2024 Red Hat, Inc 3 + */ 4 + 5 + #include "vmlinux.h" 6 + #include "hid_bpf.h" 7 + #include "hid_bpf_helpers.h" 8 + #include "hid_report_helpers.h" 9 + #include <bpf/bpf_tracing.h> 10 + 11 + #define VID_HUION 0x256C 12 + #define PID_INSPIROY_2_S 0x0066 13 + 14 + HID_BPF_CONFIG( 15 + HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_HUION, PID_INSPIROY_2_S), 16 + ); 17 + 18 + /* Filled in by udev-hid-bpf */ 19 + char UDEV_PROP_HUION_FIRMWARE_ID[64]; 20 + 21 + /* The prefix of the firmware ID we expect for this device. The full firmware 22 + * string has a date suffix, e.g. HUION_T21j_221221 23 + */ 24 + char EXPECTED_FIRMWARE_ID[] = "HUION_T21j_"; 25 + 26 + /* How this BPF program works: the tablet has two modes, firmware mode and 27 + * tablet mode. In firmware mode (out of the box) the tablet sends button events 28 + * and the dial as keyboard combinations. In tablet mode it uses a vendor specific 29 + * hid report to report everything instead. 30 + * Depending on the mode some hid reports are never sent and the corresponding 31 + * devices are mute. 32 + * 33 + * To switch the tablet use e.g. https://github.com/whot/huion-switcher 34 + * or one of the tools from the digimend project 35 + * 36 + * This BPF works for both modes. The huion-switcher tool sets the 37 + * HUION_FIRMWARE_ID udev property - if that is set then we disable the firmware 38 + * pad and pen reports (by making them vendor collections that are ignored). 39 + * If that property is not set we fix all hidraw nodes so the tablet works in 40 + * either mode though the drawback is that the device will show up twice if 41 + * you bind it to all event nodes 42 + * 43 + * Default report descriptor for the first exposed hidraw node: 44 + * 45 + * # HUION Huion Tablet_H641P 46 + * # Report descriptor length: 18 bytes 47 + * # 0x06, 0x00, 0xff, // Usage Page (Vendor Defined Page 0xFF00) 0 48 + * # 0x09, 0x01, // Usage (Vendor Usage 0x01) 3 49 + * # 0xa1, 0x01, // Collection (Application) 5 50 + * # 0x85, 0x08, // Report ID (8) 7 51 + * # 0x75, 0x58, // Report Size (88) 9 52 + * # 0x95, 0x01, // Report Count (1) 11 53 + * # 0x09, 0x01, // Usage (Vendor Usage 0x01) 13 54 + * # 0x81, 0x02, // Input (Data,Var,Abs) 15 55 + * # 0xc0, // End Collection 17 56 + * R: 18 06 00 ff 09 01 a1 01 85 08 75 58 95 01 09 01 81 02 c0 57 + * 58 + * This rdesc does nothing until the tablet is switched to raw mode, see 59 + * https://github.com/whot/huion-switcher 60 + * 61 + * 62 + * Second hidraw node is the Pen. This one sends events until the tablet is 63 + * switched to raw mode, then it's mute. 64 + * 65 + * # Report descriptor length: 93 bytes 66 + * # 0x05, 0x0d, // Usage Page (Digitizers) 0 67 + * # 0x09, 0x02, // Usage (Pen) 2 68 + * # 0xa1, 0x01, // Collection (Application) 4 69 + * # 0x85, 0x0a, // Report ID (10) 6 70 + * # 0x09, 0x20, // Usage (Stylus) 8 71 + * # 0xa1, 0x01, // Collection (Application) 10 72 + * # 0x09, 0x42, // Usage (Tip Switch) 12 73 + * # 0x09, 0x44, // Usage (Barrel Switch) 14 74 + * # 0x09, 0x45, // Usage (Eraser) 16 75 + * # 0x09, 0x3c, // Usage (Invert) 18 <-- has no Invert eraser 76 + * # 0x15, 0x00, // Logical Minimum (0) 20 77 + * # 0x25, 0x01, // Logical Maximum (1) 22 78 + * # 0x75, 0x01, // Report Size (1) 24 79 + * # 0x95, 0x06, // Report Count (6) 26 80 + * # 0x81, 0x02, // Input (Data,Var,Abs) 28 81 + * # 0x09, 0x32, // Usage (In Range) 30 82 + * # 0x75, 0x01, // Report Size (1) 32 83 + * # 0x95, 0x01, // Report Count (1) 34 84 + * # 0x81, 0x02, // Input (Data,Var,Abs) 36 85 + * # 0x81, 0x03, // Input (Cnst,Var,Abs) 38 86 + * # 0x05, 0x01, // Usage Page (Generic Desktop) 40 87 + * # 0x09, 0x30, // Usage (X) 42 88 + * # 0x09, 0x31, // Usage (Y) 44 89 + * # 0x55, 0x0d, // Unit Exponent (-3) 46 <-- change to -2 90 + * # 0x65, 0x33, // Unit (EnglishLinear: in³) 48 <-- change in³ to in 91 + * # 0x26, 0xff, 0x7f, // Logical Maximum (32767) 50 92 + * # 0x35, 0x00, // Physical Minimum (0) 53 93 + * # 0x46, 0x00, 0x08, // Physical Maximum (2048) 55 <-- invalid size 94 + * # 0x75, 0x10, // Report Size (16) 58 95 + * # 0x95, 0x02, // Report Count (2) 60 96 + * # 0x81, 0x02, // Input (Data,Var,Abs) 62 97 + * # 0x05, 0x0d, // Usage Page (Digitizers) 64 98 + * # 0x09, 0x30, // Usage (Tip Pressure) 66 99 + * # 0x26, 0xff, 0x1f, // Logical Maximum (8191) 68 100 + * # 0x75, 0x10, // Report Size (16) 71 101 + * # 0x95, 0x01, // Report Count (1) 73 102 + * # 0x81, 0x02, // Input (Data,Var,Abs) 75 103 + * # 0x09, 0x3d, // Usage (X Tilt) 77 <-- No tilt reported 104 + * # 0x09, 0x3e, // Usage (Y Tilt) 79 105 + * # 0x15, 0x81, // Logical Minimum (-127) 81 106 + * # 0x25, 0x7f, // Logical Maximum (127) 83 107 + * # 0x75, 0x08, // Report Size (8) 85 108 + * # 0x95, 0x02, // Report Count (2) 87 109 + * # 0x81, 0x02, // Input (Data,Var,Abs) 89 110 + * # 0xc0, // End Collection 91 111 + * # 0xc0, // End Collection 92 112 + * 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 113 + * 114 + * Third hidraw node is the pad which sends a combination of keyboard shortcuts until 115 + * the tablet is switched to raw mode, then it's mute: 116 + * 117 + * # Report descriptor length: 65 bytes 118 + * # 0x05, 0x01, // Usage Page (Generic Desktop) 0 119 + * # 0x09, 0x06, // Usage (Keyboard) 2 120 + * # 0xa1, 0x01, // Collection (Application) 4 121 + * # 0x85, 0x03, // Report ID (3) 6 122 + * # 0x05, 0x07, // Usage Page (Keyboard/Keypad) 8 123 + * # 0x19, 0xe0, // UsageMinimum (224) 10 124 + * # 0x29, 0xe7, // UsageMaximum (231) 12 125 + * # 0x15, 0x00, // Logical Minimum (0) 14 126 + * # 0x25, 0x01, // Logical Maximum (1) 16 127 + * # 0x75, 0x01, // Report Size (1) 18 128 + * # 0x95, 0x08, // Report Count (8) 20 129 + * # 0x81, 0x02, // Input (Data,Var,Abs) 22 130 + * # 0x05, 0x07, // Usage Page (Keyboard/Keypad) 24 131 + * # 0x19, 0x00, // UsageMinimum (0) 26 132 + * # 0x29, 0xff, // UsageMaximum (255) 28 133 + * # 0x26, 0xff, 0x00, // Logical Maximum (255) 30 134 + * # 0x75, 0x08, // Report Size (8) 33 135 + * # 0x95, 0x06, // Report Count (6) 35 136 + * # 0x81, 0x00, // Input (Data,Arr,Abs) 37 137 + * # 0xc0, // End Collection 39 138 + * # 0x05, 0x0c, // Usage Page (Consumer) 40 139 + * # 0x09, 0x01, // Usage (Consumer Control) 42 140 + * # 0xa1, 0x01, // Collection (Application) 44 141 + * # 0x85, 0x04, // Report ID (4) 46 142 + * # 0x19, 0x00, // UsageMinimum (0) 48 143 + * # 0x2a, 0x3c, 0x02, // UsageMaximum (572) 50 144 + * # 0x15, 0x00, // Logical Minimum (0) 53 145 + * # 0x26, 0x3c, 0x02, // Logical Maximum (572) 55 146 + * # 0x95, 0x01, // Report Count (1) 58 147 + * # 0x75, 0x10, // Report Size (16) 60 148 + * # 0x81, 0x00, // Input (Data,Arr,Abs) 62 149 + * # 0xc0, // End Collection 64 150 + * 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 151 + * N: HUION Huion Tablet_H641P 152 + */ 153 + 154 + #define PAD_REPORT_DESCRIPTOR_LENGTH 65 155 + #define PEN_REPORT_DESCRIPTOR_LENGTH 93 156 + #define VENDOR_REPORT_DESCRIPTOR_LENGTH 18 157 + #define PAD_REPORT_ID 3 158 + #define PEN_REPORT_ID 10 159 + #define VENDOR_REPORT_ID 8 160 + #define PAD_REPORT_LENGTH 8 161 + #define PEN_REPORT_LENGTH 10 162 + #define VENDOR_REPORT_LENGTH 12 163 + 164 + 165 + __u8 last_button_state; 166 + 167 + static const __u8 fixed_rdesc_pad[] = { 168 + UsagePage_GenericDesktop 169 + Usage_GD_Keypad 170 + CollectionApplication( 171 + // -- Byte 0 in report 172 + ReportId(PAD_REPORT_ID) 173 + LogicalRange_i8(0, 1) 174 + UsagePage_Digitizers 175 + Usage_Dig_TabletFunctionKeys 176 + CollectionPhysical( 177 + // Byte 1 in report - just exists so we get to be a tablet pad 178 + Usage_Dig_BarrelSwitch // BTN_STYLUS 179 + ReportCount(1) 180 + ReportSize(1) 181 + Input(Var|Abs) 182 + ReportCount(7) // padding 183 + Input(Const) 184 + // Bytes 2/3 in report - just exists so we get to be a tablet pad 185 + UsagePage_GenericDesktop 186 + Usage_GD_X 187 + Usage_GD_Y 188 + ReportCount(2) 189 + ReportSize(8) 190 + Input(Var|Abs) 191 + // Byte 4 in report is the wheel 192 + Usage_GD_Wheel 193 + LogicalRange_i8(-1, 1) 194 + ReportCount(1) 195 + ReportSize(8) 196 + Input(Var|Rel) 197 + // Byte 5 is the button state 198 + UsagePage_Button 199 + UsageRange_i8(0x01, 0x6) 200 + LogicalRange_i8(0x01, 0x6) 201 + ReportCount(1) 202 + ReportSize(8) 203 + Input(Arr|Abs) 204 + ) 205 + // Make sure we match our original report length 206 + FixedSizeVendorReport(PAD_REPORT_LENGTH) 207 + ) 208 + }; 209 + 210 + static const __u8 fixed_rdesc_pen[] = { 211 + UsagePage_Digitizers 212 + Usage_Dig_Pen 213 + CollectionApplication( 214 + // -- Byte 0 in report 215 + ReportId(PEN_REPORT_ID) 216 + Usage_Dig_Pen 217 + CollectionPhysical( 218 + // -- Byte 1 in report 219 + Usage_Dig_TipSwitch 220 + Usage_Dig_BarrelSwitch 221 + Usage_Dig_SecondaryBarrelSwitch // maps eraser to BTN_STYLUS2 222 + LogicalRange_i8(0, 1) 223 + ReportSize(1) 224 + ReportCount(3) 225 + Input(Var|Abs) 226 + ReportCount(4) // Padding 227 + Input(Const) 228 + Usage_Dig_InRange 229 + ReportCount(1) 230 + Input(Var|Abs) 231 + ReportSize(16) 232 + ReportCount(1) 233 + PushPop( 234 + UsagePage_GenericDesktop 235 + Unit(cm) 236 + UnitExponent(-1) 237 + PhysicalRange_i16(0, 160) 238 + LogicalRange_i16(0, 32767) 239 + Usage_GD_X 240 + Input(Var|Abs) // Bytes 2+3 241 + PhysicalRange_i16(0, 100) 242 + LogicalRange_i16(0, 32767) 243 + Usage_GD_Y 244 + Input(Var|Abs) // Bytes 4+5 245 + ) 246 + UsagePage_Digitizers 247 + Usage_Dig_TipPressure 248 + LogicalRange_i16(0, 8191) 249 + Input(Var|Abs) // Byte 6+7 250 + // Two bytes padding so we don't need to change the report at all 251 + ReportSize(8) 252 + ReportCount(2) 253 + Input(Const) // Byte 6+7 254 + ) 255 + ) 256 + }; 257 + 258 + static const __u8 fixed_rdesc_vendor[] = { 259 + UsagePage_Digitizers 260 + Usage_Dig_Pen 261 + CollectionApplication( 262 + // Byte 0 263 + // We leave the pen on the vendor report ID 264 + ReportId(VENDOR_REPORT_ID) 265 + Usage_Dig_Pen 266 + CollectionPhysical( 267 + // Byte 1 are the buttons 268 + LogicalRange_i8(0, 1) 269 + ReportSize(1) 270 + Usage_Dig_TipSwitch 271 + Usage_Dig_BarrelSwitch 272 + Usage_Dig_SecondaryBarrelSwitch 273 + ReportCount(3) 274 + Input(Var|Abs) 275 + ReportCount(4) // Padding 276 + Input(Const) 277 + Usage_Dig_InRange 278 + ReportCount(1) 279 + Input(Var|Abs) 280 + ReportSize(16) 281 + ReportCount(1) 282 + PushPop( 283 + UsagePage_GenericDesktop 284 + Unit(cm) 285 + UnitExponent(-1) 286 + // Note: reported logical range differs 287 + // from the pen report ID for x and y 288 + LogicalRange_i16(0, 32000) 289 + PhysicalRange_i16(0, 160) 290 + // Bytes 2/3 in report 291 + Usage_GD_X 292 + Input(Var|Abs) 293 + LogicalRange_i16(0, 20000) 294 + PhysicalRange_i16(0, 100) 295 + // Bytes 4/5 in report 296 + Usage_GD_Y 297 + Input(Var|Abs) 298 + ) 299 + // Bytes 6/7 in report 300 + LogicalRange_i16(0, 8192) 301 + Usage_Dig_TipPressure 302 + Input(Var|Abs) 303 + ) 304 + ) 305 + UsagePage_GenericDesktop 306 + Usage_GD_Keypad 307 + CollectionApplication( 308 + // Byte 0 309 + ReportId(PAD_REPORT_ID) 310 + LogicalRange_i8(0, 1) 311 + UsagePage_Digitizers 312 + Usage_Dig_TabletFunctionKeys 313 + CollectionPhysical( 314 + // Byte 1 are the buttons 315 + Usage_Dig_BarrelSwitch // BTN_STYLUS, needed so we get to be a tablet pad 316 + ReportCount(1) 317 + ReportSize(1) 318 + Input(Var|Abs) 319 + ReportCount(7) // Padding 320 + Input(Const) 321 + // Bytes 2/3 - x/y just exist so we get to be a tablet pad 322 + UsagePage_GenericDesktop 323 + Usage_GD_X 324 + Usage_GD_Y 325 + ReportCount(2) 326 + ReportSize(8) 327 + Input(Var|Abs) 328 + // Byte 4 is the button state 329 + UsagePage_Button 330 + UsageRange_i8(0x01, 0x6) 331 + LogicalRange_i8(0x0, 0x1) 332 + ReportCount(6) 333 + ReportSize(1) 334 + Input(Var|Abs) 335 + ReportCount(2) 336 + Input(Const) 337 + // Byte 5 is the wheel 338 + UsagePage_GenericDesktop 339 + Usage_GD_Wheel 340 + LogicalRange_i8(-1, 1) 341 + ReportCount(1) 342 + ReportSize(8) 343 + Input(Var|Rel) 344 + ) 345 + // Make sure we match our original report length 346 + FixedSizeVendorReport(VENDOR_REPORT_LENGTH) 347 + ) 348 + }; 349 + 350 + static const __u8 disabled_rdesc_pen[] = { 351 + FixedSizeVendorReport(PEN_REPORT_LENGTH) 352 + }; 353 + 354 + static const __u8 disabled_rdesc_pad[] = { 355 + FixedSizeVendorReport(PAD_REPORT_LENGTH) 356 + }; 357 + 358 + SEC(HID_BPF_RDESC_FIXUP) 359 + int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx) 360 + { 361 + __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */); 362 + __s32 rdesc_size = hctx->size; 363 + __u8 have_fw_id; 364 + 365 + if (!data) 366 + return 0; /* EPERM check */ 367 + 368 + /* If we have a firmware ID and it matches our expected prefix, we 369 + * disable the default pad/pen nodes. They won't send events 370 + * but cause duplicate devices. 371 + */ 372 + have_fw_id = __builtin_memcmp(UDEV_PROP_HUION_FIRMWARE_ID, 373 + EXPECTED_FIRMWARE_ID, 374 + sizeof(EXPECTED_FIRMWARE_ID) - 1) == 0; 375 + if (rdesc_size == PAD_REPORT_DESCRIPTOR_LENGTH) { 376 + if (have_fw_id) { 377 + __builtin_memcpy(data, disabled_rdesc_pad, sizeof(disabled_rdesc_pad)); 378 + return sizeof(disabled_rdesc_pad); 379 + } 380 + 381 + __builtin_memcpy(data, fixed_rdesc_pad, sizeof(fixed_rdesc_pad)); 382 + return sizeof(fixed_rdesc_pad); 383 + } 384 + if (rdesc_size == PEN_REPORT_DESCRIPTOR_LENGTH) { 385 + if (have_fw_id) { 386 + __builtin_memcpy(data, disabled_rdesc_pen, sizeof(disabled_rdesc_pen)); 387 + return sizeof(disabled_rdesc_pen); 388 + } 389 + 390 + __builtin_memcpy(data, fixed_rdesc_pen, sizeof(fixed_rdesc_pen)); 391 + return sizeof(fixed_rdesc_pen); 392 + } 393 + /* Always fix the vendor mode so the tablet will work even if nothing sets 394 + * the udev property (e.g. huion-switcher run manually) 395 + */ 396 + if (rdesc_size == VENDOR_REPORT_DESCRIPTOR_LENGTH) { 397 + __builtin_memcpy(data, fixed_rdesc_vendor, sizeof(fixed_rdesc_vendor)); 398 + return sizeof(fixed_rdesc_vendor); 399 + 400 + } 401 + return 0; 402 + } 403 + 404 + SEC(HID_BPF_DEVICE_EVENT) 405 + int BPF_PROG(inspiroy_2_fix_events, struct hid_bpf_ctx *hctx) 406 + { 407 + __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */); 408 + 409 + if (!data) 410 + return 0; /* EPERM check */ 411 + 412 + /* Only sent if tablet is in default mode */ 413 + if (data[0] == PAD_REPORT_ID) { 414 + /* Nicely enough, this device only supports one button down at a time so 415 + * the reports are easy to match. Buttons numbered from the top 416 + * Button released: 03 00 00 00 00 00 00 00 417 + * Button 1: 03 00 05 00 00 00 00 00 -> b 418 + * Button 2: 03 00 0c 00 00 00 00 00 -> i 419 + * Button 3: 03 00 08 00 00 00 00 00 -> e 420 + * Button 4: 03 01 16 00 00 00 00 00 -> Ctrl S 421 + * Button 5: 03 00 2c 00 00 00 00 00 -> space 422 + * Button 6: 03 05 1d 00 00 00 00 00 -> Ctrl Alt Z 423 + * 424 + * Wheel down: 03 01 2d 00 00 00 00 00 -> Ctrl - 425 + * Wheel up: 03 01 2e 00 00 00 00 00 -> Ctrl = 426 + */ 427 + __u8 button = 0; 428 + __u8 wheel = 0; 429 + 430 + switch (data[1] << 8 | data[2]) { 431 + case 0x0000: 432 + break; 433 + case 0x0005: 434 + button = 1; 435 + break; 436 + case 0x000c: 437 + button = 2; 438 + break; 439 + case 0x0008: 440 + button = 3; 441 + break; 442 + case 0x0116: 443 + button = 4; 444 + break; 445 + case 0x002c: 446 + button = 5; 447 + break; 448 + case 0x051d: 449 + button = 6; 450 + break; 451 + case 0x012d: 452 + wheel = -1; 453 + break; 454 + case 0x012e: 455 + wheel = 1; 456 + break; 457 + 458 + } 459 + 460 + __u8 report[6] = {PAD_REPORT_ID, 0x0, 0x0, 0x0, wheel, button}; 461 + 462 + __builtin_memcpy(data, report, sizeof(report)); 463 + return sizeof(report); 464 + } 465 + 466 + /* Nothing to do for the PEN_REPORT_ID, it's already mapped */ 467 + 468 + /* Only sent if tablet is in raw mode */ 469 + if (data[0] == VENDOR_REPORT_ID) { 470 + /* Pad reports */ 471 + if (data[1] & 0x20) { 472 + /* See fixed_rdesc_pad */ 473 + struct pad_report { 474 + __u8 report_id; 475 + __u8 btn_stylus; 476 + __u8 x; 477 + __u8 y; 478 + __u8 buttons; 479 + __u8 wheel; 480 + } __attribute__((packed)) *pad_report; 481 + __u8 wheel = 0; 482 + 483 + /* Wheel report */ 484 + if (data[1] == 0xf1) { 485 + if (data[5] == 2) 486 + wheel = 0xff; 487 + else 488 + wheel = data[5]; 489 + } else { 490 + /* data[4] are the buttons, mapped correctly */ 491 + last_button_state = data[4]; 492 + wheel = 0; // wheel 493 + } 494 + 495 + pad_report = (struct pad_report *)data; 496 + 497 + pad_report->report_id = PAD_REPORT_ID; 498 + pad_report->btn_stylus = 0; 499 + pad_report->x = 0; 500 + pad_report->y = 0; 501 + pad_report->buttons = last_button_state; 502 + pad_report->wheel = wheel; 503 + 504 + return sizeof(struct pad_report); 505 + } 506 + 507 + /* Pen reports need nothing done */ 508 + } 509 + 510 + return 0; 511 + } 512 + 513 + HID_BPF_OPS(inspiroy_2) = { 514 + .hid_device_event = (void *)inspiroy_2_fix_events, 515 + .hid_rdesc_fixup = (void *)hid_fix_rdesc, 516 + }; 517 + 518 + SEC("syscall") 519 + int probe(struct hid_bpf_probe_args *ctx) 520 + { 521 + switch (ctx->rdesc_size) { 522 + case PAD_REPORT_DESCRIPTOR_LENGTH: 523 + case PEN_REPORT_DESCRIPTOR_LENGTH: 524 + case VENDOR_REPORT_DESCRIPTOR_LENGTH: 525 + ctx->retval = 0; 526 + break; 527 + default: 528 + ctx->retval = -EINVAL; 529 + } 530 + 531 + return 0; 532 + } 533 + 534 + char _license[] SEC("license") = "GPL";
+7 -2
drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c
··· 191 191 0xc0, // End Collection 327 192 192 }; 193 193 194 - SEC("fmod_ret/hid_bpf_rdesc_fixup") 194 + SEC(HID_BPF_RDESC_FIXUP) 195 195 int BPF_PROG(hid_fix_rdesc_huion_kamvas_pro_19, struct hid_bpf_ctx *hctx) 196 196 { 197 197 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */); ··· 215 215 * - if there was this out-of-proximity event, we are entering 216 216 * eraser mode, and we will until the next out-of-proximity. 217 217 */ 218 - SEC("fmod_ret/hid_bpf_device_event") 218 + SEC(HID_BPF_DEVICE_EVENT) 219 219 int BPF_PROG(kamvas_pro_19_fix_3rd_button, struct hid_bpf_ctx *hctx) 220 220 { 221 221 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */); ··· 254 254 255 255 return 0; 256 256 } 257 + 258 + HID_BPF_OPS(huion_Kamvas_pro_19) = { 259 + .hid_rdesc_fixup = (void *)hid_fix_rdesc_huion_kamvas_pro_19, 260 + .hid_device_event = (void *)kamvas_pro_19_fix_3rd_button, 261 + }; 257 262 258 263 SEC("syscall") 259 264 int probe(struct hid_bpf_probe_args *ctx)
+5 -1
drivers/hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c
··· 21 21 * We just fix the report descriptor to enable those missing 7 buttons. 22 22 */ 23 23 24 - SEC("fmod_ret/hid_bpf_rdesc_fixup") 24 + SEC(HID_BPF_RDESC_FIXUP) 25 25 int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx) 26 26 { 27 27 const u8 offsets[] = {84, 112, 140}; ··· 44 44 45 45 return 0; 46 46 } 47 + 48 + HID_BPF_OPS(iogear_kaliber_momentum) = { 49 + .hid_rdesc_fixup = (void *)hid_fix_rdesc, 50 + }; 47 51 48 52 SEC("syscall") 49 53 int probe(struct hid_bpf_probe_args *ctx)
+1 -1
drivers/hid/bpf/progs/Makefile
··· 56 56 57 57 %.bpf.o: %.bpf.c vmlinux.h $(BPFOBJ) | $(OUTPUT) 58 58 $(call msg,BPF,$@) 59 - $(Q)$(CLANG) -g -O2 --target=bpf $(INCLUDES) \ 59 + $(Q)$(CLANG) -g -O2 --target=bpf -Wall -Werror $(INCLUDES) \ 60 60 -c $(filter %.c,$^) -o $@ && \ 61 61 $(LLVM_STRIP) -g $@ 62 62
+12 -9
drivers/hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c drivers/hid/bpf/progs/Microsoft__Xbox-Elite-2.bpf.c
··· 15 15 ); 16 16 17 17 /* 18 - * When using the XBox Wireless Controller Elite 2 over Bluetooth, 19 - * the device exports the paddle on the back of the device as a single 18 + * When using the Xbox Wireless Controller Elite 2 over Bluetooth, 19 + * the device exports the paddles on the back of the device as a single 20 20 * bitfield value of usage "Assign Selection". 21 21 * 22 - * The kernel doesn't process those usages properly and report KEY_UNKNOWN 23 - * for it. 22 + * The kernel doesn't process the paddles usage properly and reports KEY_UNKNOWN. 24 23 * 25 - * SDL doesn't know how to interprete that KEY_UNKNOWN and thus ignores the paddles. 24 + * SDL doesn't know how to interpret KEY_UNKNOWN and thus ignores the paddles. 26 25 * 27 26 * Given that over USB the kernel uses BTN_TRIGGER_HAPPY[5-8], we 28 - * can tweak the report descriptor to make the kernel interprete it properly: 29 - * - we need an application collection of gamepad (so we have to close the current 27 + * can tweak the report descriptor to make the kernel interpret it properly: 28 + * - We need an application collection of gamepad (so we have to close the current 30 29 * Consumer Control one) 31 - * - we need to change the usage to be buttons from 0x15 to 0x18 30 + * - We need to change the usage to be buttons from 0x15 to 0x18 32 31 */ 33 32 34 33 #define OFFSET_ASSIGN_SELECTION 211 ··· 92 93 _Static_assert(sizeof(rdesc_assign_selection) + OFFSET_ASSIGN_SELECTION < ORIGINAL_RDESC_SIZE, 93 94 "Rdesc at given offset is too big"); 94 95 95 - SEC("fmod_ret/hid_bpf_rdesc_fixup") 96 + SEC(HID_BPF_RDESC_FIXUP) 96 97 int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx) 97 98 { 98 99 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */); ··· 112 113 113 114 return 0; 114 115 } 116 + 117 + HID_BPF_OPS(xbox_elite_2) = { 118 + .hid_rdesc_fixup = (void *)hid_fix_rdesc, 119 + }; 115 120 116 121 SEC("syscall") 117 122 int probe(struct hid_bpf_probe_args *ctx)
+144
drivers/hid/bpf/progs/Thrustmaster__TCA-Yoke-Boeing.bpf.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Copyright (c) 2024 Kumar Swarnam Iyer (kumar.s.iyer65@gmail.com) 3 + */ 4 + 5 + #include "vmlinux.h" 6 + #include "hid_bpf.h" 7 + #include "hid_bpf_helpers.h" 8 + #include <bpf/bpf_tracing.h> 9 + 10 + #define VID_THRUSTMASTER 0x044F 11 + #define PID_TCA_YOKE_BOEING 0x0409 12 + 13 + HID_BPF_CONFIG( 14 + HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_THRUSTMASTER, PID_TCA_YOKE_BOEING) 15 + ); 16 + 17 + /* The original HID descriptor of the Thrustmaster TCA Yoke Boeing joystick contains 18 + * an Input field that shows up as an axis, ABS_MISC in Linux. But it is not possible 19 + * to assign an actual physical control to this axis as they're all taken up. There 20 + * are 2 vendor-defined inputs where the Input type appears to be defined wrongly. 21 + * This bpf attempts to fix this by changing the Inputs so that it doesn't show up in 22 + * Linux at all. 23 + * This version is the short version fix that only changes 2 fields in the descriptor 24 + * instead of the whole report descriptor. 25 + * For reference, this is the original report descriptor: 26 + * 27 + * 0x05, 0x01, // Usage Page (Generic Desktop) 0 28 + * 0x09, 0x04, // Usage (Joystick) 2 29 + * 0xa1, 0x01, // Collection (Application) 4 30 + * 0x85, 0x01, // Report ID (1) 6 31 + * 0x09, 0x39, // Usage (Hat switch) 8 32 + * 0x15, 0x00, // Logical Minimum (0) 10 33 + * 0x25, 0x07, // Logical Maximum (7) 12 34 + * 0x35, 0x00, // Physical Minimum (0) 14 35 + * 0x46, 0x3b, 0x01, // Physical Maximum (315) 16 36 + * 0x65, 0x14, // Unit (EnglishRotation: deg) 19 37 + * 0x75, 0x04, // Report Size (4) 21 38 + * 0x95, 0x01, // Report Count (1) 23 39 + * 0x81, 0x42, // Input (Data,Var,Abs,Null) 25 40 + * 0x65, 0x00, // Unit (None) 27 41 + * 0x05, 0x09, // Usage Page (Button) 29 42 + * 0x19, 0x01, // Usage Minimum (1) 31 43 + * 0x29, 0x12, // Usage Maximum (18) 33 44 + * 0x15, 0x00, // Logical Minimum (0) 35 45 + * 0x25, 0x01, // Logical Maximum (1) 37 46 + * 0x75, 0x01, // Report Size (1) 39 47 + * 0x95, 0x12, // Report Count (18) 41 48 + * 0x81, 0x02, // Input (Data,Var,Abs) 43 49 + * 0x95, 0x02, // Report Count (2) 45 50 + * 0x81, 0x03, // Input (Cnst,Var,Abs) 47 51 + * 0x05, 0x01, // Usage Page (Generic Desktop) 49 52 + * 0x09, 0x31, // Usage (Y) 51 53 + * 0x09, 0x30, // Usage (X) 53 54 + * 0x09, 0x32, // Usage (Z) 55 55 + * 0x09, 0x34, // Usage (Ry) 57 56 + * 0x09, 0x33, // Usage (Rx) 59 57 + * 0x09, 0x35, // Usage (Rz) 61 58 + * 0x15, 0x00, // Logical Minimum (0) 63 59 + * 0x27, 0xff, 0xff, 0x00, 0x00, // Logical Maximum (65535) 65 60 + * 0x75, 0x10, // Report Size (16) 70 61 + * 0x95, 0x06, // Report Count (6) 72 62 + * 0x81, 0x02, // Input (Data,Var,Abs) 74 63 + * 0x06, 0xf0, 0xff, // Usage Page (Vendor Usage Page 0xfff0) 76 64 + * 0x09, 0x59, // Usage (Vendor Usage 0x59) 79 65 + * 0x15, 0x00, // Logical Minimum (0) 81 66 + * 0x26, 0xff, 0x00, // Logical Maximum (255) 83 67 + * 0x75, 0x08, // Report Size (8) 86 68 + * 0x95, 0x01, // Report Count (1) 88 69 + * 0x81, 0x02, // Input (Data,Var,Abs) 90 --> Needs to be changed 70 + * 0x09, 0x51, // Usage (Vendor Usage 0x51) 92 71 + * 0x15, 0x00, // Logical Minimum (0) 94 72 + * 0x26, 0xff, 0x00, // Logical Maximum (255) 96 73 + * 0x75, 0x08, // Report Size (8) 99 74 + * 0x95, 0x20, // Report Count (32) 101 --> Needs to be changed 75 + * 0x81, 0x02, // Input (Data,Var,Abs) 103 76 + * 0x09, 0x50, // Usage (Vendor Usage 0x50) 105 77 + * 0x15, 0x00, // Logical Minimum (0) 107 78 + * 0x26, 0xff, 0x00, // Logical Maximum (255) 109 79 + * 0x75, 0x08, // Report Size (8) 112 80 + * 0x95, 0x0f, // Report Count (15) 114 81 + * 0x81, 0x03, // Input (Cnst,Var,Abs) 116 82 + * 0x09, 0x47, // Usage (Vendor Usage 0x47) 118 83 + * 0x85, 0xf2, // Report ID (242) 120 84 + * 0x15, 0x00, // Logical Minimum (0) 122 85 + * 0x26, 0xff, 0x00, // Logical Maximum (255) 124 86 + * 0x75, 0x08, // Report Size (8) 127 87 + * 0x95, 0x3f, // Report Count (63) 129 88 + * 0xb1, 0x02, // Feature (Data,Var,Abs) 131 89 + * 0x09, 0x48, // Usage (Vendor Usage 0x48) 133 90 + * 0x85, 0xf3, // Report ID (243) 135 91 + * 0x15, 0x00, // Logical Minimum (0) 137 92 + * 0x26, 0xff, 0x00, // Logical Maximum (255) 139 93 + * 0x75, 0x08, // Report Size (8) 142 94 + * 0x95, 0x3f, // Report Count (63) 144 95 + * 0xb1, 0x02, // Feature (Data,Var,Abs) 146 96 + * 0xc0, // End Collection 148 97 + */ 98 + 99 + SEC(HID_BPF_RDESC_FIXUP) 100 + int BPF_PROG(hid_fix_rdesc_tca_yoke, struct hid_bpf_ctx *hctx) 101 + { 102 + const int expected_length = 148; 103 + 104 + if (hctx->size != expected_length) 105 + return 0; 106 + 107 + __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */); 108 + 109 + if (!data) 110 + return 0; /* EPERM */ 111 + 112 + /* Safety check, our probe() should take care of this though */ 113 + if (data[1] != 0x01 /* Generic Desktop */ || data[3] != 0x04 /* Joystick */) 114 + return 0; 115 + 116 + /* The report descriptor sets incorrect Input items in 2 places, resulting in a 117 + * non-existing axis showing up. 118 + * This change sets the correct Input which prevents the axis from showing up in Linux. 119 + */ 120 + 121 + if (data[90] == 0x81 && /* Input */ 122 + data[103] == 0x81) { /* Input */ 123 + data[91] = 0x03; /* Input set to 0x03 Constant, Variable Absolute */ 124 + data[104] = 0x03; /* Input set to 0X03 Constant, Variable Absolute */ 125 + } 126 + 127 + return 0; 128 + } 129 + 130 + HID_BPF_OPS(tca_yoke) = { 131 + .hid_rdesc_fixup = (void *)hid_fix_rdesc_tca_yoke, 132 + }; 133 + 134 + SEC("syscall") 135 + int probe(struct hid_bpf_probe_args *ctx) 136 + { 137 + /* ensure the kernel isn't fixed already */ 138 + if (ctx->rdesc[91] != 0x02) /* Input for 0x59 Usage type has changed */ 139 + ctx->retval = -EINVAL; 140 + 141 + return 0; 142 + } 143 + 144 + char _license[] SEC("license") = "GPL";
+5 -1
drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c
··· 101 101 return (__u8 *)get_bits(data, offset); 102 102 } 103 103 104 - SEC("fmod_ret/hid_bpf_device_event") 104 + SEC(HID_BPF_DEVICE_EVENT) 105 105 int BPF_PROG(artpen_pressure_interpolate, struct hid_bpf_ctx *hctx) 106 106 { 107 107 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, PEN_REPORT_LEN /* size */); ··· 138 138 139 139 return 0; 140 140 } 141 + 142 + HID_BPF_OPS(wacom_artpen) = { 143 + .hid_device_event = (void *)artpen_pressure_interpolate, 144 + }; 141 145 142 146 SEC("syscall") 143 147 int probe(struct hid_bpf_probe_args *ctx)
+7 -5
drivers/hid/bpf/progs/XPPen__Artist24.bpf.c
··· 78 78 0xc0, // End Collection 106 79 79 }; 80 80 81 - #define BIT(n) (1UL << n) 82 - 83 81 #define TIP_SWITCH BIT(0) 84 82 #define BARREL_SWITCH BIT(1) 85 83 #define ERASER BIT(2) ··· 89 91 90 92 #define U16(index) (data[index] | (data[index + 1] << 8)) 91 93 92 - SEC("fmod_ret/hid_bpf_rdesc_fixup") 94 + SEC(HID_BPF_RDESC_FIXUP) 93 95 int BPF_PROG(hid_fix_rdesc_xppen_artist24, struct hid_bpf_ctx *hctx) 94 96 { 95 97 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */); ··· 150 152 * E: TipSwitch InRange 151 153 * 152 154 */ 153 - SEC("fmod_ret/hid_bpf_device_event") 155 + SEC(HID_BPF_DEVICE_EVENT) 154 156 int BPF_PROG(xppen_24_fix_eraser, struct hid_bpf_ctx *hctx) 155 157 { 156 158 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */); 157 159 __u8 current_state, changed_state; 158 160 bool prev_tip; 159 - __u16 tilt; 160 161 161 162 if (!data) 162 163 return 0; /* EPERM check */ ··· 205 208 206 209 return 0; 207 210 } 211 + 212 + HID_BPF_OPS(xppen_artist_24) = { 213 + .hid_rdesc_fixup = (void *)hid_fix_rdesc_xppen_artist24, 214 + .hid_device_event = (void *)xppen_24_fix_eraser, 215 + }; 208 216 209 217 SEC("syscall") 210 218 int probe(struct hid_bpf_probe_args *ctx)
+19 -5
drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c
··· 82 82 0xc0, // End Collection 112 83 83 }; 84 84 85 - SEC("fmod_ret/hid_bpf_rdesc_fixup") 85 + SEC(HID_BPF_RDESC_FIXUP) 86 86 int BPF_PROG(hid_fix_rdesc_xppen_artistpro16gen2, struct hid_bpf_ctx *hctx) 87 87 { 88 88 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */); ··· 105 105 return sizeof(fixed_rdesc); 106 106 } 107 107 108 - SEC("fmod_ret/hid_bpf_device_event") 109 - int BPF_PROG(xppen_16_fix_eraser, struct hid_bpf_ctx *hctx) 108 + static int xppen_16_fix_eraser(struct hid_bpf_ctx *hctx) 110 109 { 111 110 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */); 112 111 ··· 206 207 data[idx+1] = coords >> 8; 207 208 } 208 209 209 - SEC("fmod_ret/hid_bpf_device_event") 210 - int BPF_PROG(xppen_16_fix_angle_offset, struct hid_bpf_ctx *hctx) 210 + static int xppen_16_fix_angle_offset(struct hid_bpf_ctx *hctx) 211 211 { 212 212 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */); 213 213 ··· 251 253 252 254 return 0; 253 255 } 256 + 257 + SEC(HID_BPF_DEVICE_EVENT) 258 + int BPF_PROG(xppen_artist_pro_16_device_event, struct hid_bpf_ctx *hctx) 259 + { 260 + int ret = xppen_16_fix_angle_offset(hctx); 261 + 262 + if (ret) 263 + return ret; 264 + 265 + return xppen_16_fix_eraser(hctx); 266 + } 267 + 268 + HID_BPF_OPS(xppen_artist_pro_16) = { 269 + .hid_rdesc_fixup = (void *)hid_fix_rdesc_xppen_artistpro16gen2, 270 + .hid_device_event = (void *)xppen_artist_pro_16_device_event, 271 + }; 254 272 255 273 SEC("syscall") 256 274 int probe(struct hid_bpf_probe_args *ctx)
+231
drivers/hid/bpf/progs/XPPen__DecoMini4.bpf.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Copyright (c) 2024 José Expósito 3 + */ 4 + 5 + #include "vmlinux.h" 6 + #include "hid_bpf.h" 7 + #include "hid_bpf_helpers.h" 8 + #include <bpf/bpf_tracing.h> 9 + 10 + #define VID_UGEE 0x28BD 11 + #define PID_DECO_MINI_4 0x0929 12 + #define RDESC_SIZE_PAD 177 13 + #define RDESC_SIZE_PEN 109 14 + #define PAD_REPORT_ID 0x06 15 + 16 + /* 17 + * XP-Pen devices return a descriptor with the values the driver should use when 18 + * one of its interfaces is queried. For this device the descriptor is: 19 + * 20 + * 0E 03 60 4F 88 3B 06 00 FF 1F D8 13 21 + * ----- ----- ----- ----- 22 + * | | | | 23 + * | | | `- Resolution: 5080 (13d8) 24 + * | | `- Maximum pressure: 8191 (1FFF) 25 + * | `- Logical maximum Y: 15240 (3B88) 26 + * `- Logical maximum X: 20320 (4F60) 27 + * 28 + * The physical maximum is calculated as (logical_max * 1000) / resolution. 29 + */ 30 + #define LOGICAL_MAX_X 0x60, 0x4F 31 + #define LOGICAL_MAX_Y 0x88, 0x3B 32 + #define PHYSICAL_MAX_X 0xA0, 0x0F 33 + #define PHYSICAL_MAX_Y 0xB8, 0x0B 34 + #define PRESSURE_MAX 0xFF, 0x1F 35 + 36 + HID_BPF_CONFIG( 37 + HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_UGEE, PID_DECO_MINI_4) 38 + ); 39 + 40 + /* 41 + * The tablet send these values when the pad buttons are pressed individually: 42 + * 43 + * Buttons released: 06 00 00 00 00 00 00 00 44 + * Button 1: 06 00 05 00 00 00 00 00 -> b 45 + * Button 2: 06 00 08 00 00 00 00 00 -> e 46 + * Button 3: 06 04 00 00 00 00 00 00 -> LAlt 47 + * Button 4: 06 00 2c 00 00 00 00 00 -> Space 48 + * Button 5: 06 01 16 00 00 00 00 00 -> LControl + s 49 + * Button 6: 06 01 1d 00 00 00 00 00 -> LControl + z 50 + * 51 + * When multiple buttons are pressed at the same time, the values used to 52 + * identify the buttons are identical, but they appear in different bytes of the 53 + * record. For example, when button 2 (0x08) and button 1 (0x05) are pressed, 54 + * this is the report: 55 + * 56 + * Buttons 2 and 1: 06 00 08 05 00 00 00 00 -> e + b 57 + * 58 + * Buttons 1, 2, 4, 5 and 6 can be matched by finding their values in the 59 + * report. 60 + * 61 + * Button 3 is pressed when the 3rd bit is 1. For example, pressing buttons 3 62 + * and 5 generates this report: 63 + * 64 + * Buttons 3 and 5: 06 05 16 00 00 00 00 00 -> LControl + LAlt + s 65 + * -- -- 66 + * | | 67 + * | `- Button 5 (0x16) 68 + * `- 0x05 = 0101. Button 3 is pressed 69 + * ^ 70 + * 71 + * pad_buttons contains a list of buttons that can be matched in 72 + * HID_BPF_DEVICE_EVENT. Button 3 as it has a dedicated bit. 73 + */ 74 + static const __u8 pad_buttons[] = { 0x05, 0x08, 0x00, 0x2C, 0x16, 0x1D }; 75 + 76 + static const __u8 fixed_pad_rdesc[] = { 77 + 0x05, 0x01, /* Usage Page (Desktop), */ 78 + 0x09, 0x07, /* Usage (Keypad), */ 79 + 0xA1, 0x01, /* Collection (Application), */ 80 + 0x85, 0x06, /* Report ID (6), */ 81 + 0x05, 0x0D, /* Usage Page (Digitizer), */ 82 + 0x09, 0x39, /* Usage (Tablet Function Keys), */ 83 + 0xA0, /* Collection (Physical), */ 84 + 0x05, 0x09, /* Usage Page (Button), */ 85 + 0x75, 0x01, /* Report Size (1), */ 86 + 0x95, 0x06, /* Report Count (6), */ 87 + 0x19, 0x01, /* Usage Minimum (01h), */ 88 + 0x29, 0x06, /* Usage Maximum (06h), */ 89 + 0x14, /* Logical Minimum (0), */ 90 + 0x25, 0x01, /* Logical Maximum (1), */ 91 + 0x81, 0x02, /* Input (Variable), */ 92 + 0x95, 0x32, /* Report Count (50), */ 93 + 0x81, 0x01, /* Input (Constant), */ 94 + 0xC0, /* End Collection, */ 95 + 0xC0 /* End Collection */ 96 + }; 97 + 98 + static const __u8 fixed_pen_rdesc[] = { 99 + 0x05, 0x0d, /* Usage Page (Digitizers), */ 100 + 0x09, 0x01, /* Usage (Digitizer), */ 101 + 0xa1, 0x01, /* Collection (Application), */ 102 + 0x85, 0x07, /* Report ID (7), */ 103 + 0x09, 0x20, /* Usage (Stylus), */ 104 + 0xa1, 0x00, /* Collection (Physical), */ 105 + 0x09, 0x42, /* Usage (Tip Switch), */ 106 + 0x09, 0x44, /* Usage (Barrel Switch), */ 107 + 0x09, 0x46, /* Usage (Tablet Pick), */ 108 + 0x75, 0x01, /* Report Size (1), */ 109 + 0x95, 0x03, /* Report Count (3), */ 110 + 0x14, /* Logical Minimum (0), */ 111 + 0x25, 0x01, /* Logical Maximum (1), */ 112 + 0x81, 0x02, /* Input (Variable), */ 113 + 0x95, 0x02, /* Report Count (2), */ 114 + 0x81, 0x03, /* Input (Constant, Variable), */ 115 + 0x09, 0x32, /* Usage (In Range), */ 116 + 0x95, 0x01, /* Report Count (1), */ 117 + 0x81, 0x02, /* Input (Variable), */ 118 + 0x95, 0x02, /* Report Count (2), */ 119 + 0x81, 0x03, /* Input (Constant, Variable), */ 120 + 0x75, 0x10, /* Report Size (16), */ 121 + 0x95, 0x01, /* Report Count (1), */ 122 + 0x35, 0x00, /* Physical Minimum (0), */ 123 + 0xa4, /* Push, */ 124 + 0x05, 0x01, /* Usage Page (Desktop), */ 125 + 0x09, 0x30, /* Usage (X), */ 126 + 0x65, 0x13, /* Unit (Inch), */ 127 + 0x55, 0x0d, /* Unit Exponent (-3), */ 128 + 0x26, LOGICAL_MAX_X, /* Logical Maximum, */ 129 + 0x46, PHYSICAL_MAX_X, /* Physical Maximum, */ 130 + 0x81, 0x02, /* Input (Variable), */ 131 + 0x09, 0x31, /* Usage (Y), */ 132 + 0x26, LOGICAL_MAX_Y, /* Logical Maximum, */ 133 + 0x46, PHYSICAL_MAX_Y, /* Physical Maximum, */ 134 + 0x81, 0x02, /* Input (Variable), */ 135 + 0xb4, /* Pop, */ 136 + 0x09, 0x30, /* Usage (Tip Pressure), */ 137 + 0x45, 0x00, /* Physical Maximum (0), */ 138 + 0x26, PRESSURE_MAX, /* Logical Maximum, */ 139 + 0x75, 0x0D, /* Report Size (13), */ 140 + 0x95, 0x01, /* Report Count (1), */ 141 + 0x81, 0x02, /* Input (Variable), */ 142 + 0x75, 0x01, /* Report Size (1), */ 143 + 0x95, 0x13, /* Report Count (19), */ 144 + 0x81, 0x01, /* Input (Constant), */ 145 + 0xc0, /* End Collection, */ 146 + 0xc0, /* End Collection */ 147 + }; 148 + 149 + static const size_t fixed_pad_rdesc_size = sizeof(fixed_pad_rdesc); 150 + static const size_t fixed_pen_rdesc_size = sizeof(fixed_pen_rdesc); 151 + 152 + SEC(HID_BPF_RDESC_FIXUP) 153 + int BPF_PROG(hid_rdesc_fixup_xppen_deco_mini_4, struct hid_bpf_ctx *hctx) 154 + { 155 + __u8 *data = hid_bpf_get_data(hctx, 0, HID_MAX_DESCRIPTOR_SIZE); 156 + 157 + if (!data) 158 + return 0; /* EPERM check */ 159 + 160 + if (hctx->size == RDESC_SIZE_PAD) { 161 + __builtin_memcpy(data, fixed_pad_rdesc, fixed_pad_rdesc_size); 162 + return fixed_pad_rdesc_size; 163 + } else if (hctx->size == RDESC_SIZE_PEN) { 164 + __builtin_memcpy(data, fixed_pen_rdesc, fixed_pen_rdesc_size); 165 + return fixed_pen_rdesc_size; 166 + } 167 + 168 + return 0; 169 + } 170 + 171 + SEC(HID_BPF_DEVICE_EVENT) 172 + int BPF_PROG(hid_device_event_xppen_deco_mini_4, struct hid_bpf_ctx *hctx) 173 + { 174 + __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 8 /* size */); 175 + __u8 button_mask = 0; 176 + int d, b; 177 + 178 + if (!data) 179 + return 0; /* EPERM check */ 180 + 181 + if (data[0] != PAD_REPORT_ID) 182 + return 0; 183 + 184 + /* data[1] stores the status of BTN_2 in the 3rd bit*/ 185 + if (data[1] & BIT(2)) 186 + button_mask |= BIT(2); 187 + 188 + /* The rest of the descriptor stores the buttons as in pad_buttons */ 189 + for (d = 2; d < 8; d++) { 190 + for (b = 0; b < sizeof(pad_buttons); b++) { 191 + if (data[d] != 0 && data[d] == pad_buttons[b]) 192 + button_mask |= BIT(b); 193 + } 194 + } 195 + 196 + __u8 report[8] = {PAD_REPORT_ID, button_mask, 0x00}; 197 + 198 + __builtin_memcpy(data, report, sizeof(report)); 199 + 200 + return 0; 201 + } 202 + 203 + HID_BPF_OPS(deco_mini_4) = { 204 + .hid_device_event = (void *)hid_device_event_xppen_deco_mini_4, 205 + .hid_rdesc_fixup = (void *)hid_rdesc_fixup_xppen_deco_mini_4, 206 + }; 207 + 208 + SEC("syscall") 209 + int probe(struct hid_bpf_probe_args *ctx) 210 + { 211 + /* 212 + * The device has 2 modes: The compatibility mode, enabled by default, 213 + * and the raw mode, that can be activated by sending a buffer of magic 214 + * data to a certain USB endpoint. 215 + * 216 + * Depending on the mode, different interfaces of the device are used: 217 + * - First interface: Pad in compatibility mode 218 + * - Second interface: Pen in compatibility mode 219 + * - Third interface: Only used in raw mode 220 + * 221 + * We'll use the device in compatibility mode. 222 + */ 223 + ctx->retval = ctx->rdesc_size != RDESC_SIZE_PAD && 224 + ctx->rdesc_size != RDESC_SIZE_PEN; 225 + if (ctx->retval) 226 + ctx->retval = -EINVAL; 227 + 228 + return 0; 229 + } 230 + 231 + char _license[] SEC("license") = "GPL";
+6
drivers/hid/bpf/progs/hid_bpf.h
··· 5 5 #ifndef ____HID_BPF__H 6 6 #define ____HID_BPF__H 7 7 8 + #define HID_BPF_DEVICE_EVENT "struct_ops/hid_device_event" 9 + #define HID_BPF_RDESC_FIXUP "struct_ops/hid_rdesc_fixup" 10 + #define HID_BPF_OPS(name) SEC(".struct_ops.link") \ 11 + struct hid_bpf_ops name 12 + #define hid_set_name(_hdev, _name) __builtin_memcpy(_hdev->name, _name, sizeof(_name)) 13 + 8 14 struct hid_bpf_probe_args { 9 15 unsigned int hid; 10 16 unsigned int rdesc_size;
+1
drivers/hid/bpf/progs/hid_bpf_helpers.h
··· 66 66 #define HID_VID_ANY 0x0000 67 67 #define HID_PID_ANY 0x0000 68 68 69 + #define BIT(n) (1UL << (n)) 69 70 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 70 71 71 72 /* Helper macro to convert (foo, __LINE__) into foo134 so we can use __LINE__ for
+2960
drivers/hid/bpf/progs/hid_report_helpers.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* Copyright (c) 2024 Red Hat, Inc 3 + */ 4 + 5 + // THIS FILE IS GENERATED, DO NOT EDIT 6 + 7 + #pragma once 8 + 9 + 10 + /* Macros for composing HID reports. 11 + * 12 + * HID Fields are added manually to the template, please add to it as needed 13 + * for any individual device. The Usage Pages and Usages are generated. 14 + * 15 + * Some macros have a _i8, _i16, or _i32 suffix. Pick the 16 + * right suffix given the passed-in value. 17 + */ 18 + 19 + /* 20 + * This macro behaves like static_assert(), failing to 21 + * compile if its argument is not true. However, it always 22 + * returns 0, which allows using it everywhere an expression 23 + * can be used. 24 + */ 25 + #define must_be(e, msg_) \ 26 + ( \ 27 + 0 * (int) sizeof( \ 28 + struct { \ 29 + _Static_assert(e, msg_); \ 30 + int ISO_C_forbids_a_struct_with_no_members; \ 31 + } \ 32 + ) \ 33 + ) 34 + 35 + /* Ensure the given value fits within 8/16/32 bits */ 36 + #define i4(v_) (((__u8)(v_) & 0xf) + must_be((v_) >= -0x8 && (v_) <= 0x7, "not a i4")) 37 + #define i8(v_) ((__u8)(v_) + must_be((v_) >= -0x80 && (v_) <= 0xff, "not a i8/u8")) 38 + #define i16(v_) ((__u16)(v_) + must_be((v_) >= -0x8000 && (v_) <= 0xffff, "not a i16/u16")) 39 + #define i32(v_) ((__u32)(v_) + must_be((v_) >= -0x80000000L && (v_) <= 0xffffffffL, \ 40 + "not a i32/u16")) 41 + 42 + /* Split a value across multiple bytes in LE order */ 43 + #define LE16(v_) i16(v_) & 0xff, ((v_) >> 8) & 0xff 44 + #define LE32(v_) i32(v_) & 0xff, ((v_) >> 8) & 0xff, ((v_) >> 16) & 0xff, ((v_) >> 24) & 0xff 45 + 46 + /* Collections require two items in the report descriptor, the start 47 + * of the collection (0xa?) and the EndCollection item (0xc?). 48 + * This macro provides both, use like this: 49 + * 50 + * static const __u8 fixed_rdesc[] = { 51 + * UsagePage_Generic_Desktop 52 + * Usage_GD_Keyboard 53 + * CollectionApplication( ← Open the collection 54 + * ReportId(3) 55 + * LogicalRange_i8(0, 1) 56 + * // other fields 57 + * ) ← End EndCollection 58 + * 59 + * Collections may be nested. 60 + */ 61 + #define Collection(col_, ...) 0xa1, i8(col_), __VA_ARGS__ 0xc0, 62 + #define CollectionPhysical(...) Collection(0x00, __VA_ARGS__) 63 + #define CollectionApplication(...) Collection(0x01, __VA_ARGS__) 64 + #define CollectionLogical(...) Collection(0x02, __VA_ARGS__) 65 + 66 + /* See Collections, this macro provides Push and Pop with 67 + * elements in between 68 + */ 69 + #define PushPop(...) 0xa4, __VA_ARGS__ 0xb4, 70 + 71 + /* Arguments to use in bitwise-or for Input, Output, Feature */ 72 + #define Const 0x1 73 + #define Var 0x2 74 + #define Arr 0x0 75 + #define Abs 0x0 76 + #define Rel 0x4 77 + 78 + /* Use like this: Input(Var|Abs) */ 79 + #define Input(i_) 0x081, i8(i_), 80 + #define Output(i_) 0x091, i8(i_), 81 + #define Feature(i_) 0x0b1, i8(i_), 82 + 83 + #define ReportId(id_) 0x85, i8(id_), 84 + #define ReportSize(sz_) 0x75, i8(sz_), 85 + #define ReportCount(cnt_) 0x95, i8(cnt_), 86 + 87 + #define LogicalRange_i8(min_, max_) 0x15, i8(min_), 0x25, i8(max_), 88 + #define LogicalRange_i16(min_, max_) 0x16, LE16(min_), 0x26, LE16(max_), 89 + #define LogicalRange_i32(min_, max_) 0x17, LE32(min_), 0x27, LE32(max_), 90 + 91 + #define PhysicalRange_i8(min_, max_) 0x35, i8(min_), 0x45, i8(max_), 92 + #define PhysicalRange_i16(min_, max_) 0x36, LE16(min_), 0x46, LE16(max_), 93 + #define PhysicalRange_i32(min_, max_) 0x37, LE32(min_), 0x47, LE32(max_), 94 + 95 + #define UsageRange_i8(min_, max_) 0x19, i8(min_), 0x29, i8(max_), 96 + #define UsageRange_i16(min_, max_) 0x1a, LE16(min_), 0x2a, LE16(max_), 97 + 98 + #define UsagePage_i8(p_) 0x05, i8(p_), 99 + #define UsagePage_i16(p_) 0x06, LE16(p_), 100 + 101 + #define Usage_i8(u_) 0x09, i8(u_), 102 + #define Usage_i16(u_) 0x0a, LE16(u_), 103 + #define Usage_i32(u_) 0x0b, LE32(u_), 104 + 105 + #define SILinear 0x1 106 + #define SIRotation 0x2 107 + #define EnglishLinear 0x3 108 + #define EnglishRotation 0x4 109 + #define cm (SILinear | (0x1 << 4)) 110 + #define rad (SIRotation | (0x1 << 4)) 111 + #define deg (EnglishRotation | (0x1 << 4)) 112 + #define in (EnglishLinear | (0x1 << 4)) 113 + /* Use as Unit(cm) or Unit(rad) or similar. 114 + * This macro currently defaults to exponent 1 only, so no 115 + * cm^2 or others 116 + */ 117 + #define Unit(u_) Unit_i8(u_) 118 + #define Unit_i8(u_) 0x65, i8(u_), 119 + #define Unit_i16(u_) 0x66, i16(u_), 120 + #define Unit_i32(u_) 0x67, i32(u_), 121 + 122 + #define UnitExponent(u_) 0x55, i4(u_), 123 + 124 + /* A macro to generate a vendor-specific padding-only 125 + * report with Report ID 0xac of the given size in bytes. 126 + * The size is inclusive of the 1 byte Report ID prefix. 127 + * 128 + * HID-BPF requires that at least one report has 129 + * the same size as the original report from the device. 130 + * The easy way to ensure that is to add this 131 + * macro as the last element of your CollectionApplication 132 + * other reports can be of any size less than this. 133 + * 134 + * e.g. 135 + * static __u8 fixed_rdesc = [ 136 + * UsagePage_Generic_Desktop 137 + * Usage_GD_Keyboard 138 + * CollectionApplication( 139 + * ... intended rdesc items go here ... 140 + * FixedSizeVendorReport(12) 141 + * ) 142 + * ]; 143 + * 144 + * If the FixedSizeVendorReport is placed outside 145 + * a CollectionApplication it will result in 146 + * an extra useless evdev node being created. 147 + */ 148 + #define FixedSizeVendorReport(bytes_) \ 149 + UsagePage_Vendor(0xffff) \ 150 + Usage_i8(0x01) \ 151 + CollectionPhysical( \ 152 + ReportId(0xac) \ 153 + ReportSize(8) \ 154 + ReportCount((bytes_) - 1) \ 155 + Input(Const) \ 156 + ) 157 + 158 + /* ----- Generated Usage Pages and Usages ------ */ 159 + #define UsagePage_GenericDesktop UsagePage_i8(0x1) 160 + #define UsagePage_SimulationControls UsagePage_i8(0x2) 161 + #define UsagePage_VRControls UsagePage_i8(0x3) 162 + #define UsagePage_SportControls UsagePage_i8(0x4) 163 + #define UsagePage_GameControls UsagePage_i8(0x5) 164 + #define UsagePage_GenericDeviceControls UsagePage_i8(0x6) 165 + #define UsagePage_KeyboardKeypad UsagePage_i8(0x7) 166 + #define UsagePage_LED UsagePage_i8(0x8) 167 + #define UsagePage_Button UsagePage_i8(0x9) 168 + #define UsagePage_Ordinal UsagePage_i8(0xa) 169 + #define UsagePage_TelephonyDevice UsagePage_i8(0xb) 170 + #define UsagePage_Consumer UsagePage_i8(0xc) 171 + #define UsagePage_Digitizers UsagePage_i8(0xd) 172 + #define UsagePage_Haptics UsagePage_i8(0xe) 173 + #define UsagePage_PhysicalInputDevice UsagePage_i8(0xf) 174 + #define UsagePage_Unicode UsagePage_i8(0x10) 175 + #define UsagePage_SoC UsagePage_i8(0x11) 176 + #define UsagePage_EyeandHeadTrackers UsagePage_i8(0x12) 177 + #define UsagePage_AuxiliaryDisplay UsagePage_i8(0x14) 178 + #define UsagePage_Sensors UsagePage_i8(0x20) 179 + #define UsagePage_MedicalInstrument UsagePage_i8(0x40) 180 + #define UsagePage_BrailleDisplay UsagePage_i8(0x41) 181 + #define UsagePage_LightingAndIllumination UsagePage_i8(0x59) 182 + #define UsagePage_Monitor UsagePage_i8(0x80) 183 + #define UsagePage_MonitorEnumerated UsagePage_i8(0x81) 184 + #define UsagePage_VESAVirtualControls UsagePage_i8(0x82) 185 + #define UsagePage_Power UsagePage_i8(0x84) 186 + #define UsagePage_BatterySystem UsagePage_i8(0x85) 187 + #define UsagePage_BarcodeScanner UsagePage_i8(0x8c) 188 + #define UsagePage_Scales UsagePage_i8(0x8d) 189 + #define UsagePage_MagneticStripeReader UsagePage_i8(0x8e) 190 + #define UsagePage_CameraControl UsagePage_i8(0x90) 191 + #define UsagePage_Arcade UsagePage_i8(0x91) 192 + #define UsagePage_FIDOAlliance UsagePage_i16(0xf1d0) 193 + #define UsagePage_Vendor(u_) \ 194 + UsagePage_i16((u_) + must_be(((u_) & 0xff00) == 0xff00, "not a 0xff00 vendor page")) 195 + 196 + #define Usage_GD_Pointer Usage_i8(0x1) 197 + #define Usage_GD_Mouse Usage_i8(0x2) 198 + #define Usage_GD_Joystick Usage_i8(0x4) 199 + #define Usage_GD_Gamepad Usage_i8(0x5) 200 + #define Usage_GD_Keyboard Usage_i8(0x6) 201 + #define Usage_GD_Keypad Usage_i8(0x7) 202 + #define Usage_GD_MultiaxisController Usage_i8(0x8) 203 + #define Usage_GD_TabletPCSystemControls Usage_i8(0x9) 204 + #define Usage_GD_WaterCoolingDevice Usage_i8(0xa) 205 + #define Usage_GD_ComputerChassisDevice Usage_i8(0xb) 206 + #define Usage_GD_WirelessRadioControls Usage_i8(0xc) 207 + #define Usage_GD_PortableDeviceControl Usage_i8(0xd) 208 + #define Usage_GD_SystemMultiAxisController Usage_i8(0xe) 209 + #define Usage_GD_SpatialController Usage_i8(0xf) 210 + #define Usage_GD_AssistiveControl Usage_i8(0x10) 211 + #define Usage_GD_DeviceDock Usage_i8(0x11) 212 + #define Usage_GD_DockableDevice Usage_i8(0x12) 213 + #define Usage_GD_CallStateManagementControl Usage_i8(0x13) 214 + #define Usage_GD_X Usage_i8(0x30) 215 + #define Usage_GD_Y Usage_i8(0x31) 216 + #define Usage_GD_Z Usage_i8(0x32) 217 + #define Usage_GD_Rx Usage_i8(0x33) 218 + #define Usage_GD_Ry Usage_i8(0x34) 219 + #define Usage_GD_Rz Usage_i8(0x35) 220 + #define Usage_GD_Slider Usage_i8(0x36) 221 + #define Usage_GD_Dial Usage_i8(0x37) 222 + #define Usage_GD_Wheel Usage_i8(0x38) 223 + #define Usage_GD_HatSwitch Usage_i8(0x39) 224 + #define Usage_GD_CountedBuffer Usage_i8(0x3a) 225 + #define Usage_GD_ByteCount Usage_i8(0x3b) 226 + #define Usage_GD_MotionWakeup Usage_i8(0x3c) 227 + #define Usage_GD_Start Usage_i8(0x3d) 228 + #define Usage_GD_Select Usage_i8(0x3e) 229 + #define Usage_GD_Vx Usage_i8(0x40) 230 + #define Usage_GD_Vy Usage_i8(0x41) 231 + #define Usage_GD_Vz Usage_i8(0x42) 232 + #define Usage_GD_Vbrx Usage_i8(0x43) 233 + #define Usage_GD_Vbry Usage_i8(0x44) 234 + #define Usage_GD_Vbrz Usage_i8(0x45) 235 + #define Usage_GD_Vno Usage_i8(0x46) 236 + #define Usage_GD_FeatureNotification Usage_i8(0x47) 237 + #define Usage_GD_ResolutionMultiplier Usage_i8(0x48) 238 + #define Usage_GD_Qx Usage_i8(0x49) 239 + #define Usage_GD_Qy Usage_i8(0x4a) 240 + #define Usage_GD_Qz Usage_i8(0x4b) 241 + #define Usage_GD_Qw Usage_i8(0x4c) 242 + #define Usage_GD_SystemControl Usage_i8(0x80) 243 + #define Usage_GD_SystemPowerDown Usage_i8(0x81) 244 + #define Usage_GD_SystemSleep Usage_i8(0x82) 245 + #define Usage_GD_SystemWakeUp Usage_i8(0x83) 246 + #define Usage_GD_SystemContextMenu Usage_i8(0x84) 247 + #define Usage_GD_SystemMainMenu Usage_i8(0x85) 248 + #define Usage_GD_SystemAppMenu Usage_i8(0x86) 249 + #define Usage_GD_SystemMenuHelp Usage_i8(0x87) 250 + #define Usage_GD_SystemMenuExit Usage_i8(0x88) 251 + #define Usage_GD_SystemMenuSelect Usage_i8(0x89) 252 + #define Usage_GD_SystemMenuRight Usage_i8(0x8a) 253 + #define Usage_GD_SystemMenuLeft Usage_i8(0x8b) 254 + #define Usage_GD_SystemMenuUp Usage_i8(0x8c) 255 + #define Usage_GD_SystemMenuDown Usage_i8(0x8d) 256 + #define Usage_GD_SystemColdRestart Usage_i8(0x8e) 257 + #define Usage_GD_SystemWarmRestart Usage_i8(0x8f) 258 + #define Usage_GD_DpadUp Usage_i8(0x90) 259 + #define Usage_GD_DpadDown Usage_i8(0x91) 260 + #define Usage_GD_DpadRight Usage_i8(0x92) 261 + #define Usage_GD_DpadLeft Usage_i8(0x93) 262 + #define Usage_GD_IndexTrigger Usage_i8(0x94) 263 + #define Usage_GD_PalmTrigger Usage_i8(0x95) 264 + #define Usage_GD_Thumbstick Usage_i8(0x96) 265 + #define Usage_GD_SystemFunctionShift Usage_i8(0x97) 266 + #define Usage_GD_SystemFunctionShiftLock Usage_i8(0x98) 267 + #define Usage_GD_SystemFunctionShiftLockIndicator Usage_i8(0x99) 268 + #define Usage_GD_SystemDismissNotification Usage_i8(0x9a) 269 + #define Usage_GD_SystemDoNotDisturb Usage_i8(0x9b) 270 + #define Usage_GD_SystemDock Usage_i8(0xa0) 271 + #define Usage_GD_SystemUndock Usage_i8(0xa1) 272 + #define Usage_GD_SystemSetup Usage_i8(0xa2) 273 + #define Usage_GD_SystemBreak Usage_i8(0xa3) 274 + #define Usage_GD_SystemDebuggerBreak Usage_i8(0xa4) 275 + #define Usage_GD_ApplicationBreak Usage_i8(0xa5) 276 + #define Usage_GD_ApplicationDebuggerBreak Usage_i8(0xa6) 277 + #define Usage_GD_SystemSpeakerMute Usage_i8(0xa7) 278 + #define Usage_GD_SystemHibernate Usage_i8(0xa8) 279 + #define Usage_GD_SystemMicrophoneMute Usage_i8(0xa9) 280 + #define Usage_GD_SystemDisplayInvert Usage_i8(0xb0) 281 + #define Usage_GD_SystemDisplayInternal Usage_i8(0xb1) 282 + #define Usage_GD_SystemDisplayExternal Usage_i8(0xb2) 283 + #define Usage_GD_SystemDisplayBoth Usage_i8(0xb3) 284 + #define Usage_GD_SystemDisplayDual Usage_i8(0xb4) 285 + #define Usage_GD_SystemDisplayToggleIntExtMode Usage_i8(0xb5) 286 + #define Usage_GD_SystemDisplaySwapPrimarySecondary Usage_i8(0xb6) 287 + #define Usage_GD_SystemDisplayToggleLCDAutoscale Usage_i8(0xb7) 288 + #define Usage_GD_SensorZone Usage_i8(0xc0) 289 + #define Usage_GD_RPM Usage_i8(0xc1) 290 + #define Usage_GD_CoolantLevel Usage_i8(0xc2) 291 + #define Usage_GD_CoolantCriticalLevel Usage_i8(0xc3) 292 + #define Usage_GD_CoolantPump Usage_i8(0xc4) 293 + #define Usage_GD_ChassisEnclosure Usage_i8(0xc5) 294 + #define Usage_GD_WirelessRadioButton Usage_i8(0xc6) 295 + #define Usage_GD_WirelessRadioLED Usage_i8(0xc7) 296 + #define Usage_GD_WirelessRadioSliderSwitch Usage_i8(0xc8) 297 + #define Usage_GD_SystemDisplayRotationLockButton Usage_i8(0xc9) 298 + #define Usage_GD_SystemDisplayRotationLockSliderSwitch Usage_i8(0xca) 299 + #define Usage_GD_ControlEnable Usage_i8(0xcb) 300 + #define Usage_GD_DockableDeviceUniqueID Usage_i8(0xd0) 301 + #define Usage_GD_DockableDeviceVendorID Usage_i8(0xd1) 302 + #define Usage_GD_DockableDevicePrimaryUsagePage Usage_i8(0xd2) 303 + #define Usage_GD_DockableDevicePrimaryUsageID Usage_i8(0xd3) 304 + #define Usage_GD_DockableDeviceDockingState Usage_i8(0xd4) 305 + #define Usage_GD_DockableDeviceDisplayOcclusion Usage_i8(0xd5) 306 + #define Usage_GD_DockableDeviceObjectType Usage_i8(0xd6) 307 + #define Usage_GD_CallActiveLED Usage_i8(0xe0) 308 + #define Usage_GD_CallMuteToggle Usage_i8(0xe1) 309 + #define Usage_GD_CallMuteLED Usage_i8(0xe2) 310 + #define Usage_SC_FlightSimulationDevice Usage_i8(0x1) 311 + #define Usage_SC_AutomobileSimulationDevice Usage_i8(0x2) 312 + #define Usage_SC_TankSimulationDevice Usage_i8(0x3) 313 + #define Usage_SC_SpaceshipSimulationDevice Usage_i8(0x4) 314 + #define Usage_SC_SubmarineSimulationDevice Usage_i8(0x5) 315 + #define Usage_SC_SailingSimulationDevice Usage_i8(0x6) 316 + #define Usage_SC_MotorcycleSimulationDevice Usage_i8(0x7) 317 + #define Usage_SC_SportsSimulationDevice Usage_i8(0x8) 318 + #define Usage_SC_AirplaneSimulationDevice Usage_i8(0x9) 319 + #define Usage_SC_HelicopterSimulationDevice Usage_i8(0xa) 320 + #define Usage_SC_MagicCarpetSimulationDevice Usage_i8(0xb) 321 + #define Usage_SC_BicycleSimulationDevice Usage_i8(0xc) 322 + #define Usage_SC_FlightControlStick Usage_i8(0x20) 323 + #define Usage_SC_FlightStick Usage_i8(0x21) 324 + #define Usage_SC_CyclicControl Usage_i8(0x22) 325 + #define Usage_SC_CyclicTrim Usage_i8(0x23) 326 + #define Usage_SC_FlightYoke Usage_i8(0x24) 327 + #define Usage_SC_TrackControl Usage_i8(0x25) 328 + #define Usage_SC_Aileron Usage_i8(0xb0) 329 + #define Usage_SC_AileronTrim Usage_i8(0xb1) 330 + #define Usage_SC_AntiTorqueControl Usage_i8(0xb2) 331 + #define Usage_SC_AutopilotEnable Usage_i8(0xb3) 332 + #define Usage_SC_ChaffRelease Usage_i8(0xb4) 333 + #define Usage_SC_CollectiveControl Usage_i8(0xb5) 334 + #define Usage_SC_DiveBrake Usage_i8(0xb6) 335 + #define Usage_SC_ElectronicCountermeasures Usage_i8(0xb7) 336 + #define Usage_SC_Elevator Usage_i8(0xb8) 337 + #define Usage_SC_ElevatorTrim Usage_i8(0xb9) 338 + #define Usage_SC_Rudder Usage_i8(0xba) 339 + #define Usage_SC_Throttle Usage_i8(0xbb) 340 + #define Usage_SC_FlightCommunications Usage_i8(0xbc) 341 + #define Usage_SC_FlareRelease Usage_i8(0xbd) 342 + #define Usage_SC_LandingGear Usage_i8(0xbe) 343 + #define Usage_SC_ToeBrake Usage_i8(0xbf) 344 + #define Usage_SC_Trigger Usage_i8(0xc0) 345 + #define Usage_SC_WeaponsArm Usage_i8(0xc1) 346 + #define Usage_SC_WeaponsSelect Usage_i8(0xc2) 347 + #define Usage_SC_WingFlaps Usage_i8(0xc3) 348 + #define Usage_SC_Accelerator Usage_i8(0xc4) 349 + #define Usage_SC_Brake Usage_i8(0xc5) 350 + #define Usage_SC_Clutch Usage_i8(0xc6) 351 + #define Usage_SC_Shifter Usage_i8(0xc7) 352 + #define Usage_SC_Steering Usage_i8(0xc8) 353 + #define Usage_SC_TurretDirection Usage_i8(0xc9) 354 + #define Usage_SC_BarrelElevation Usage_i8(0xca) 355 + #define Usage_SC_DivePlane Usage_i8(0xcb) 356 + #define Usage_SC_Ballast Usage_i8(0xcc) 357 + #define Usage_SC_BicycleCrank Usage_i8(0xcd) 358 + #define Usage_SC_HandleBars Usage_i8(0xce) 359 + #define Usage_SC_FrontBrake Usage_i8(0xcf) 360 + #define Usage_SC_RearBrake Usage_i8(0xd0) 361 + #define Usage_VRC_Belt Usage_i8(0x1) 362 + #define Usage_VRC_BodySuit Usage_i8(0x2) 363 + #define Usage_VRC_Flexor Usage_i8(0x3) 364 + #define Usage_VRC_Glove Usage_i8(0x4) 365 + #define Usage_VRC_HeadTracker Usage_i8(0x5) 366 + #define Usage_VRC_HeadMountedDisplay Usage_i8(0x6) 367 + #define Usage_VRC_HandTracker Usage_i8(0x7) 368 + #define Usage_VRC_Oculometer Usage_i8(0x8) 369 + #define Usage_VRC_Vest Usage_i8(0x9) 370 + #define Usage_VRC_AnimatronicDevice Usage_i8(0xa) 371 + #define Usage_VRC_StereoEnable Usage_i8(0x20) 372 + #define Usage_VRC_DisplayEnable Usage_i8(0x21) 373 + #define Usage_SC_BaseballBat Usage_i8(0x1) 374 + #define Usage_SC_GolfClub Usage_i8(0x2) 375 + #define Usage_SC_RowingMachine Usage_i8(0x3) 376 + #define Usage_SC_Treadmill Usage_i8(0x4) 377 + #define Usage_SC_Oar Usage_i8(0x30) 378 + #define Usage_SC_Slope Usage_i8(0x31) 379 + #define Usage_SC_Rate Usage_i8(0x32) 380 + #define Usage_SC_StickSpeed Usage_i8(0x33) 381 + #define Usage_SC_StickFaceAngle Usage_i8(0x34) 382 + #define Usage_SC_StickHeelToe Usage_i8(0x35) 383 + #define Usage_SC_StickFollowThrough Usage_i8(0x36) 384 + #define Usage_SC_StickTempo Usage_i8(0x37) 385 + #define Usage_SC_StickType Usage_i8(0x38) 386 + #define Usage_SC_StickHeight Usage_i8(0x39) 387 + #define Usage_SC_Putter Usage_i8(0x50) 388 + #define Usage_SC_OneIron Usage_i8(0x51) 389 + #define Usage_SC_TwoIron Usage_i8(0x52) 390 + #define Usage_SC_ThreeIron Usage_i8(0x53) 391 + #define Usage_SC_FourIron Usage_i8(0x54) 392 + #define Usage_SC_FiveIron Usage_i8(0x55) 393 + #define Usage_SC_SixIron Usage_i8(0x56) 394 + #define Usage_SC_SevenIron Usage_i8(0x57) 395 + #define Usage_SC_EightIron Usage_i8(0x58) 396 + #define Usage_SC_NineIron Usage_i8(0x59) 397 + #define Usage_SC_One0Iron Usage_i8(0x5a) 398 + #define Usage_SC_One1Iron Usage_i8(0x5b) 399 + #define Usage_SC_SandWedge Usage_i8(0x5c) 400 + #define Usage_SC_LoftWedge Usage_i8(0x5d) 401 + #define Usage_SC_PowerWedge Usage_i8(0x5e) 402 + #define Usage_SC_OneWood Usage_i8(0x5f) 403 + #define Usage_SC_ThreeWood Usage_i8(0x60) 404 + #define Usage_SC_FiveWood Usage_i8(0x61) 405 + #define Usage_SC_SevenWood Usage_i8(0x62) 406 + #define Usage_SC_NineWood Usage_i8(0x63) 407 + #define Usage_GC_ThreeDGameController Usage_i8(0x1) 408 + #define Usage_GC_PinballDevice Usage_i8(0x2) 409 + #define Usage_GC_GunDevice Usage_i8(0x3) 410 + #define Usage_GC_PointofView Usage_i8(0x20) 411 + #define Usage_GC_TurnRightLeft Usage_i8(0x21) 412 + #define Usage_GC_PitchForwardBackward Usage_i8(0x22) 413 + #define Usage_GC_RollRightLeft Usage_i8(0x23) 414 + #define Usage_GC_MoveRightLeft Usage_i8(0x24) 415 + #define Usage_GC_MoveForwardBackward Usage_i8(0x25) 416 + #define Usage_GC_MoveUpDown Usage_i8(0x26) 417 + #define Usage_GC_LeanRightLeft Usage_i8(0x27) 418 + #define Usage_GC_LeanForwardBackward Usage_i8(0x28) 419 + #define Usage_GC_HeightofPOV Usage_i8(0x29) 420 + #define Usage_GC_Flipper Usage_i8(0x2a) 421 + #define Usage_GC_SecondaryFlipper Usage_i8(0x2b) 422 + #define Usage_GC_Bump Usage_i8(0x2c) 423 + #define Usage_GC_NewGame Usage_i8(0x2d) 424 + #define Usage_GC_ShootBall Usage_i8(0x2e) 425 + #define Usage_GC_Player Usage_i8(0x2f) 426 + #define Usage_GC_GunBolt Usage_i8(0x30) 427 + #define Usage_GC_GunClip Usage_i8(0x31) 428 + #define Usage_GC_GunSelector Usage_i8(0x32) 429 + #define Usage_GC_GunSingleShot Usage_i8(0x33) 430 + #define Usage_GC_GunBurst Usage_i8(0x34) 431 + #define Usage_GC_GunAutomatic Usage_i8(0x35) 432 + #define Usage_GC_GunSafety Usage_i8(0x36) 433 + #define Usage_GC_GamepadFireJump Usage_i8(0x37) 434 + #define Usage_GC_GamepadTrigger Usage_i8(0x39) 435 + #define Usage_GC_FormfittingGamepad Usage_i8(0x3a) 436 + #define Usage_GDC_BackgroundNonuserControls Usage_i8(0x1) 437 + #define Usage_GDC_BatteryStrength Usage_i8(0x20) 438 + #define Usage_GDC_WirelessChannel Usage_i8(0x21) 439 + #define Usage_GDC_WirelessID Usage_i8(0x22) 440 + #define Usage_GDC_DiscoverWirelessControl Usage_i8(0x23) 441 + #define Usage_GDC_SecurityCodeCharacterEntered Usage_i8(0x24) 442 + #define Usage_GDC_SecurityCodeCharacterErased Usage_i8(0x25) 443 + #define Usage_GDC_SecurityCodeCleared Usage_i8(0x26) 444 + #define Usage_GDC_SequenceID Usage_i8(0x27) 445 + #define Usage_GDC_SequenceIDReset Usage_i8(0x28) 446 + #define Usage_GDC_RFSignalStrength Usage_i8(0x29) 447 + #define Usage_GDC_SoftwareVersion Usage_i8(0x2a) 448 + #define Usage_GDC_ProtocolVersion Usage_i8(0x2b) 449 + #define Usage_GDC_HardwareVersion Usage_i8(0x2c) 450 + #define Usage_GDC_Major Usage_i8(0x2d) 451 + #define Usage_GDC_Minor Usage_i8(0x2e) 452 + #define Usage_GDC_Revision Usage_i8(0x2f) 453 + #define Usage_GDC_Handedness Usage_i8(0x30) 454 + #define Usage_GDC_EitherHand Usage_i8(0x31) 455 + #define Usage_GDC_LeftHand Usage_i8(0x32) 456 + #define Usage_GDC_RightHand Usage_i8(0x33) 457 + #define Usage_GDC_BothHands Usage_i8(0x34) 458 + #define Usage_GDC_GripPoseOffset Usage_i8(0x40) 459 + #define Usage_GDC_PointerPoseOffset Usage_i8(0x41) 460 + #define Usage_KK_ErrorRollOver Usage_i8(0x1) 461 + #define Usage_KK_POSTFail Usage_i8(0x2) 462 + #define Usage_KK_ErrorUndefined Usage_i8(0x3) 463 + #define Usage_KK_KeyboardA Usage_i8(0x4) 464 + #define Usage_KK_KeyboardB Usage_i8(0x5) 465 + #define Usage_KK_KeyboardC Usage_i8(0x6) 466 + #define Usage_KK_KeyboardD Usage_i8(0x7) 467 + #define Usage_KK_KeyboardE Usage_i8(0x8) 468 + #define Usage_KK_KeyboardF Usage_i8(0x9) 469 + #define Usage_KK_KeyboardG Usage_i8(0xa) 470 + #define Usage_KK_KeyboardH Usage_i8(0xb) 471 + #define Usage_KK_KeyboardI Usage_i8(0xc) 472 + #define Usage_KK_KeyboardJ Usage_i8(0xd) 473 + #define Usage_KK_KeyboardK Usage_i8(0xe) 474 + #define Usage_KK_KeyboardL Usage_i8(0xf) 475 + #define Usage_KK_KeyboardM Usage_i8(0x10) 476 + #define Usage_KK_KeyboardN Usage_i8(0x11) 477 + #define Usage_KK_KeyboardO Usage_i8(0x12) 478 + #define Usage_KK_KeyboardP Usage_i8(0x13) 479 + #define Usage_KK_KeyboardQ Usage_i8(0x14) 480 + #define Usage_KK_KeyboardR Usage_i8(0x15) 481 + #define Usage_KK_KeyboardS Usage_i8(0x16) 482 + #define Usage_KK_KeyboardT Usage_i8(0x17) 483 + #define Usage_KK_KeyboardU Usage_i8(0x18) 484 + #define Usage_KK_KeyboardV Usage_i8(0x19) 485 + #define Usage_KK_KeyboardW Usage_i8(0x1a) 486 + #define Usage_KK_KeyboardX Usage_i8(0x1b) 487 + #define Usage_KK_KeyboardY Usage_i8(0x1c) 488 + #define Usage_KK_KeyboardZ Usage_i8(0x1d) 489 + #define Usage_KK_Keyboard1andBang Usage_i8(0x1e) 490 + #define Usage_KK_Keyboard2andAt Usage_i8(0x1f) 491 + #define Usage_KK_Keyboard3andHash Usage_i8(0x20) 492 + #define Usage_KK_Keyboard4andDollar Usage_i8(0x21) 493 + #define Usage_KK_Keyboard5andPercent Usage_i8(0x22) 494 + #define Usage_KK_Keyboard6andCaret Usage_i8(0x23) 495 + #define Usage_KK_Keyboard7andAmpersand Usage_i8(0x24) 496 + #define Usage_KK_Keyboard8andStar Usage_i8(0x25) 497 + #define Usage_KK_Keyboard9andLeftBracket Usage_i8(0x26) 498 + #define Usage_KK_Keyboard0andRightBracket Usage_i8(0x27) 499 + #define Usage_KK_KeyboardReturnEnter Usage_i8(0x28) 500 + #define Usage_KK_KeyboardEscape Usage_i8(0x29) 501 + #define Usage_KK_KeyboardDelete Usage_i8(0x2a) 502 + #define Usage_KK_KeyboardTab Usage_i8(0x2b) 503 + #define Usage_KK_KeyboardSpacebar Usage_i8(0x2c) 504 + #define Usage_KK_KeyboardDashandUnderscore Usage_i8(0x2d) 505 + #define Usage_KK_KeyboardEqualsandPlus Usage_i8(0x2e) 506 + #define Usage_KK_KeyboardLeftBrace Usage_i8(0x2f) 507 + #define Usage_KK_KeyboardRightBrace Usage_i8(0x30) 508 + #define Usage_KK_KeyboardBackslashandPipe Usage_i8(0x31) 509 + #define Usage_KK_KeyboardNonUSHashandTilde Usage_i8(0x32) 510 + #define Usage_KK_KeyboardSemiColonandColon Usage_i8(0x33) 511 + #define Usage_KK_KeyboardLeftAposandDouble Usage_i8(0x34) 512 + #define Usage_KK_KeyboardGraveAccentandTilde Usage_i8(0x35) 513 + #define Usage_KK_KeyboardCommaandLessThan Usage_i8(0x36) 514 + #define Usage_KK_KeyboardPeriodandGreaterThan Usage_i8(0x37) 515 + #define Usage_KK_KeyboardForwardSlashandQuestionMark Usage_i8(0x38) 516 + #define Usage_KK_KeyboardCapsLock Usage_i8(0x39) 517 + #define Usage_KK_KeyboardF1 Usage_i8(0x3a) 518 + #define Usage_KK_KeyboardF2 Usage_i8(0x3b) 519 + #define Usage_KK_KeyboardF3 Usage_i8(0x3c) 520 + #define Usage_KK_KeyboardF4 Usage_i8(0x3d) 521 + #define Usage_KK_KeyboardF5 Usage_i8(0x3e) 522 + #define Usage_KK_KeyboardF6 Usage_i8(0x3f) 523 + #define Usage_KK_KeyboardF7 Usage_i8(0x40) 524 + #define Usage_KK_KeyboardF8 Usage_i8(0x41) 525 + #define Usage_KK_KeyboardF9 Usage_i8(0x42) 526 + #define Usage_KK_KeyboardF10 Usage_i8(0x43) 527 + #define Usage_KK_KeyboardF11 Usage_i8(0x44) 528 + #define Usage_KK_KeyboardF12 Usage_i8(0x45) 529 + #define Usage_KK_KeyboardPrintScreen Usage_i8(0x46) 530 + #define Usage_KK_KeyboardScrollLock Usage_i8(0x47) 531 + #define Usage_KK_KeyboardPause Usage_i8(0x48) 532 + #define Usage_KK_KeyboardInsert Usage_i8(0x49) 533 + #define Usage_KK_KeyboardHome Usage_i8(0x4a) 534 + #define Usage_KK_KeyboardPageUp Usage_i8(0x4b) 535 + #define Usage_KK_KeyboardDeleteForward Usage_i8(0x4c) 536 + #define Usage_KK_KeyboardEnd Usage_i8(0x4d) 537 + #define Usage_KK_KeyboardPageDown Usage_i8(0x4e) 538 + #define Usage_KK_KeyboardRightArrow Usage_i8(0x4f) 539 + #define Usage_KK_KeyboardLeftArrow Usage_i8(0x50) 540 + #define Usage_KK_KeyboardDownArrow Usage_i8(0x51) 541 + #define Usage_KK_KeyboardUpArrow Usage_i8(0x52) 542 + #define Usage_KK_KeypadNumLockandClear Usage_i8(0x53) 543 + #define Usage_KK_KeypadForwardSlash Usage_i8(0x54) 544 + #define Usage_KK_KeypadStar Usage_i8(0x55) 545 + #define Usage_KK_KeypadDash Usage_i8(0x56) 546 + #define Usage_KK_KeypadPlus Usage_i8(0x57) 547 + #define Usage_KK_KeypadENTER Usage_i8(0x58) 548 + #define Usage_KK_Keypad1andEnd Usage_i8(0x59) 549 + #define Usage_KK_Keypad2andDownArrow Usage_i8(0x5a) 550 + #define Usage_KK_Keypad3andPageDn Usage_i8(0x5b) 551 + #define Usage_KK_Keypad4andLeftArrow Usage_i8(0x5c) 552 + #define Usage_KK_Keypad5 Usage_i8(0x5d) 553 + #define Usage_KK_Keypad6andRightArrow Usage_i8(0x5e) 554 + #define Usage_KK_Keypad7andHome Usage_i8(0x5f) 555 + #define Usage_KK_Keypad8andUpArrow Usage_i8(0x60) 556 + #define Usage_KK_Keypad9andPageUp Usage_i8(0x61) 557 + #define Usage_KK_Keypad0andInsert Usage_i8(0x62) 558 + #define Usage_KK_KeypadPeriodandDelete Usage_i8(0x63) 559 + #define Usage_KK_KeyboardNonUSBackslashandPipe Usage_i8(0x64) 560 + #define Usage_KK_KeyboardApplication Usage_i8(0x65) 561 + #define Usage_KK_KeyboardPower Usage_i8(0x66) 562 + #define Usage_KK_KeypadEquals Usage_i8(0x67) 563 + #define Usage_KK_KeyboardF13 Usage_i8(0x68) 564 + #define Usage_KK_KeyboardF14 Usage_i8(0x69) 565 + #define Usage_KK_KeyboardF15 Usage_i8(0x6a) 566 + #define Usage_KK_KeyboardF16 Usage_i8(0x6b) 567 + #define Usage_KK_KeyboardF17 Usage_i8(0x6c) 568 + #define Usage_KK_KeyboardF18 Usage_i8(0x6d) 569 + #define Usage_KK_KeyboardF19 Usage_i8(0x6e) 570 + #define Usage_KK_KeyboardF20 Usage_i8(0x6f) 571 + #define Usage_KK_KeyboardF21 Usage_i8(0x70) 572 + #define Usage_KK_KeyboardF22 Usage_i8(0x71) 573 + #define Usage_KK_KeyboardF23 Usage_i8(0x72) 574 + #define Usage_KK_KeyboardF24 Usage_i8(0x73) 575 + #define Usage_KK_KeyboardExecute Usage_i8(0x74) 576 + #define Usage_KK_KeyboardHelp Usage_i8(0x75) 577 + #define Usage_KK_KeyboardMenu Usage_i8(0x76) 578 + #define Usage_KK_KeyboardSelect Usage_i8(0x77) 579 + #define Usage_KK_KeyboardStop Usage_i8(0x78) 580 + #define Usage_KK_KeyboardAgain Usage_i8(0x79) 581 + #define Usage_KK_KeyboardUndo Usage_i8(0x7a) 582 + #define Usage_KK_KeyboardCut Usage_i8(0x7b) 583 + #define Usage_KK_KeyboardCopy Usage_i8(0x7c) 584 + #define Usage_KK_KeyboardPaste Usage_i8(0x7d) 585 + #define Usage_KK_KeyboardFind Usage_i8(0x7e) 586 + #define Usage_KK_KeyboardMute Usage_i8(0x7f) 587 + #define Usage_KK_KeyboardVolumeUp Usage_i8(0x80) 588 + #define Usage_KK_KeyboardVolumeDown Usage_i8(0x81) 589 + #define Usage_KK_KeyboardLockingCapsLock Usage_i8(0x82) 590 + #define Usage_KK_KeyboardLockingNumLock Usage_i8(0x83) 591 + #define Usage_KK_KeyboardLockingScrollLock Usage_i8(0x84) 592 + #define Usage_KK_KeypadComma Usage_i8(0x85) 593 + #define Usage_KK_KeypadEqualSign Usage_i8(0x86) 594 + #define Usage_KK_KeyboardInternational1 Usage_i8(0x87) 595 + #define Usage_KK_KeyboardInternational2 Usage_i8(0x88) 596 + #define Usage_KK_KeyboardInternational3 Usage_i8(0x89) 597 + #define Usage_KK_KeyboardInternational4 Usage_i8(0x8a) 598 + #define Usage_KK_KeyboardInternational5 Usage_i8(0x8b) 599 + #define Usage_KK_KeyboardInternational6 Usage_i8(0x8c) 600 + #define Usage_KK_KeyboardInternational7 Usage_i8(0x8d) 601 + #define Usage_KK_KeyboardInternational8 Usage_i8(0x8e) 602 + #define Usage_KK_KeyboardInternational9 Usage_i8(0x8f) 603 + #define Usage_KK_KeyboardLANG1 Usage_i8(0x90) 604 + #define Usage_KK_KeyboardLANG2 Usage_i8(0x91) 605 + #define Usage_KK_KeyboardLANG3 Usage_i8(0x92) 606 + #define Usage_KK_KeyboardLANG4 Usage_i8(0x93) 607 + #define Usage_KK_KeyboardLANG5 Usage_i8(0x94) 608 + #define Usage_KK_KeyboardLANG6 Usage_i8(0x95) 609 + #define Usage_KK_KeyboardLANG7 Usage_i8(0x96) 610 + #define Usage_KK_KeyboardLANG8 Usage_i8(0x97) 611 + #define Usage_KK_KeyboardLANG9 Usage_i8(0x98) 612 + #define Usage_KK_KeyboardAlternateErase Usage_i8(0x99) 613 + #define Usage_KK_KeyboardSysReqAttention Usage_i8(0x9a) 614 + #define Usage_KK_KeyboardCancel Usage_i8(0x9b) 615 + #define Usage_KK_KeyboardClear Usage_i8(0x9c) 616 + #define Usage_KK_KeyboardPrior Usage_i8(0x9d) 617 + #define Usage_KK_KeyboardReturn Usage_i8(0x9e) 618 + #define Usage_KK_KeyboardSeparator Usage_i8(0x9f) 619 + #define Usage_KK_KeyboardOut Usage_i8(0xa0) 620 + #define Usage_KK_KeyboardOper Usage_i8(0xa1) 621 + #define Usage_KK_KeyboardClearAgain Usage_i8(0xa2) 622 + #define Usage_KK_KeyboardCrSelProps Usage_i8(0xa3) 623 + #define Usage_KK_KeyboardExSel Usage_i8(0xa4) 624 + #define Usage_KK_KeypadDouble0 Usage_i8(0xb0) 625 + #define Usage_KK_KeypadTriple0 Usage_i8(0xb1) 626 + #define Usage_KK_ThousandsSeparator Usage_i8(0xb2) 627 + #define Usage_KK_DecimalSeparator Usage_i8(0xb3) 628 + #define Usage_KK_CurrencyUnit Usage_i8(0xb4) 629 + #define Usage_KK_CurrencySubunit Usage_i8(0xb5) 630 + #define Usage_KK_KeypadLeftBracket Usage_i8(0xb6) 631 + #define Usage_KK_KeypadRightBracket Usage_i8(0xb7) 632 + #define Usage_KK_KeypadLeftBrace Usage_i8(0xb8) 633 + #define Usage_KK_KeypadRightBrace Usage_i8(0xb9) 634 + #define Usage_KK_KeypadTab Usage_i8(0xba) 635 + #define Usage_KK_KeypadBackspace Usage_i8(0xbb) 636 + #define Usage_KK_KeypadA Usage_i8(0xbc) 637 + #define Usage_KK_KeypadB Usage_i8(0xbd) 638 + #define Usage_KK_KeypadC Usage_i8(0xbe) 639 + #define Usage_KK_KeypadD Usage_i8(0xbf) 640 + #define Usage_KK_KeypadE Usage_i8(0xc0) 641 + #define Usage_KK_KeypadF Usage_i8(0xc1) 642 + #define Usage_KK_KeypadXOR Usage_i8(0xc2) 643 + #define Usage_KK_KeypadCaret Usage_i8(0xc3) 644 + #define Usage_KK_KeypadPercentage Usage_i8(0xc4) 645 + #define Usage_KK_KeypadLess Usage_i8(0xc5) 646 + #define Usage_KK_KeypadGreater Usage_i8(0xc6) 647 + #define Usage_KK_KeypadAmpersand Usage_i8(0xc7) 648 + #define Usage_KK_KeypadDoubleAmpersand Usage_i8(0xc8) 649 + #define Usage_KK_KeypadBar Usage_i8(0xc9) 650 + #define Usage_KK_KeypadDoubleBar Usage_i8(0xca) 651 + #define Usage_KK_KeypadColon Usage_i8(0xcb) 652 + #define Usage_KK_KeypadHash Usage_i8(0xcc) 653 + #define Usage_KK_KeypadSpace Usage_i8(0xcd) 654 + #define Usage_KK_KeypadAt Usage_i8(0xce) 655 + #define Usage_KK_KeypadBang Usage_i8(0xcf) 656 + #define Usage_KK_KeypadMemoryStore Usage_i8(0xd0) 657 + #define Usage_KK_KeypadMemoryRecall Usage_i8(0xd1) 658 + #define Usage_KK_KeypadMemoryClear Usage_i8(0xd2) 659 + #define Usage_KK_KeypadMemoryAdd Usage_i8(0xd3) 660 + #define Usage_KK_KeypadMemorySubtract Usage_i8(0xd4) 661 + #define Usage_KK_KeypadMemoryMultiply Usage_i8(0xd5) 662 + #define Usage_KK_KeypadMemoryDivide Usage_i8(0xd6) 663 + #define Usage_KK_KeypadPlusMinus Usage_i8(0xd7) 664 + #define Usage_KK_KeypadClear Usage_i8(0xd8) 665 + #define Usage_KK_KeypadClearEntry Usage_i8(0xd9) 666 + #define Usage_KK_KeypadBinary Usage_i8(0xda) 667 + #define Usage_KK_KeypadOctal Usage_i8(0xdb) 668 + #define Usage_KK_KeypadDecimal Usage_i8(0xdc) 669 + #define Usage_KK_KeypadHexadecimal Usage_i8(0xdd) 670 + #define Usage_KK_KeyboardLeftControl Usage_i8(0xe0) 671 + #define Usage_KK_KeyboardLeftShift Usage_i8(0xe1) 672 + #define Usage_KK_KeyboardLeftAlt Usage_i8(0xe2) 673 + #define Usage_KK_KeyboardLeftGUI Usage_i8(0xe3) 674 + #define Usage_KK_KeyboardRightControl Usage_i8(0xe4) 675 + #define Usage_KK_KeyboardRightShift Usage_i8(0xe5) 676 + #define Usage_KK_KeyboardRightAlt Usage_i8(0xe6) 677 + #define Usage_KK_KeyboardRightGUI Usage_i8(0xe7) 678 + #define Usage_LED_NumLock Usage_i8(0x1) 679 + #define Usage_LED_CapsLock Usage_i8(0x2) 680 + #define Usage_LED_ScrollLock Usage_i8(0x3) 681 + #define Usage_LED_Compose Usage_i8(0x4) 682 + #define Usage_LED_Kana Usage_i8(0x5) 683 + #define Usage_LED_Power Usage_i8(0x6) 684 + #define Usage_LED_Shift Usage_i8(0x7) 685 + #define Usage_LED_DoNotDisturb Usage_i8(0x8) 686 + #define Usage_LED_Mute Usage_i8(0x9) 687 + #define Usage_LED_ToneEnable Usage_i8(0xa) 688 + #define Usage_LED_HighCutFilter Usage_i8(0xb) 689 + #define Usage_LED_LowCutFilter Usage_i8(0xc) 690 + #define Usage_LED_EqualizerEnable Usage_i8(0xd) 691 + #define Usage_LED_SoundFieldOn Usage_i8(0xe) 692 + #define Usage_LED_SurroundOn Usage_i8(0xf) 693 + #define Usage_LED_Repeat Usage_i8(0x10) 694 + #define Usage_LED_Stereo Usage_i8(0x11) 695 + #define Usage_LED_SamplingRateDetect Usage_i8(0x12) 696 + #define Usage_LED_Spinning Usage_i8(0x13) 697 + #define Usage_LED_CAV Usage_i8(0x14) 698 + #define Usage_LED_CLV Usage_i8(0x15) 699 + #define Usage_LED_RecordingFormatDetect Usage_i8(0x16) 700 + #define Usage_LED_OffHook Usage_i8(0x17) 701 + #define Usage_LED_Ring Usage_i8(0x18) 702 + #define Usage_LED_MessageWaiting Usage_i8(0x19) 703 + #define Usage_LED_DataMode Usage_i8(0x1a) 704 + #define Usage_LED_BatteryOperation Usage_i8(0x1b) 705 + #define Usage_LED_BatteryOK Usage_i8(0x1c) 706 + #define Usage_LED_BatteryLow Usage_i8(0x1d) 707 + #define Usage_LED_Speaker Usage_i8(0x1e) 708 + #define Usage_LED_Headset Usage_i8(0x1f) 709 + #define Usage_LED_Hold Usage_i8(0x20) 710 + #define Usage_LED_Microphone Usage_i8(0x21) 711 + #define Usage_LED_Coverage Usage_i8(0x22) 712 + #define Usage_LED_NightMode Usage_i8(0x23) 713 + #define Usage_LED_SendCalls Usage_i8(0x24) 714 + #define Usage_LED_CallPickup Usage_i8(0x25) 715 + #define Usage_LED_Conference Usage_i8(0x26) 716 + #define Usage_LED_Standby Usage_i8(0x27) 717 + #define Usage_LED_CameraOn Usage_i8(0x28) 718 + #define Usage_LED_CameraOff Usage_i8(0x29) 719 + #define Usage_LED_OnLine Usage_i8(0x2a) 720 + #define Usage_LED_OffLine Usage_i8(0x2b) 721 + #define Usage_LED_Busy Usage_i8(0x2c) 722 + #define Usage_LED_Ready Usage_i8(0x2d) 723 + #define Usage_LED_PaperOut Usage_i8(0x2e) 724 + #define Usage_LED_PaperJam Usage_i8(0x2f) 725 + #define Usage_LED_Remote Usage_i8(0x30) 726 + #define Usage_LED_Forward Usage_i8(0x31) 727 + #define Usage_LED_Reverse Usage_i8(0x32) 728 + #define Usage_LED_Stop Usage_i8(0x33) 729 + #define Usage_LED_Rewind Usage_i8(0x34) 730 + #define Usage_LED_FastForward Usage_i8(0x35) 731 + #define Usage_LED_Play Usage_i8(0x36) 732 + #define Usage_LED_Pause Usage_i8(0x37) 733 + #define Usage_LED_Record Usage_i8(0x38) 734 + #define Usage_LED_Error Usage_i8(0x39) 735 + #define Usage_LED_UsageSelectedIndicator Usage_i8(0x3a) 736 + #define Usage_LED_UsageInUseIndicator Usage_i8(0x3b) 737 + #define Usage_LED_UsageMultiModeIndicator Usage_i8(0x3c) 738 + #define Usage_LED_IndicatorOn Usage_i8(0x3d) 739 + #define Usage_LED_IndicatorFlash Usage_i8(0x3e) 740 + #define Usage_LED_IndicatorSlowBlink Usage_i8(0x3f) 741 + #define Usage_LED_IndicatorFastBlink Usage_i8(0x40) 742 + #define Usage_LED_IndicatorOff Usage_i8(0x41) 743 + #define Usage_LED_FlashOnTime Usage_i8(0x42) 744 + #define Usage_LED_SlowBlinkOnTime Usage_i8(0x43) 745 + #define Usage_LED_SlowBlinkOffTime Usage_i8(0x44) 746 + #define Usage_LED_FastBlinkOnTime Usage_i8(0x45) 747 + #define Usage_LED_FastBlinkOffTime Usage_i8(0x46) 748 + #define Usage_LED_UsageIndicatorColor Usage_i8(0x47) 749 + #define Usage_LED_IndicatorRed Usage_i8(0x48) 750 + #define Usage_LED_IndicatorGreen Usage_i8(0x49) 751 + #define Usage_LED_IndicatorAmber Usage_i8(0x4a) 752 + #define Usage_LED_GenericIndicator Usage_i8(0x4b) 753 + #define Usage_LED_SystemSuspend Usage_i8(0x4c) 754 + #define Usage_LED_ExternalPowerConnected Usage_i8(0x4d) 755 + #define Usage_LED_IndicatorBlue Usage_i8(0x4e) 756 + #define Usage_LED_IndicatorOrange Usage_i8(0x4f) 757 + #define Usage_LED_GoodStatus Usage_i8(0x50) 758 + #define Usage_LED_WarningStatus Usage_i8(0x51) 759 + #define Usage_LED_RGBLED Usage_i8(0x52) 760 + #define Usage_LED_RedLEDChannel Usage_i8(0x53) 761 + #define Usage_LED_BlueLEDChannel Usage_i8(0x54) 762 + #define Usage_LED_GreenLEDChannel Usage_i8(0x55) 763 + #define Usage_LED_LEDIntensity Usage_i8(0x56) 764 + #define Usage_LED_SystemMicrophoneMute Usage_i8(0x57) 765 + #define Usage_LED_PlayerIndicator Usage_i8(0x60) 766 + #define Usage_LED_Player1 Usage_i8(0x61) 767 + #define Usage_LED_Player2 Usage_i8(0x62) 768 + #define Usage_LED_Player3 Usage_i8(0x63) 769 + #define Usage_LED_Player4 Usage_i8(0x64) 770 + #define Usage_LED_Player5 Usage_i8(0x65) 771 + #define Usage_LED_Player6 Usage_i8(0x66) 772 + #define Usage_LED_Player7 Usage_i8(0x67) 773 + #define Usage_LED_Player8 Usage_i8(0x68) 774 + #define Usage_TD_Phone Usage_i8(0x1) 775 + #define Usage_TD_AnsweringMachine Usage_i8(0x2) 776 + #define Usage_TD_MessageControls Usage_i8(0x3) 777 + #define Usage_TD_Handset Usage_i8(0x4) 778 + #define Usage_TD_Headset Usage_i8(0x5) 779 + #define Usage_TD_TelephonyKeyPad Usage_i8(0x6) 780 + #define Usage_TD_ProgrammableButton Usage_i8(0x7) 781 + #define Usage_TD_HookSwitch Usage_i8(0x20) 782 + #define Usage_TD_Flash Usage_i8(0x21) 783 + #define Usage_TD_Feature Usage_i8(0x22) 784 + #define Usage_TD_Hold Usage_i8(0x23) 785 + #define Usage_TD_Redial Usage_i8(0x24) 786 + #define Usage_TD_Transfer Usage_i8(0x25) 787 + #define Usage_TD_Drop Usage_i8(0x26) 788 + #define Usage_TD_Park Usage_i8(0x27) 789 + #define Usage_TD_ForwardCalls Usage_i8(0x28) 790 + #define Usage_TD_AlternateFunction Usage_i8(0x29) 791 + #define Usage_TD_Line Usage_i8(0x2a) 792 + #define Usage_TD_SpeakerPhone Usage_i8(0x2b) 793 + #define Usage_TD_Conference Usage_i8(0x2c) 794 + #define Usage_TD_RingEnable Usage_i8(0x2d) 795 + #define Usage_TD_RingSelect Usage_i8(0x2e) 796 + #define Usage_TD_PhoneMute Usage_i8(0x2f) 797 + #define Usage_TD_CallerID Usage_i8(0x30) 798 + #define Usage_TD_Send Usage_i8(0x31) 799 + #define Usage_TD_SpeedDial Usage_i8(0x50) 800 + #define Usage_TD_StoreNumber Usage_i8(0x51) 801 + #define Usage_TD_RecallNumber Usage_i8(0x52) 802 + #define Usage_TD_PhoneDirectory Usage_i8(0x53) 803 + #define Usage_TD_VoiceMail Usage_i8(0x70) 804 + #define Usage_TD_ScreenCalls Usage_i8(0x71) 805 + #define Usage_TD_DoNotDisturb Usage_i8(0x72) 806 + #define Usage_TD_Message Usage_i8(0x73) 807 + #define Usage_TD_AnswerOnOff Usage_i8(0x74) 808 + #define Usage_TD_InsideDialTone Usage_i8(0x90) 809 + #define Usage_TD_OutsideDialTone Usage_i8(0x91) 810 + #define Usage_TD_InsideRingTone Usage_i8(0x92) 811 + #define Usage_TD_OutsideRingTone Usage_i8(0x93) 812 + #define Usage_TD_PriorityRingTone Usage_i8(0x94) 813 + #define Usage_TD_InsideRingback Usage_i8(0x95) 814 + #define Usage_TD_PriorityRingback Usage_i8(0x96) 815 + #define Usage_TD_LineBusyTone Usage_i8(0x97) 816 + #define Usage_TD_ReorderTone Usage_i8(0x98) 817 + #define Usage_TD_CallWaitingTone Usage_i8(0x99) 818 + #define Usage_TD_ConfirmationTone1 Usage_i8(0x9a) 819 + #define Usage_TD_ConfirmationTone2 Usage_i8(0x9b) 820 + #define Usage_TD_TonesOff Usage_i8(0x9c) 821 + #define Usage_TD_OutsideRingback Usage_i8(0x9d) 822 + #define Usage_TD_Ringer Usage_i8(0x9e) 823 + #define Usage_TD_PhoneKey0 Usage_i8(0xb0) 824 + #define Usage_TD_PhoneKey1 Usage_i8(0xb1) 825 + #define Usage_TD_PhoneKey2 Usage_i8(0xb2) 826 + #define Usage_TD_PhoneKey3 Usage_i8(0xb3) 827 + #define Usage_TD_PhoneKey4 Usage_i8(0xb4) 828 + #define Usage_TD_PhoneKey5 Usage_i8(0xb5) 829 + #define Usage_TD_PhoneKey6 Usage_i8(0xb6) 830 + #define Usage_TD_PhoneKey7 Usage_i8(0xb7) 831 + #define Usage_TD_PhoneKey8 Usage_i8(0xb8) 832 + #define Usage_TD_PhoneKey9 Usage_i8(0xb9) 833 + #define Usage_TD_PhoneKeyStar Usage_i8(0xba) 834 + #define Usage_TD_PhoneKeyPound Usage_i8(0xbb) 835 + #define Usage_TD_PhoneKeyA Usage_i8(0xbc) 836 + #define Usage_TD_PhoneKeyB Usage_i8(0xbd) 837 + #define Usage_TD_PhoneKeyC Usage_i8(0xbe) 838 + #define Usage_TD_PhoneKeyD Usage_i8(0xbf) 839 + #define Usage_TD_PhoneCallHistoryKey Usage_i8(0xc0) 840 + #define Usage_TD_PhoneCallerIDKey Usage_i8(0xc1) 841 + #define Usage_TD_PhoneSettingsKey Usage_i8(0xc2) 842 + #define Usage_TD_HostControl Usage_i8(0xf0) 843 + #define Usage_TD_HostAvailable Usage_i8(0xf1) 844 + #define Usage_TD_HostCallActive Usage_i8(0xf2) 845 + #define Usage_TD_ActivateHandsetAudio Usage_i8(0xf3) 846 + #define Usage_TD_RingType Usage_i8(0xf4) 847 + #define Usage_TD_RedialablePhoneNumber Usage_i8(0xf5) 848 + #define Usage_TD_StopRingTone Usage_i8(0xf8) 849 + #define Usage_TD_PSTNRingTone Usage_i8(0xf9) 850 + #define Usage_TD_HostRingTone Usage_i8(0xfa) 851 + #define Usage_TD_AlertSoundError Usage_i8(0xfb) 852 + #define Usage_TD_AlertSoundConfirm Usage_i8(0xfc) 853 + #define Usage_TD_AlertSoundNotification Usage_i8(0xfd) 854 + #define Usage_TD_SilentRing Usage_i8(0xfe) 855 + #define Usage_TD_EmailMessageWaiting Usage_i16(0x108) 856 + #define Usage_TD_VoicemailMessageWaiting Usage_i16(0x109) 857 + #define Usage_TD_HostHold Usage_i16(0x10a) 858 + #define Usage_TD_IncomingCallHistoryCount Usage_i16(0x110) 859 + #define Usage_TD_OutgoingCallHistoryCount Usage_i16(0x111) 860 + #define Usage_TD_IncomingCallHistory Usage_i16(0x112) 861 + #define Usage_TD_OutgoingCallHistory Usage_i16(0x113) 862 + #define Usage_TD_PhoneLocale Usage_i16(0x114) 863 + #define Usage_TD_PhoneTimeSecond Usage_i16(0x140) 864 + #define Usage_TD_PhoneTimeMinute Usage_i16(0x141) 865 + #define Usage_TD_PhoneTimeHour Usage_i16(0x142) 866 + #define Usage_TD_PhoneDateDay Usage_i16(0x143) 867 + #define Usage_TD_PhoneDateMonth Usage_i16(0x144) 868 + #define Usage_TD_PhoneDateYear Usage_i16(0x145) 869 + #define Usage_TD_HandsetNickname Usage_i16(0x146) 870 + #define Usage_TD_AddressBookID Usage_i16(0x147) 871 + #define Usage_TD_CallDuration Usage_i16(0x14a) 872 + #define Usage_TD_DualModePhone Usage_i16(0x14b) 873 + #define Usage_Con_ConsumerControl Usage_i8(0x1) 874 + #define Usage_Con_NumericKeyPad Usage_i8(0x2) 875 + #define Usage_Con_ProgrammableButtons Usage_i8(0x3) 876 + #define Usage_Con_Microphone Usage_i8(0x4) 877 + #define Usage_Con_Headphone Usage_i8(0x5) 878 + #define Usage_Con_GraphicEqualizer Usage_i8(0x6) 879 + #define Usage_Con_Plus10 Usage_i8(0x20) 880 + #define Usage_Con_Plus100 Usage_i8(0x21) 881 + #define Usage_Con_AMPM Usage_i8(0x22) 882 + #define Usage_Con_Power Usage_i8(0x30) 883 + #define Usage_Con_Reset Usage_i8(0x31) 884 + #define Usage_Con_Sleep Usage_i8(0x32) 885 + #define Usage_Con_SleepAfter Usage_i8(0x33) 886 + #define Usage_Con_SleepMode Usage_i8(0x34) 887 + #define Usage_Con_Illumination Usage_i8(0x35) 888 + #define Usage_Con_FunctionButtons Usage_i8(0x36) 889 + #define Usage_Con_Menu Usage_i8(0x40) 890 + #define Usage_Con_MenuPick Usage_i8(0x41) 891 + #define Usage_Con_MenuUp Usage_i8(0x42) 892 + #define Usage_Con_MenuDown Usage_i8(0x43) 893 + #define Usage_Con_MenuLeft Usage_i8(0x44) 894 + #define Usage_Con_MenuRight Usage_i8(0x45) 895 + #define Usage_Con_MenuEscape Usage_i8(0x46) 896 + #define Usage_Con_MenuValueIncrease Usage_i8(0x47) 897 + #define Usage_Con_MenuValueDecrease Usage_i8(0x48) 898 + #define Usage_Con_DataOnScreen Usage_i8(0x60) 899 + #define Usage_Con_ClosedCaption Usage_i8(0x61) 900 + #define Usage_Con_ClosedCaptionSelect Usage_i8(0x62) 901 + #define Usage_Con_VCRTV Usage_i8(0x63) 902 + #define Usage_Con_BroadcastMode Usage_i8(0x64) 903 + #define Usage_Con_Snapshot Usage_i8(0x65) 904 + #define Usage_Con_Still Usage_i8(0x66) 905 + #define Usage_Con_PictureinPictureToggle Usage_i8(0x67) 906 + #define Usage_Con_PictureinPictureSwap Usage_i8(0x68) 907 + #define Usage_Con_RedMenuButton Usage_i8(0x69) 908 + #define Usage_Con_GreenMenuButton Usage_i8(0x6a) 909 + #define Usage_Con_BlueMenuButton Usage_i8(0x6b) 910 + #define Usage_Con_YellowMenuButton Usage_i8(0x6c) 911 + #define Usage_Con_Aspect Usage_i8(0x6d) 912 + #define Usage_Con_ThreeDModeSelect Usage_i8(0x6e) 913 + #define Usage_Con_DisplayBrightnessIncrement Usage_i8(0x6f) 914 + #define Usage_Con_DisplayBrightnessDecrement Usage_i8(0x70) 915 + #define Usage_Con_DisplayBrightness Usage_i8(0x71) 916 + #define Usage_Con_DisplayBacklightToggle Usage_i8(0x72) 917 + #define Usage_Con_DisplaySetBrightnesstoMinimum Usage_i8(0x73) 918 + #define Usage_Con_DisplaySetBrightnesstoMaximum Usage_i8(0x74) 919 + #define Usage_Con_DisplaySetAutoBrightness Usage_i8(0x75) 920 + #define Usage_Con_CameraAccessEnabled Usage_i8(0x76) 921 + #define Usage_Con_CameraAccessDisabled Usage_i8(0x77) 922 + #define Usage_Con_CameraAccessToggle Usage_i8(0x78) 923 + #define Usage_Con_KeyboardBrightnessIncrement Usage_i8(0x79) 924 + #define Usage_Con_KeyboardBrightnessDecrement Usage_i8(0x7a) 925 + #define Usage_Con_KeyboardBacklightSetLevel Usage_i8(0x7b) 926 + #define Usage_Con_KeyboardBacklightOOC Usage_i8(0x7c) 927 + #define Usage_Con_KeyboardBacklightSetMinimum Usage_i8(0x7d) 928 + #define Usage_Con_KeyboardBacklightSetMaximum Usage_i8(0x7e) 929 + #define Usage_Con_KeyboardBacklightAuto Usage_i8(0x7f) 930 + #define Usage_Con_Selection Usage_i8(0x80) 931 + #define Usage_Con_AssignSelection Usage_i8(0x81) 932 + #define Usage_Con_ModeStep Usage_i8(0x82) 933 + #define Usage_Con_RecallLast Usage_i8(0x83) 934 + #define Usage_Con_EnterChannel Usage_i8(0x84) 935 + #define Usage_Con_OrderMovie Usage_i8(0x85) 936 + #define Usage_Con_Channel Usage_i8(0x86) 937 + #define Usage_Con_MediaSelection Usage_i8(0x87) 938 + #define Usage_Con_MediaSelectComputer Usage_i8(0x88) 939 + #define Usage_Con_MediaSelectTV Usage_i8(0x89) 940 + #define Usage_Con_MediaSelectWWW Usage_i8(0x8a) 941 + #define Usage_Con_MediaSelectDVD Usage_i8(0x8b) 942 + #define Usage_Con_MediaSelectTelephone Usage_i8(0x8c) 943 + #define Usage_Con_MediaSelectProgramGuide Usage_i8(0x8d) 944 + #define Usage_Con_MediaSelectVideoPhone Usage_i8(0x8e) 945 + #define Usage_Con_MediaSelectGames Usage_i8(0x8f) 946 + #define Usage_Con_MediaSelectMessages Usage_i8(0x90) 947 + #define Usage_Con_MediaSelectCD Usage_i8(0x91) 948 + #define Usage_Con_MediaSelectVCR Usage_i8(0x92) 949 + #define Usage_Con_MediaSelectTuner Usage_i8(0x93) 950 + #define Usage_Con_Quit Usage_i8(0x94) 951 + #define Usage_Con_Help Usage_i8(0x95) 952 + #define Usage_Con_MediaSelectTape Usage_i8(0x96) 953 + #define Usage_Con_MediaSelectCable Usage_i8(0x97) 954 + #define Usage_Con_MediaSelectSatellite Usage_i8(0x98) 955 + #define Usage_Con_MediaSelectSecurity Usage_i8(0x99) 956 + #define Usage_Con_MediaSelectHome Usage_i8(0x9a) 957 + #define Usage_Con_MediaSelectCall Usage_i8(0x9b) 958 + #define Usage_Con_ChannelIncrement Usage_i8(0x9c) 959 + #define Usage_Con_ChannelDecrement Usage_i8(0x9d) 960 + #define Usage_Con_MediaSelectSAP Usage_i8(0x9e) 961 + #define Usage_Con_VCRPlus Usage_i8(0xa0) 962 + #define Usage_Con_Once Usage_i8(0xa1) 963 + #define Usage_Con_Daily Usage_i8(0xa2) 964 + #define Usage_Con_Weekly Usage_i8(0xa3) 965 + #define Usage_Con_Monthly Usage_i8(0xa4) 966 + #define Usage_Con_Play Usage_i8(0xb0) 967 + #define Usage_Con_Pause Usage_i8(0xb1) 968 + #define Usage_Con_Record Usage_i8(0xb2) 969 + #define Usage_Con_FastForward Usage_i8(0xb3) 970 + #define Usage_Con_Rewind Usage_i8(0xb4) 971 + #define Usage_Con_ScanNextTrack Usage_i8(0xb5) 972 + #define Usage_Con_ScanPreviousTrack Usage_i8(0xb6) 973 + #define Usage_Con_Stop Usage_i8(0xb7) 974 + #define Usage_Con_Eject Usage_i8(0xb8) 975 + #define Usage_Con_RandomPlay Usage_i8(0xb9) 976 + #define Usage_Con_SelectDisc Usage_i8(0xba) 977 + #define Usage_Con_EnterDisc Usage_i8(0xbb) 978 + #define Usage_Con_Repeat Usage_i8(0xbc) 979 + #define Usage_Con_Tracking Usage_i8(0xbd) 980 + #define Usage_Con_TrackNormal Usage_i8(0xbe) 981 + #define Usage_Con_SlowTracking Usage_i8(0xbf) 982 + #define Usage_Con_FrameForward Usage_i8(0xc0) 983 + #define Usage_Con_FrameBack Usage_i8(0xc1) 984 + #define Usage_Con_Mark Usage_i8(0xc2) 985 + #define Usage_Con_ClearMark Usage_i8(0xc3) 986 + #define Usage_Con_RepeatFromMark Usage_i8(0xc4) 987 + #define Usage_Con_ReturnToMark Usage_i8(0xc5) 988 + #define Usage_Con_SearchMarkForward Usage_i8(0xc6) 989 + #define Usage_Con_SearchMarkBackwards Usage_i8(0xc7) 990 + #define Usage_Con_CounterReset Usage_i8(0xc8) 991 + #define Usage_Con_ShowCounter Usage_i8(0xc9) 992 + #define Usage_Con_TrackingIncrement Usage_i8(0xca) 993 + #define Usage_Con_TrackingDecrement Usage_i8(0xcb) 994 + #define Usage_Con_StopEject Usage_i8(0xcc) 995 + #define Usage_Con_PlayPause Usage_i8(0xcd) 996 + #define Usage_Con_PlaySkip Usage_i8(0xce) 997 + #define Usage_Con_VoiceCommand Usage_i8(0xcf) 998 + #define Usage_Con_InvokeCaptureInterface Usage_i8(0xd0) 999 + #define Usage_Con_StartorStopGameRecording Usage_i8(0xd1) 1000 + #define Usage_Con_HistoricalGameCapture Usage_i8(0xd2) 1001 + #define Usage_Con_CaptureGameScreenshot Usage_i8(0xd3) 1002 + #define Usage_Con_ShoworHideRecordingIndicator Usage_i8(0xd4) 1003 + #define Usage_Con_StartorStopMicrophoneCapture Usage_i8(0xd5) 1004 + #define Usage_Con_StartorStopCameraCapture Usage_i8(0xd6) 1005 + #define Usage_Con_StartorStopGameBroadcast Usage_i8(0xd7) 1006 + #define Usage_Con_StartorStopVoiceDictationSession Usage_i8(0xd8) 1007 + #define Usage_Con_InvokeDismissEmojiPicker Usage_i8(0xd9) 1008 + #define Usage_Con_Volume Usage_i8(0xe0) 1009 + #define Usage_Con_Balance Usage_i8(0xe1) 1010 + #define Usage_Con_Mute Usage_i8(0xe2) 1011 + #define Usage_Con_Bass Usage_i8(0xe3) 1012 + #define Usage_Con_Treble Usage_i8(0xe4) 1013 + #define Usage_Con_BassBoost Usage_i8(0xe5) 1014 + #define Usage_Con_SurroundMode Usage_i8(0xe6) 1015 + #define Usage_Con_Loudness Usage_i8(0xe7) 1016 + #define Usage_Con_MPX Usage_i8(0xe8) 1017 + #define Usage_Con_VolumeIncrement Usage_i8(0xe9) 1018 + #define Usage_Con_VolumeDecrement Usage_i8(0xea) 1019 + #define Usage_Con_SpeedSelect Usage_i8(0xf0) 1020 + #define Usage_Con_PlaybackSpeed Usage_i8(0xf1) 1021 + #define Usage_Con_StandardPlay Usage_i8(0xf2) 1022 + #define Usage_Con_LongPlay Usage_i8(0xf3) 1023 + #define Usage_Con_ExtendedPlay Usage_i8(0xf4) 1024 + #define Usage_Con_Slow Usage_i8(0xf5) 1025 + #define Usage_Con_FanEnable Usage_i16(0x100) 1026 + #define Usage_Con_FanSpeed Usage_i16(0x101) 1027 + #define Usage_Con_LightEnable Usage_i16(0x102) 1028 + #define Usage_Con_LightIlluminationLevel Usage_i16(0x103) 1029 + #define Usage_Con_ClimateControlEnable Usage_i16(0x104) 1030 + #define Usage_Con_RoomTemperature Usage_i16(0x105) 1031 + #define Usage_Con_SecurityEnable Usage_i16(0x106) 1032 + #define Usage_Con_FireAlarm Usage_i16(0x107) 1033 + #define Usage_Con_PoliceAlarm Usage_i16(0x108) 1034 + #define Usage_Con_Proximity Usage_i16(0x109) 1035 + #define Usage_Con_Motion Usage_i16(0x10a) 1036 + #define Usage_Con_DuressAlarm Usage_i16(0x10b) 1037 + #define Usage_Con_HoldupAlarm Usage_i16(0x10c) 1038 + #define Usage_Con_MedicalAlarm Usage_i16(0x10d) 1039 + #define Usage_Con_BalanceRight Usage_i16(0x150) 1040 + #define Usage_Con_BalanceLeft Usage_i16(0x151) 1041 + #define Usage_Con_BassIncrement Usage_i16(0x152) 1042 + #define Usage_Con_BassDecrement Usage_i16(0x153) 1043 + #define Usage_Con_TrebleIncrement Usage_i16(0x154) 1044 + #define Usage_Con_TrebleDecrement Usage_i16(0x155) 1045 + #define Usage_Con_SpeakerSystem Usage_i16(0x160) 1046 + #define Usage_Con_ChannelLeft Usage_i16(0x161) 1047 + #define Usage_Con_ChannelRight Usage_i16(0x162) 1048 + #define Usage_Con_ChannelCenter Usage_i16(0x163) 1049 + #define Usage_Con_ChannelFront Usage_i16(0x164) 1050 + #define Usage_Con_ChannelCenterFront Usage_i16(0x165) 1051 + #define Usage_Con_ChannelSide Usage_i16(0x166) 1052 + #define Usage_Con_ChannelSurround Usage_i16(0x167) 1053 + #define Usage_Con_ChannelLowFrequencyEnhancement Usage_i16(0x168) 1054 + #define Usage_Con_ChannelTop Usage_i16(0x169) 1055 + #define Usage_Con_ChannelUnknown Usage_i16(0x16a) 1056 + #define Usage_Con_Subchannel Usage_i16(0x170) 1057 + #define Usage_Con_SubchannelIncrement Usage_i16(0x171) 1058 + #define Usage_Con_SubchannelDecrement Usage_i16(0x172) 1059 + #define Usage_Con_AlternateAudioIncrement Usage_i16(0x173) 1060 + #define Usage_Con_AlternateAudioDecrement Usage_i16(0x174) 1061 + #define Usage_Con_ApplicationLaunchButtons Usage_i16(0x180) 1062 + #define Usage_Con_ALLaunchButtonConfigurationTool Usage_i16(0x181) 1063 + #define Usage_Con_ALProgrammableButtonConfiguration Usage_i16(0x182) 1064 + #define Usage_Con_ALConsumerControlConfiguration Usage_i16(0x183) 1065 + #define Usage_Con_ALWordProcessor Usage_i16(0x184) 1066 + #define Usage_Con_ALTextEditor Usage_i16(0x185) 1067 + #define Usage_Con_ALSpreadsheet Usage_i16(0x186) 1068 + #define Usage_Con_ALGraphicsEditor Usage_i16(0x187) 1069 + #define Usage_Con_ALPresentationApp Usage_i16(0x188) 1070 + #define Usage_Con_ALDatabaseApp Usage_i16(0x189) 1071 + #define Usage_Con_ALEmailReader Usage_i16(0x18a) 1072 + #define Usage_Con_ALNewsreader Usage_i16(0x18b) 1073 + #define Usage_Con_ALVoicemail Usage_i16(0x18c) 1074 + #define Usage_Con_ALContactsAddressBook Usage_i16(0x18d) 1075 + #define Usage_Con_ALCalendarSchedule Usage_i16(0x18e) 1076 + #define Usage_Con_ALTaskProjectManager Usage_i16(0x18f) 1077 + #define Usage_Con_ALLogJournalTimecard Usage_i16(0x190) 1078 + #define Usage_Con_ALCheckbookFinance Usage_i16(0x191) 1079 + #define Usage_Con_ALCalculator Usage_i16(0x192) 1080 + #define Usage_Con_ALAVCapturePlayback Usage_i16(0x193) 1081 + #define Usage_Con_ALLocalMachineBrowser Usage_i16(0x194) 1082 + #define Usage_Con_ALLANWANBrowser Usage_i16(0x195) 1083 + #define Usage_Con_ALInternetBrowser Usage_i16(0x196) 1084 + #define Usage_Con_ALRemoteNetworkingISPConnect Usage_i16(0x197) 1085 + #define Usage_Con_ALNetworkConference Usage_i16(0x198) 1086 + #define Usage_Con_ALNetworkChat Usage_i16(0x199) 1087 + #define Usage_Con_ALTelephonyDialer Usage_i16(0x19a) 1088 + #define Usage_Con_ALLogon Usage_i16(0x19b) 1089 + #define Usage_Con_ALLogoff Usage_i16(0x19c) 1090 + #define Usage_Con_ALLogonLogoff Usage_i16(0x19d) 1091 + #define Usage_Con_ALTerminalLockScreensaver Usage_i16(0x19e) 1092 + #define Usage_Con_ALControlPanel Usage_i16(0x19f) 1093 + #define Usage_Con_ALCommandLineProcessorRun Usage_i16(0x1a0) 1094 + #define Usage_Con_ALProcessTaskManager Usage_i16(0x1a1) 1095 + #define Usage_Con_ALSelectTaskApplication Usage_i16(0x1a2) 1096 + #define Usage_Con_ALNextTaskApplication Usage_i16(0x1a3) 1097 + #define Usage_Con_ALPreviousTaskApplication Usage_i16(0x1a4) 1098 + #define Usage_Con_ALPreemptiveHaltTaskApplication Usage_i16(0x1a5) 1099 + #define Usage_Con_ALIntegratedHelpCenter Usage_i16(0x1a6) 1100 + #define Usage_Con_ALDocuments Usage_i16(0x1a7) 1101 + #define Usage_Con_ALThesaurus Usage_i16(0x1a8) 1102 + #define Usage_Con_ALDictionary Usage_i16(0x1a9) 1103 + #define Usage_Con_ALDesktop Usage_i16(0x1aa) 1104 + #define Usage_Con_ALSpellCheck Usage_i16(0x1ab) 1105 + #define Usage_Con_ALGrammarCheck Usage_i16(0x1ac) 1106 + #define Usage_Con_ALWirelessStatus Usage_i16(0x1ad) 1107 + #define Usage_Con_ALKeyboardLayout Usage_i16(0x1ae) 1108 + #define Usage_Con_ALVirusProtection Usage_i16(0x1af) 1109 + #define Usage_Con_ALEncryption Usage_i16(0x1b0) 1110 + #define Usage_Con_ALScreenSaver Usage_i16(0x1b1) 1111 + #define Usage_Con_ALAlarms Usage_i16(0x1b2) 1112 + #define Usage_Con_ALClock Usage_i16(0x1b3) 1113 + #define Usage_Con_ALFileBrowser Usage_i16(0x1b4) 1114 + #define Usage_Con_ALPowerStatus Usage_i16(0x1b5) 1115 + #define Usage_Con_ALImageBrowser Usage_i16(0x1b6) 1116 + #define Usage_Con_ALAudioBrowser Usage_i16(0x1b7) 1117 + #define Usage_Con_ALMovieBrowser Usage_i16(0x1b8) 1118 + #define Usage_Con_ALDigitalRightsManager Usage_i16(0x1b9) 1119 + #define Usage_Con_ALDigitalWallet Usage_i16(0x1ba) 1120 + #define Usage_Con_ALInstantMessaging Usage_i16(0x1bc) 1121 + #define Usage_Con_ALOEMFeaturesTipsTutorialBrowser Usage_i16(0x1bd) 1122 + #define Usage_Con_ALOEMHelp Usage_i16(0x1be) 1123 + #define Usage_Con_ALOnlineCommunity Usage_i16(0x1bf) 1124 + #define Usage_Con_ALEntertainmentContentBrowser Usage_i16(0x1c0) 1125 + #define Usage_Con_ALOnlineShoppingBrowser Usage_i16(0x1c1) 1126 + #define Usage_Con_ALSmartCardInformationHelp Usage_i16(0x1c2) 1127 + #define Usage_Con_ALMarketMonitorFinanceBrowser Usage_i16(0x1c3) 1128 + #define Usage_Con_ALCustomizedCorporateNewsBrowser Usage_i16(0x1c4) 1129 + #define Usage_Con_ALOnlineActivityBrowser Usage_i16(0x1c5) 1130 + #define Usage_Con_ALResearchSearchBrowser Usage_i16(0x1c6) 1131 + #define Usage_Con_ALAudioPlayer Usage_i16(0x1c7) 1132 + #define Usage_Con_ALMessageStatus Usage_i16(0x1c8) 1133 + #define Usage_Con_ALContactSync Usage_i16(0x1c9) 1134 + #define Usage_Con_ALNavigation Usage_i16(0x1ca) 1135 + #define Usage_Con_ALContextawareDesktopAssistant Usage_i16(0x1cb) 1136 + #define Usage_Con_GenericGUIApplicationControls Usage_i16(0x200) 1137 + #define Usage_Con_ACNew Usage_i16(0x201) 1138 + #define Usage_Con_ACOpen Usage_i16(0x202) 1139 + #define Usage_Con_ACClose Usage_i16(0x203) 1140 + #define Usage_Con_ACExit Usage_i16(0x204) 1141 + #define Usage_Con_ACMaximize Usage_i16(0x205) 1142 + #define Usage_Con_ACMinimize Usage_i16(0x206) 1143 + #define Usage_Con_ACSave Usage_i16(0x207) 1144 + #define Usage_Con_ACPrint Usage_i16(0x208) 1145 + #define Usage_Con_ACProperties Usage_i16(0x209) 1146 + #define Usage_Con_ACUndo Usage_i16(0x21a) 1147 + #define Usage_Con_ACCopy Usage_i16(0x21b) 1148 + #define Usage_Con_ACCut Usage_i16(0x21c) 1149 + #define Usage_Con_ACPaste Usage_i16(0x21d) 1150 + #define Usage_Con_ACSelectAll Usage_i16(0x21e) 1151 + #define Usage_Con_ACFind Usage_i16(0x21f) 1152 + #define Usage_Con_ACFindandReplace Usage_i16(0x220) 1153 + #define Usage_Con_ACSearch Usage_i16(0x221) 1154 + #define Usage_Con_ACGoTo Usage_i16(0x222) 1155 + #define Usage_Con_ACHome Usage_i16(0x223) 1156 + #define Usage_Con_ACBack Usage_i16(0x224) 1157 + #define Usage_Con_ACForward Usage_i16(0x225) 1158 + #define Usage_Con_ACStop Usage_i16(0x226) 1159 + #define Usage_Con_ACRefresh Usage_i16(0x227) 1160 + #define Usage_Con_ACPreviousLink Usage_i16(0x228) 1161 + #define Usage_Con_ACNextLink Usage_i16(0x229) 1162 + #define Usage_Con_ACBookmarks Usage_i16(0x22a) 1163 + #define Usage_Con_ACHistory Usage_i16(0x22b) 1164 + #define Usage_Con_ACSubscriptions Usage_i16(0x22c) 1165 + #define Usage_Con_ACZoomIn Usage_i16(0x22d) 1166 + #define Usage_Con_ACZoomOut Usage_i16(0x22e) 1167 + #define Usage_Con_ACZoom Usage_i16(0x22f) 1168 + #define Usage_Con_ACFullScreenView Usage_i16(0x230) 1169 + #define Usage_Con_ACNormalView Usage_i16(0x231) 1170 + #define Usage_Con_ACViewToggle Usage_i16(0x232) 1171 + #define Usage_Con_ACScrollUp Usage_i16(0x233) 1172 + #define Usage_Con_ACScrollDown Usage_i16(0x234) 1173 + #define Usage_Con_ACScroll Usage_i16(0x235) 1174 + #define Usage_Con_ACPanLeft Usage_i16(0x236) 1175 + #define Usage_Con_ACPanRight Usage_i16(0x237) 1176 + #define Usage_Con_ACPan Usage_i16(0x238) 1177 + #define Usage_Con_ACNewWindow Usage_i16(0x239) 1178 + #define Usage_Con_ACTileHorizontally Usage_i16(0x23a) 1179 + #define Usage_Con_ACTileVertically Usage_i16(0x23b) 1180 + #define Usage_Con_ACFormat Usage_i16(0x23c) 1181 + #define Usage_Con_ACEdit Usage_i16(0x23d) 1182 + #define Usage_Con_ACBold Usage_i16(0x23e) 1183 + #define Usage_Con_ACItalics Usage_i16(0x23f) 1184 + #define Usage_Con_ACUnderline Usage_i16(0x240) 1185 + #define Usage_Con_ACStrikethrough Usage_i16(0x241) 1186 + #define Usage_Con_ACSubscript Usage_i16(0x242) 1187 + #define Usage_Con_ACSuperscript Usage_i16(0x243) 1188 + #define Usage_Con_ACAllCaps Usage_i16(0x244) 1189 + #define Usage_Con_ACRotate Usage_i16(0x245) 1190 + #define Usage_Con_ACResize Usage_i16(0x246) 1191 + #define Usage_Con_ACFlipHorizontal Usage_i16(0x247) 1192 + #define Usage_Con_ACFlipVertical Usage_i16(0x248) 1193 + #define Usage_Con_ACMirrorHorizontal Usage_i16(0x249) 1194 + #define Usage_Con_ACMirrorVertical Usage_i16(0x24a) 1195 + #define Usage_Con_ACFontSelect Usage_i16(0x24b) 1196 + #define Usage_Con_ACFontColor Usage_i16(0x24c) 1197 + #define Usage_Con_ACFontSize Usage_i16(0x24d) 1198 + #define Usage_Con_ACJustifyLeft Usage_i16(0x24e) 1199 + #define Usage_Con_ACJustifyCenterH Usage_i16(0x24f) 1200 + #define Usage_Con_ACJustifyRight Usage_i16(0x250) 1201 + #define Usage_Con_ACJustifyBlockH Usage_i16(0x251) 1202 + #define Usage_Con_ACJustifyTop Usage_i16(0x252) 1203 + #define Usage_Con_ACJustifyCenterV Usage_i16(0x253) 1204 + #define Usage_Con_ACJustifyBottom Usage_i16(0x254) 1205 + #define Usage_Con_ACJustifyBlockV Usage_i16(0x255) 1206 + #define Usage_Con_ACIndentDecrease Usage_i16(0x256) 1207 + #define Usage_Con_ACIndentIncrease Usage_i16(0x257) 1208 + #define Usage_Con_ACNumberedList Usage_i16(0x258) 1209 + #define Usage_Con_ACRestartNumbering Usage_i16(0x259) 1210 + #define Usage_Con_ACBulletedList Usage_i16(0x25a) 1211 + #define Usage_Con_ACPromote Usage_i16(0x25b) 1212 + #define Usage_Con_ACDemote Usage_i16(0x25c) 1213 + #define Usage_Con_ACYes Usage_i16(0x25d) 1214 + #define Usage_Con_ACNo Usage_i16(0x25e) 1215 + #define Usage_Con_ACCancel Usage_i16(0x25f) 1216 + #define Usage_Con_ACCatalog Usage_i16(0x260) 1217 + #define Usage_Con_ACBuyCheckout Usage_i16(0x261) 1218 + #define Usage_Con_ACAddtoCart Usage_i16(0x262) 1219 + #define Usage_Con_ACExpand Usage_i16(0x263) 1220 + #define Usage_Con_ACExpandAll Usage_i16(0x264) 1221 + #define Usage_Con_ACCollapse Usage_i16(0x265) 1222 + #define Usage_Con_ACCollapseAll Usage_i16(0x266) 1223 + #define Usage_Con_ACPrintPreview Usage_i16(0x267) 1224 + #define Usage_Con_ACPasteSpecial Usage_i16(0x268) 1225 + #define Usage_Con_ACInsertMode Usage_i16(0x269) 1226 + #define Usage_Con_ACDelete Usage_i16(0x26a) 1227 + #define Usage_Con_ACLock Usage_i16(0x26b) 1228 + #define Usage_Con_ACUnlock Usage_i16(0x26c) 1229 + #define Usage_Con_ACProtect Usage_i16(0x26d) 1230 + #define Usage_Con_ACUnprotect Usage_i16(0x26e) 1231 + #define Usage_Con_ACAttachComment Usage_i16(0x26f) 1232 + #define Usage_Con_ACDeleteComment Usage_i16(0x270) 1233 + #define Usage_Con_ACViewComment Usage_i16(0x271) 1234 + #define Usage_Con_ACSelectWord Usage_i16(0x272) 1235 + #define Usage_Con_ACSelectSentence Usage_i16(0x273) 1236 + #define Usage_Con_ACSelectParagraph Usage_i16(0x274) 1237 + #define Usage_Con_ACSelectColumn Usage_i16(0x275) 1238 + #define Usage_Con_ACSelectRow Usage_i16(0x276) 1239 + #define Usage_Con_ACSelectTable Usage_i16(0x277) 1240 + #define Usage_Con_ACSelectObject Usage_i16(0x278) 1241 + #define Usage_Con_ACRedoRepeat Usage_i16(0x279) 1242 + #define Usage_Con_ACSort Usage_i16(0x27a) 1243 + #define Usage_Con_ACSortAscending Usage_i16(0x27b) 1244 + #define Usage_Con_ACSortDescending Usage_i16(0x27c) 1245 + #define Usage_Con_ACFilter Usage_i16(0x27d) 1246 + #define Usage_Con_ACSetClock Usage_i16(0x27e) 1247 + #define Usage_Con_ACViewClock Usage_i16(0x27f) 1248 + #define Usage_Con_ACSelectTimeZone Usage_i16(0x280) 1249 + #define Usage_Con_ACEditTimeZones Usage_i16(0x281) 1250 + #define Usage_Con_ACSetAlarm Usage_i16(0x282) 1251 + #define Usage_Con_ACClearAlarm Usage_i16(0x283) 1252 + #define Usage_Con_ACSnoozeAlarm Usage_i16(0x284) 1253 + #define Usage_Con_ACResetAlarm Usage_i16(0x285) 1254 + #define Usage_Con_ACSynchronize Usage_i16(0x286) 1255 + #define Usage_Con_ACSendReceive Usage_i16(0x287) 1256 + #define Usage_Con_ACSendTo Usage_i16(0x288) 1257 + #define Usage_Con_ACReply Usage_i16(0x289) 1258 + #define Usage_Con_ACReplyAll Usage_i16(0x28a) 1259 + #define Usage_Con_ACForwardMsg Usage_i16(0x28b) 1260 + #define Usage_Con_ACSend Usage_i16(0x28c) 1261 + #define Usage_Con_ACAttachFile Usage_i16(0x28d) 1262 + #define Usage_Con_ACUpload Usage_i16(0x28e) 1263 + #define Usage_Con_ACDownloadSaveTargetAs Usage_i16(0x28f) 1264 + #define Usage_Con_ACSetBorders Usage_i16(0x290) 1265 + #define Usage_Con_ACInsertRow Usage_i16(0x291) 1266 + #define Usage_Con_ACInsertColumn Usage_i16(0x292) 1267 + #define Usage_Con_ACInsertFile Usage_i16(0x293) 1268 + #define Usage_Con_ACInsertPicture Usage_i16(0x294) 1269 + #define Usage_Con_ACInsertObject Usage_i16(0x295) 1270 + #define Usage_Con_ACInsertSymbol Usage_i16(0x296) 1271 + #define Usage_Con_ACSaveandClose Usage_i16(0x297) 1272 + #define Usage_Con_ACRename Usage_i16(0x298) 1273 + #define Usage_Con_ACMerge Usage_i16(0x299) 1274 + #define Usage_Con_ACSplit Usage_i16(0x29a) 1275 + #define Usage_Con_ACDisributeHorizontally Usage_i16(0x29b) 1276 + #define Usage_Con_ACDistributeVertically Usage_i16(0x29c) 1277 + #define Usage_Con_ACNextKeyboardLayoutSelect Usage_i16(0x29d) 1278 + #define Usage_Con_ACNavigationGuidance Usage_i16(0x29e) 1279 + #define Usage_Con_ACDesktopShowAllWindows Usage_i16(0x29f) 1280 + #define Usage_Con_ACSoftKeyLeft Usage_i16(0x2a0) 1281 + #define Usage_Con_ACSoftKeyRight Usage_i16(0x2a1) 1282 + #define Usage_Con_ACDesktopShowAllApplications Usage_i16(0x2a2) 1283 + #define Usage_Con_ACIdleKeepAlive Usage_i16(0x2b0) 1284 + #define Usage_Con_ExtendedKeyboardAttributesCollection Usage_i16(0x2c0) 1285 + #define Usage_Con_KeyboardFormFactor Usage_i16(0x2c1) 1286 + #define Usage_Con_KeyboardKeyType Usage_i16(0x2c2) 1287 + #define Usage_Con_KeyboardPhysicalLayout Usage_i16(0x2c3) 1288 + #define Usage_Con_VendorSpecificKeyboardPhysicalLayout Usage_i16(0x2c4) 1289 + #define Usage_Con_KeyboardIETFLanguageTagIndex Usage_i16(0x2c5) 1290 + #define Usage_Con_ImplementedKeyboardInputAssistControls Usage_i16(0x2c6) 1291 + #define Usage_Con_KeyboardInputAssistPrevious Usage_i16(0x2c7) 1292 + #define Usage_Con_KeyboardInputAssistNext Usage_i16(0x2c8) 1293 + #define Usage_Con_KeyboardInputAssistPreviousGroup Usage_i16(0x2c9) 1294 + #define Usage_Con_KeyboardInputAssistNextGroup Usage_i16(0x2ca) 1295 + #define Usage_Con_KeyboardInputAssistAccept Usage_i16(0x2cb) 1296 + #define Usage_Con_KeyboardInputAssistCancel Usage_i16(0x2cc) 1297 + #define Usage_Con_PrivacyScreenToggle Usage_i16(0x2d0) 1298 + #define Usage_Con_PrivacyScreenLevelDecrement Usage_i16(0x2d1) 1299 + #define Usage_Con_PrivacyScreenLevelIncrement Usage_i16(0x2d2) 1300 + #define Usage_Con_PrivacyScreenLevelMinimum Usage_i16(0x2d3) 1301 + #define Usage_Con_PrivacyScreenLevelMaximum Usage_i16(0x2d4) 1302 + #define Usage_Con_ContactEdited Usage_i16(0x500) 1303 + #define Usage_Con_ContactAdded Usage_i16(0x501) 1304 + #define Usage_Con_ContactRecordActive Usage_i16(0x502) 1305 + #define Usage_Con_ContactIndex Usage_i16(0x503) 1306 + #define Usage_Con_ContactNickname Usage_i16(0x504) 1307 + #define Usage_Con_ContactFirstName Usage_i16(0x505) 1308 + #define Usage_Con_ContactLastName Usage_i16(0x506) 1309 + #define Usage_Con_ContactFullName Usage_i16(0x507) 1310 + #define Usage_Con_ContactPhoneNumberPersonal Usage_i16(0x508) 1311 + #define Usage_Con_ContactPhoneNumberBusiness Usage_i16(0x509) 1312 + #define Usage_Con_ContactPhoneNumberMobile Usage_i16(0x50a) 1313 + #define Usage_Con_ContactPhoneNumberPager Usage_i16(0x50b) 1314 + #define Usage_Con_ContactPhoneNumberFax Usage_i16(0x50c) 1315 + #define Usage_Con_ContactPhoneNumberOther Usage_i16(0x50d) 1316 + #define Usage_Con_ContactEmailPersonal Usage_i16(0x50e) 1317 + #define Usage_Con_ContactEmailBusiness Usage_i16(0x50f) 1318 + #define Usage_Con_ContactEmailOther Usage_i16(0x510) 1319 + #define Usage_Con_ContactEmailMain Usage_i16(0x511) 1320 + #define Usage_Con_ContactSpeedDialNumber Usage_i16(0x512) 1321 + #define Usage_Con_ContactStatusFlag Usage_i16(0x513) 1322 + #define Usage_Con_ContactMisc Usage_i16(0x514) 1323 + #define Usage_Dig_Digitizer Usage_i8(0x1) 1324 + #define Usage_Dig_Pen Usage_i8(0x2) 1325 + #define Usage_Dig_LightPen Usage_i8(0x3) 1326 + #define Usage_Dig_TouchScreen Usage_i8(0x4) 1327 + #define Usage_Dig_TouchPad Usage_i8(0x5) 1328 + #define Usage_Dig_Whiteboard Usage_i8(0x6) 1329 + #define Usage_Dig_CoordinateMeasuringMachine Usage_i8(0x7) 1330 + #define Usage_Dig_ThreeDDigitizer Usage_i8(0x8) 1331 + #define Usage_Dig_StereoPlotter Usage_i8(0x9) 1332 + #define Usage_Dig_ArticulatedArm Usage_i8(0xa) 1333 + #define Usage_Dig_Armature Usage_i8(0xb) 1334 + #define Usage_Dig_MultiplePointDigitizer Usage_i8(0xc) 1335 + #define Usage_Dig_FreeSpaceWand Usage_i8(0xd) 1336 + #define Usage_Dig_DeviceConfiguration Usage_i8(0xe) 1337 + #define Usage_Dig_CapacitiveHeatMapDigitizer Usage_i8(0xf) 1338 + #define Usage_Dig_Stylus Usage_i8(0x20) 1339 + #define Usage_Dig_Puck Usage_i8(0x21) 1340 + #define Usage_Dig_Finger Usage_i8(0x22) 1341 + #define Usage_Dig_Devicesettings Usage_i8(0x23) 1342 + #define Usage_Dig_CharacterGesture Usage_i8(0x24) 1343 + #define Usage_Dig_TipPressure Usage_i8(0x30) 1344 + #define Usage_Dig_BarrelPressure Usage_i8(0x31) 1345 + #define Usage_Dig_InRange Usage_i8(0x32) 1346 + #define Usage_Dig_Touch Usage_i8(0x33) 1347 + #define Usage_Dig_Untouch Usage_i8(0x34) 1348 + #define Usage_Dig_Tap Usage_i8(0x35) 1349 + #define Usage_Dig_Quality Usage_i8(0x36) 1350 + #define Usage_Dig_DataValid Usage_i8(0x37) 1351 + #define Usage_Dig_TransducerIndex Usage_i8(0x38) 1352 + #define Usage_Dig_TabletFunctionKeys Usage_i8(0x39) 1353 + #define Usage_Dig_ProgramChangeKeys Usage_i8(0x3a) 1354 + #define Usage_Dig_BatteryStrength Usage_i8(0x3b) 1355 + #define Usage_Dig_Invert Usage_i8(0x3c) 1356 + #define Usage_Dig_XTilt Usage_i8(0x3d) 1357 + #define Usage_Dig_YTilt Usage_i8(0x3e) 1358 + #define Usage_Dig_Azimuth Usage_i8(0x3f) 1359 + #define Usage_Dig_Altitude Usage_i8(0x40) 1360 + #define Usage_Dig_Twist Usage_i8(0x41) 1361 + #define Usage_Dig_TipSwitch Usage_i8(0x42) 1362 + #define Usage_Dig_SecondaryTipSwitch Usage_i8(0x43) 1363 + #define Usage_Dig_BarrelSwitch Usage_i8(0x44) 1364 + #define Usage_Dig_Eraser Usage_i8(0x45) 1365 + #define Usage_Dig_TabletPick Usage_i8(0x46) 1366 + #define Usage_Dig_TouchValid Usage_i8(0x47) 1367 + #define Usage_Dig_Width Usage_i8(0x48) 1368 + #define Usage_Dig_Height Usage_i8(0x49) 1369 + #define Usage_Dig_ContactIdentifier Usage_i8(0x51) 1370 + #define Usage_Dig_DeviceMode Usage_i8(0x52) 1371 + #define Usage_Dig_DeviceIdentifier Usage_i8(0x53) 1372 + #define Usage_Dig_ContactCount Usage_i8(0x54) 1373 + #define Usage_Dig_ContactCountMaximum Usage_i8(0x55) 1374 + #define Usage_Dig_ScanTime Usage_i8(0x56) 1375 + #define Usage_Dig_SurfaceSwitch Usage_i8(0x57) 1376 + #define Usage_Dig_ButtonSwitch Usage_i8(0x58) 1377 + #define Usage_Dig_PadType Usage_i8(0x59) 1378 + #define Usage_Dig_SecondaryBarrelSwitch Usage_i8(0x5a) 1379 + #define Usage_Dig_TransducerSerialNumber Usage_i8(0x5b) 1380 + #define Usage_Dig_PreferredColor Usage_i8(0x5c) 1381 + #define Usage_Dig_PreferredColorisLocked Usage_i8(0x5d) 1382 + #define Usage_Dig_PreferredLineWidth Usage_i8(0x5e) 1383 + #define Usage_Dig_PreferredLineWidthisLocked Usage_i8(0x5f) 1384 + #define Usage_Dig_LatencyMode Usage_i8(0x60) 1385 + #define Usage_Dig_GestureCharacterQuality Usage_i8(0x61) 1386 + #define Usage_Dig_CharacterGestureDataLength Usage_i8(0x62) 1387 + #define Usage_Dig_CharacterGestureData Usage_i8(0x63) 1388 + #define Usage_Dig_GestureCharacterEncoding Usage_i8(0x64) 1389 + #define Usage_Dig_UTF8CharacterGestureEncoding Usage_i8(0x65) 1390 + #define Usage_Dig_UTF16LittleEndianCharacterGestureEncoding Usage_i8(0x66) 1391 + #define Usage_Dig_UTF16BigEndianCharacterGestureEncoding Usage_i8(0x67) 1392 + #define Usage_Dig_UTF32LittleEndianCharacterGestureEncoding Usage_i8(0x68) 1393 + #define Usage_Dig_UTF32BigEndianCharacterGestureEncoding Usage_i8(0x69) 1394 + #define Usage_Dig_CapacitiveHeatMapProtocolVendorID Usage_i8(0x6a) 1395 + #define Usage_Dig_CapacitiveHeatMapProtocolVersion Usage_i8(0x6b) 1396 + #define Usage_Dig_CapacitiveHeatMapFrameData Usage_i8(0x6c) 1397 + #define Usage_Dig_GestureCharacterEnable Usage_i8(0x6d) 1398 + #define Usage_Dig_TransducerSerialNumberPart2 Usage_i8(0x6e) 1399 + #define Usage_Dig_NoPreferredColor Usage_i8(0x6f) 1400 + #define Usage_Dig_PreferredLineStyle Usage_i8(0x70) 1401 + #define Usage_Dig_PreferredLineStyleisLocked Usage_i8(0x71) 1402 + #define Usage_Dig_Ink Usage_i8(0x72) 1403 + #define Usage_Dig_Pencil Usage_i8(0x73) 1404 + #define Usage_Dig_Highlighter Usage_i8(0x74) 1405 + #define Usage_Dig_ChiselMarker Usage_i8(0x75) 1406 + #define Usage_Dig_Brush Usage_i8(0x76) 1407 + #define Usage_Dig_NoPreference Usage_i8(0x77) 1408 + #define Usage_Dig_DigitizerDiagnostic Usage_i8(0x80) 1409 + #define Usage_Dig_DigitizerError Usage_i8(0x81) 1410 + #define Usage_Dig_ErrNormalStatus Usage_i8(0x82) 1411 + #define Usage_Dig_ErrTransducersExceeded Usage_i8(0x83) 1412 + #define Usage_Dig_ErrFullTransFeaturesUnavailable Usage_i8(0x84) 1413 + #define Usage_Dig_ErrChargeLow Usage_i8(0x85) 1414 + #define Usage_Dig_TransducerSoftwareInfo Usage_i8(0x90) 1415 + #define Usage_Dig_TransducerVendorId Usage_i8(0x91) 1416 + #define Usage_Dig_TransducerProductId Usage_i8(0x92) 1417 + #define Usage_Dig_DeviceSupportedProtocols Usage_i8(0x93) 1418 + #define Usage_Dig_TransducerSupportedProtocols Usage_i8(0x94) 1419 + #define Usage_Dig_NoProtocol Usage_i8(0x95) 1420 + #define Usage_Dig_WacomAESProtocol Usage_i8(0x96) 1421 + #define Usage_Dig_USIProtocol Usage_i8(0x97) 1422 + #define Usage_Dig_MicrosoftPenProtocol Usage_i8(0x98) 1423 + #define Usage_Dig_SupportedReportRates Usage_i8(0xa0) 1424 + #define Usage_Dig_ReportRate Usage_i8(0xa1) 1425 + #define Usage_Dig_TransducerConnected Usage_i8(0xa2) 1426 + #define Usage_Dig_SwitchDisabled Usage_i8(0xa3) 1427 + #define Usage_Dig_SwitchUnimplemented Usage_i8(0xa4) 1428 + #define Usage_Dig_TransducerSwitches Usage_i8(0xa5) 1429 + #define Usage_Dig_TransducerIndexSelector Usage_i8(0xa6) 1430 + #define Usage_Dig_ButtonPressThreshold Usage_i8(0xb0) 1431 + #define Usage_Hap_SimpleHapticController Usage_i8(0x1) 1432 + #define Usage_Hap_WaveformList Usage_i8(0x10) 1433 + #define Usage_Hap_DurationList Usage_i8(0x11) 1434 + #define Usage_Hap_AutoTrigger Usage_i8(0x20) 1435 + #define Usage_Hap_ManualTrigger Usage_i8(0x21) 1436 + #define Usage_Hap_AutoTriggerAssociatedControl Usage_i8(0x22) 1437 + #define Usage_Hap_Intensity Usage_i8(0x23) 1438 + #define Usage_Hap_RepeatCount Usage_i8(0x24) 1439 + #define Usage_Hap_RetriggerPeriod Usage_i8(0x25) 1440 + #define Usage_Hap_WaveformVendorPage Usage_i8(0x26) 1441 + #define Usage_Hap_WaveformVendorID Usage_i8(0x27) 1442 + #define Usage_Hap_WaveformCutoffTime Usage_i8(0x28) 1443 + #define Usage_Hap_WaveformNone Usage_i16(0x1001) 1444 + #define Usage_Hap_WaveformStop Usage_i16(0x1002) 1445 + #define Usage_Hap_WaveformClick Usage_i16(0x1003) 1446 + #define Usage_Hap_WaveformBuzzContinuous Usage_i16(0x1004) 1447 + #define Usage_Hap_WaveformRumbleContinuous Usage_i16(0x1005) 1448 + #define Usage_Hap_WaveformPress Usage_i16(0x1006) 1449 + #define Usage_Hap_WaveformRelease Usage_i16(0x1007) 1450 + #define Usage_Hap_WaveformHover Usage_i16(0x1008) 1451 + #define Usage_Hap_WaveformSuccess Usage_i16(0x1009) 1452 + #define Usage_Hap_WaveformError Usage_i16(0x100a) 1453 + #define Usage_Hap_WaveformInkContinuous Usage_i16(0x100b) 1454 + #define Usage_Hap_WaveformPencilContinuous Usage_i16(0x100c) 1455 + #define Usage_Hap_WaveformMarkerContinuous Usage_i16(0x100d) 1456 + #define Usage_Hap_WaveformChiselMarkerContinuous Usage_i16(0x100e) 1457 + #define Usage_Hap_WaveformBrushContinuous Usage_i16(0x100f) 1458 + #define Usage_Hap_WaveformEraserContinuous Usage_i16(0x1010) 1459 + #define Usage_Hap_WaveformSparkleContinuous Usage_i16(0x1011) 1460 + #define Usage_PID_PhysicalInputDevice Usage_i8(0x1) 1461 + #define Usage_PID_Normal Usage_i8(0x20) 1462 + #define Usage_PID_SetEffectReport Usage_i8(0x21) 1463 + #define Usage_PID_EffectParameterBlockIndex Usage_i8(0x22) 1464 + #define Usage_PID_ParameterBlockOffset Usage_i8(0x23) 1465 + #define Usage_PID_ROMFlag Usage_i8(0x24) 1466 + #define Usage_PID_EffectType Usage_i8(0x25) 1467 + #define Usage_PID_ETConstantForce Usage_i8(0x26) 1468 + #define Usage_PID_ETRamp Usage_i8(0x27) 1469 + #define Usage_PID_ETCustomForce Usage_i8(0x28) 1470 + #define Usage_PID_ETSquare Usage_i8(0x30) 1471 + #define Usage_PID_ETSine Usage_i8(0x31) 1472 + #define Usage_PID_ETTriangle Usage_i8(0x32) 1473 + #define Usage_PID_ETSawtoothUp Usage_i8(0x33) 1474 + #define Usage_PID_ETSawtoothDown Usage_i8(0x34) 1475 + #define Usage_PID_ETSpring Usage_i8(0x40) 1476 + #define Usage_PID_ETDamper Usage_i8(0x41) 1477 + #define Usage_PID_ETInertia Usage_i8(0x42) 1478 + #define Usage_PID_ETFriction Usage_i8(0x43) 1479 + #define Usage_PID_Duration Usage_i8(0x50) 1480 + #define Usage_PID_SamplePeriod Usage_i8(0x51) 1481 + #define Usage_PID_Gain Usage_i8(0x52) 1482 + #define Usage_PID_TriggerButton Usage_i8(0x53) 1483 + #define Usage_PID_TriggerRepeatInterval Usage_i8(0x54) 1484 + #define Usage_PID_AxesEnable Usage_i8(0x55) 1485 + #define Usage_PID_DirectionEnable Usage_i8(0x56) 1486 + #define Usage_PID_Direction Usage_i8(0x57) 1487 + #define Usage_PID_TypeSpecificBlockOffset Usage_i8(0x58) 1488 + #define Usage_PID_BlockType Usage_i8(0x59) 1489 + #define Usage_PID_SetEnvelopeReport Usage_i8(0x5a) 1490 + #define Usage_PID_AttackLevel Usage_i8(0x5b) 1491 + #define Usage_PID_AttackTime Usage_i8(0x5c) 1492 + #define Usage_PID_FadeLevel Usage_i8(0x5d) 1493 + #define Usage_PID_FadeTime Usage_i8(0x5e) 1494 + #define Usage_PID_SetConditionReport Usage_i8(0x5f) 1495 + #define Usage_PID_CenterPointOffset Usage_i8(0x60) 1496 + #define Usage_PID_PositiveCoefficient Usage_i8(0x61) 1497 + #define Usage_PID_NegativeCoefficient Usage_i8(0x62) 1498 + #define Usage_PID_PositiveSaturation Usage_i8(0x63) 1499 + #define Usage_PID_NegativeSaturation Usage_i8(0x64) 1500 + #define Usage_PID_DeadBand Usage_i8(0x65) 1501 + #define Usage_PID_DownloadForceSample Usage_i8(0x66) 1502 + #define Usage_PID_IsochCustomForceEnable Usage_i8(0x67) 1503 + #define Usage_PID_CustomForceDataReport Usage_i8(0x68) 1504 + #define Usage_PID_CustomForceData Usage_i8(0x69) 1505 + #define Usage_PID_CustomForceVendorDefinedData Usage_i8(0x6a) 1506 + #define Usage_PID_SetCustomForceReport Usage_i8(0x6b) 1507 + #define Usage_PID_CustomForceDataOffset Usage_i8(0x6c) 1508 + #define Usage_PID_SampleCount Usage_i8(0x6d) 1509 + #define Usage_PID_SetPeriodicReport Usage_i8(0x6e) 1510 + #define Usage_PID_Offset Usage_i8(0x6f) 1511 + #define Usage_PID_Magnitude Usage_i8(0x70) 1512 + #define Usage_PID_Phase Usage_i8(0x71) 1513 + #define Usage_PID_Period Usage_i8(0x72) 1514 + #define Usage_PID_SetConstantForceReport Usage_i8(0x73) 1515 + #define Usage_PID_SetRampForceReport Usage_i8(0x74) 1516 + #define Usage_PID_RampStart Usage_i8(0x75) 1517 + #define Usage_PID_RampEnd Usage_i8(0x76) 1518 + #define Usage_PID_EffectOperationReport Usage_i8(0x77) 1519 + #define Usage_PID_EffectOperation Usage_i8(0x78) 1520 + #define Usage_PID_OpEffectStart Usage_i8(0x79) 1521 + #define Usage_PID_OpEffectStartSolo Usage_i8(0x7a) 1522 + #define Usage_PID_OpEffectStop Usage_i8(0x7b) 1523 + #define Usage_PID_LoopCount Usage_i8(0x7c) 1524 + #define Usage_PID_DeviceGainReport Usage_i8(0x7d) 1525 + #define Usage_PID_DeviceGain Usage_i8(0x7e) 1526 + #define Usage_PID_ParameterBlockPoolsReport Usage_i8(0x7f) 1527 + #define Usage_PID_RAMPoolSize Usage_i8(0x80) 1528 + #define Usage_PID_ROMPoolSize Usage_i8(0x81) 1529 + #define Usage_PID_ROMEffectBlockCount Usage_i8(0x82) 1530 + #define Usage_PID_SimultaneousEffectsMax Usage_i8(0x83) 1531 + #define Usage_PID_PoolAlignment Usage_i8(0x84) 1532 + #define Usage_PID_ParameterBlockMoveReport Usage_i8(0x85) 1533 + #define Usage_PID_MoveSource Usage_i8(0x86) 1534 + #define Usage_PID_MoveDestination Usage_i8(0x87) 1535 + #define Usage_PID_MoveLength Usage_i8(0x88) 1536 + #define Usage_PID_EffectParameterBlockLoadReport Usage_i8(0x89) 1537 + #define Usage_PID_EffectParameterBlockLoadStatus Usage_i8(0x8b) 1538 + #define Usage_PID_BlockLoadSuccess Usage_i8(0x8c) 1539 + #define Usage_PID_BlockLoadFull Usage_i8(0x8d) 1540 + #define Usage_PID_BlockLoadError Usage_i8(0x8e) 1541 + #define Usage_PID_BlockHandle Usage_i8(0x8f) 1542 + #define Usage_PID_EffectParameterBlockFreeReport Usage_i8(0x90) 1543 + #define Usage_PID_TypeSpecificBlockHandle Usage_i8(0x91) 1544 + #define Usage_PID_PIDStateReport Usage_i8(0x92) 1545 + #define Usage_PID_EffectPlaying Usage_i8(0x94) 1546 + #define Usage_PID_PIDDeviceControlReport Usage_i8(0x95) 1547 + #define Usage_PID_PIDDeviceControl Usage_i8(0x96) 1548 + #define Usage_PID_DCEnableActuators Usage_i8(0x97) 1549 + #define Usage_PID_DCDisableActuators Usage_i8(0x98) 1550 + #define Usage_PID_DCStopAllEffects Usage_i8(0x99) 1551 + #define Usage_PID_DCReset Usage_i8(0x9a) 1552 + #define Usage_PID_DCPause Usage_i8(0x9b) 1553 + #define Usage_PID_DCContinue Usage_i8(0x9c) 1554 + #define Usage_PID_DevicePaused Usage_i8(0x9f) 1555 + #define Usage_PID_ActuatorsEnabled Usage_i8(0xa0) 1556 + #define Usage_PID_SafetySwitch Usage_i8(0xa4) 1557 + #define Usage_PID_ActuatorOverrideSwitch Usage_i8(0xa5) 1558 + #define Usage_PID_ActuatorPower Usage_i8(0xa6) 1559 + #define Usage_PID_StartDelay Usage_i8(0xa7) 1560 + #define Usage_PID_ParameterBlockSize Usage_i8(0xa8) 1561 + #define Usage_PID_DeviceManagedPool Usage_i8(0xa9) 1562 + #define Usage_PID_SharedParameterBlocks Usage_i8(0xaa) 1563 + #define Usage_PID_CreateNewEffectParameterBlockReport Usage_i8(0xab) 1564 + #define Usage_PID_RAMPoolAvailable Usage_i8(0xac) 1565 + #define Usage_SC_SocControl Usage_i8(0x1) 1566 + #define Usage_SC_FirmwareTransfer Usage_i8(0x2) 1567 + #define Usage_SC_FirmwareFileId Usage_i8(0x3) 1568 + #define Usage_SC_FileOffsetInBytes Usage_i8(0x4) 1569 + #define Usage_SC_FileTransferSizeMaxInBytes Usage_i8(0x5) 1570 + #define Usage_SC_FilePayload Usage_i8(0x6) 1571 + #define Usage_SC_FilePayloadSizeInBytes Usage_i8(0x7) 1572 + #define Usage_SC_FilePayloadContainsLastBytes Usage_i8(0x8) 1573 + #define Usage_SC_FileTransferStop Usage_i8(0x9) 1574 + #define Usage_SC_FileTransferTillEnd Usage_i8(0xa) 1575 + #define Usage_EHT_EyeTracker Usage_i8(0x1) 1576 + #define Usage_EHT_HeadTracker Usage_i8(0x2) 1577 + #define Usage_EHT_TrackingData Usage_i8(0x10) 1578 + #define Usage_EHT_Capabilities Usage_i8(0x11) 1579 + #define Usage_EHT_Configuration Usage_i8(0x12) 1580 + #define Usage_EHT_Status Usage_i8(0x13) 1581 + #define Usage_EHT_Control Usage_i8(0x14) 1582 + #define Usage_EHT_SensorTimestamp Usage_i8(0x20) 1583 + #define Usage_EHT_PositionX Usage_i8(0x21) 1584 + #define Usage_EHT_PositionY Usage_i8(0x22) 1585 + #define Usage_EHT_PositionZ Usage_i8(0x23) 1586 + #define Usage_EHT_GazePoint Usage_i8(0x24) 1587 + #define Usage_EHT_LeftEyePosition Usage_i8(0x25) 1588 + #define Usage_EHT_RightEyePosition Usage_i8(0x26) 1589 + #define Usage_EHT_HeadPosition Usage_i8(0x27) 1590 + #define Usage_EHT_HeadDirectionPoint Usage_i8(0x28) 1591 + #define Usage_EHT_RotationaboutXaxis Usage_i8(0x29) 1592 + #define Usage_EHT_RotationaboutYaxis Usage_i8(0x2a) 1593 + #define Usage_EHT_RotationaboutZaxis Usage_i8(0x2b) 1594 + #define Usage_EHT_TrackerQuality Usage_i16(0x100) 1595 + #define Usage_EHT_MinimumTrackingDistance Usage_i16(0x101) 1596 + #define Usage_EHT_OptimumTrackingDistance Usage_i16(0x102) 1597 + #define Usage_EHT_MaximumTrackingDistance Usage_i16(0x103) 1598 + #define Usage_EHT_MaximumScreenPlaneWidth Usage_i16(0x104) 1599 + #define Usage_EHT_MaximumScreenPlaneHeight Usage_i16(0x105) 1600 + #define Usage_EHT_DisplayManufacturerID Usage_i16(0x200) 1601 + #define Usage_EHT_DisplayProductID Usage_i16(0x201) 1602 + #define Usage_EHT_DisplaySerialNumber Usage_i16(0x202) 1603 + #define Usage_EHT_DisplayManufacturerDate Usage_i16(0x203) 1604 + #define Usage_EHT_CalibratedScreenWidth Usage_i16(0x204) 1605 + #define Usage_EHT_CalibratedScreenHeight Usage_i16(0x205) 1606 + #define Usage_EHT_SamplingFrequency Usage_i16(0x300) 1607 + #define Usage_EHT_ConfigurationStatus Usage_i16(0x301) 1608 + #define Usage_EHT_DeviceModeRequest Usage_i16(0x400) 1609 + #define Usage_AD_AlphanumericDisplay Usage_i8(0x1) 1610 + #define Usage_AD_AuxiliaryDisplay Usage_i8(0x2) 1611 + #define Usage_AD_DisplayAttributesReport Usage_i8(0x20) 1612 + #define Usage_AD_ASCIICharacterSet Usage_i8(0x21) 1613 + #define Usage_AD_DataReadBack Usage_i8(0x22) 1614 + #define Usage_AD_FontReadBack Usage_i8(0x23) 1615 + #define Usage_AD_DisplayControlReport Usage_i8(0x24) 1616 + #define Usage_AD_ClearDisplay Usage_i8(0x25) 1617 + #define Usage_AD_DisplayEnable Usage_i8(0x26) 1618 + #define Usage_AD_ScreenSaverDelay Usage_i8(0x27) 1619 + #define Usage_AD_ScreenSaverEnable Usage_i8(0x28) 1620 + #define Usage_AD_VerticalScroll Usage_i8(0x29) 1621 + #define Usage_AD_HorizontalScroll Usage_i8(0x2a) 1622 + #define Usage_AD_CharacterReport Usage_i8(0x2b) 1623 + #define Usage_AD_DisplayData Usage_i8(0x2c) 1624 + #define Usage_AD_DisplayStatus Usage_i8(0x2d) 1625 + #define Usage_AD_StatNotReady Usage_i8(0x2e) 1626 + #define Usage_AD_StatReady Usage_i8(0x2f) 1627 + #define Usage_AD_ErrNotaloadablecharacter Usage_i8(0x30) 1628 + #define Usage_AD_ErrFontdatacannotberead Usage_i8(0x31) 1629 + #define Usage_AD_CursorPositionReport Usage_i8(0x32) 1630 + #define Usage_AD_Row Usage_i8(0x33) 1631 + #define Usage_AD_Column Usage_i8(0x34) 1632 + #define Usage_AD_Rows Usage_i8(0x35) 1633 + #define Usage_AD_Columns Usage_i8(0x36) 1634 + #define Usage_AD_CursorPixelPositioning Usage_i8(0x37) 1635 + #define Usage_AD_CursorMode Usage_i8(0x38) 1636 + #define Usage_AD_CursorEnable Usage_i8(0x39) 1637 + #define Usage_AD_CursorBlink Usage_i8(0x3a) 1638 + #define Usage_AD_FontReport Usage_i8(0x3b) 1639 + #define Usage_AD_FontData Usage_i8(0x3c) 1640 + #define Usage_AD_CharacterWidth Usage_i8(0x3d) 1641 + #define Usage_AD_CharacterHeight Usage_i8(0x3e) 1642 + #define Usage_AD_CharacterSpacingHorizontal Usage_i8(0x3f) 1643 + #define Usage_AD_CharacterSpacingVertical Usage_i8(0x40) 1644 + #define Usage_AD_UnicodeCharacterSet Usage_i8(0x41) 1645 + #define Usage_AD_Font7Segment Usage_i8(0x42) 1646 + #define Usage_AD_SevenSegmentDirectMap Usage_i8(0x43) 1647 + #define Usage_AD_Font14Segment Usage_i8(0x44) 1648 + #define Usage_AD_One4SegmentDirectMap Usage_i8(0x45) 1649 + #define Usage_AD_DisplayBrightness Usage_i8(0x46) 1650 + #define Usage_AD_DisplayContrast Usage_i8(0x47) 1651 + #define Usage_AD_CharacterAttribute Usage_i8(0x48) 1652 + #define Usage_AD_AttributeReadback Usage_i8(0x49) 1653 + #define Usage_AD_AttributeData Usage_i8(0x4a) 1654 + #define Usage_AD_CharAttrEnhance Usage_i8(0x4b) 1655 + #define Usage_AD_CharAttrUnderline Usage_i8(0x4c) 1656 + #define Usage_AD_CharAttrBlink Usage_i8(0x4d) 1657 + #define Usage_AD_BitmapSizeX Usage_i8(0x80) 1658 + #define Usage_AD_BitmapSizeY Usage_i8(0x81) 1659 + #define Usage_AD_MaxBlitSize Usage_i8(0x82) 1660 + #define Usage_AD_BitDepthFormat Usage_i8(0x83) 1661 + #define Usage_AD_DisplayOrientation Usage_i8(0x84) 1662 + #define Usage_AD_PaletteReport Usage_i8(0x85) 1663 + #define Usage_AD_PaletteDataSize Usage_i8(0x86) 1664 + #define Usage_AD_PaletteDataOffset Usage_i8(0x87) 1665 + #define Usage_AD_PaletteData Usage_i8(0x88) 1666 + #define Usage_AD_BlitReport Usage_i8(0x8a) 1667 + #define Usage_AD_BlitRectangleX1 Usage_i8(0x8b) 1668 + #define Usage_AD_BlitRectangleY1 Usage_i8(0x8c) 1669 + #define Usage_AD_BlitRectangleX2 Usage_i8(0x8d) 1670 + #define Usage_AD_BlitRectangleY2 Usage_i8(0x8e) 1671 + #define Usage_AD_BlitData Usage_i8(0x8f) 1672 + #define Usage_AD_SoftButton Usage_i8(0x90) 1673 + #define Usage_AD_SoftButtonID Usage_i8(0x91) 1674 + #define Usage_AD_SoftButtonSide Usage_i8(0x92) 1675 + #define Usage_AD_SoftButtonOffset1 Usage_i8(0x93) 1676 + #define Usage_AD_SoftButtonOffset2 Usage_i8(0x94) 1677 + #define Usage_AD_SoftButtonReport Usage_i8(0x95) 1678 + #define Usage_AD_SoftKeys Usage_i8(0xc2) 1679 + #define Usage_AD_DisplayDataExtensions Usage_i8(0xcc) 1680 + #define Usage_AD_CharacterMapping Usage_i8(0xcf) 1681 + #define Usage_AD_UnicodeEquivalent Usage_i8(0xdd) 1682 + #define Usage_AD_CharacterPageMapping Usage_i8(0xdf) 1683 + #define Usage_AD_RequestReport Usage_i16(0xff) 1684 + #define Usage_Sen_Sensor Usage_i8(0x1) 1685 + #define Usage_Sen_Biometric Usage_i8(0x10) 1686 + #define Usage_Sen_BiometricHumanPresence Usage_i8(0x11) 1687 + #define Usage_Sen_BiometricHumanProximity Usage_i8(0x12) 1688 + #define Usage_Sen_BiometricHumanTouch Usage_i8(0x13) 1689 + #define Usage_Sen_BiometricBloodPressure Usage_i8(0x14) 1690 + #define Usage_Sen_BiometricBodyTemperature Usage_i8(0x15) 1691 + #define Usage_Sen_BiometricHeartRate Usage_i8(0x16) 1692 + #define Usage_Sen_BiometricHeartRateVariability Usage_i8(0x17) 1693 + #define Usage_Sen_BiometricPeripheralOxygenSaturation Usage_i8(0x18) 1694 + #define Usage_Sen_BiometricRespiratoryRate Usage_i8(0x19) 1695 + #define Usage_Sen_Electrical Usage_i8(0x20) 1696 + #define Usage_Sen_ElectricalCapacitance Usage_i8(0x21) 1697 + #define Usage_Sen_ElectricalCurrent Usage_i8(0x22) 1698 + #define Usage_Sen_ElectricalPower Usage_i8(0x23) 1699 + #define Usage_Sen_ElectricalInductance Usage_i8(0x24) 1700 + #define Usage_Sen_ElectricalResistance Usage_i8(0x25) 1701 + #define Usage_Sen_ElectricalVoltage Usage_i8(0x26) 1702 + #define Usage_Sen_ElectricalPotentiometer Usage_i8(0x27) 1703 + #define Usage_Sen_ElectricalFrequency Usage_i8(0x28) 1704 + #define Usage_Sen_ElectricalPeriod Usage_i8(0x29) 1705 + #define Usage_Sen_Environmental Usage_i8(0x30) 1706 + #define Usage_Sen_EnvironmentalAtmosphericPressure Usage_i8(0x31) 1707 + #define Usage_Sen_EnvironmentalHumidity Usage_i8(0x32) 1708 + #define Usage_Sen_EnvironmentalTemperature Usage_i8(0x33) 1709 + #define Usage_Sen_EnvironmentalWindDirection Usage_i8(0x34) 1710 + #define Usage_Sen_EnvironmentalWindSpeed Usage_i8(0x35) 1711 + #define Usage_Sen_EnvironmentalAirQuality Usage_i8(0x36) 1712 + #define Usage_Sen_EnvironmentalHeatIndex Usage_i8(0x37) 1713 + #define Usage_Sen_EnvironmentalSurfaceTemperature Usage_i8(0x38) 1714 + #define Usage_Sen_EnvironmentalVolatileOrganicCompounds Usage_i8(0x39) 1715 + #define Usage_Sen_EnvironmentalObjectPresence Usage_i8(0x3a) 1716 + #define Usage_Sen_EnvironmentalObjectProximity Usage_i8(0x3b) 1717 + #define Usage_Sen_Light Usage_i8(0x40) 1718 + #define Usage_Sen_LightAmbientLight Usage_i8(0x41) 1719 + #define Usage_Sen_LightConsumerInfrared Usage_i8(0x42) 1720 + #define Usage_Sen_LightInfraredLight Usage_i8(0x43) 1721 + #define Usage_Sen_LightVisibleLight Usage_i8(0x44) 1722 + #define Usage_Sen_LightUltravioletLight Usage_i8(0x45) 1723 + #define Usage_Sen_Location Usage_i8(0x50) 1724 + #define Usage_Sen_LocationBroadcast Usage_i8(0x51) 1725 + #define Usage_Sen_LocationDeadReckoning Usage_i8(0x52) 1726 + #define Usage_Sen_LocationGPSGlobalPositioningSystem Usage_i8(0x53) 1727 + #define Usage_Sen_LocationLookup Usage_i8(0x54) 1728 + #define Usage_Sen_LocationOther Usage_i8(0x55) 1729 + #define Usage_Sen_LocationStatic Usage_i8(0x56) 1730 + #define Usage_Sen_LocationTriangulation Usage_i8(0x57) 1731 + #define Usage_Sen_Mechanical Usage_i8(0x60) 1732 + #define Usage_Sen_MechanicalBooleanSwitch Usage_i8(0x61) 1733 + #define Usage_Sen_MechanicalBooleanSwitchArray Usage_i8(0x62) 1734 + #define Usage_Sen_MechanicalMultivalueSwitch Usage_i8(0x63) 1735 + #define Usage_Sen_MechanicalForce Usage_i8(0x64) 1736 + #define Usage_Sen_MechanicalPressure Usage_i8(0x65) 1737 + #define Usage_Sen_MechanicalStrain Usage_i8(0x66) 1738 + #define Usage_Sen_MechanicalWeight Usage_i8(0x67) 1739 + #define Usage_Sen_MechanicalHapticVibrator Usage_i8(0x68) 1740 + #define Usage_Sen_MechanicalHallEffectSwitch Usage_i8(0x69) 1741 + #define Usage_Sen_Motion Usage_i8(0x70) 1742 + #define Usage_Sen_MotionAccelerometer1D Usage_i8(0x71) 1743 + #define Usage_Sen_MotionAccelerometer2D Usage_i8(0x72) 1744 + #define Usage_Sen_MotionAccelerometer3D Usage_i8(0x73) 1745 + #define Usage_Sen_MotionGyrometer1D Usage_i8(0x74) 1746 + #define Usage_Sen_MotionGyrometer2D Usage_i8(0x75) 1747 + #define Usage_Sen_MotionGyrometer3D Usage_i8(0x76) 1748 + #define Usage_Sen_MotionMotionDetector Usage_i8(0x77) 1749 + #define Usage_Sen_MotionSpeedometer Usage_i8(0x78) 1750 + #define Usage_Sen_MotionAccelerometer Usage_i8(0x79) 1751 + #define Usage_Sen_MotionGyrometer Usage_i8(0x7a) 1752 + #define Usage_Sen_MotionGravityVector Usage_i8(0x7b) 1753 + #define Usage_Sen_MotionLinearAccelerometer Usage_i8(0x7c) 1754 + #define Usage_Sen_Orientation Usage_i8(0x80) 1755 + #define Usage_Sen_OrientationCompass1D Usage_i8(0x81) 1756 + #define Usage_Sen_OrientationCompass2D Usage_i8(0x82) 1757 + #define Usage_Sen_OrientationCompass3D Usage_i8(0x83) 1758 + #define Usage_Sen_OrientationInclinometer1D Usage_i8(0x84) 1759 + #define Usage_Sen_OrientationInclinometer2D Usage_i8(0x85) 1760 + #define Usage_Sen_OrientationInclinometer3D Usage_i8(0x86) 1761 + #define Usage_Sen_OrientationDistance1D Usage_i8(0x87) 1762 + #define Usage_Sen_OrientationDistance2D Usage_i8(0x88) 1763 + #define Usage_Sen_OrientationDistance3D Usage_i8(0x89) 1764 + #define Usage_Sen_OrientationDeviceOrientation Usage_i8(0x8a) 1765 + #define Usage_Sen_OrientationCompass Usage_i8(0x8b) 1766 + #define Usage_Sen_OrientationInclinometer Usage_i8(0x8c) 1767 + #define Usage_Sen_OrientationDistance Usage_i8(0x8d) 1768 + #define Usage_Sen_OrientationRelativeOrientation Usage_i8(0x8e) 1769 + #define Usage_Sen_OrientationSimpleOrientation Usage_i8(0x8f) 1770 + #define Usage_Sen_Scanner Usage_i8(0x90) 1771 + #define Usage_Sen_ScannerBarcode Usage_i8(0x91) 1772 + #define Usage_Sen_ScannerRFID Usage_i8(0x92) 1773 + #define Usage_Sen_ScannerNFC Usage_i8(0x93) 1774 + #define Usage_Sen_Time Usage_i8(0xa0) 1775 + #define Usage_Sen_TimeAlarmTimer Usage_i8(0xa1) 1776 + #define Usage_Sen_TimeRealTimeClock Usage_i8(0xa2) 1777 + #define Usage_Sen_PersonalActivity Usage_i8(0xb0) 1778 + #define Usage_Sen_PersonalActivityActivityDetection Usage_i8(0xb1) 1779 + #define Usage_Sen_PersonalActivityDevicePosition Usage_i8(0xb2) 1780 + #define Usage_Sen_PersonalActivityFloorTracker Usage_i8(0xb3) 1781 + #define Usage_Sen_PersonalActivityPedometer Usage_i8(0xb4) 1782 + #define Usage_Sen_PersonalActivityStepDetection Usage_i8(0xb5) 1783 + #define Usage_Sen_OrientationExtended Usage_i8(0xc0) 1784 + #define Usage_Sen_OrientationExtendedGeomagneticOrientation Usage_i8(0xc1) 1785 + #define Usage_Sen_OrientationExtendedMagnetometer Usage_i8(0xc2) 1786 + #define Usage_Sen_Gesture Usage_i8(0xd0) 1787 + #define Usage_Sen_GestureChassisFlipGesture Usage_i8(0xd1) 1788 + #define Usage_Sen_GestureHingeFoldGesture Usage_i8(0xd2) 1789 + #define Usage_Sen_Other Usage_i8(0xe0) 1790 + #define Usage_Sen_OtherCustom Usage_i8(0xe1) 1791 + #define Usage_Sen_OtherGeneric Usage_i8(0xe2) 1792 + #define Usage_Sen_OtherGenericEnumerator Usage_i8(0xe3) 1793 + #define Usage_Sen_OtherHingeAngle Usage_i8(0xe4) 1794 + #define Usage_Sen_VendorReserved1 Usage_i8(0xf0) 1795 + #define Usage_Sen_VendorReserved2 Usage_i8(0xf1) 1796 + #define Usage_Sen_VendorReserved3 Usage_i8(0xf2) 1797 + #define Usage_Sen_VendorReserved4 Usage_i8(0xf3) 1798 + #define Usage_Sen_VendorReserved5 Usage_i8(0xf4) 1799 + #define Usage_Sen_VendorReserved6 Usage_i8(0xf5) 1800 + #define Usage_Sen_VendorReserved7 Usage_i8(0xf6) 1801 + #define Usage_Sen_VendorReserved8 Usage_i8(0xf7) 1802 + #define Usage_Sen_VendorReserved9 Usage_i8(0xf8) 1803 + #define Usage_Sen_VendorReserved10 Usage_i8(0xf9) 1804 + #define Usage_Sen_VendorReserved11 Usage_i8(0xfa) 1805 + #define Usage_Sen_VendorReserved12 Usage_i8(0xfb) 1806 + #define Usage_Sen_VendorReserved13 Usage_i8(0xfc) 1807 + #define Usage_Sen_VendorReserved14 Usage_i8(0xfd) 1808 + #define Usage_Sen_VendorReserved15 Usage_i8(0xfe) 1809 + #define Usage_Sen_VendorReserved16 Usage_i16(0xff) 1810 + #define Usage_Sen_Event Usage_i16(0x200) 1811 + #define Usage_Sen_EventSensorState Usage_i16(0x201) 1812 + #define Usage_Sen_EventSensorEvent Usage_i16(0x202) 1813 + #define Usage_Sen_Property Usage_i16(0x300) 1814 + #define Usage_Sen_PropertyFriendlyName Usage_i16(0x301) 1815 + #define Usage_Sen_PropertyPersistentUniqueID Usage_i16(0x302) 1816 + #define Usage_Sen_PropertySensorStatus Usage_i16(0x303) 1817 + #define Usage_Sen_PropertyMinimumReportInterval Usage_i16(0x304) 1818 + #define Usage_Sen_PropertySensorManufacturer Usage_i16(0x305) 1819 + #define Usage_Sen_PropertySensorModel Usage_i16(0x306) 1820 + #define Usage_Sen_PropertySensorSerialNumber Usage_i16(0x307) 1821 + #define Usage_Sen_PropertySensorDescription Usage_i16(0x308) 1822 + #define Usage_Sen_PropertySensorConnectionType Usage_i16(0x309) 1823 + #define Usage_Sen_PropertySensorDevicePath Usage_i16(0x30a) 1824 + #define Usage_Sen_PropertyHardwareRevision Usage_i16(0x30b) 1825 + #define Usage_Sen_PropertyFirmwareVersion Usage_i16(0x30c) 1826 + #define Usage_Sen_PropertyReleaseDate Usage_i16(0x30d) 1827 + #define Usage_Sen_PropertyReportInterval Usage_i16(0x30e) 1828 + #define Usage_Sen_PropertyChangeSensitivityAbsolute Usage_i16(0x30f) 1829 + #define Usage_Sen_PropertyChangeSensitivityPercentofRange Usage_i16(0x310) 1830 + #define Usage_Sen_PropertyChangeSensitivityPercentRelative Usage_i16(0x311) 1831 + #define Usage_Sen_PropertyAccuracy Usage_i16(0x312) 1832 + #define Usage_Sen_PropertyResolution Usage_i16(0x313) 1833 + #define Usage_Sen_PropertyMaximum Usage_i16(0x314) 1834 + #define Usage_Sen_PropertyMinimum Usage_i16(0x315) 1835 + #define Usage_Sen_PropertyReportingState Usage_i16(0x316) 1836 + #define Usage_Sen_PropertySamplingRate Usage_i16(0x317) 1837 + #define Usage_Sen_PropertyResponseCurve Usage_i16(0x318) 1838 + #define Usage_Sen_PropertyPowerState Usage_i16(0x319) 1839 + #define Usage_Sen_PropertyMaximumFIFOEvents Usage_i16(0x31a) 1840 + #define Usage_Sen_PropertyReportLatency Usage_i16(0x31b) 1841 + #define Usage_Sen_PropertyFlushFIFOEvents Usage_i16(0x31c) 1842 + #define Usage_Sen_PropertyMaximumPowerConsumption Usage_i16(0x31d) 1843 + #define Usage_Sen_PropertyIsPrimary Usage_i16(0x31e) 1844 + #define Usage_Sen_PropertyHumanPresenceDetectionType Usage_i16(0x31f) 1845 + #define Usage_Sen_DataFieldLocation Usage_i16(0x400) 1846 + #define Usage_Sen_DataFieldAltitudeAntennaSeaLevel Usage_i16(0x402) 1847 + #define Usage_Sen_DataFieldDifferentialReferenceStationID Usage_i16(0x403) 1848 + #define Usage_Sen_DataFieldAltitudeEllipsoidError Usage_i16(0x404) 1849 + #define Usage_Sen_DataFieldAltitudeEllipsoid Usage_i16(0x405) 1850 + #define Usage_Sen_DataFieldAltitudeSeaLevelError Usage_i16(0x406) 1851 + #define Usage_Sen_DataFieldAltitudeSeaLevel Usage_i16(0x407) 1852 + #define Usage_Sen_DataFieldDifferentialGPSDataAge Usage_i16(0x408) 1853 + #define Usage_Sen_DataFieldErrorRadius Usage_i16(0x409) 1854 + #define Usage_Sen_DataFieldFixQuality Usage_i16(0x40a) 1855 + #define Usage_Sen_DataFieldFixType Usage_i16(0x40b) 1856 + #define Usage_Sen_DataFieldGeoidalSeparation Usage_i16(0x40c) 1857 + #define Usage_Sen_DataFieldGPSOperationMode Usage_i16(0x40d) 1858 + #define Usage_Sen_DataFieldGPSSelectionMode Usage_i16(0x40e) 1859 + #define Usage_Sen_DataFieldGPSStatus Usage_i16(0x40f) 1860 + #define Usage_Sen_DataFieldPositionDilutionofPrecision Usage_i16(0x410) 1861 + #define Usage_Sen_DataFieldHorizontalDilutionofPrecision Usage_i16(0x411) 1862 + #define Usage_Sen_DataFieldVerticalDilutionofPrecision Usage_i16(0x412) 1863 + #define Usage_Sen_DataFieldLatitude Usage_i16(0x413) 1864 + #define Usage_Sen_DataFieldLongitude Usage_i16(0x414) 1865 + #define Usage_Sen_DataFieldTrueHeading Usage_i16(0x415) 1866 + #define Usage_Sen_DataFieldMagneticHeading Usage_i16(0x416) 1867 + #define Usage_Sen_DataFieldMagneticVariation Usage_i16(0x417) 1868 + #define Usage_Sen_DataFieldSpeed Usage_i16(0x418) 1869 + #define Usage_Sen_DataFieldSatellitesinView Usage_i16(0x419) 1870 + #define Usage_Sen_DataFieldSatellitesinViewAzimuth Usage_i16(0x41a) 1871 + #define Usage_Sen_DataFieldSatellitesinViewElevation Usage_i16(0x41b) 1872 + #define Usage_Sen_DataFieldSatellitesinViewIDs Usage_i16(0x41c) 1873 + #define Usage_Sen_DataFieldSatellitesinViewPRNs Usage_i16(0x41d) 1874 + #define Usage_Sen_DataFieldSatellitesinViewSNRatios Usage_i16(0x41e) 1875 + #define Usage_Sen_DataFieldSatellitesUsedCount Usage_i16(0x41f) 1876 + #define Usage_Sen_DataFieldSatellitesUsedPRNs Usage_i16(0x420) 1877 + #define Usage_Sen_DataFieldNMEASentence Usage_i16(0x421) 1878 + #define Usage_Sen_DataFieldAddressLine1 Usage_i16(0x422) 1879 + #define Usage_Sen_DataFieldAddressLine2 Usage_i16(0x423) 1880 + #define Usage_Sen_DataFieldCity Usage_i16(0x424) 1881 + #define Usage_Sen_DataFieldStateorProvince Usage_i16(0x425) 1882 + #define Usage_Sen_DataFieldCountryorRegion Usage_i16(0x426) 1883 + #define Usage_Sen_DataFieldPostalCode Usage_i16(0x427) 1884 + #define Usage_Sen_PropertyLocation Usage_i16(0x42a) 1885 + #define Usage_Sen_PropertyLocationDesiredAccuracy Usage_i16(0x42b) 1886 + #define Usage_Sen_DataFieldEnvironmental Usage_i16(0x430) 1887 + #define Usage_Sen_DataFieldAtmosphericPressure Usage_i16(0x431) 1888 + #define Usage_Sen_DataFieldRelativeHumidity Usage_i16(0x433) 1889 + #define Usage_Sen_DataFieldTemperature Usage_i16(0x434) 1890 + #define Usage_Sen_DataFieldWindDirection Usage_i16(0x435) 1891 + #define Usage_Sen_DataFieldWindSpeed Usage_i16(0x436) 1892 + #define Usage_Sen_DataFieldAirQualityIndex Usage_i16(0x437) 1893 + #define Usage_Sen_DataFieldEquivalentCO2 Usage_i16(0x438) 1894 + #define Usage_Sen_DataFieldVolatileOrganicCompoundConcentration Usage_i16(0x439) 1895 + #define Usage_Sen_DataFieldObjectPresence Usage_i16(0x43a) 1896 + #define Usage_Sen_DataFieldObjectProximityRange Usage_i16(0x43b) 1897 + #define Usage_Sen_DataFieldObjectProximityOutofRange Usage_i16(0x43c) 1898 + #define Usage_Sen_PropertyEnvironmental Usage_i16(0x440) 1899 + #define Usage_Sen_PropertyReferencePressure Usage_i16(0x441) 1900 + #define Usage_Sen_DataFieldMotion Usage_i16(0x450) 1901 + #define Usage_Sen_DataFieldMotionState Usage_i16(0x451) 1902 + #define Usage_Sen_DataFieldAcceleration Usage_i16(0x452) 1903 + #define Usage_Sen_DataFieldAccelerationAxisX Usage_i16(0x453) 1904 + #define Usage_Sen_DataFieldAccelerationAxisY Usage_i16(0x454) 1905 + #define Usage_Sen_DataFieldAccelerationAxisZ Usage_i16(0x455) 1906 + #define Usage_Sen_DataFieldAngularVelocity Usage_i16(0x456) 1907 + #define Usage_Sen_DataFieldAngularVelocityaboutXAxis Usage_i16(0x457) 1908 + #define Usage_Sen_DataFieldAngularVelocityaboutYAxis Usage_i16(0x458) 1909 + #define Usage_Sen_DataFieldAngularVelocityaboutZAxis Usage_i16(0x459) 1910 + #define Usage_Sen_DataFieldAngularPosition Usage_i16(0x45a) 1911 + #define Usage_Sen_DataFieldAngularPositionaboutXAxis Usage_i16(0x45b) 1912 + #define Usage_Sen_DataFieldAngularPositionaboutYAxis Usage_i16(0x45c) 1913 + #define Usage_Sen_DataFieldAngularPositionaboutZAxis Usage_i16(0x45d) 1914 + #define Usage_Sen_DataFieldMotionSpeed Usage_i16(0x45e) 1915 + #define Usage_Sen_DataFieldMotionIntensity Usage_i16(0x45f) 1916 + #define Usage_Sen_DataFieldOrientation Usage_i16(0x470) 1917 + #define Usage_Sen_DataFieldHeading Usage_i16(0x471) 1918 + #define Usage_Sen_DataFieldHeadingXAxis Usage_i16(0x472) 1919 + #define Usage_Sen_DataFieldHeadingYAxis Usage_i16(0x473) 1920 + #define Usage_Sen_DataFieldHeadingZAxis Usage_i16(0x474) 1921 + #define Usage_Sen_DataFieldHeadingCompensatedMagneticNorth Usage_i16(0x475) 1922 + #define Usage_Sen_DataFieldHeadingCompensatedTrueNorth Usage_i16(0x476) 1923 + #define Usage_Sen_DataFieldHeadingMagneticNorth Usage_i16(0x477) 1924 + #define Usage_Sen_DataFieldHeadingTrueNorth Usage_i16(0x478) 1925 + #define Usage_Sen_DataFieldDistance Usage_i16(0x479) 1926 + #define Usage_Sen_DataFieldDistanceXAxis Usage_i16(0x47a) 1927 + #define Usage_Sen_DataFieldDistanceYAxis Usage_i16(0x47b) 1928 + #define Usage_Sen_DataFieldDistanceZAxis Usage_i16(0x47c) 1929 + #define Usage_Sen_DataFieldDistanceOutofRange Usage_i16(0x47d) 1930 + #define Usage_Sen_DataFieldTilt Usage_i16(0x47e) 1931 + #define Usage_Sen_DataFieldTiltXAxis Usage_i16(0x47f) 1932 + #define Usage_Sen_DataFieldTiltYAxis Usage_i16(0x480) 1933 + #define Usage_Sen_DataFieldTiltZAxis Usage_i16(0x481) 1934 + #define Usage_Sen_DataFieldRotationMatrix Usage_i16(0x482) 1935 + #define Usage_Sen_DataFieldQuaternion Usage_i16(0x483) 1936 + #define Usage_Sen_DataFieldMagneticFlux Usage_i16(0x484) 1937 + #define Usage_Sen_DataFieldMagneticFluxXAxis Usage_i16(0x485) 1938 + #define Usage_Sen_DataFieldMagneticFluxYAxis Usage_i16(0x486) 1939 + #define Usage_Sen_DataFieldMagneticFluxZAxis Usage_i16(0x487) 1940 + #define Usage_Sen_DataFieldMagnetometerAccuracy Usage_i16(0x488) 1941 + #define Usage_Sen_DataFieldSimpleOrientationDirection Usage_i16(0x489) 1942 + #define Usage_Sen_DataFieldMechanical Usage_i16(0x490) 1943 + #define Usage_Sen_DataFieldBooleanSwitchState Usage_i16(0x491) 1944 + #define Usage_Sen_DataFieldBooleanSwitchArrayStates Usage_i16(0x492) 1945 + #define Usage_Sen_DataFieldMultivalueSwitchValue Usage_i16(0x493) 1946 + #define Usage_Sen_DataFieldForce Usage_i16(0x494) 1947 + #define Usage_Sen_DataFieldAbsolutePressure Usage_i16(0x495) 1948 + #define Usage_Sen_DataFieldGaugePressure Usage_i16(0x496) 1949 + #define Usage_Sen_DataFieldStrain Usage_i16(0x497) 1950 + #define Usage_Sen_DataFieldWeight Usage_i16(0x498) 1951 + #define Usage_Sen_PropertyMechanical Usage_i16(0x4a0) 1952 + #define Usage_Sen_PropertyVibrationState Usage_i16(0x4a1) 1953 + #define Usage_Sen_PropertyForwardVibrationSpeed Usage_i16(0x4a2) 1954 + #define Usage_Sen_PropertyBackwardVibrationSpeed Usage_i16(0x4a3) 1955 + #define Usage_Sen_DataFieldBiometric Usage_i16(0x4b0) 1956 + #define Usage_Sen_DataFieldHumanPresence Usage_i16(0x4b1) 1957 + #define Usage_Sen_DataFieldHumanProximityRange Usage_i16(0x4b2) 1958 + #define Usage_Sen_DataFieldHumanProximityOutofRange Usage_i16(0x4b3) 1959 + #define Usage_Sen_DataFieldHumanTouchState Usage_i16(0x4b4) 1960 + #define Usage_Sen_DataFieldBloodPressure Usage_i16(0x4b5) 1961 + #define Usage_Sen_DataFieldBloodPressureDiastolic Usage_i16(0x4b6) 1962 + #define Usage_Sen_DataFieldBloodPressureSystolic Usage_i16(0x4b7) 1963 + #define Usage_Sen_DataFieldHeartRate Usage_i16(0x4b8) 1964 + #define Usage_Sen_DataFieldRestingHeartRate Usage_i16(0x4b9) 1965 + #define Usage_Sen_DataFieldHeartbeatInterval Usage_i16(0x4ba) 1966 + #define Usage_Sen_DataFieldRespiratoryRate Usage_i16(0x4bb) 1967 + #define Usage_Sen_DataFieldSpO2 Usage_i16(0x4bc) 1968 + #define Usage_Sen_DataFieldHumanAttentionDetected Usage_i16(0x4bd) 1969 + #define Usage_Sen_DataFieldHumanHeadAzimuth Usage_i16(0x4be) 1970 + #define Usage_Sen_DataFieldHumanHeadAltitude Usage_i16(0x4bf) 1971 + #define Usage_Sen_DataFieldHumanHeadRoll Usage_i16(0x4c0) 1972 + #define Usage_Sen_DataFieldHumanHeadPitch Usage_i16(0x4c1) 1973 + #define Usage_Sen_DataFieldHumanHeadYaw Usage_i16(0x4c2) 1974 + #define Usage_Sen_DataFieldHumanCorrelationId Usage_i16(0x4c3) 1975 + #define Usage_Sen_DataFieldLight Usage_i16(0x4d0) 1976 + #define Usage_Sen_DataFieldIlluminance Usage_i16(0x4d1) 1977 + #define Usage_Sen_DataFieldColorTemperature Usage_i16(0x4d2) 1978 + #define Usage_Sen_DataFieldChromaticity Usage_i16(0x4d3) 1979 + #define Usage_Sen_DataFieldChromaticityX Usage_i16(0x4d4) 1980 + #define Usage_Sen_DataFieldChromaticityY Usage_i16(0x4d5) 1981 + #define Usage_Sen_DataFieldConsumerIRSentenceReceive Usage_i16(0x4d6) 1982 + #define Usage_Sen_DataFieldInfraredLight Usage_i16(0x4d7) 1983 + #define Usage_Sen_DataFieldRedLight Usage_i16(0x4d8) 1984 + #define Usage_Sen_DataFieldGreenLight Usage_i16(0x4d9) 1985 + #define Usage_Sen_DataFieldBlueLight Usage_i16(0x4da) 1986 + #define Usage_Sen_DataFieldUltravioletALight Usage_i16(0x4db) 1987 + #define Usage_Sen_DataFieldUltravioletBLight Usage_i16(0x4dc) 1988 + #define Usage_Sen_DataFieldUltravioletIndex Usage_i16(0x4dd) 1989 + #define Usage_Sen_DataFieldNearInfraredLight Usage_i16(0x4de) 1990 + #define Usage_Sen_PropertyLight Usage_i16(0x4df) 1991 + #define Usage_Sen_PropertyConsumerIRSentenceSend Usage_i16(0x4e0) 1992 + #define Usage_Sen_PropertyAutoBrightnessPreferred Usage_i16(0x4e2) 1993 + #define Usage_Sen_PropertyAutoColorPreferred Usage_i16(0x4e3) 1994 + #define Usage_Sen_DataFieldScanner Usage_i16(0x4f0) 1995 + #define Usage_Sen_DataFieldRFIDTag40Bit Usage_i16(0x4f1) 1996 + #define Usage_Sen_DataFieldNFCSentenceReceive Usage_i16(0x4f2) 1997 + #define Usage_Sen_PropertyScanner Usage_i16(0x4f8) 1998 + #define Usage_Sen_PropertyNFCSentenceSend Usage_i16(0x4f9) 1999 + #define Usage_Sen_DataFieldElectrical Usage_i16(0x500) 2000 + #define Usage_Sen_DataFieldCapacitance Usage_i16(0x501) 2001 + #define Usage_Sen_DataFieldCurrent Usage_i16(0x502) 2002 + #define Usage_Sen_DataFieldElectricalPower Usage_i16(0x503) 2003 + #define Usage_Sen_DataFieldInductance Usage_i16(0x504) 2004 + #define Usage_Sen_DataFieldResistance Usage_i16(0x505) 2005 + #define Usage_Sen_DataFieldVoltage Usage_i16(0x506) 2006 + #define Usage_Sen_DataFieldFrequency Usage_i16(0x507) 2007 + #define Usage_Sen_DataFieldPeriod Usage_i16(0x508) 2008 + #define Usage_Sen_DataFieldPercentofRange Usage_i16(0x509) 2009 + #define Usage_Sen_DataFieldTime Usage_i16(0x520) 2010 + #define Usage_Sen_DataFieldYear Usage_i16(0x521) 2011 + #define Usage_Sen_DataFieldMonth Usage_i16(0x522) 2012 + #define Usage_Sen_DataFieldDay Usage_i16(0x523) 2013 + #define Usage_Sen_DataFieldDayofWeek Usage_i16(0x524) 2014 + #define Usage_Sen_DataFieldHour Usage_i16(0x525) 2015 + #define Usage_Sen_DataFieldMinute Usage_i16(0x526) 2016 + #define Usage_Sen_DataFieldSecond Usage_i16(0x527) 2017 + #define Usage_Sen_DataFieldMillisecond Usage_i16(0x528) 2018 + #define Usage_Sen_DataFieldTimestamp Usage_i16(0x529) 2019 + #define Usage_Sen_DataFieldJulianDayofYear Usage_i16(0x52a) 2020 + #define Usage_Sen_DataFieldTimeSinceSystemBoot Usage_i16(0x52b) 2021 + #define Usage_Sen_PropertyTime Usage_i16(0x530) 2022 + #define Usage_Sen_PropertyTimeZoneOffsetfromUTC Usage_i16(0x531) 2023 + #define Usage_Sen_PropertyTimeZoneName Usage_i16(0x532) 2024 + #define Usage_Sen_PropertyDaylightSavingsTimeObserved Usage_i16(0x533) 2025 + #define Usage_Sen_PropertyTimeTrimAdjustment Usage_i16(0x534) 2026 + #define Usage_Sen_PropertyArmAlarm Usage_i16(0x535) 2027 + #define Usage_Sen_DataFieldCustom Usage_i16(0x540) 2028 + #define Usage_Sen_DataFieldCustomUsage Usage_i16(0x541) 2029 + #define Usage_Sen_DataFieldCustomBooleanArray Usage_i16(0x542) 2030 + #define Usage_Sen_DataFieldCustomValue Usage_i16(0x543) 2031 + #define Usage_Sen_DataFieldCustomValue1 Usage_i16(0x544) 2032 + #define Usage_Sen_DataFieldCustomValue2 Usage_i16(0x545) 2033 + #define Usage_Sen_DataFieldCustomValue3 Usage_i16(0x546) 2034 + #define Usage_Sen_DataFieldCustomValue4 Usage_i16(0x547) 2035 + #define Usage_Sen_DataFieldCustomValue5 Usage_i16(0x548) 2036 + #define Usage_Sen_DataFieldCustomValue6 Usage_i16(0x549) 2037 + #define Usage_Sen_DataFieldCustomValue7 Usage_i16(0x54a) 2038 + #define Usage_Sen_DataFieldCustomValue8 Usage_i16(0x54b) 2039 + #define Usage_Sen_DataFieldCustomValue9 Usage_i16(0x54c) 2040 + #define Usage_Sen_DataFieldCustomValue10 Usage_i16(0x54d) 2041 + #define Usage_Sen_DataFieldCustomValue11 Usage_i16(0x54e) 2042 + #define Usage_Sen_DataFieldCustomValue12 Usage_i16(0x54f) 2043 + #define Usage_Sen_DataFieldCustomValue13 Usage_i16(0x550) 2044 + #define Usage_Sen_DataFieldCustomValue14 Usage_i16(0x551) 2045 + #define Usage_Sen_DataFieldCustomValue15 Usage_i16(0x552) 2046 + #define Usage_Sen_DataFieldCustomValue16 Usage_i16(0x553) 2047 + #define Usage_Sen_DataFieldCustomValue17 Usage_i16(0x554) 2048 + #define Usage_Sen_DataFieldCustomValue18 Usage_i16(0x555) 2049 + #define Usage_Sen_DataFieldCustomValue19 Usage_i16(0x556) 2050 + #define Usage_Sen_DataFieldCustomValue20 Usage_i16(0x557) 2051 + #define Usage_Sen_DataFieldCustomValue21 Usage_i16(0x558) 2052 + #define Usage_Sen_DataFieldCustomValue22 Usage_i16(0x559) 2053 + #define Usage_Sen_DataFieldCustomValue23 Usage_i16(0x55a) 2054 + #define Usage_Sen_DataFieldCustomValue24 Usage_i16(0x55b) 2055 + #define Usage_Sen_DataFieldCustomValue25 Usage_i16(0x55c) 2056 + #define Usage_Sen_DataFieldCustomValue26 Usage_i16(0x55d) 2057 + #define Usage_Sen_DataFieldCustomValue27 Usage_i16(0x55e) 2058 + #define Usage_Sen_DataFieldCustomValue28 Usage_i16(0x55f) 2059 + #define Usage_Sen_DataFieldGeneric Usage_i16(0x560) 2060 + #define Usage_Sen_DataFieldGenericGUIDorPROPERTYKEY Usage_i16(0x561) 2061 + #define Usage_Sen_DataFieldGenericCategoryGUID Usage_i16(0x562) 2062 + #define Usage_Sen_DataFieldGenericTypeGUID Usage_i16(0x563) 2063 + #define Usage_Sen_DataFieldGenericEventPROPERTYKEY Usage_i16(0x564) 2064 + #define Usage_Sen_DataFieldGenericPropertyPROPERTYKEY Usage_i16(0x565) 2065 + #define Usage_Sen_DataFieldGenericDataFieldPROPERTYKEY Usage_i16(0x566) 2066 + #define Usage_Sen_DataFieldGenericEvent Usage_i16(0x567) 2067 + #define Usage_Sen_DataFieldGenericProperty Usage_i16(0x568) 2068 + #define Usage_Sen_DataFieldGenericDataField Usage_i16(0x569) 2069 + #define Usage_Sen_DataFieldEnumeratorTableRowIndex Usage_i16(0x56a) 2070 + #define Usage_Sen_DataFieldEnumeratorTableRowCount Usage_i16(0x56b) 2071 + #define Usage_Sen_DataFieldGenericGUIDorPROPERTYKEYkind Usage_i16(0x56c) 2072 + #define Usage_Sen_DataFieldGenericGUID Usage_i16(0x56d) 2073 + #define Usage_Sen_DataFieldGenericPROPERTYKEY Usage_i16(0x56e) 2074 + #define Usage_Sen_DataFieldGenericTopLevelCollectionID Usage_i16(0x56f) 2075 + #define Usage_Sen_DataFieldGenericReportID Usage_i16(0x570) 2076 + #define Usage_Sen_DataFieldGenericReportItemPositionIndex Usage_i16(0x571) 2077 + #define Usage_Sen_DataFieldGenericFirmwareVARTYPE Usage_i16(0x572) 2078 + #define Usage_Sen_DataFieldGenericUnitofMeasure Usage_i16(0x573) 2079 + #define Usage_Sen_DataFieldGenericUnitExponent Usage_i16(0x574) 2080 + #define Usage_Sen_DataFieldGenericReportSize Usage_i16(0x575) 2081 + #define Usage_Sen_DataFieldGenericReportCount Usage_i16(0x576) 2082 + #define Usage_Sen_PropertyGeneric Usage_i16(0x580) 2083 + #define Usage_Sen_PropertyEnumeratorTableRowIndex Usage_i16(0x581) 2084 + #define Usage_Sen_PropertyEnumeratorTableRowCount Usage_i16(0x582) 2085 + #define Usage_Sen_DataFieldPersonalActivity Usage_i16(0x590) 2086 + #define Usage_Sen_DataFieldActivityType Usage_i16(0x591) 2087 + #define Usage_Sen_DataFieldActivityState Usage_i16(0x592) 2088 + #define Usage_Sen_DataFieldDevicePosition Usage_i16(0x593) 2089 + #define Usage_Sen_DataFieldStepCount Usage_i16(0x594) 2090 + #define Usage_Sen_DataFieldStepCountReset Usage_i16(0x595) 2091 + #define Usage_Sen_DataFieldStepDuration Usage_i16(0x596) 2092 + #define Usage_Sen_DataFieldStepType Usage_i16(0x597) 2093 + #define Usage_Sen_PropertyMinimumActivityDetectionInterval Usage_i16(0x5a0) 2094 + #define Usage_Sen_PropertySupportedActivityTypes Usage_i16(0x5a1) 2095 + #define Usage_Sen_PropertySubscribedActivityTypes Usage_i16(0x5a2) 2096 + #define Usage_Sen_PropertySupportedStepTypes Usage_i16(0x5a3) 2097 + #define Usage_Sen_PropertySubscribedStepTypes Usage_i16(0x5a4) 2098 + #define Usage_Sen_PropertyFloorHeight Usage_i16(0x5a5) 2099 + #define Usage_Sen_DataFieldCustomTypeID Usage_i16(0x5b0) 2100 + #define Usage_Sen_PropertyCustom Usage_i16(0x5c0) 2101 + #define Usage_Sen_PropertyCustomValue1 Usage_i16(0x5c1) 2102 + #define Usage_Sen_PropertyCustomValue2 Usage_i16(0x5c2) 2103 + #define Usage_Sen_PropertyCustomValue3 Usage_i16(0x5c3) 2104 + #define Usage_Sen_PropertyCustomValue4 Usage_i16(0x5c4) 2105 + #define Usage_Sen_PropertyCustomValue5 Usage_i16(0x5c5) 2106 + #define Usage_Sen_PropertyCustomValue6 Usage_i16(0x5c6) 2107 + #define Usage_Sen_PropertyCustomValue7 Usage_i16(0x5c7) 2108 + #define Usage_Sen_PropertyCustomValue8 Usage_i16(0x5c8) 2109 + #define Usage_Sen_PropertyCustomValue9 Usage_i16(0x5c9) 2110 + #define Usage_Sen_PropertyCustomValue10 Usage_i16(0x5ca) 2111 + #define Usage_Sen_PropertyCustomValue11 Usage_i16(0x5cb) 2112 + #define Usage_Sen_PropertyCustomValue12 Usage_i16(0x5cc) 2113 + #define Usage_Sen_PropertyCustomValue13 Usage_i16(0x5cd) 2114 + #define Usage_Sen_PropertyCustomValue14 Usage_i16(0x5ce) 2115 + #define Usage_Sen_PropertyCustomValue15 Usage_i16(0x5cf) 2116 + #define Usage_Sen_PropertyCustomValue16 Usage_i16(0x5d0) 2117 + #define Usage_Sen_DataFieldHinge Usage_i16(0x5e0) 2118 + #define Usage_Sen_DataFieldHingeAngle Usage_i16(0x5e1) 2119 + #define Usage_Sen_DataFieldGestureSensor Usage_i16(0x5f0) 2120 + #define Usage_Sen_DataFieldGestureState Usage_i16(0x5f1) 2121 + #define Usage_Sen_DataFieldHingeFoldInitialAngle Usage_i16(0x5f2) 2122 + #define Usage_Sen_DataFieldHingeFoldFinalAngle Usage_i16(0x5f3) 2123 + #define Usage_Sen_DataFieldHingeFoldContributingPanel Usage_i16(0x5f4) 2124 + #define Usage_Sen_DataFieldHingeFoldType Usage_i16(0x5f5) 2125 + #define Usage_Sen_SensorStateUndefined Usage_i16(0x800) 2126 + #define Usage_Sen_SensorStateReady Usage_i16(0x801) 2127 + #define Usage_Sen_SensorStateNotAvailable Usage_i16(0x802) 2128 + #define Usage_Sen_SensorStateNoData Usage_i16(0x803) 2129 + #define Usage_Sen_SensorStateInitializing Usage_i16(0x804) 2130 + #define Usage_Sen_SensorStateAccessDenied Usage_i16(0x805) 2131 + #define Usage_Sen_SensorStateError Usage_i16(0x806) 2132 + #define Usage_Sen_SensorEventUnknown Usage_i16(0x810) 2133 + #define Usage_Sen_SensorEventStateChanged Usage_i16(0x811) 2134 + #define Usage_Sen_SensorEventPropertyChanged Usage_i16(0x812) 2135 + #define Usage_Sen_SensorEventDataUpdated Usage_i16(0x813) 2136 + #define Usage_Sen_SensorEventPollResponse Usage_i16(0x814) 2137 + #define Usage_Sen_SensorEventChangeSensitivity Usage_i16(0x815) 2138 + #define Usage_Sen_SensorEventRangeMaximumReached Usage_i16(0x816) 2139 + #define Usage_Sen_SensorEventRangeMinimumReached Usage_i16(0x817) 2140 + #define Usage_Sen_SensorEventHighThresholdCrossUpward Usage_i16(0x818) 2141 + #define Usage_Sen_SensorEventHighThresholdCrossDownward Usage_i16(0x819) 2142 + #define Usage_Sen_SensorEventLowThresholdCrossUpward Usage_i16(0x81a) 2143 + #define Usage_Sen_SensorEventLowThresholdCrossDownward Usage_i16(0x81b) 2144 + #define Usage_Sen_SensorEventZeroThresholdCrossUpward Usage_i16(0x81c) 2145 + #define Usage_Sen_SensorEventZeroThresholdCrossDownward Usage_i16(0x81d) 2146 + #define Usage_Sen_SensorEventPeriodExceeded Usage_i16(0x81e) 2147 + #define Usage_Sen_SensorEventFrequencyExceeded Usage_i16(0x81f) 2148 + #define Usage_Sen_SensorEventComplexTrigger Usage_i16(0x820) 2149 + #define Usage_Sen_ConnectionTypePCIntegrated Usage_i16(0x830) 2150 + #define Usage_Sen_ConnectionTypePCAttached Usage_i16(0x831) 2151 + #define Usage_Sen_ConnectionTypePCExternal Usage_i16(0x832) 2152 + #define Usage_Sen_ReportingStateReportNoEvents Usage_i16(0x840) 2153 + #define Usage_Sen_ReportingStateReportAllEvents Usage_i16(0x841) 2154 + #define Usage_Sen_ReportingStateReportThresholdEvents Usage_i16(0x842) 2155 + #define Usage_Sen_ReportingStateWakeOnNoEvents Usage_i16(0x843) 2156 + #define Usage_Sen_ReportingStateWakeOnAllEvents Usage_i16(0x844) 2157 + #define Usage_Sen_ReportingStateWakeOnThresholdEvents Usage_i16(0x845) 2158 + #define Usage_Sen_ReportingStateAnytime Usage_i16(0x846) 2159 + #define Usage_Sen_PowerStateUndefined Usage_i16(0x850) 2160 + #define Usage_Sen_PowerStateD0FullPower Usage_i16(0x851) 2161 + #define Usage_Sen_PowerStateD1LowPower Usage_i16(0x852) 2162 + #define Usage_Sen_PowerStateD2StandbyPowerwithWakeup Usage_i16(0x853) 2163 + #define Usage_Sen_PowerStateD3SleepwithWakeup Usage_i16(0x854) 2164 + #define Usage_Sen_PowerStateD4PowerOff Usage_i16(0x855) 2165 + #define Usage_Sen_AccuracyDefault Usage_i16(0x860) 2166 + #define Usage_Sen_AccuracyHigh Usage_i16(0x861) 2167 + #define Usage_Sen_AccuracyMedium Usage_i16(0x862) 2168 + #define Usage_Sen_AccuracyLow Usage_i16(0x863) 2169 + #define Usage_Sen_FixQualityNoFix Usage_i16(0x870) 2170 + #define Usage_Sen_FixQualityGPS Usage_i16(0x871) 2171 + #define Usage_Sen_FixQualityDGPS Usage_i16(0x872) 2172 + #define Usage_Sen_FixTypeNoFix Usage_i16(0x880) 2173 + #define Usage_Sen_FixTypeGPSSPSModeFixValid Usage_i16(0x881) 2174 + #define Usage_Sen_FixTypeDGPSSPSModeFixValid Usage_i16(0x882) 2175 + #define Usage_Sen_FixTypeGPSPPSModeFixValid Usage_i16(0x883) 2176 + #define Usage_Sen_FixTypeRealTimeKinematic Usage_i16(0x884) 2177 + #define Usage_Sen_FixTypeFloatRTK Usage_i16(0x885) 2178 + #define Usage_Sen_FixTypeEstimateddeadreckoned Usage_i16(0x886) 2179 + #define Usage_Sen_FixTypeManualInputMode Usage_i16(0x887) 2180 + #define Usage_Sen_FixTypeSimulatorMode Usage_i16(0x888) 2181 + #define Usage_Sen_GPSOperationModeManual Usage_i16(0x890) 2182 + #define Usage_Sen_GPSOperationModeAutomatic Usage_i16(0x891) 2183 + #define Usage_Sen_GPSSelectionModeAutonomous Usage_i16(0x8a0) 2184 + #define Usage_Sen_GPSSelectionModeDGPS Usage_i16(0x8a1) 2185 + #define Usage_Sen_GPSSelectionModeEstimateddeadreckoned Usage_i16(0x8a2) 2186 + #define Usage_Sen_GPSSelectionModeManualInput Usage_i16(0x8a3) 2187 + #define Usage_Sen_GPSSelectionModeSimulator Usage_i16(0x8a4) 2188 + #define Usage_Sen_GPSSelectionModeDataNotValid Usage_i16(0x8a5) 2189 + #define Usage_Sen_GPSStatusDataValid Usage_i16(0x8b0) 2190 + #define Usage_Sen_GPSStatusDataNotValid Usage_i16(0x8b1) 2191 + #define Usage_Sen_DayofWeekSunday Usage_i16(0x8c0) 2192 + #define Usage_Sen_DayofWeekMonday Usage_i16(0x8c1) 2193 + #define Usage_Sen_DayofWeekTuesday Usage_i16(0x8c2) 2194 + #define Usage_Sen_DayofWeekWednesday Usage_i16(0x8c3) 2195 + #define Usage_Sen_DayofWeekThursday Usage_i16(0x8c4) 2196 + #define Usage_Sen_DayofWeekFriday Usage_i16(0x8c5) 2197 + #define Usage_Sen_DayofWeekSaturday Usage_i16(0x8c6) 2198 + #define Usage_Sen_KindCategory Usage_i16(0x8d0) 2199 + #define Usage_Sen_KindType Usage_i16(0x8d1) 2200 + #define Usage_Sen_KindEvent Usage_i16(0x8d2) 2201 + #define Usage_Sen_KindProperty Usage_i16(0x8d3) 2202 + #define Usage_Sen_KindDataField Usage_i16(0x8d4) 2203 + #define Usage_Sen_MagnetometerAccuracyLow Usage_i16(0x8e0) 2204 + #define Usage_Sen_MagnetometerAccuracyMedium Usage_i16(0x8e1) 2205 + #define Usage_Sen_MagnetometerAccuracyHigh Usage_i16(0x8e2) 2206 + #define Usage_Sen_SimpleOrientationDirectionNotRotated Usage_i16(0x8f0) 2207 + #define Usage_Sen_SimpleOrientationDirectionRotated90DegreesCCW Usage_i16(0x8f1) 2208 + #define Usage_Sen_SimpleOrientationDirectionRotated180DegreesCCW Usage_i16(0x8f2) 2209 + #define Usage_Sen_SimpleOrientationDirectionRotated270DegreesCCW Usage_i16(0x8f3) 2210 + #define Usage_Sen_SimpleOrientationDirectionFaceUp Usage_i16(0x8f4) 2211 + #define Usage_Sen_SimpleOrientationDirectionFaceDown Usage_i16(0x8f5) 2212 + #define Usage_Sen_VT_NULL Usage_i16(0x900) 2213 + #define Usage_Sen_VT_BOOL Usage_i16(0x901) 2214 + #define Usage_Sen_VT_UI1 Usage_i16(0x902) 2215 + #define Usage_Sen_VT_I1 Usage_i16(0x903) 2216 + #define Usage_Sen_VT_UI2 Usage_i16(0x904) 2217 + #define Usage_Sen_VT_I2 Usage_i16(0x905) 2218 + #define Usage_Sen_VT_UI4 Usage_i16(0x906) 2219 + #define Usage_Sen_VT_I4 Usage_i16(0x907) 2220 + #define Usage_Sen_VT_UI8 Usage_i16(0x908) 2221 + #define Usage_Sen_VT_I8 Usage_i16(0x909) 2222 + #define Usage_Sen_VT_R4 Usage_i16(0x90a) 2223 + #define Usage_Sen_VT_R8 Usage_i16(0x90b) 2224 + #define Usage_Sen_VT_WSTR Usage_i16(0x90c) 2225 + #define Usage_Sen_VT_STR Usage_i16(0x90d) 2226 + #define Usage_Sen_VT_CLSID Usage_i16(0x90e) 2227 + #define Usage_Sen_VT_VECTORVT_UI1 Usage_i16(0x90f) 2228 + #define Usage_Sen_VT_F16E0 Usage_i16(0x910) 2229 + #define Usage_Sen_VT_F16E1 Usage_i16(0x911) 2230 + #define Usage_Sen_VT_F16E2 Usage_i16(0x912) 2231 + #define Usage_Sen_VT_F16E3 Usage_i16(0x913) 2232 + #define Usage_Sen_VT_F16E4 Usage_i16(0x914) 2233 + #define Usage_Sen_VT_F16E5 Usage_i16(0x915) 2234 + #define Usage_Sen_VT_F16E6 Usage_i16(0x916) 2235 + #define Usage_Sen_VT_F16E7 Usage_i16(0x917) 2236 + #define Usage_Sen_VT_F16E8 Usage_i16(0x918) 2237 + #define Usage_Sen_VT_F16E9 Usage_i16(0x919) 2238 + #define Usage_Sen_VT_F16EA Usage_i16(0x91a) 2239 + #define Usage_Sen_VT_F16EB Usage_i16(0x91b) 2240 + #define Usage_Sen_VT_F16EC Usage_i16(0x91c) 2241 + #define Usage_Sen_VT_F16ED Usage_i16(0x91d) 2242 + #define Usage_Sen_VT_F16EE Usage_i16(0x91e) 2243 + #define Usage_Sen_VT_F16EF Usage_i16(0x91f) 2244 + #define Usage_Sen_VT_F32E0 Usage_i16(0x920) 2245 + #define Usage_Sen_VT_F32E1 Usage_i16(0x921) 2246 + #define Usage_Sen_VT_F32E2 Usage_i16(0x922) 2247 + #define Usage_Sen_VT_F32E3 Usage_i16(0x923) 2248 + #define Usage_Sen_VT_F32E4 Usage_i16(0x924) 2249 + #define Usage_Sen_VT_F32E5 Usage_i16(0x925) 2250 + #define Usage_Sen_VT_F32E6 Usage_i16(0x926) 2251 + #define Usage_Sen_VT_F32E7 Usage_i16(0x927) 2252 + #define Usage_Sen_VT_F32E8 Usage_i16(0x928) 2253 + #define Usage_Sen_VT_F32E9 Usage_i16(0x929) 2254 + #define Usage_Sen_VT_F32EA Usage_i16(0x92a) 2255 + #define Usage_Sen_VT_F32EB Usage_i16(0x92b) 2256 + #define Usage_Sen_VT_F32EC Usage_i16(0x92c) 2257 + #define Usage_Sen_VT_F32ED Usage_i16(0x92d) 2258 + #define Usage_Sen_VT_F32EE Usage_i16(0x92e) 2259 + #define Usage_Sen_VT_F32EF Usage_i16(0x92f) 2260 + #define Usage_Sen_ActivityTypeUnknown Usage_i16(0x930) 2261 + #define Usage_Sen_ActivityTypeStationary Usage_i16(0x931) 2262 + #define Usage_Sen_ActivityTypeFidgeting Usage_i16(0x932) 2263 + #define Usage_Sen_ActivityTypeWalking Usage_i16(0x933) 2264 + #define Usage_Sen_ActivityTypeRunning Usage_i16(0x934) 2265 + #define Usage_Sen_ActivityTypeInVehicle Usage_i16(0x935) 2266 + #define Usage_Sen_ActivityTypeBiking Usage_i16(0x936) 2267 + #define Usage_Sen_ActivityTypeIdle Usage_i16(0x937) 2268 + #define Usage_Sen_UnitNotSpecified Usage_i16(0x940) 2269 + #define Usage_Sen_UnitLux Usage_i16(0x941) 2270 + #define Usage_Sen_UnitDegreesKelvin Usage_i16(0x942) 2271 + #define Usage_Sen_UnitDegreesCelsius Usage_i16(0x943) 2272 + #define Usage_Sen_UnitPascal Usage_i16(0x944) 2273 + #define Usage_Sen_UnitNewton Usage_i16(0x945) 2274 + #define Usage_Sen_UnitMetersSecond Usage_i16(0x946) 2275 + #define Usage_Sen_UnitKilogram Usage_i16(0x947) 2276 + #define Usage_Sen_UnitMeter Usage_i16(0x948) 2277 + #define Usage_Sen_UnitMetersSecondSecond Usage_i16(0x949) 2278 + #define Usage_Sen_UnitFarad Usage_i16(0x94a) 2279 + #define Usage_Sen_UnitAmpere Usage_i16(0x94b) 2280 + #define Usage_Sen_UnitWatt Usage_i16(0x94c) 2281 + #define Usage_Sen_UnitHenry Usage_i16(0x94d) 2282 + #define Usage_Sen_UnitOhm Usage_i16(0x94e) 2283 + #define Usage_Sen_UnitVolt Usage_i16(0x94f) 2284 + #define Usage_Sen_UnitHertz Usage_i16(0x950) 2285 + #define Usage_Sen_UnitBar Usage_i16(0x951) 2286 + #define Usage_Sen_UnitDegreesAnticlockwise Usage_i16(0x952) 2287 + #define Usage_Sen_UnitDegreesClockwise Usage_i16(0x953) 2288 + #define Usage_Sen_UnitDegrees Usage_i16(0x954) 2289 + #define Usage_Sen_UnitDegreesSecond Usage_i16(0x955) 2290 + #define Usage_Sen_UnitDegreesSecondSecond Usage_i16(0x956) 2291 + #define Usage_Sen_UnitKnot Usage_i16(0x957) 2292 + #define Usage_Sen_UnitPercent Usage_i16(0x958) 2293 + #define Usage_Sen_UnitSecond Usage_i16(0x959) 2294 + #define Usage_Sen_UnitMillisecond Usage_i16(0x95a) 2295 + #define Usage_Sen_UnitG Usage_i16(0x95b) 2296 + #define Usage_Sen_UnitBytes Usage_i16(0x95c) 2297 + #define Usage_Sen_UnitMilligauss Usage_i16(0x95d) 2298 + #define Usage_Sen_UnitBits Usage_i16(0x95e) 2299 + #define Usage_Sen_ActivityStateNoStateChange Usage_i16(0x960) 2300 + #define Usage_Sen_ActivityStateStartActivity Usage_i16(0x961) 2301 + #define Usage_Sen_ActivityStateEndActivity Usage_i16(0x962) 2302 + #define Usage_Sen_Exponent0 Usage_i16(0x970) 2303 + #define Usage_Sen_Exponent1 Usage_i16(0x971) 2304 + #define Usage_Sen_Exponent2 Usage_i16(0x972) 2305 + #define Usage_Sen_Exponent3 Usage_i16(0x973) 2306 + #define Usage_Sen_Exponent4 Usage_i16(0x974) 2307 + #define Usage_Sen_Exponent5 Usage_i16(0x975) 2308 + #define Usage_Sen_Exponent6 Usage_i16(0x976) 2309 + #define Usage_Sen_Exponent7 Usage_i16(0x977) 2310 + #define Usage_Sen_Exponent8 Usage_i16(0x978) 2311 + #define Usage_Sen_Exponent9 Usage_i16(0x979) 2312 + #define Usage_Sen_ExponentA Usage_i16(0x97a) 2313 + #define Usage_Sen_ExponentB Usage_i16(0x97b) 2314 + #define Usage_Sen_ExponentC Usage_i16(0x97c) 2315 + #define Usage_Sen_ExponentD Usage_i16(0x97d) 2316 + #define Usage_Sen_ExponentE Usage_i16(0x97e) 2317 + #define Usage_Sen_ExponentF Usage_i16(0x97f) 2318 + #define Usage_Sen_DevicePositionUnknown Usage_i16(0x980) 2319 + #define Usage_Sen_DevicePositionUnchanged Usage_i16(0x981) 2320 + #define Usage_Sen_DevicePositionOnDesk Usage_i16(0x982) 2321 + #define Usage_Sen_DevicePositionInHand Usage_i16(0x983) 2322 + #define Usage_Sen_DevicePositionMovinginBag Usage_i16(0x984) 2323 + #define Usage_Sen_DevicePositionStationaryinBag Usage_i16(0x985) 2324 + #define Usage_Sen_StepTypeUnknown Usage_i16(0x990) 2325 + #define Usage_Sen_StepTypeWalking Usage_i16(0x991) 2326 + #define Usage_Sen_StepTypeRunning Usage_i16(0x992) 2327 + #define Usage_Sen_GestureStateUnknown Usage_i16(0x9a0) 2328 + #define Usage_Sen_GestureStateStarted Usage_i16(0x9a1) 2329 + #define Usage_Sen_GestureStateCompleted Usage_i16(0x9a2) 2330 + #define Usage_Sen_GestureStateCancelled Usage_i16(0x9a3) 2331 + #define Usage_Sen_HingeFoldContributingPanelUnknown Usage_i16(0x9b0) 2332 + #define Usage_Sen_HingeFoldContributingPanelPanel1 Usage_i16(0x9b1) 2333 + #define Usage_Sen_HingeFoldContributingPanelPanel2 Usage_i16(0x9b2) 2334 + #define Usage_Sen_HingeFoldContributingPanelBoth Usage_i16(0x9b3) 2335 + #define Usage_Sen_HingeFoldTypeUnknown Usage_i16(0x9b4) 2336 + #define Usage_Sen_HingeFoldTypeIncreasing Usage_i16(0x9b5) 2337 + #define Usage_Sen_HingeFoldTypeDecreasing Usage_i16(0x9b6) 2338 + #define Usage_Sen_HumanPresenceDetectionTypeVendorDefinedNonBiometric Usage_i16(0x9c0) 2339 + #define Usage_Sen_HumanPresenceDetectionTypeVendorDefinedBiometric Usage_i16(0x9c1) 2340 + #define Usage_Sen_HumanPresenceDetectionTypeFacialBiometric Usage_i16(0x9c2) 2341 + #define Usage_Sen_HumanPresenceDetectionTypeAudioBiometric Usage_i16(0x9c3) 2342 + #define Usage_Sen_ModifierChangeSensitivityAbsolute Usage_i16(0x1000) 2343 + #define Usage_Sen_ModifierMaximum Usage_i16(0x2000) 2344 + #define Usage_Sen_ModifierMinimum Usage_i16(0x3000) 2345 + #define Usage_Sen_ModifierAccuracy Usage_i16(0x4000) 2346 + #define Usage_Sen_ModifierResolution Usage_i16(0x5000) 2347 + #define Usage_Sen_ModifierThresholdHigh Usage_i16(0x6000) 2348 + #define Usage_Sen_ModifierThresholdLow Usage_i16(0x7000) 2349 + #define Usage_Sen_ModifierCalibrationOffset Usage_i16(0x8000) 2350 + #define Usage_Sen_ModifierCalibrationMultiplier Usage_i16(0x9000) 2351 + #define Usage_Sen_ModifierReportInterval Usage_i16(0xa000) 2352 + #define Usage_Sen_ModifierFrequencyMax Usage_i16(0xb000) 2353 + #define Usage_Sen_ModifierPeriodMax Usage_i16(0xc000) 2354 + #define Usage_Sen_ModifierChangeSensitivityPercentofRange Usage_i16(0xd000) 2355 + #define Usage_Sen_ModifierChangeSensitivityPercentRelative Usage_i16(0xe000) 2356 + #define Usage_Sen_ModifierVendorReserved Usage_i16(0xf000) 2357 + #define Usage_MI_MedicalUltrasound Usage_i8(0x1) 2358 + #define Usage_MI_VCRAcquisition Usage_i8(0x20) 2359 + #define Usage_MI_FreezeThaw Usage_i8(0x21) 2360 + #define Usage_MI_ClipStore Usage_i8(0x22) 2361 + #define Usage_MI_Update Usage_i8(0x23) 2362 + #define Usage_MI_Next Usage_i8(0x24) 2363 + #define Usage_MI_Save Usage_i8(0x25) 2364 + #define Usage_MI_Print Usage_i8(0x26) 2365 + #define Usage_MI_MicrophoneEnable Usage_i8(0x27) 2366 + #define Usage_MI_Cine Usage_i8(0x40) 2367 + #define Usage_MI_TransmitPower Usage_i8(0x41) 2368 + #define Usage_MI_Volume Usage_i8(0x42) 2369 + #define Usage_MI_Focus Usage_i8(0x43) 2370 + #define Usage_MI_Depth Usage_i8(0x44) 2371 + #define Usage_MI_SoftStepPrimary Usage_i8(0x60) 2372 + #define Usage_MI_SoftStepSecondary Usage_i8(0x61) 2373 + #define Usage_MI_DepthGainCompensation Usage_i8(0x70) 2374 + #define Usage_MI_ZoomSelect Usage_i8(0x80) 2375 + #define Usage_MI_ZoomAdjust Usage_i8(0x81) 2376 + #define Usage_MI_SpectralDopplerModeSelect Usage_i8(0x82) 2377 + #define Usage_MI_SpectralDopplerAdjust Usage_i8(0x83) 2378 + #define Usage_MI_ColorDopplerModeSelect Usage_i8(0x84) 2379 + #define Usage_MI_ColorDopplerAdjust Usage_i8(0x85) 2380 + #define Usage_MI_MotionModeSelect Usage_i8(0x86) 2381 + #define Usage_MI_MotionModeAdjust Usage_i8(0x87) 2382 + #define Usage_MI_TwoDModeSelect Usage_i8(0x88) 2383 + #define Usage_MI_TwoDModeAdjust Usage_i8(0x89) 2384 + #define Usage_MI_SoftControlSelect Usage_i8(0xa0) 2385 + #define Usage_MI_SoftControlAdjust Usage_i8(0xa1) 2386 + #define Usage_BD_BrailleDisplay Usage_i8(0x1) 2387 + #define Usage_BD_BrailleRow Usage_i8(0x2) 2388 + #define Usage_BD_EightDotBrailleCell Usage_i8(0x3) 2389 + #define Usage_BD_SixDotBrailleCell Usage_i8(0x4) 2390 + #define Usage_BD_NumberofBrailleCells Usage_i8(0x5) 2391 + #define Usage_BD_ScreenReaderControl Usage_i8(0x6) 2392 + #define Usage_BD_ScreenReaderIdentifier Usage_i8(0x7) 2393 + #define Usage_BD_RouterSet1 Usage_i8(0xfa) 2394 + #define Usage_BD_RouterSet2 Usage_i8(0xfb) 2395 + #define Usage_BD_RouterSet3 Usage_i8(0xfc) 2396 + #define Usage_BD_RouterKey Usage_i16(0x100) 2397 + #define Usage_BD_RowRouterKey Usage_i16(0x101) 2398 + #define Usage_BD_BrailleButtons Usage_i16(0x200) 2399 + #define Usage_BD_BrailleKeyboardDot1 Usage_i16(0x201) 2400 + #define Usage_BD_BrailleKeyboardDot2 Usage_i16(0x202) 2401 + #define Usage_BD_BrailleKeyboardDot3 Usage_i16(0x203) 2402 + #define Usage_BD_BrailleKeyboardDot4 Usage_i16(0x204) 2403 + #define Usage_BD_BrailleKeyboardDot5 Usage_i16(0x205) 2404 + #define Usage_BD_BrailleKeyboardDot6 Usage_i16(0x206) 2405 + #define Usage_BD_BrailleKeyboardDot7 Usage_i16(0x207) 2406 + #define Usage_BD_BrailleKeyboardDot8 Usage_i16(0x208) 2407 + #define Usage_BD_BrailleKeyboardSpace Usage_i16(0x209) 2408 + #define Usage_BD_BrailleKeyboardLeftSpace Usage_i16(0x20a) 2409 + #define Usage_BD_BrailleKeyboardRightSpace Usage_i16(0x20b) 2410 + #define Usage_BD_BrailleFaceControls Usage_i16(0x20c) 2411 + #define Usage_BD_BrailleLeftControls Usage_i16(0x20d) 2412 + #define Usage_BD_BrailleRightControls Usage_i16(0x20e) 2413 + #define Usage_BD_BrailleTopControls Usage_i16(0x20f) 2414 + #define Usage_BD_BrailleJoystickCenter Usage_i16(0x210) 2415 + #define Usage_BD_BrailleJoystickUp Usage_i16(0x211) 2416 + #define Usage_BD_BrailleJoystickDown Usage_i16(0x212) 2417 + #define Usage_BD_BrailleJoystickLeft Usage_i16(0x213) 2418 + #define Usage_BD_BrailleJoystickRight Usage_i16(0x214) 2419 + #define Usage_BD_BrailleDPadCenter Usage_i16(0x215) 2420 + #define Usage_BD_BrailleDPadUp Usage_i16(0x216) 2421 + #define Usage_BD_BrailleDPadDown Usage_i16(0x217) 2422 + #define Usage_BD_BrailleDPadLeft Usage_i16(0x218) 2423 + #define Usage_BD_BrailleDPadRight Usage_i16(0x219) 2424 + #define Usage_BD_BraillePanLeft Usage_i16(0x21a) 2425 + #define Usage_BD_BraillePanRight Usage_i16(0x21b) 2426 + #define Usage_BD_BrailleRockerUp Usage_i16(0x21c) 2427 + #define Usage_BD_BrailleRockerDown Usage_i16(0x21d) 2428 + #define Usage_BD_BrailleRockerPress Usage_i16(0x21e) 2429 + #define Usage_LAI_LampArray Usage_i8(0x1) 2430 + #define Usage_LAI_LampArrayAttributesReport Usage_i8(0x2) 2431 + #define Usage_LAI_LampCount Usage_i8(0x3) 2432 + #define Usage_LAI_BoundingBoxWidthInMicrometers Usage_i8(0x4) 2433 + #define Usage_LAI_BoundingBoxHeightInMicrometers Usage_i8(0x5) 2434 + #define Usage_LAI_BoundingBoxDepthInMicrometers Usage_i8(0x6) 2435 + #define Usage_LAI_LampArrayKind Usage_i8(0x7) 2436 + #define Usage_LAI_MinUpdateIntervalInMicroseconds Usage_i8(0x8) 2437 + #define Usage_LAI_LampAttributesRequestReport Usage_i8(0x20) 2438 + #define Usage_LAI_LampId Usage_i8(0x21) 2439 + #define Usage_LAI_LampAttributesResponseReport Usage_i8(0x22) 2440 + #define Usage_LAI_PositionXInMicrometers Usage_i8(0x23) 2441 + #define Usage_LAI_PositionYInMicrometers Usage_i8(0x24) 2442 + #define Usage_LAI_PositionZInMicrometers Usage_i8(0x25) 2443 + #define Usage_LAI_LampPurposes Usage_i8(0x26) 2444 + #define Usage_LAI_UpdateLatencyInMicroseconds Usage_i8(0x27) 2445 + #define Usage_LAI_RedLevelCount Usage_i8(0x28) 2446 + #define Usage_LAI_GreenLevelCount Usage_i8(0x29) 2447 + #define Usage_LAI_BlueLevelCount Usage_i8(0x2a) 2448 + #define Usage_LAI_IntensityLevelCount Usage_i8(0x2b) 2449 + #define Usage_LAI_IsProgrammable Usage_i8(0x2c) 2450 + #define Usage_LAI_InputBinding Usage_i8(0x2d) 2451 + #define Usage_LAI_LampMultiUpdateReport Usage_i8(0x50) 2452 + #define Usage_LAI_RedUpdateChannel Usage_i8(0x51) 2453 + #define Usage_LAI_GreenUpdateChannel Usage_i8(0x52) 2454 + #define Usage_LAI_BlueUpdateChannel Usage_i8(0x53) 2455 + #define Usage_LAI_IntensityUpdateChannel Usage_i8(0x54) 2456 + #define Usage_LAI_LampUpdateFlags Usage_i8(0x55) 2457 + #define Usage_LAI_LampRangeUpdateReport Usage_i8(0x60) 2458 + #define Usage_LAI_LampIdStart Usage_i8(0x61) 2459 + #define Usage_LAI_LampIdEnd Usage_i8(0x62) 2460 + #define Usage_LAI_LampArrayControlReport Usage_i8(0x70) 2461 + #define Usage_LAI_AutonomousMode Usage_i8(0x71) 2462 + #define Usage_Mon_MonitorControl Usage_i8(0x1) 2463 + #define Usage_Mon_EDIDInformation Usage_i8(0x2) 2464 + #define Usage_Mon_VDIFInformation Usage_i8(0x3) 2465 + #define Usage_Mon_VESAVersion Usage_i8(0x4) 2466 + #define Usage_VESAVC_Degauss Usage_i8(0x1) 2467 + #define Usage_VESAVC_Brightness Usage_i8(0x10) 2468 + #define Usage_VESAVC_Contrast Usage_i8(0x12) 2469 + #define Usage_VESAVC_RedVideoGain Usage_i8(0x16) 2470 + #define Usage_VESAVC_GreenVideoGain Usage_i8(0x18) 2471 + #define Usage_VESAVC_BlueVideoGain Usage_i8(0x1a) 2472 + #define Usage_VESAVC_Focus Usage_i8(0x1c) 2473 + #define Usage_VESAVC_HorizontalPosition Usage_i8(0x20) 2474 + #define Usage_VESAVC_HorizontalSize Usage_i8(0x22) 2475 + #define Usage_VESAVC_HorizontalPincushion Usage_i8(0x24) 2476 + #define Usage_VESAVC_HorizontalPincushionBalance Usage_i8(0x26) 2477 + #define Usage_VESAVC_HorizontalMisconvergence Usage_i8(0x28) 2478 + #define Usage_VESAVC_HorizontalLinearity Usage_i8(0x2a) 2479 + #define Usage_VESAVC_HorizontalLinearityBalance Usage_i8(0x2c) 2480 + #define Usage_VESAVC_VerticalPosition Usage_i8(0x30) 2481 + #define Usage_VESAVC_VerticalSize Usage_i8(0x32) 2482 + #define Usage_VESAVC_VerticalPincushion Usage_i8(0x34) 2483 + #define Usage_VESAVC_VerticalPincushionBalance Usage_i8(0x36) 2484 + #define Usage_VESAVC_VerticalMisconvergence Usage_i8(0x38) 2485 + #define Usage_VESAVC_VerticalLinearity Usage_i8(0x3a) 2486 + #define Usage_VESAVC_VerticalLinearityBalance Usage_i8(0x3c) 2487 + #define Usage_VESAVC_ParallelogramDistortionKeyBalance Usage_i8(0x40) 2488 + #define Usage_VESAVC_TrapezoidalDistortionKey Usage_i8(0x42) 2489 + #define Usage_VESAVC_TiltRotation Usage_i8(0x44) 2490 + #define Usage_VESAVC_TopCornerDistortionControl Usage_i8(0x46) 2491 + #define Usage_VESAVC_TopCornerDistortionBalance Usage_i8(0x48) 2492 + #define Usage_VESAVC_BottomCornerDistortionControl Usage_i8(0x4a) 2493 + #define Usage_VESAVC_BottomCornerDistortionBalance Usage_i8(0x4c) 2494 + #define Usage_VESAVC_HorizontalMoiré Usage_i8(0x56) 2495 + #define Usage_VESAVC_VerticalMoiré Usage_i8(0x58) 2496 + #define Usage_VESAVC_InputLevelSelect Usage_i8(0x5e) 2497 + #define Usage_VESAVC_InputSourceSelect Usage_i8(0x60) 2498 + #define Usage_VESAVC_RedVideoBlackLevel Usage_i8(0x6c) 2499 + #define Usage_VESAVC_GreenVideoBlackLevel Usage_i8(0x6e) 2500 + #define Usage_VESAVC_BlueVideoBlackLevel Usage_i8(0x70) 2501 + #define Usage_VESAVC_AutoSizeCenter Usage_i8(0xa2) 2502 + #define Usage_VESAVC_PolarityHorizontalSynchronization Usage_i8(0xa4) 2503 + #define Usage_VESAVC_PolarityVerticalSynchronization Usage_i8(0xa6) 2504 + #define Usage_VESAVC_SynchronizationType Usage_i8(0xa8) 2505 + #define Usage_VESAVC_ScreenOrientation Usage_i8(0xaa) 2506 + #define Usage_VESAVC_HorizontalFrequency Usage_i8(0xac) 2507 + #define Usage_VESAVC_VerticalFrequency Usage_i8(0xae) 2508 + #define Usage_VESAVC_Settings Usage_i8(0xb0) 2509 + #define Usage_VESAVC_OnScreenDisplay Usage_i8(0xca) 2510 + #define Usage_VESAVC_StereoMode Usage_i8(0xd4) 2511 + #define Usage_Pow_iName Usage_i8(0x1) 2512 + #define Usage_Pow_PresentStatus Usage_i8(0x2) 2513 + #define Usage_Pow_ChangedStatus Usage_i8(0x3) 2514 + #define Usage_Pow_UPS Usage_i8(0x4) 2515 + #define Usage_Pow_PowerSupply Usage_i8(0x5) 2516 + #define Usage_Pow_BatterySystem Usage_i8(0x10) 2517 + #define Usage_Pow_BatterySystemId Usage_i8(0x11) 2518 + #define Usage_Pow_Battery Usage_i8(0x12) 2519 + #define Usage_Pow_BatteryId Usage_i8(0x13) 2520 + #define Usage_Pow_Charger Usage_i8(0x14) 2521 + #define Usage_Pow_ChargerId Usage_i8(0x15) 2522 + #define Usage_Pow_PowerConverter Usage_i8(0x16) 2523 + #define Usage_Pow_PowerConverterId Usage_i8(0x17) 2524 + #define Usage_Pow_OutletSystem Usage_i8(0x18) 2525 + #define Usage_Pow_OutletSystemId Usage_i8(0x19) 2526 + #define Usage_Pow_Input Usage_i8(0x1a) 2527 + #define Usage_Pow_InputId Usage_i8(0x1b) 2528 + #define Usage_Pow_Output Usage_i8(0x1c) 2529 + #define Usage_Pow_OutputId Usage_i8(0x1d) 2530 + #define Usage_Pow_Flow Usage_i8(0x1e) 2531 + #define Usage_Pow_FlowId Usage_i8(0x1f) 2532 + #define Usage_Pow_Outlet Usage_i8(0x20) 2533 + #define Usage_Pow_OutletId Usage_i8(0x21) 2534 + #define Usage_Pow_Gang Usage_i8(0x22) 2535 + #define Usage_Pow_GangId Usage_i8(0x23) 2536 + #define Usage_Pow_PowerSummary Usage_i8(0x24) 2537 + #define Usage_Pow_PowerSummaryId Usage_i8(0x25) 2538 + #define Usage_Pow_Voltage Usage_i8(0x30) 2539 + #define Usage_Pow_Current Usage_i8(0x31) 2540 + #define Usage_Pow_Frequency Usage_i8(0x32) 2541 + #define Usage_Pow_ApparentPower Usage_i8(0x33) 2542 + #define Usage_Pow_ActivePower Usage_i8(0x34) 2543 + #define Usage_Pow_PercentLoad Usage_i8(0x35) 2544 + #define Usage_Pow_Temperature Usage_i8(0x36) 2545 + #define Usage_Pow_Humidity Usage_i8(0x37) 2546 + #define Usage_Pow_BadCount Usage_i8(0x38) 2547 + #define Usage_Pow_ConfigVoltage Usage_i8(0x40) 2548 + #define Usage_Pow_ConfigCurrent Usage_i8(0x41) 2549 + #define Usage_Pow_ConfigFrequency Usage_i8(0x42) 2550 + #define Usage_Pow_ConfigApparentPower Usage_i8(0x43) 2551 + #define Usage_Pow_ConfigActivePower Usage_i8(0x44) 2552 + #define Usage_Pow_ConfigPercentLoad Usage_i8(0x45) 2553 + #define Usage_Pow_ConfigTemperature Usage_i8(0x46) 2554 + #define Usage_Pow_ConfigHumidity Usage_i8(0x47) 2555 + #define Usage_Pow_SwitchOnControl Usage_i8(0x50) 2556 + #define Usage_Pow_SwitchOffControl Usage_i8(0x51) 2557 + #define Usage_Pow_ToggleControl Usage_i8(0x52) 2558 + #define Usage_Pow_LowVoltageTransfer Usage_i8(0x53) 2559 + #define Usage_Pow_HighVoltageTransfer Usage_i8(0x54) 2560 + #define Usage_Pow_DelayBeforeReboot Usage_i8(0x55) 2561 + #define Usage_Pow_DelayBeforeStartup Usage_i8(0x56) 2562 + #define Usage_Pow_DelayBeforeShutdown Usage_i8(0x57) 2563 + #define Usage_Pow_Test Usage_i8(0x58) 2564 + #define Usage_Pow_ModuleReset Usage_i8(0x59) 2565 + #define Usage_Pow_AudibleAlarmControl Usage_i8(0x5a) 2566 + #define Usage_Pow_Present Usage_i8(0x60) 2567 + #define Usage_Pow_Good Usage_i8(0x61) 2568 + #define Usage_Pow_InternalFailure Usage_i8(0x62) 2569 + #define Usage_Pow_VoltagOutOfRange Usage_i8(0x63) 2570 + #define Usage_Pow_FrequencyOutOfRange Usage_i8(0x64) 2571 + #define Usage_Pow_Overload Usage_i8(0x65) 2572 + #define Usage_Pow_OverCharged Usage_i8(0x66) 2573 + #define Usage_Pow_OverTemperature Usage_i8(0x67) 2574 + #define Usage_Pow_ShutdownRequested Usage_i8(0x68) 2575 + #define Usage_Pow_ShutdownImminent Usage_i8(0x69) 2576 + #define Usage_Pow_SwitchOnOff Usage_i8(0x6b) 2577 + #define Usage_Pow_Switchable Usage_i8(0x6c) 2578 + #define Usage_Pow_Used Usage_i8(0x6d) 2579 + #define Usage_Pow_Boost Usage_i8(0x6e) 2580 + #define Usage_Pow_Buck Usage_i8(0x6f) 2581 + #define Usage_Pow_Initialized Usage_i8(0x70) 2582 + #define Usage_Pow_Tested Usage_i8(0x71) 2583 + #define Usage_Pow_AwaitingPower Usage_i8(0x72) 2584 + #define Usage_Pow_CommunicationLost Usage_i8(0x73) 2585 + #define Usage_Pow_iManufacturer Usage_i8(0xfd) 2586 + #define Usage_Pow_iProduct Usage_i8(0xfe) 2587 + #define Usage_Pow_iSerialNumber Usage_i16(0xff) 2588 + #define Usage_BS_SmartBatteryBatteryMode Usage_i8(0x1) 2589 + #define Usage_BS_SmartBatteryBatteryStatus Usage_i8(0x2) 2590 + #define Usage_BS_SmartBatteryAlarmWarning Usage_i8(0x3) 2591 + #define Usage_BS_SmartBatteryChargerMode Usage_i8(0x4) 2592 + #define Usage_BS_SmartBatteryChargerStatus Usage_i8(0x5) 2593 + #define Usage_BS_SmartBatteryChargerSpecInfo Usage_i8(0x6) 2594 + #define Usage_BS_SmartBatterySelectorState Usage_i8(0x7) 2595 + #define Usage_BS_SmartBatterySelectorPresets Usage_i8(0x8) 2596 + #define Usage_BS_SmartBatterySelectorInfo Usage_i8(0x9) 2597 + #define Usage_BS_OptionalMfgFunction1 Usage_i8(0x10) 2598 + #define Usage_BS_OptionalMfgFunction2 Usage_i8(0x11) 2599 + #define Usage_BS_OptionalMfgFunction3 Usage_i8(0x12) 2600 + #define Usage_BS_OptionalMfgFunction4 Usage_i8(0x13) 2601 + #define Usage_BS_OptionalMfgFunction5 Usage_i8(0x14) 2602 + #define Usage_BS_ConnectionToSMBus Usage_i8(0x15) 2603 + #define Usage_BS_OutputConnection Usage_i8(0x16) 2604 + #define Usage_BS_ChargerConnection Usage_i8(0x17) 2605 + #define Usage_BS_BatteryInsertion Usage_i8(0x18) 2606 + #define Usage_BS_UseNext Usage_i8(0x19) 2607 + #define Usage_BS_OKToUse Usage_i8(0x1a) 2608 + #define Usage_BS_BatterySupported Usage_i8(0x1b) 2609 + #define Usage_BS_SelectorRevision Usage_i8(0x1c) 2610 + #define Usage_BS_ChargingIndicator Usage_i8(0x1d) 2611 + #define Usage_BS_ManufacturerAccess Usage_i8(0x28) 2612 + #define Usage_BS_RemainingCapacityLimit Usage_i8(0x29) 2613 + #define Usage_BS_RemainingTimeLimit Usage_i8(0x2a) 2614 + #define Usage_BS_AtRate Usage_i8(0x2b) 2615 + #define Usage_BS_CapacityMode Usage_i8(0x2c) 2616 + #define Usage_BS_BroadcastToCharger Usage_i8(0x2d) 2617 + #define Usage_BS_PrimaryBattery Usage_i8(0x2e) 2618 + #define Usage_BS_ChargeController Usage_i8(0x2f) 2619 + #define Usage_BS_TerminateCharge Usage_i8(0x40) 2620 + #define Usage_BS_TerminateDischarge Usage_i8(0x41) 2621 + #define Usage_BS_BelowRemainingCapacityLimit Usage_i8(0x42) 2622 + #define Usage_BS_RemainingTimeLimitExpired Usage_i8(0x43) 2623 + #define Usage_BS_Charging Usage_i8(0x44) 2624 + #define Usage_BS_Discharging Usage_i8(0x45) 2625 + #define Usage_BS_FullyCharged Usage_i8(0x46) 2626 + #define Usage_BS_FullyDischarged Usage_i8(0x47) 2627 + #define Usage_BS_ConditioningFlag Usage_i8(0x48) 2628 + #define Usage_BS_AtRateOK Usage_i8(0x49) 2629 + #define Usage_BS_SmartBatteryErrorCode Usage_i8(0x4a) 2630 + #define Usage_BS_NeedReplacement Usage_i8(0x4b) 2631 + #define Usage_BS_AtRateTimeToFull Usage_i8(0x60) 2632 + #define Usage_BS_AtRateTimeToEmpty Usage_i8(0x61) 2633 + #define Usage_BS_AverageCurrent Usage_i8(0x62) 2634 + #define Usage_BS_MaxError Usage_i8(0x63) 2635 + #define Usage_BS_RelativeStateOfCharge Usage_i8(0x64) 2636 + #define Usage_BS_AbsoluteStateOfCharge Usage_i8(0x65) 2637 + #define Usage_BS_RemainingCapacity Usage_i8(0x66) 2638 + #define Usage_BS_FullChargeCapacity Usage_i8(0x67) 2639 + #define Usage_BS_RunTimeToEmpty Usage_i8(0x68) 2640 + #define Usage_BS_AverageTimeToEmpty Usage_i8(0x69) 2641 + #define Usage_BS_AverageTimeToFull Usage_i8(0x6a) 2642 + #define Usage_BS_CycleCount Usage_i8(0x6b) 2643 + #define Usage_BS_BatteryPackModelLevel Usage_i8(0x80) 2644 + #define Usage_BS_InternalChargeController Usage_i8(0x81) 2645 + #define Usage_BS_PrimaryBatterySupport Usage_i8(0x82) 2646 + #define Usage_BS_DesignCapacity Usage_i8(0x83) 2647 + #define Usage_BS_SpecificationInfo Usage_i8(0x84) 2648 + #define Usage_BS_ManufactureDate Usage_i8(0x85) 2649 + #define Usage_BS_SerialNumber Usage_i8(0x86) 2650 + #define Usage_BS_iManufacturerName Usage_i8(0x87) 2651 + #define Usage_BS_iDeviceName Usage_i8(0x88) 2652 + #define Usage_BS_iDeviceChemistry Usage_i8(0x89) 2653 + #define Usage_BS_ManufacturerData Usage_i8(0x8a) 2654 + #define Usage_BS_Rechargable Usage_i8(0x8b) 2655 + #define Usage_BS_WarningCapacityLimit Usage_i8(0x8c) 2656 + #define Usage_BS_CapacityGranularity1 Usage_i8(0x8d) 2657 + #define Usage_BS_CapacityGranularity2 Usage_i8(0x8e) 2658 + #define Usage_BS_iOEMInformation Usage_i8(0x8f) 2659 + #define Usage_BS_InhibitCharge Usage_i8(0xc0) 2660 + #define Usage_BS_EnablePolling Usage_i8(0xc1) 2661 + #define Usage_BS_ResetToZero Usage_i8(0xc2) 2662 + #define Usage_BS_ACPresent Usage_i8(0xd0) 2663 + #define Usage_BS_BatteryPresent Usage_i8(0xd1) 2664 + #define Usage_BS_PowerFail Usage_i8(0xd2) 2665 + #define Usage_BS_AlarmInhibited Usage_i8(0xd3) 2666 + #define Usage_BS_ThermistorUnderRange Usage_i8(0xd4) 2667 + #define Usage_BS_ThermistorHot Usage_i8(0xd5) 2668 + #define Usage_BS_ThermistorCold Usage_i8(0xd6) 2669 + #define Usage_BS_ThermistorOverRange Usage_i8(0xd7) 2670 + #define Usage_BS_VoltageOutOfRange Usage_i8(0xd8) 2671 + #define Usage_BS_CurrentOutOfRange Usage_i8(0xd9) 2672 + #define Usage_BS_CurrentNotRegulated Usage_i8(0xda) 2673 + #define Usage_BS_VoltageNotRegulated Usage_i8(0xdb) 2674 + #define Usage_BS_MasterMode Usage_i8(0xdc) 2675 + #define Usage_BS_ChargerSelectorSupport Usage_i8(0xf0) 2676 + #define Usage_BS_ChargerSpec Usage_i8(0xf1) 2677 + #define Usage_BS_Level2 Usage_i8(0xf2) 2678 + #define Usage_BS_Level3 Usage_i8(0xf3) 2679 + #define Usage_BS_BarcodeBadgeReader Usage_i8(0x1) 2680 + #define Usage_BS_BarcodeScanner Usage_i8(0x2) 2681 + #define Usage_BS_DumbBarCodeScanner Usage_i8(0x3) 2682 + #define Usage_BS_CordlessScannerBase Usage_i8(0x4) 2683 + #define Usage_BS_BarCodeScannerCradle Usage_i8(0x5) 2684 + #define Usage_BS_AttributeReport Usage_i8(0x10) 2685 + #define Usage_BS_SettingsReport Usage_i8(0x11) 2686 + #define Usage_BS_ScannedDataReport Usage_i8(0x12) 2687 + #define Usage_BS_RawScannedDataReport Usage_i8(0x13) 2688 + #define Usage_BS_TriggerReport Usage_i8(0x14) 2689 + #define Usage_BS_StatusReport Usage_i8(0x15) 2690 + #define Usage_BS_UPCEANControlReport Usage_i8(0x16) 2691 + #define Usage_BS_EAN23LabelControlReport Usage_i8(0x17) 2692 + #define Usage_BS_Code39ControlReport Usage_i8(0x18) 2693 + #define Usage_BS_Interleaved2of5ControlReport Usage_i8(0x19) 2694 + #define Usage_BS_Standard2of5ControlReport Usage_i8(0x1a) 2695 + #define Usage_BS_MSIPlesseyControlReport Usage_i8(0x1b) 2696 + #define Usage_BS_CodabarControlReport Usage_i8(0x1c) 2697 + #define Usage_BS_Code128ControlReport Usage_i8(0x1d) 2698 + #define Usage_BS_Misc1DControlReport Usage_i8(0x1e) 2699 + #define Usage_BS_TwoDControlReport Usage_i8(0x1f) 2700 + #define Usage_BS_AimingPointerMode Usage_i8(0x30) 2701 + #define Usage_BS_BarCodePresentSensor Usage_i8(0x31) 2702 + #define Usage_BS_Class1ALaser Usage_i8(0x32) 2703 + #define Usage_BS_Class2Laser Usage_i8(0x33) 2704 + #define Usage_BS_HeaterPresent Usage_i8(0x34) 2705 + #define Usage_BS_ContactScanner Usage_i8(0x35) 2706 + #define Usage_BS_ElectronicArticleSurveillanceNotification Usage_i8(0x36) 2707 + #define Usage_BS_ConstantElectronicArticleSurveillance Usage_i8(0x37) 2708 + #define Usage_BS_ErrorIndication Usage_i8(0x38) 2709 + #define Usage_BS_FixedBeeper Usage_i8(0x39) 2710 + #define Usage_BS_GoodDecodeIndication Usage_i8(0x3a) 2711 + #define Usage_BS_HandsFreeScanning Usage_i8(0x3b) 2712 + #define Usage_BS_IntrinsicallySafe Usage_i8(0x3c) 2713 + #define Usage_BS_KlasseEinsLaser Usage_i8(0x3d) 2714 + #define Usage_BS_LongRangeScanner Usage_i8(0x3e) 2715 + #define Usage_BS_MirrorSpeedControl Usage_i8(0x3f) 2716 + #define Usage_BS_NotOnFileIndication Usage_i8(0x40) 2717 + #define Usage_BS_ProgrammableBeeper Usage_i8(0x41) 2718 + #define Usage_BS_Triggerless Usage_i8(0x42) 2719 + #define Usage_BS_Wand Usage_i8(0x43) 2720 + #define Usage_BS_WaterResistant Usage_i8(0x44) 2721 + #define Usage_BS_MultiRangeScanner Usage_i8(0x45) 2722 + #define Usage_BS_ProximitySensor Usage_i8(0x46) 2723 + #define Usage_BS_FragmentDecoding Usage_i8(0x4d) 2724 + #define Usage_BS_ScannerReadConfidence Usage_i8(0x4e) 2725 + #define Usage_BS_DataPrefix Usage_i8(0x4f) 2726 + #define Usage_BS_PrefixAIMI Usage_i8(0x50) 2727 + #define Usage_BS_PrefixNone Usage_i8(0x51) 2728 + #define Usage_BS_PrefixProprietary Usage_i8(0x52) 2729 + #define Usage_BS_ActiveTime Usage_i8(0x55) 2730 + #define Usage_BS_AimingLaserPattern Usage_i8(0x56) 2731 + #define Usage_BS_BarCodePresent Usage_i8(0x57) 2732 + #define Usage_BS_BeeperState Usage_i8(0x58) 2733 + #define Usage_BS_LaserOnTime Usage_i8(0x59) 2734 + #define Usage_BS_LaserState Usage_i8(0x5a) 2735 + #define Usage_BS_LockoutTime Usage_i8(0x5b) 2736 + #define Usage_BS_MotorState Usage_i8(0x5c) 2737 + #define Usage_BS_MotorTimeout Usage_i8(0x5d) 2738 + #define Usage_BS_PowerOnResetScanner Usage_i8(0x5e) 2739 + #define Usage_BS_PreventReadofBarcodes Usage_i8(0x5f) 2740 + #define Usage_BS_InitiateBarcodeRead Usage_i8(0x60) 2741 + #define Usage_BS_TriggerState Usage_i8(0x61) 2742 + #define Usage_BS_TriggerMode Usage_i8(0x62) 2743 + #define Usage_BS_TriggerModeBlinkingLaserOn Usage_i8(0x63) 2744 + #define Usage_BS_TriggerModeContinuousLaserOn Usage_i8(0x64) 2745 + #define Usage_BS_TriggerModeLaseronwhilePulled Usage_i8(0x65) 2746 + #define Usage_BS_TriggerModeLaserstaysonafterrelease Usage_i8(0x66) 2747 + #define Usage_BS_CommitParameterstoNVM Usage_i8(0x6d) 2748 + #define Usage_BS_ParameterScanning Usage_i8(0x6e) 2749 + #define Usage_BS_ParametersChanged Usage_i8(0x6f) 2750 + #define Usage_BS_Setparameterdefaultvalues Usage_i8(0x70) 2751 + #define Usage_BS_ScannerInCradle Usage_i8(0x75) 2752 + #define Usage_BS_ScannerInRange Usage_i8(0x76) 2753 + #define Usage_BS_AimDuration Usage_i8(0x7a) 2754 + #define Usage_BS_GoodReadLampDuration Usage_i8(0x7b) 2755 + #define Usage_BS_GoodReadLampIntensity Usage_i8(0x7c) 2756 + #define Usage_BS_GoodReadLED Usage_i8(0x7d) 2757 + #define Usage_BS_GoodReadToneFrequency Usage_i8(0x7e) 2758 + #define Usage_BS_GoodReadToneLength Usage_i8(0x7f) 2759 + #define Usage_BS_GoodReadToneVolume Usage_i8(0x80) 2760 + #define Usage_BS_NoReadMessage Usage_i8(0x82) 2761 + #define Usage_BS_NotonFileVolume Usage_i8(0x83) 2762 + #define Usage_BS_PowerupBeep Usage_i8(0x84) 2763 + #define Usage_BS_SoundErrorBeep Usage_i8(0x85) 2764 + #define Usage_BS_SoundGoodReadBeep Usage_i8(0x86) 2765 + #define Usage_BS_SoundNotOnFileBeep Usage_i8(0x87) 2766 + #define Usage_BS_GoodReadWhentoWrite Usage_i8(0x88) 2767 + #define Usage_BS_GRWTIAfterDecode Usage_i8(0x89) 2768 + #define Usage_BS_GRWTIBeepLampaftertransmit Usage_i8(0x8a) 2769 + #define Usage_BS_GRWTINoBeepLampuseatall Usage_i8(0x8b) 2770 + #define Usage_BS_BooklandEAN Usage_i8(0x91) 2771 + #define Usage_BS_ConvertEAN8to13Type Usage_i8(0x92) 2772 + #define Usage_BS_ConvertUPCAtoEAN13 Usage_i8(0x93) 2773 + #define Usage_BS_ConvertUPCEtoA Usage_i8(0x94) 2774 + #define Usage_BS_EAN13 Usage_i8(0x95) 2775 + #define Usage_BS_EAN8 Usage_i8(0x96) 2776 + #define Usage_BS_EAN99128Mandatory Usage_i8(0x97) 2777 + #define Usage_BS_EAN99P5128Optional Usage_i8(0x98) 2778 + #define Usage_BS_EnableEANTwoLabel Usage_i8(0x99) 2779 + #define Usage_BS_UPCEAN Usage_i8(0x9a) 2780 + #define Usage_BS_UPCEANCouponCode Usage_i8(0x9b) 2781 + #define Usage_BS_UPCEANPeriodicals Usage_i8(0x9c) 2782 + #define Usage_BS_UPCA Usage_i8(0x9d) 2783 + #define Usage_BS_UPCAwith128Mandatory Usage_i8(0x9e) 2784 + #define Usage_BS_UPCAwith128Optional Usage_i8(0x9f) 2785 + #define Usage_BS_UPCAwithP5Optional Usage_i8(0xa0) 2786 + #define Usage_BS_UPCE Usage_i8(0xa1) 2787 + #define Usage_BS_UPCE1 Usage_i8(0xa2) 2788 + #define Usage_BS_Periodical Usage_i8(0xa9) 2789 + #define Usage_BS_PeriodicalAutoDiscriminatePlus2 Usage_i8(0xaa) 2790 + #define Usage_BS_PeriodicalOnlyDecodewithPlus2 Usage_i8(0xab) 2791 + #define Usage_BS_PeriodicalIgnorePlus2 Usage_i8(0xac) 2792 + #define Usage_BS_PeriodicalAutoDiscriminatePlus5 Usage_i8(0xad) 2793 + #define Usage_BS_PeriodicalOnlyDecodewithPlus5 Usage_i8(0xae) 2794 + #define Usage_BS_PeriodicalIgnorePlus5 Usage_i8(0xaf) 2795 + #define Usage_BS_Check Usage_i8(0xb0) 2796 + #define Usage_BS_CheckDisablePrice Usage_i8(0xb1) 2797 + #define Usage_BS_CheckEnable4digitPrice Usage_i8(0xb2) 2798 + #define Usage_BS_CheckEnable5digitPrice Usage_i8(0xb3) 2799 + #define Usage_BS_CheckEnableEuropean4digitPrice Usage_i8(0xb4) 2800 + #define Usage_BS_CheckEnableEuropean5digitPrice Usage_i8(0xb5) 2801 + #define Usage_BS_EANTwoLabel Usage_i8(0xb7) 2802 + #define Usage_BS_EANThreeLabel Usage_i8(0xb8) 2803 + #define Usage_BS_EAN8FlagDigit1 Usage_i8(0xb9) 2804 + #define Usage_BS_EAN8FlagDigit2 Usage_i8(0xba) 2805 + #define Usage_BS_EAN8FlagDigit3 Usage_i8(0xbb) 2806 + #define Usage_BS_EAN13FlagDigit1 Usage_i8(0xbc) 2807 + #define Usage_BS_EAN13FlagDigit2 Usage_i8(0xbd) 2808 + #define Usage_BS_EAN13FlagDigit3 Usage_i8(0xbe) 2809 + #define Usage_BS_AddEAN23LabelDefinition Usage_i8(0xbf) 2810 + #define Usage_BS_ClearallEAN23LabelDefinitions Usage_i8(0xc0) 2811 + #define Usage_BS_Codabar Usage_i8(0xc3) 2812 + #define Usage_BS_Code128 Usage_i8(0xc4) 2813 + #define Usage_BS_Code39 Usage_i8(0xc7) 2814 + #define Usage_BS_Code93 Usage_i8(0xc8) 2815 + #define Usage_BS_FullASCIIConversion Usage_i8(0xc9) 2816 + #define Usage_BS_Interleaved2of5 Usage_i8(0xca) 2817 + #define Usage_BS_ItalianPharmacyCode Usage_i8(0xcb) 2818 + #define Usage_BS_MSIPlessey Usage_i8(0xcc) 2819 + #define Usage_BS_Standard2of5IATA Usage_i8(0xcd) 2820 + #define Usage_BS_Standard2of5 Usage_i8(0xce) 2821 + #define Usage_BS_TransmitStartStop Usage_i8(0xd3) 2822 + #define Usage_BS_TriOptic Usage_i8(0xd4) 2823 + #define Usage_BS_UCCEAN128 Usage_i8(0xd5) 2824 + #define Usage_BS_CheckDigit Usage_i8(0xd6) 2825 + #define Usage_BS_CheckDigitDisable Usage_i8(0xd7) 2826 + #define Usage_BS_CheckDigitEnableInterleaved2of5OPCC Usage_i8(0xd8) 2827 + #define Usage_BS_CheckDigitEnableInterleaved2of5USS Usage_i8(0xd9) 2828 + #define Usage_BS_CheckDigitEnableStandard2of5OPCC Usage_i8(0xda) 2829 + #define Usage_BS_CheckDigitEnableStandard2of5USS Usage_i8(0xdb) 2830 + #define Usage_BS_CheckDigitEnableOneMSIPlessey Usage_i8(0xdc) 2831 + #define Usage_BS_CheckDigitEnableTwoMSIPlessey Usage_i8(0xdd) 2832 + #define Usage_BS_CheckDigitCodabarEnable Usage_i8(0xde) 2833 + #define Usage_BS_CheckDigitCode39Enable Usage_i8(0xdf) 2834 + #define Usage_BS_TransmitCheckDigit Usage_i8(0xf0) 2835 + #define Usage_BS_DisableCheckDigitTransmit Usage_i8(0xf1) 2836 + #define Usage_BS_EnableCheckDigitTransmit Usage_i8(0xf2) 2837 + #define Usage_BS_SymbologyIdentifier1 Usage_i8(0xfb) 2838 + #define Usage_BS_SymbologyIdentifier2 Usage_i8(0xfc) 2839 + #define Usage_BS_SymbologyIdentifier3 Usage_i8(0xfd) 2840 + #define Usage_BS_DecodedData Usage_i8(0xfe) 2841 + #define Usage_BS_DecodeDataContinued Usage_i16(0xff) 2842 + #define Usage_BS_BarSpaceData Usage_i16(0x100) 2843 + #define Usage_BS_ScannerDataAccuracy Usage_i16(0x101) 2844 + #define Usage_BS_RawDataPolarity Usage_i16(0x102) 2845 + #define Usage_BS_PolarityInvertedBarCode Usage_i16(0x103) 2846 + #define Usage_BS_PolarityNormalBarCode Usage_i16(0x104) 2847 + #define Usage_BS_MinimumLengthtoDecode Usage_i16(0x106) 2848 + #define Usage_BS_MaximumLengthtoDecode Usage_i16(0x107) 2849 + #define Usage_BS_DiscreteLengthtoDecode1 Usage_i16(0x108) 2850 + #define Usage_BS_DiscreteLengthtoDecode2 Usage_i16(0x109) 2851 + #define Usage_BS_DataLengthMethod Usage_i16(0x10a) 2852 + #define Usage_BS_DLMethodReadany Usage_i16(0x10b) 2853 + #define Usage_BS_DLMethodCheckinRange Usage_i16(0x10c) 2854 + #define Usage_BS_DLMethodCheckforDiscrete Usage_i16(0x10d) 2855 + #define Usage_BS_AztecCode Usage_i16(0x110) 2856 + #define Usage_BS_BC412 Usage_i16(0x111) 2857 + #define Usage_BS_ChannelCode Usage_i16(0x112) 2858 + #define Usage_BS_Code16 Usage_i16(0x113) 2859 + #define Usage_BS_Code32 Usage_i16(0x114) 2860 + #define Usage_BS_Code49 Usage_i16(0x115) 2861 + #define Usage_BS_CodeOne Usage_i16(0x116) 2862 + #define Usage_BS_Colorcode Usage_i16(0x117) 2863 + #define Usage_BS_DataMatrix Usage_i16(0x118) 2864 + #define Usage_BS_MaxiCode Usage_i16(0x119) 2865 + #define Usage_BS_MicroPDF Usage_i16(0x11a) 2866 + #define Usage_BS_PDF417 Usage_i16(0x11b) 2867 + #define Usage_BS_PosiCode Usage_i16(0x11c) 2868 + #define Usage_BS_QRCode Usage_i16(0x11d) 2869 + #define Usage_BS_SuperCode Usage_i16(0x11e) 2870 + #define Usage_BS_UltraCode Usage_i16(0x11f) 2871 + #define Usage_BS_USD5SlugCode Usage_i16(0x120) 2872 + #define Usage_BS_VeriCode Usage_i16(0x121) 2873 + #define Usage_Sca_Scales Usage_i8(0x1) 2874 + #define Usage_Sca_ScaleDevice Usage_i8(0x20) 2875 + #define Usage_Sca_ScaleClass Usage_i8(0x21) 2876 + #define Usage_Sca_ScaleClassIMetric Usage_i8(0x22) 2877 + #define Usage_Sca_ScaleClassIIMetric Usage_i8(0x23) 2878 + #define Usage_Sca_ScaleClassIIIMetric Usage_i8(0x24) 2879 + #define Usage_Sca_ScaleClassIIILMetric Usage_i8(0x25) 2880 + #define Usage_Sca_ScaleClassIVMetric Usage_i8(0x26) 2881 + #define Usage_Sca_ScaleClassIIIEnglish Usage_i8(0x27) 2882 + #define Usage_Sca_ScaleClassIIILEnglish Usage_i8(0x28) 2883 + #define Usage_Sca_ScaleClassIVEnglish Usage_i8(0x29) 2884 + #define Usage_Sca_ScaleClassGeneric Usage_i8(0x2a) 2885 + #define Usage_Sca_ScaleAttributeReport Usage_i8(0x30) 2886 + #define Usage_Sca_ScaleControlReport Usage_i8(0x31) 2887 + #define Usage_Sca_ScaleDataReport Usage_i8(0x32) 2888 + #define Usage_Sca_ScaleStatusReport Usage_i8(0x33) 2889 + #define Usage_Sca_ScaleWeightLimitReport Usage_i8(0x34) 2890 + #define Usage_Sca_ScaleStatisticsReport Usage_i8(0x35) 2891 + #define Usage_Sca_DataWeight Usage_i8(0x40) 2892 + #define Usage_Sca_DataScaling Usage_i8(0x41) 2893 + #define Usage_Sca_WeightUnit Usage_i8(0x50) 2894 + #define Usage_Sca_WeightUnitMilligram Usage_i8(0x51) 2895 + #define Usage_Sca_WeightUnitGram Usage_i8(0x52) 2896 + #define Usage_Sca_WeightUnitKilogram Usage_i8(0x53) 2897 + #define Usage_Sca_WeightUnitCarats Usage_i8(0x54) 2898 + #define Usage_Sca_WeightUnitTaels Usage_i8(0x55) 2899 + #define Usage_Sca_WeightUnitGrains Usage_i8(0x56) 2900 + #define Usage_Sca_WeightUnitPennyweights Usage_i8(0x57) 2901 + #define Usage_Sca_WeightUnitMetricTon Usage_i8(0x58) 2902 + #define Usage_Sca_WeightUnitAvoirTon Usage_i8(0x59) 2903 + #define Usage_Sca_WeightUnitTroyOunce Usage_i8(0x5a) 2904 + #define Usage_Sca_WeightUnitOunce Usage_i8(0x5b) 2905 + #define Usage_Sca_WeightUnitPound Usage_i8(0x5c) 2906 + #define Usage_Sca_CalibrationCount Usage_i8(0x60) 2907 + #define Usage_Sca_ReZeroCount Usage_i8(0x61) 2908 + #define Usage_Sca_ScaleStatus Usage_i8(0x70) 2909 + #define Usage_Sca_ScaleStatusFault Usage_i8(0x71) 2910 + #define Usage_Sca_ScaleStatusStableatCenterofZero Usage_i8(0x72) 2911 + #define Usage_Sca_ScaleStatusInMotion Usage_i8(0x73) 2912 + #define Usage_Sca_ScaleStatusWeightStable Usage_i8(0x74) 2913 + #define Usage_Sca_ScaleStatusUnderZero Usage_i8(0x75) 2914 + #define Usage_Sca_ScaleStatusOverWeightLimit Usage_i8(0x76) 2915 + #define Usage_Sca_ScaleStatusRequiresCalibration Usage_i8(0x77) 2916 + #define Usage_Sca_ScaleStatusRequiresRezeroing Usage_i8(0x78) 2917 + #define Usage_Sca_ZeroScale Usage_i8(0x80) 2918 + #define Usage_Sca_EnforcedZeroReturn Usage_i8(0x81) 2919 + #define Usage_MSR_MSRDeviceReadOnly Usage_i8(0x1) 2920 + #define Usage_MSR_Track1Length Usage_i8(0x11) 2921 + #define Usage_MSR_Track2Length Usage_i8(0x12) 2922 + #define Usage_MSR_Track3Length Usage_i8(0x13) 2923 + #define Usage_MSR_TrackJISLength Usage_i8(0x14) 2924 + #define Usage_MSR_TrackData Usage_i8(0x20) 2925 + #define Usage_MSR_Track1Data Usage_i8(0x21) 2926 + #define Usage_MSR_Track2Data Usage_i8(0x22) 2927 + #define Usage_MSR_Track3Data Usage_i8(0x23) 2928 + #define Usage_MSR_TrackJISData Usage_i8(0x24) 2929 + #define Usage_CC_CameraAutofocus Usage_i8(0x20) 2930 + #define Usage_CC_CameraShutter Usage_i8(0x21) 2931 + #define Usage_Arc_GeneralPurposeIOCard Usage_i8(0x1) 2932 + #define Usage_Arc_CoinDoor Usage_i8(0x2) 2933 + #define Usage_Arc_WatchdogTimer Usage_i8(0x3) 2934 + #define Usage_Arc_GeneralPurposeAnalogInputState Usage_i8(0x30) 2935 + #define Usage_Arc_GeneralPurposeDigitalInputState Usage_i8(0x31) 2936 + #define Usage_Arc_GeneralPurposeOpticalInputState Usage_i8(0x32) 2937 + #define Usage_Arc_GeneralPurposeDigitalOutputState Usage_i8(0x33) 2938 + #define Usage_Arc_NumberofCoinDoors Usage_i8(0x34) 2939 + #define Usage_Arc_CoinDrawerDropCount Usage_i8(0x35) 2940 + #define Usage_Arc_CoinDrawerStart Usage_i8(0x36) 2941 + #define Usage_Arc_CoinDrawerService Usage_i8(0x37) 2942 + #define Usage_Arc_CoinDrawerTilt Usage_i8(0x38) 2943 + #define Usage_Arc_CoinDoorTest Usage_i8(0x39) 2944 + #define Usage_Arc_CoinDoorLockout Usage_i8(0x40) 2945 + #define Usage_Arc_WatchdogTimeout Usage_i8(0x41) 2946 + #define Usage_Arc_WatchdogAction Usage_i8(0x42) 2947 + #define Usage_Arc_WatchdogReboot Usage_i8(0x43) 2948 + #define Usage_Arc_WatchdogRestart Usage_i8(0x44) 2949 + #define Usage_Arc_AlarmInput Usage_i8(0x45) 2950 + #define Usage_Arc_CoinDoorCounter Usage_i8(0x46) 2951 + #define Usage_Arc_IODirectionMapping Usage_i8(0x47) 2952 + #define Usage_Arc_SetIODirectionMapping Usage_i8(0x48) 2953 + #define Usage_Arc_ExtendedOpticalInputState Usage_i8(0x49) 2954 + #define Usage_Arc_PinPadInputState Usage_i8(0x4a) 2955 + #define Usage_Arc_PinPadStatus Usage_i8(0x4b) 2956 + #define Usage_Arc_PinPadOutput Usage_i8(0x4c) 2957 + #define Usage_Arc_PinPadCommand Usage_i8(0x4d) 2958 + #define Usage_FIDOA_U2FAuthenticatorDevice Usage_i8(0x1) 2959 + #define Usage_FIDOA_InputReportData Usage_i8(0x20) 2960 + #define Usage_FIDOA_OutputReportData Usage_i8(0x21)
+1
drivers/hid/hid-a4tech.c
··· 163 163 }; 164 164 module_hid_driver(a4_driver); 165 165 166 + MODULE_DESCRIPTION("HID driver for some a4tech \"special\" devices"); 166 167 MODULE_LICENSE("GPL");
+88
drivers/hid/hid-apple.c
··· 8 8 * Copyright (c) 2006-2007 Jiri Kosina 9 9 * Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com> 10 10 * Copyright (c) 2019 Paul Pawlowski <paul@mrarm.io> 11 + * Copyright (c) 2023 Orlando Chamberlain <orlandoch.dev@gmail.com> 12 + * Copyright (c) 2024 Aditya Garg <gargaditya08@live.com> 11 13 */ 12 14 13 15 /* ··· 25 23 #include <linux/timer.h> 26 24 #include <linux/string.h> 27 25 #include <linux/leds.h> 26 + #include <dt-bindings/leds/common.h> 28 27 29 28 #include "hid-ids.h" 30 29 ··· 41 38 #define APPLE_RDESC_BATTERY BIT(9) 42 39 #define APPLE_BACKLIGHT_CTL BIT(10) 43 40 #define APPLE_IS_NON_APPLE BIT(11) 41 + #define APPLE_MAGIC_BACKLIGHT BIT(12) 44 42 45 43 #define APPLE_FLAG_FKEY 0x01 46 44 47 45 #define HID_COUNTRY_INTERNATIONAL_ISO 13 48 46 #define APPLE_BATTERY_TIMEOUT_MS 60000 47 + 48 + #define HID_USAGE_MAGIC_BL 0xff00000f 49 + #define APPLE_MAGIC_REPORT_ID_POWER 3 50 + #define APPLE_MAGIC_REPORT_ID_BRIGHTNESS 1 49 51 50 52 static unsigned int fnmode = 3; 51 53 module_param(fnmode, uint, 0644); ··· 87 79 struct apple_sc_backlight { 88 80 struct led_classdev cdev; 89 81 struct hid_device *hdev; 82 + }; 83 + 84 + struct apple_magic_backlight { 85 + struct led_classdev cdev; 86 + struct hid_report *brightness; 87 + struct hid_report *power; 90 88 }; 91 89 92 90 struct apple_sc { ··· 836 822 return ret; 837 823 } 838 824 825 + static void apple_magic_backlight_report_set(struct hid_report *rep, s32 value, u8 rate) 826 + { 827 + rep->field[0]->value[0] = value; 828 + rep->field[1]->value[0] = 0x5e; /* Mimic Windows */ 829 + rep->field[1]->value[0] |= rate << 8; 830 + 831 + hid_hw_request(rep->device, rep, HID_REQ_SET_REPORT); 832 + } 833 + 834 + static void apple_magic_backlight_set(struct apple_magic_backlight *backlight, 835 + int brightness, char rate) 836 + { 837 + apple_magic_backlight_report_set(backlight->power, brightness ? 1 : 0, rate); 838 + if (brightness) 839 + apple_magic_backlight_report_set(backlight->brightness, brightness, rate); 840 + } 841 + 842 + static int apple_magic_backlight_led_set(struct led_classdev *led_cdev, 843 + enum led_brightness brightness) 844 + { 845 + struct apple_magic_backlight *backlight = container_of(led_cdev, 846 + struct apple_magic_backlight, cdev); 847 + 848 + apple_magic_backlight_set(backlight, brightness, 1); 849 + return 0; 850 + } 851 + 852 + static int apple_magic_backlight_init(struct hid_device *hdev) 853 + { 854 + struct apple_magic_backlight *backlight; 855 + struct hid_report_enum *report_enum; 856 + 857 + /* 858 + * Ensure this usb endpoint is for the keyboard backlight, not touchbar 859 + * backlight. 860 + */ 861 + if (hdev->collection[0].usage != HID_USAGE_MAGIC_BL) 862 + return -ENODEV; 863 + 864 + backlight = devm_kzalloc(&hdev->dev, sizeof(*backlight), GFP_KERNEL); 865 + if (!backlight) 866 + return -ENOMEM; 867 + 868 + report_enum = &hdev->report_enum[HID_FEATURE_REPORT]; 869 + backlight->brightness = report_enum->report_id_hash[APPLE_MAGIC_REPORT_ID_BRIGHTNESS]; 870 + backlight->power = report_enum->report_id_hash[APPLE_MAGIC_REPORT_ID_POWER]; 871 + 872 + if (!backlight->brightness || !backlight->power) 873 + return -ENODEV; 874 + 875 + backlight->cdev.name = ":white:" LED_FUNCTION_KBD_BACKLIGHT; 876 + backlight->cdev.max_brightness = backlight->brightness->field[0]->logical_maximum; 877 + backlight->cdev.brightness_set_blocking = apple_magic_backlight_led_set; 878 + 879 + apple_magic_backlight_set(backlight, 0, 0); 880 + 881 + return devm_led_classdev_register(&hdev->dev, &backlight->cdev); 882 + 883 + } 884 + 839 885 static int apple_probe(struct hid_device *hdev, 840 886 const struct hid_device_id *id) 841 887 { ··· 934 860 if (quirks & APPLE_BACKLIGHT_CTL) 935 861 apple_backlight_init(hdev); 936 862 863 + if (quirks & APPLE_MAGIC_BACKLIGHT) { 864 + ret = apple_magic_backlight_init(hdev); 865 + if (ret) 866 + goto out_err; 867 + } 868 + 937 869 return 0; 870 + 871 + out_err: 872 + del_timer_sync(&asc->battery_timer); 873 + hid_hw_stop(hdev); 874 + return ret; 938 875 } 939 876 940 877 static void apple_remove(struct hid_device *hdev) ··· 1158 1073 .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY }, 1159 1074 { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021), 1160 1075 .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, 1076 + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT), 1077 + .driver_data = APPLE_MAGIC_BACKLIGHT }, 1161 1078 1162 1079 { } 1163 1080 }; ··· 1178 1091 }; 1179 1092 module_hid_driver(apple_driver); 1180 1093 1094 + MODULE_DESCRIPTION("Apple USB HID quirks support for Linux"); 1181 1095 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-aureal.c
··· 41 41 }; 42 42 module_hid_driver(aureal_driver); 43 43 44 + MODULE_DESCRIPTION("HID driver for Aureal Cy se W-01RN USB_V3.1 devices"); 44 45 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-belkin.c
··· 85 85 }; 86 86 module_hid_driver(belkin_driver); 87 87 88 + MODULE_DESCRIPTION("HID driver for some belkin \"special\" devices"); 88 89 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-betopff.c
··· 162 162 }; 163 163 module_hid_driver(betop_driver); 164 164 165 + MODULE_DESCRIPTION("Force feedback support for Betop based devices"); 165 166 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-bigbenff.c
··· 490 490 }; 491 491 module_hid_driver(bigben_driver); 492 492 493 + MODULE_DESCRIPTION("LED & force feedback support for BigBen Interactive"); 493 494 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-cherry.c
··· 68 68 }; 69 69 module_hid_driver(ch_driver); 70 70 71 + MODULE_DESCRIPTION("HID driver for some cherry \"special\" devices"); 71 72 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-chicony.c
··· 152 152 }; 153 153 module_hid_driver(ch_driver); 154 154 155 + MODULE_DESCRIPTION("HID driver for some chicony \"special\" devices"); 155 156 MODULE_LICENSE("GPL");
+91 -42
drivers/hid/hid-core.c
··· 95 95 return NULL; 96 96 } 97 97 98 - field = kzalloc((sizeof(struct hid_field) + 99 - usages * sizeof(struct hid_usage) + 100 - 3 * usages * sizeof(unsigned int)), GFP_KERNEL); 98 + field = kvzalloc((sizeof(struct hid_field) + 99 + usages * sizeof(struct hid_usage) + 100 + 3 * usages * sizeof(unsigned int)), GFP_KERNEL); 101 101 if (!field) 102 102 return NULL; 103 103 ··· 661 661 kfree(report->field_entries); 662 662 663 663 for (n = 0; n < report->maxfield; n++) 664 - kfree(report->field[n]); 664 + kvfree(report->field[n]); 665 665 kfree(report); 666 666 } 667 667 ··· 2025 2025 } 2026 2026 EXPORT_SYMBOL_GPL(hid_report_raw_event); 2027 2027 2028 - /** 2029 - * hid_input_report - report data from lower layer (usb, bt...) 2030 - * 2031 - * @hid: hid device 2032 - * @type: HID report type (HID_*_REPORT) 2033 - * @data: report contents 2034 - * @size: size of data parameter 2035 - * @interrupt: distinguish between interrupt and control transfers 2036 - * 2037 - * This is data entry for lower layers. 2038 - */ 2039 - int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size, 2040 - int interrupt) 2028 + 2029 + static int __hid_input_report(struct hid_device *hid, enum hid_report_type type, 2030 + u8 *data, u32 size, int interrupt, u64 source, bool from_bpf, 2031 + bool lock_already_taken) 2041 2032 { 2042 2033 struct hid_report_enum *report_enum; 2043 2034 struct hid_driver *hdrv; ··· 2038 2047 if (!hid) 2039 2048 return -ENODEV; 2040 2049 2041 - if (down_trylock(&hid->driver_input_lock)) 2050 + ret = down_trylock(&hid->driver_input_lock); 2051 + if (lock_already_taken && !ret) { 2052 + up(&hid->driver_input_lock); 2053 + return -EINVAL; 2054 + } else if (!lock_already_taken && ret) { 2042 2055 return -EBUSY; 2056 + } 2043 2057 2044 2058 if (!hid->driver) { 2045 2059 ret = -ENODEV; ··· 2053 2057 report_enum = hid->report_enum + type; 2054 2058 hdrv = hid->driver; 2055 2059 2056 - data = dispatch_hid_bpf_device_event(hid, type, data, &size, interrupt); 2060 + data = dispatch_hid_bpf_device_event(hid, type, data, &size, interrupt, source, from_bpf); 2057 2061 if (IS_ERR(data)) { 2058 2062 ret = PTR_ERR(data); 2059 2063 goto unlock; ··· 2085 2089 ret = hid_report_raw_event(hid, type, data, size, interrupt); 2086 2090 2087 2091 unlock: 2088 - up(&hid->driver_input_lock); 2092 + if (!lock_already_taken) 2093 + up(&hid->driver_input_lock); 2089 2094 return ret; 2095 + } 2096 + 2097 + /** 2098 + * hid_input_report - report data from lower layer (usb, bt...) 2099 + * 2100 + * @hid: hid device 2101 + * @type: HID report type (HID_*_REPORT) 2102 + * @data: report contents 2103 + * @size: size of data parameter 2104 + * @interrupt: distinguish between interrupt and control transfers 2105 + * 2106 + * This is data entry for lower layers. 2107 + */ 2108 + int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size, 2109 + int interrupt) 2110 + { 2111 + return __hid_input_report(hid, type, data, size, interrupt, 0, 2112 + false, /* from_bpf */ 2113 + false /* lock_already_taken */); 2090 2114 } 2091 2115 EXPORT_SYMBOL_GPL(hid_input_report); 2092 2116 ··· 2408 2392 } 2409 2393 EXPORT_SYMBOL_GPL(hid_hw_request); 2410 2394 2395 + int __hid_hw_raw_request(struct hid_device *hdev, 2396 + unsigned char reportnum, __u8 *buf, 2397 + size_t len, enum hid_report_type rtype, 2398 + enum hid_class_request reqtype, 2399 + u64 source, bool from_bpf) 2400 + { 2401 + unsigned int max_buffer_size = HID_MAX_BUFFER_SIZE; 2402 + int ret; 2403 + 2404 + if (hdev->ll_driver->max_buffer_size) 2405 + max_buffer_size = hdev->ll_driver->max_buffer_size; 2406 + 2407 + if (len < 1 || len > max_buffer_size || !buf) 2408 + return -EINVAL; 2409 + 2410 + ret = dispatch_hid_bpf_raw_requests(hdev, reportnum, buf, len, rtype, 2411 + reqtype, source, from_bpf); 2412 + if (ret) 2413 + return ret; 2414 + 2415 + return hdev->ll_driver->raw_request(hdev, reportnum, buf, len, 2416 + rtype, reqtype); 2417 + } 2418 + 2411 2419 /** 2412 2420 * hid_hw_raw_request - send report request to device 2413 2421 * ··· 2450 2410 unsigned char reportnum, __u8 *buf, 2451 2411 size_t len, enum hid_report_type rtype, enum hid_class_request reqtype) 2452 2412 { 2413 + return __hid_hw_raw_request(hdev, reportnum, buf, len, rtype, reqtype, 0, false); 2414 + } 2415 + EXPORT_SYMBOL_GPL(hid_hw_raw_request); 2416 + 2417 + int __hid_hw_output_report(struct hid_device *hdev, __u8 *buf, size_t len, u64 source, 2418 + bool from_bpf) 2419 + { 2453 2420 unsigned int max_buffer_size = HID_MAX_BUFFER_SIZE; 2421 + int ret; 2454 2422 2455 2423 if (hdev->ll_driver->max_buffer_size) 2456 2424 max_buffer_size = hdev->ll_driver->max_buffer_size; ··· 2466 2418 if (len < 1 || len > max_buffer_size || !buf) 2467 2419 return -EINVAL; 2468 2420 2469 - return hdev->ll_driver->raw_request(hdev, reportnum, buf, len, 2470 - rtype, reqtype); 2421 + ret = dispatch_hid_bpf_output_report(hdev, buf, len, source, from_bpf); 2422 + if (ret) 2423 + return ret; 2424 + 2425 + if (hdev->ll_driver->output_report) 2426 + return hdev->ll_driver->output_report(hdev, buf, len); 2427 + 2428 + return -ENOSYS; 2471 2429 } 2472 - EXPORT_SYMBOL_GPL(hid_hw_raw_request); 2473 2430 2474 2431 /** 2475 2432 * hid_hw_output_report - send output report to device ··· 2487 2434 */ 2488 2435 int hid_hw_output_report(struct hid_device *hdev, __u8 *buf, size_t len) 2489 2436 { 2490 - unsigned int max_buffer_size = HID_MAX_BUFFER_SIZE; 2491 - 2492 - if (hdev->ll_driver->max_buffer_size) 2493 - max_buffer_size = hdev->ll_driver->max_buffer_size; 2494 - 2495 - if (len < 1 || len > max_buffer_size || !buf) 2496 - return -EINVAL; 2497 - 2498 - if (hdev->ll_driver->output_report) 2499 - return hdev->ll_driver->output_report(hdev, buf, len); 2500 - 2501 - return -ENOSYS; 2437 + return __hid_hw_output_report(hdev, buf, len, 0, false); 2502 2438 } 2503 2439 EXPORT_SYMBOL_GPL(hid_hw_output_report); 2504 2440 ··· 2896 2854 mutex_init(&hdev->ll_open_lock); 2897 2855 kref_init(&hdev->ref); 2898 2856 2899 - hid_bpf_device_init(hdev); 2857 + ret = hid_bpf_device_init(hdev); 2858 + if (ret) 2859 + goto out_err; 2900 2860 2901 2861 return hdev; 2862 + 2863 + out_err: 2864 + hid_destroy_device(hdev); 2865 + return ERR_PTR(ret); 2902 2866 } 2903 2867 EXPORT_SYMBOL_GPL(hid_allocate_device); 2904 2868 ··· 3018 2970 EXPORT_SYMBOL_GPL(hid_check_keys_pressed); 3019 2971 3020 2972 #ifdef CONFIG_HID_BPF 3021 - static struct hid_bpf_ops hid_ops = { 2973 + static struct hid_ops __hid_ops = { 3022 2974 .hid_get_report = hid_get_report, 3023 - .hid_hw_raw_request = hid_hw_raw_request, 3024 - .hid_hw_output_report = hid_hw_output_report, 3025 - .hid_input_report = hid_input_report, 2975 + .hid_hw_raw_request = __hid_hw_raw_request, 2976 + .hid_hw_output_report = __hid_hw_output_report, 2977 + .hid_input_report = __hid_input_report, 3026 2978 .owner = THIS_MODULE, 3027 2979 .bus_type = &hid_bus_type, 3028 2980 }; ··· 3039 2991 } 3040 2992 3041 2993 #ifdef CONFIG_HID_BPF 3042 - hid_bpf_ops = &hid_ops; 2994 + hid_ops = &__hid_ops; 3043 2995 #endif 3044 2996 3045 2997 ret = hidraw_init(); ··· 3058 3010 static void __exit hid_exit(void) 3059 3011 { 3060 3012 #ifdef CONFIG_HID_BPF 3061 - hid_bpf_ops = NULL; 3013 + hid_ops = NULL; 3062 3014 #endif 3063 3015 hid_debug_exit(); 3064 3016 hidraw_exit(); ··· 3072 3024 MODULE_AUTHOR("Andreas Gal"); 3073 3025 MODULE_AUTHOR("Vojtech Pavlik"); 3074 3026 MODULE_AUTHOR("Jiri Kosina"); 3027 + MODULE_DESCRIPTION("HID support for Linux"); 3075 3028 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-cypress.c
··· 176 176 }; 177 177 module_hid_driver(cp_driver); 178 178 179 + MODULE_DESCRIPTION("HID driver for some cypress \"special\" devices"); 179 180 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-dr.c
··· 316 316 }; 317 317 module_hid_driver(dr_driver); 318 318 319 + MODULE_DESCRIPTION("Force feedback support for DragonRise Inc. game controllers"); 319 320 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-elecom.c
··· 136 136 }; 137 137 module_hid_driver(elecom_driver); 138 138 139 + MODULE_DESCRIPTION("HID driver for ELECOM devices"); 139 140 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-elo.c
··· 313 313 module_exit(elo_driver_exit); 314 314 315 315 MODULE_AUTHOR("Jiri Slaby <jslaby@suse.cz>"); 316 + MODULE_DESCRIPTION("HID driver for ELO usb touchscreen 4000/4500"); 316 317 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-emsff.c
··· 144 144 }; 145 145 module_hid_driver(ems_driver); 146 146 147 + MODULE_DESCRIPTION("Force feedback support for EMS Trio Linker Plus II"); 147 148 MODULE_LICENSE("GPL"); 148 149
+1
drivers/hid/hid-evision.c
··· 50 50 }; 51 51 module_hid_driver(evision_driver); 52 52 53 + MODULE_DESCRIPTION("HID driver for EVision devices"); 53 54 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-ezkey.c
··· 75 75 }; 76 76 module_hid_driver(ez_driver); 77 77 78 + MODULE_DESCRIPTION("HID driver for some ezkey \"special\" devices"); 78 79 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-gaff.c
··· 169 169 }; 170 170 module_hid_driver(ga_driver); 171 171 172 + MODULE_DESCRIPTION("Force feedback support for GreenAsia (Product ID 0x12) based devices"); 172 173 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-google-hammer.c
··· 641 641 } 642 642 module_exit(hammer_exit); 643 643 644 + MODULE_DESCRIPTION("HID driver for Google Hammer device."); 644 645 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-google-stadiaff.c
··· 155 155 }; 156 156 module_hid_driver(stadia_driver); 157 157 158 + MODULE_DESCRIPTION("Google Stadia controller rumble support."); 158 159 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-gyration.c
··· 87 87 }; 88 88 module_hid_driver(gyration_driver); 89 89 90 + MODULE_DESCRIPTION("HID driver for some gyration \"special\" devices"); 90 91 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-holtek-kbd.c
··· 180 180 }; 181 181 module_hid_driver(holtek_kbd_driver); 182 182 183 + MODULE_DESCRIPTION("HID driver for Holtek keyboard"); 183 184 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-holtek-mouse.c
··· 110 110 }; 111 111 112 112 module_hid_driver(holtek_mouse_driver); 113 + MODULE_DESCRIPTION("HID driver for Holtek gaming mice"); 113 114 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-ite.c
··· 141 141 module_hid_driver(ite_driver); 142 142 143 143 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 144 + MODULE_DESCRIPTION("HID driver for some ITE \"special\" devices"); 144 145 MODULE_LICENSE("GPL");
+2 -1
drivers/hid/hid-kensington.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-or-later 2 2 /* 3 - * HID driver for Kensigton Slimblade Trackball 3 + * HID driver for Kensington Slimblade Trackball 4 4 * 5 5 * Copyright (c) 2009 Jiri Kosina 6 6 */ ··· 46 46 }; 47 47 module_hid_driver(ks_driver); 48 48 49 + MODULE_DESCRIPTION("HID driver for Kensington Slimblade Trackball"); 49 50 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-keytouch.c
··· 48 48 }; 49 49 module_hid_driver(keytouch_driver); 50 50 51 + MODULE_DESCRIPTION("HID driver for Keytouch devices not fully compliant with HID standard"); 51 52 MODULE_LICENSE("GPL"); 52 53 MODULE_AUTHOR("Jiri Kosina");
+1
drivers/hid/hid-kye.c
··· 671 671 }; 672 672 module_hid_driver(kye_driver); 673 673 674 + MODULE_DESCRIPTION("HID driver for Kye/Genius devices not fully compliant with HID standard"); 674 675 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-lcpower.c
··· 53 53 }; 54 54 module_hid_driver(ts_driver); 55 55 56 + MODULE_DESCRIPTION("HID driver for LC Power Model RC1000MCE"); 56 57 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-lenovo.c
··· 1442 1442 }; 1443 1443 module_hid_driver(lenovo_driver); 1444 1444 1445 + MODULE_DESCRIPTION("HID driver for IBM/Lenovo"); 1445 1446 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-letsketch.c
··· 319 319 module_hid_driver(letsketch_driver); 320 320 321 321 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 322 + MODULE_DESCRIPTION("Driver for the LetSketch / VSON WP9620N drawing tablet"); 322 323 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-lg-g15.c
··· 954 954 module_hid_driver(lg_g15_driver); 955 955 956 956 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 957 + MODULE_DESCRIPTION("HID driver for gaming keys on Logitech gaming keyboards"); 957 958 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-lg.c
··· 942 942 MODULE_PARM_DESC(lg4ff_no_autoswitch, "Do not switch multimode wheels to their native mode automatically"); 943 943 #endif 944 944 945 + MODULE_DESCRIPTION("HID driver for some logitech \"special\" devices"); 945 946 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-logitech-dj.c
··· 2047 2047 2048 2048 module_hid_driver(logi_djreceiver_driver); 2049 2049 2050 + MODULE_DESCRIPTION("HID driver for Logitech receivers"); 2050 2051 MODULE_LICENSE("GPL"); 2051 2052 MODULE_AUTHOR("Logitech"); 2052 2053 MODULE_AUTHOR("Nestor Lopez Casado");
+1
drivers/hid/hid-magicmouse.c
··· 968 968 }; 969 969 module_hid_driver(magicmouse_driver); 970 970 971 + MODULE_DESCRIPTION("Apple \"Magic\" Wireless Mouse driver"); 971 972 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-maltron.c
··· 162 162 }; 163 163 module_hid_driver(maltron_driver); 164 164 165 + MODULE_DESCRIPTION("HID driver for Maltron L90"); 165 166 MODULE_LICENSE("GPL");
+1 -1
drivers/hid/hid-mcp2221.c
··· 1048 1048 break; 1049 1049 default: 1050 1050 continue; 1051 - }; 1051 + } 1052 1052 1053 1053 chan->type = IIO_VOLTAGE; 1054 1054 chan->indexed = 1;
+1
drivers/hid/hid-megaworld.c
··· 122 122 }; 123 123 module_hid_driver(mwctrl_driver); 124 124 125 + MODULE_DESCRIPTION("Vibration support for Mega World controllers"); 125 126 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-mf.c
··· 166 166 }; 167 167 module_hid_driver(mf_driver); 168 168 169 + MODULE_DESCRIPTION("Force feedback support for Mayflash game controller adapters."); 169 170 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-microsoft.c
··· 475 475 }; 476 476 module_hid_driver(ms_driver); 477 477 478 + MODULE_DESCRIPTION("HID driver for some microsoft \"special\" devices"); 478 479 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-monterey.c
··· 62 62 }; 63 63 module_hid_driver(mr_driver); 64 64 65 + MODULE_DESCRIPTION("HID driver for some monterey \"special\" devices"); 65 66 MODULE_LICENSE("GPL");
-21
drivers/hid/hid-nintendo.c
··· 658 658 (ctlr->ctlr_type == JOYCON_CTLR_TYPE_JCR || \ 659 659 ctlr->ctlr_type == JOYCON_CTLR_TYPE_PRO) 660 660 661 - 662 661 /* 663 662 * Controller device helpers 664 663 * ··· 668 669 * These helpers are most useful early during the HID probe or in conjunction 669 670 * with the capability helpers below. 670 671 */ 671 - static inline bool joycon_device_is_procon(struct joycon_ctlr *ctlr) 672 - { 673 - return ctlr->hdev->product == USB_DEVICE_ID_NINTENDO_PROCON; 674 - } 675 - 676 672 static inline bool joycon_device_is_chrggrip(struct joycon_ctlr *ctlr) 677 673 { 678 674 return ctlr->hdev->product == USB_DEVICE_ID_NINTENDO_CHRGGRIP; 679 - } 680 - 681 - static inline bool joycon_device_is_snescon(struct joycon_ctlr *ctlr) 682 - { 683 - return ctlr->hdev->product == USB_DEVICE_ID_NINTENDO_SNESCON; 684 - } 685 - 686 - static inline bool joycon_device_is_gencon(struct joycon_ctlr *ctlr) 687 - { 688 - return ctlr->hdev->product == USB_DEVICE_ID_NINTENDO_GENCON; 689 - } 690 - 691 - static inline bool joycon_device_is_n64con(struct joycon_ctlr *ctlr) 692 - { 693 - return ctlr->hdev->product == USB_DEVICE_ID_NINTENDO_N64CON; 694 675 } 695 676 696 677 /*
+1
drivers/hid/hid-ntrig.c
··· 1029 1029 }; 1030 1030 module_hid_driver(ntrig_driver); 1031 1031 1032 + MODULE_DESCRIPTION("HID driver for N-Trig touchscreens"); 1032 1033 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-ortek.c
··· 51 51 }; 52 52 module_hid_driver(ortek_driver); 53 53 54 + MODULE_DESCRIPTION("HID driver for Ortek PKB-1700/WKB-2000/Skycable wireless keyboard and mouse trackpad"); 54 55 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-petalynx.c
··· 102 102 }; 103 103 module_hid_driver(pl_driver); 104 104 105 + MODULE_DESCRIPTION("HID driver for some petalynx \"special\" devices"); 105 106 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-pl.c
··· 219 219 }; 220 220 module_hid_driver(pl_driver); 221 221 222 + MODULE_DESCRIPTION("Force feedback support for PantherLord/GreenAsia based devices"); 222 223 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-primax.c
··· 70 70 module_hid_driver(px_driver); 71 71 72 72 MODULE_AUTHOR("Terry Lambert <tlambert@google.com>"); 73 + MODULE_DESCRIPTION("HID driver for primax and similar keyboards with in-band modifiers"); 73 74 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-prodikeys.c
··· 862 862 }; 863 863 module_hid_driver(pk_driver); 864 864 865 + MODULE_DESCRIPTION("HID driver for the Prodikeys PC-MIDI Keyboard"); 865 866 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-razer.c
··· 122 122 module_hid_driver(razer_driver); 123 123 124 124 MODULE_AUTHOR("Jelle van der Waa <jvanderwaa@redhat.com>"); 125 + MODULE_DESCRIPTION("HID driver for gaming keys on Razer Blackwidow gaming keyboards"); 125 126 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-redragon.c
··· 59 59 60 60 module_hid_driver(redragon_driver); 61 61 62 + MODULE_DESCRIPTION("HID driver for Redragon keyboards"); 62 63 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-retrode.c
··· 94 94 95 95 module_hid_driver(retrode_driver); 96 96 97 + MODULE_DESCRIPTION("HID driver for Retrode 2 controller adapter and plug-in extensions"); 97 98 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-saitek.c
··· 204 204 }; 205 205 module_hid_driver(saitek_driver); 206 206 207 + MODULE_DESCRIPTION("HID driver for Saitek devices."); 207 208 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-samsung.c
··· 561 561 }; 562 562 module_hid_driver(samsung_driver); 563 563 564 + MODULE_DESCRIPTION("HID driver for some samsung \"special\" devices"); 564 565 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-semitek.c
··· 37 37 }; 38 38 module_hid_driver(semitek_driver); 39 39 40 + MODULE_DESCRIPTION("HID driver for Semitek keyboards"); 40 41 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-sjoy.c
··· 168 168 }; 169 169 module_hid_driver(sjoy_driver); 170 170 171 + MODULE_DESCRIPTION("Force feedback support for SmartJoy PLUS PS2->USB adapter"); 171 172 MODULE_LICENSE("GPL"); 172 173 MODULE_AUTHOR("Jussi Kivilinna"); 173 174
+1
drivers/hid/hid-sony.c
··· 2308 2308 module_init(sony_init); 2309 2309 module_exit(sony_exit); 2310 2310 2311 + MODULE_DESCRIPTION("HID driver for Sony / PS2 / PS3 / PS4 BD devices"); 2311 2312 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-speedlink.c
··· 75 75 }; 76 76 module_hid_driver(speedlink_driver); 77 77 78 + MODULE_DESCRIPTION("HID driver for Speedlink Vicious and Divine Cezanne (USB mouse)"); 78 79 MODULE_LICENSE("GPL");
+3 -2
drivers/hid/hid-steam.c
··· 45 45 #include <linux/power_supply.h> 46 46 #include "hid-ids.h" 47 47 48 + MODULE_DESCRIPTION("HID driver for Valve Steam Controller"); 48 49 MODULE_LICENSE("GPL"); 49 50 MODULE_AUTHOR("Rodrigo Rivas Costa <rodrigorivascosta@gmail.com>"); 50 51 ··· 1268 1267 steam->client_hdev = steam_create_client_hid(hdev); 1269 1268 if (IS_ERR(steam->client_hdev)) { 1270 1269 ret = PTR_ERR(steam->client_hdev); 1271 - goto err_stream_unregister; 1270 + goto err_steam_unregister; 1272 1271 } 1273 1272 steam->client_hdev->driver_data = steam; 1274 1273 ··· 1280 1279 1281 1280 err_destroy: 1282 1281 hid_destroy_device(steam->client_hdev); 1283 - err_stream_unregister: 1282 + err_steam_unregister: 1284 1283 if (steam->connected) 1285 1284 steam_unregister(steam); 1286 1285 err_hw_close:
+1
drivers/hid/hid-steelseries.c
··· 662 662 }; 663 663 664 664 module_hid_driver(steelseries_driver); 665 + MODULE_DESCRIPTION("HID driver for Steelseries devices"); 665 666 MODULE_LICENSE("GPL"); 666 667 MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>"); 667 668 MODULE_AUTHOR("Simon Wood <simon@mungewell.org>");
+1
drivers/hid/hid-sunplus.c
··· 62 62 }; 63 63 module_hid_driver(sp_driver); 64 64 65 + MODULE_DESCRIPTION("HID driver for some sunplus \"special\" devices"); 65 66 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-tivo.c
··· 73 73 }; 74 74 module_hid_driver(tivo_driver); 75 75 76 + MODULE_DESCRIPTION("HID driver for TiVo Slide Bluetooth remote"); 76 77 MODULE_LICENSE("GPL"); 77 78 MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
+1
drivers/hid/hid-tmff.c
··· 265 265 }; 266 266 module_hid_driver(tm_driver); 267 267 268 + MODULE_DESCRIPTION("Force feedback support for various HID compliant devices by ThrustMaster"); 268 269 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-topseed.c
··· 78 78 }; 79 79 module_hid_driver(ts_driver); 80 80 81 + MODULE_DESCRIPTION("HID driver for TopSeed Cyberlink remote"); 81 82 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-twinhan.c
··· 131 131 }; 132 132 module_hid_driver(twinhan_driver); 133 133 134 + MODULE_DESCRIPTION("HID driver for TwinHan IR remote control"); 134 135 MODULE_LICENSE("GPL");
+2
drivers/hid/hid-uclogic-core.c
··· 567 567 568 568 MODULE_AUTHOR("Martin Rusko"); 569 569 MODULE_AUTHOR("Nikolai Kondrashov"); 570 + MODULE_DESCRIPTION("HID driver for UC-Logic devices not fully compliant with HID standard"); 570 571 MODULE_LICENSE("GPL"); 572 + MODULE_DESCRIPTION("HID driver for UC-Logic devices not fully compliant with HID standard"); 571 573 572 574 #ifdef CONFIG_HID_KUNIT_TEST 573 575 #include "hid-uclogic-core-test.c"
+2
drivers/hid/hid-uclogic-rdesc-test.c
··· 9 9 #include <kunit/test.h> 10 10 #include "./hid-uclogic-rdesc.h" 11 11 12 + MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING); 13 + 12 14 struct uclogic_template_case { 13 15 const char *name; 14 16 const __u8 *template;
+7 -4
drivers/hid/hid-uclogic-rdesc.c
··· 17 17 #include "hid-uclogic-rdesc.h" 18 18 #include <linux/slab.h> 19 19 #include <asm/unaligned.h> 20 + #include <kunit/visibility.h> 20 21 21 22 /* Fixed WP4030U report descriptor */ 22 23 __u8 uclogic_rdesc_wp4030u_fixed_arr[] = { ··· 690 689 0xA0, /* Collection (Physical), */ \ 691 690 0x05, 0x09, /* Usage Page (Button), */ \ 692 691 0x19, 0x01, /* Usage Minimum (01h), */ \ 693 - 0x29, 0x03, /* Usage Maximum (03h), */ \ 694 - 0x95, 0x03, /* Report Count (3), */ \ 692 + 0x29, 0x0A, /* Usage Maximum (0Ah), */ \ 693 + 0x95, 0x0A, /* Report Count (10), */ \ 695 694 0x81, 0x02, /* Input (Variable), */ \ 696 - 0x95, ((_size) * 8 - 45), \ 695 + 0x95, ((_size) * 8 - 52), \ 697 696 /* Report Count (padding), */ \ 698 697 0x81, 0x01, /* Input (Constant), */ \ 699 698 0xC0, /* End Collection, */ \ ··· 790 789 0x95, 0x01, /* Report Count (1), */ 791 790 0x81, 0x02, /* Input (Variable), */ 792 791 0x05, 0x01, /* Usage Page (Desktop), */ 793 - 0x09, 0x38, /* Usage (Wheel), */ 792 + 0x09, 0x33, /* Usage (Rx), */ 793 + 0x09, 0x34, /* Usage (Ry), */ 794 794 0x95, 0x01, /* Report Count (1), */ 795 795 0x15, 0x00, /* Logical Minimum (0), */ 796 796 0x25, 0x07, /* Logical Maximum (7), */ ··· 1244 1242 1245 1243 return rdesc_ptr; 1246 1244 } 1245 + EXPORT_SYMBOL_IF_KUNIT(uclogic_rdesc_template_apply);
+1
drivers/hid/hid-viewsonic.c
··· 102 102 }; 103 103 module_hid_driver(viewsonic_driver); 104 104 105 + MODULE_DESCRIPTION("HID driver for ViewSonic devices not fully compliant with HID standard"); 105 106 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-vivaldi-common.c
··· 138 138 }; 139 139 EXPORT_SYMBOL_GPL(vivaldi_attribute_groups); 140 140 141 + MODULE_DESCRIPTION("Helpers for ChromeOS HID Vivaldi keyboards"); 141 142 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-waltop.c
··· 742 742 }; 743 743 module_hid_driver(waltop_driver); 744 744 745 + MODULE_DESCRIPTION("HID driver for Waltop devices not fully compliant with HID standard"); 745 746 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-winwing.c
··· 223 223 }; 224 224 module_hid_driver(winwing_driver); 225 225 226 + MODULE_DESCRIPTION("HID driver for WinWing Orion 2 throttle"); 226 227 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-xinmo.c
··· 56 56 }; 57 57 58 58 module_hid_driver(xinmo_driver); 59 + MODULE_DESCRIPTION("HID driver for Xin-Mo devices"); 59 60 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-zpff.c
··· 138 138 }; 139 139 module_hid_driver(zp_driver); 140 140 141 + MODULE_DESCRIPTION("Force feedback support for Zeroplus based devices"); 141 142 MODULE_LICENSE("GPL");
+1
drivers/hid/hid-zydacron.c
··· 205 205 }; 206 206 module_hid_driver(zc_driver); 207 207 208 + MODULE_DESCRIPTION("HID driver for zydacron remote control"); 208 209 MODULE_LICENSE("GPL");
+5 -5
drivers/hid/hidraw.c
··· 140 140 141 141 if ((report_type == HID_OUTPUT_REPORT) && 142 142 !(dev->quirks & HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP)) { 143 - ret = hid_hw_output_report(dev, buf, count); 143 + ret = __hid_hw_output_report(dev, buf, count, (u64)(long)file, false); 144 144 /* 145 145 * compatibility with old implementation of USB-HID and I2C-HID: 146 146 * if the device does not support receiving output reports, ··· 150 150 goto out_free; 151 151 } 152 152 153 - ret = hid_hw_raw_request(dev, buf[0], buf, count, report_type, 154 - HID_REQ_SET_REPORT); 153 + ret = __hid_hw_raw_request(dev, buf[0], buf, count, report_type, 154 + HID_REQ_SET_REPORT, (u64)(long)file, false); 155 155 156 156 out_free: 157 157 kfree(buf); ··· 227 227 goto out_free; 228 228 } 229 229 230 - ret = hid_hw_raw_request(dev, report_number, buf, count, report_type, 231 - HID_REQ_GET_REPORT); 230 + ret = __hid_hw_raw_request(dev, report_number, buf, count, report_type, 231 + HID_REQ_GET_REPORT, (u64)(long)file, false); 232 232 233 233 if (ret < 0) 234 234 goto out_free;
+2
drivers/hid/intel-ish-hid/ishtp/bus.c
··· 844 844 845 845 /** 846 846 * ishtp_wait_resume() - Wait for IPC resume 847 + * @dev: ishtp device 847 848 * 848 849 * Wait for IPC resume 849 850 * ··· 932 931 module_init(ishtp_bus_register); 933 932 module_exit(ishtp_bus_unregister); 934 933 934 + MODULE_DESCRIPTION("ISHTP bus driver"); 935 935 MODULE_LICENSE("GPL");
+2
drivers/hid/usbhid/hid-core.c
··· 19 19 #include <linux/list.h> 20 20 #include <linux/mm.h> 21 21 #include <linux/mutex.h> 22 + #include <linux/property.h> 22 23 #include <linux/spinlock.h> 23 24 #include <asm/unaligned.h> 24 25 #include <asm/byteorder.h> ··· 1375 1374 hid->hiddev_report_event = hiddev_report_event; 1376 1375 #endif 1377 1376 hid->dev.parent = &intf->dev; 1377 + device_set_node(&hid->dev, dev_fwnode(&intf->dev)); 1378 1378 hid->bus = BUS_USB; 1379 1379 hid->vendor = le16_to_cpu(dev->descriptor.idVendor); 1380 1380 hid->product = le16_to_cpu(dev->descriptor.idProduct);
+7
include/linux/hid.h
··· 1125 1125 void hid_hw_close(struct hid_device *hdev); 1126 1126 void hid_hw_request(struct hid_device *hdev, 1127 1127 struct hid_report *report, enum hid_class_request reqtype); 1128 + int __hid_hw_raw_request(struct hid_device *hdev, 1129 + unsigned char reportnum, __u8 *buf, 1130 + size_t len, enum hid_report_type rtype, 1131 + enum hid_class_request reqtype, 1132 + __u64 source, bool from_bpf); 1133 + int __hid_hw_output_report(struct hid_device *hdev, __u8 *buf, size_t len, __u64 source, 1134 + bool from_bpf); 1128 1135 int hid_hw_raw_request(struct hid_device *hdev, 1129 1136 unsigned char reportnum, __u8 *buf, 1130 1137 size_t len, enum hid_report_type rtype,
+139 -63
include/linux/hid_bpf.h
··· 4 4 #define __HID_BPF_H 5 5 6 6 #include <linux/bpf.h> 7 - #include <linux/spinlock.h> 7 + #include <linux/mutex.h> 8 + #include <linux/srcu.h> 8 9 #include <uapi/linux/hid.h> 9 10 10 11 struct hid_device; ··· 21 20 * struct hid_bpf_ctx - User accessible data for all HID programs 22 21 * 23 22 * ``data`` is not directly accessible from the context. We need to issue 24 - * a call to ``hid_bpf_get_data()`` in order to get a pointer to that field. 23 + * a call to hid_bpf_get_data() in order to get a pointer to that field. 25 24 * 26 - * All of these fields are currently read-only. 27 - * 28 - * @index: program index in the jump table. No special meaning (a smaller index 29 - * doesn't mean the program will be executed before another program with 30 - * a bigger index). 31 - * @hid: the ``struct hid_device`` representing the device itself 32 - * @report_type: used for ``hid_bpf_device_event()`` 25 + * @hid: the &struct hid_device representing the device itself 33 26 * @allocated_size: Allocated size of data. 34 27 * 35 28 * This is how much memory is available and can be requested ··· 40 45 * ``size`` must always be less or equal than ``allocated_size`` (it is enforced 41 46 * once all BPF programs have been run). 42 47 * @retval: Return value of the previous program. 48 + * 49 + * ``hid`` and ``allocated_size`` are read-only, ``size`` and ``retval`` are read-write. 43 50 */ 44 51 struct hid_bpf_ctx { 45 - __u32 index; 46 - const struct hid_device *hid; 52 + struct hid_device *hid; 47 53 __u32 allocated_size; 48 - enum hid_report_type report_type; 49 54 union { 50 55 __s32 retval; 51 56 __s32 size; 52 57 }; 53 58 }; 54 59 55 - /** 56 - * enum hid_bpf_attach_flags - flags used when attaching a HIF-BPF program 57 - * 58 - * @HID_BPF_FLAG_NONE: no specific flag is used, the kernel choses where to 59 - * insert the program 60 - * @HID_BPF_FLAG_INSERT_HEAD: insert the given program before any other program 61 - * currently attached to the device. This doesn't 62 - * guarantee that this program will always be first 63 - * @HID_BPF_FLAG_MAX: sentinel value, not to be used by the callers 64 - */ 65 - enum hid_bpf_attach_flags { 66 - HID_BPF_FLAG_NONE = 0, 67 - HID_BPF_FLAG_INSERT_HEAD = _BITUL(0), 68 - HID_BPF_FLAG_MAX, 69 - }; 70 - 71 - /* Following functions are tracepoints that BPF programs can attach to */ 72 - int hid_bpf_device_event(struct hid_bpf_ctx *ctx); 73 - int hid_bpf_rdesc_fixup(struct hid_bpf_ctx *ctx); 74 - 75 60 /* 76 61 * Below is HID internal 77 62 */ 78 63 79 - /* internal function to call eBPF programs, not to be used by anybody */ 80 - int __hid_bpf_tail_call(struct hid_bpf_ctx *ctx); 81 - 82 64 #define HID_BPF_MAX_PROGS_PER_DEV 64 83 65 #define HID_BPF_FLAG_MASK (((HID_BPF_FLAG_MAX - 1) << 1) - 1) 84 66 85 - /* types of HID programs to attach to */ 86 - enum hid_bpf_prog_type { 87 - HID_BPF_PROG_TYPE_UNDEF = -1, 88 - HID_BPF_PROG_TYPE_DEVICE_EVENT, /* an event is emitted from the device */ 89 - HID_BPF_PROG_TYPE_RDESC_FIXUP, 90 - HID_BPF_PROG_TYPE_MAX, 91 - }; 92 67 93 68 struct hid_report_enum; 94 69 95 - struct hid_bpf_ops { 70 + struct hid_ops { 96 71 struct hid_report *(*hid_get_report)(struct hid_report_enum *report_enum, const u8 *data); 97 72 int (*hid_hw_raw_request)(struct hid_device *hdev, 98 73 unsigned char reportnum, __u8 *buf, 99 74 size_t len, enum hid_report_type rtype, 100 - enum hid_class_request reqtype); 101 - int (*hid_hw_output_report)(struct hid_device *hdev, __u8 *buf, size_t len); 75 + enum hid_class_request reqtype, 76 + u64 source, bool from_bpf); 77 + int (*hid_hw_output_report)(struct hid_device *hdev, __u8 *buf, size_t len, 78 + u64 source, bool from_bpf); 102 79 int (*hid_input_report)(struct hid_device *hid, enum hid_report_type type, 103 - u8 *data, u32 size, int interrupt); 80 + u8 *data, u32 size, int interrupt, u64 source, bool from_bpf, 81 + bool lock_already_taken); 104 82 struct module *owner; 105 83 const struct bus_type *bus_type; 106 84 }; 107 85 108 - extern struct hid_bpf_ops *hid_bpf_ops; 86 + extern struct hid_ops *hid_ops; 109 87 110 - struct hid_bpf_prog_list { 111 - u16 prog_idx[HID_BPF_MAX_PROGS_PER_DEV]; 112 - u8 prog_cnt; 88 + /** 89 + * struct hid_bpf_ops - A BPF struct_ops of callbacks allowing to attach HID-BPF 90 + * programs to a HID device 91 + * @hid_id: the HID uniq ID to attach to. This is writeable before ``load()``, and 92 + * cannot be changed after 93 + * @flags: flags used while attaching the struct_ops to the device. Currently only 94 + * available value is %0 or ``BPF_F_BEFORE``. 95 + * Writeable only before ``load()`` 96 + */ 97 + struct hid_bpf_ops { 98 + /* hid_id needs to stay first so we can easily change it 99 + * from userspace. 100 + */ 101 + int hid_id; 102 + u32 flags; 103 + 104 + /* private: do not show up in the docs */ 105 + struct list_head list; 106 + 107 + /* public: rest should show up in the docs */ 108 + 109 + /** 110 + * @hid_device_event: called whenever an event is coming in from the device 111 + * 112 + * It has the following arguments: 113 + * 114 + * ``ctx``: The HID-BPF context as &struct hid_bpf_ctx 115 + * 116 + * Return: %0 on success and keep processing; a positive 117 + * value to change the incoming size buffer; a negative 118 + * error code to interrupt the processing of this event 119 + * 120 + * Context: Interrupt context. 121 + */ 122 + int (*hid_device_event)(struct hid_bpf_ctx *ctx, enum hid_report_type report_type, 123 + u64 source); 124 + 125 + /** 126 + * @hid_rdesc_fixup: called when the probe function parses the report descriptor 127 + * of the HID device 128 + * 129 + * It has the following arguments: 130 + * 131 + * ``ctx``: The HID-BPF context as &struct hid_bpf_ctx 132 + * 133 + * Return: %0 on success and keep processing; a positive 134 + * value to change the incoming size buffer; a negative 135 + * error code to interrupt the processing of this device 136 + */ 137 + int (*hid_rdesc_fixup)(struct hid_bpf_ctx *ctx); 138 + 139 + /** 140 + * @hid_hw_request: called whenever a hid_hw_raw_request() call is emitted 141 + * on the HID device 142 + * 143 + * It has the following arguments: 144 + * 145 + * ``ctx``: The HID-BPF context as &struct hid_bpf_ctx 146 + * 147 + * ``reportnum``: the report number, as in hid_hw_raw_request() 148 + * 149 + * ``rtype``: the report type (``HID_INPUT_REPORT``, ``HID_FEATURE_REPORT``, 150 + * ``HID_OUTPUT_REPORT``) 151 + * 152 + * ``reqtype``: the request 153 + * 154 + * ``source``: a u64 referring to a uniq but identifiable source. If %0, the 155 + * kernel itself emitted that call. For hidraw, ``source`` is set 156 + * to the associated ``struct file *``. 157 + * 158 + * Return: %0 to keep processing the request by hid-core; any other value 159 + * stops hid-core from processing that event. A positive value should be 160 + * returned with the number of bytes returned in the incoming buffer; a 161 + * negative error code interrupts the processing of this call. 162 + */ 163 + int (*hid_hw_request)(struct hid_bpf_ctx *ctx, unsigned char reportnum, 164 + enum hid_report_type rtype, enum hid_class_request reqtype, 165 + u64 source); 166 + 167 + /** 168 + * @hid_hw_output_report: called whenever a hid_hw_output_report() call is emitted 169 + * on the HID device 170 + * 171 + * It has the following arguments: 172 + * 173 + * ``ctx``: The HID-BPF context as &struct hid_bpf_ctx 174 + * 175 + * ``source``: a u64 referring to a uniq but identifiable source. If %0, the 176 + * kernel itself emitted that call. For hidraw, ``source`` is set 177 + * to the associated ``struct file *``. 178 + * 179 + * Return: %0 to keep processing the request by hid-core; any other value 180 + * stops hid-core from processing that event. A positive value should be 181 + * returned with the number of bytes written to the device; a negative error 182 + * code interrupts the processing of this call. 183 + */ 184 + int (*hid_hw_output_report)(struct hid_bpf_ctx *ctx, u64 source); 185 + 186 + 187 + /* private: do not show up in the docs */ 188 + struct hid_device *hdev; 113 189 }; 114 190 115 191 /* stored in each device */ ··· 190 124 * to this HID device 191 125 */ 192 126 u32 allocated_data; 193 - 194 - struct hid_bpf_prog_list __rcu *progs[HID_BPF_PROG_TYPE_MAX]; /* attached BPF progs */ 195 127 bool destroyed; /* prevents the assignment of any progs */ 196 128 197 - spinlock_t progs_lock; /* protects RCU update of progs */ 198 - }; 199 - 200 - /* specific HID-BPF link when a program is attached to a device */ 201 - struct hid_bpf_link { 202 - struct bpf_link link; 203 - int hid_table_index; 129 + struct hid_bpf_ops *rdesc_ops; 130 + struct list_head prog_list; 131 + struct mutex prog_list_lock; /* protects prog_list update */ 132 + struct srcu_struct srcu; /* protects prog_list read-only access */ 204 133 }; 205 134 206 135 #ifdef CONFIG_HID_BPF 207 136 u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, u8 *data, 208 - u32 *size, int interrupt); 137 + u32 *size, int interrupt, u64 source, bool from_bpf); 138 + int dispatch_hid_bpf_raw_requests(struct hid_device *hdev, 139 + unsigned char reportnum, __u8 *buf, 140 + u32 size, enum hid_report_type rtype, 141 + enum hid_class_request reqtype, 142 + u64 source, bool from_bpf); 143 + int dispatch_hid_bpf_output_report(struct hid_device *hdev, __u8 *buf, u32 size, 144 + u64 source, bool from_bpf); 209 145 int hid_bpf_connect_device(struct hid_device *hdev); 210 146 void hid_bpf_disconnect_device(struct hid_device *hdev); 211 147 void hid_bpf_destroy_device(struct hid_device *hid); 212 - void hid_bpf_device_init(struct hid_device *hid); 148 + int hid_bpf_device_init(struct hid_device *hid); 213 149 u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *size); 214 150 #else /* CONFIG_HID_BPF */ 215 151 static inline u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, 216 - u8 *data, u32 *size, int interrupt) { return data; } 152 + u8 *data, u32 *size, int interrupt, 153 + u64 source, bool from_bpf) { return data; } 154 + static inline int dispatch_hid_bpf_raw_requests(struct hid_device *hdev, 155 + unsigned char reportnum, u8 *buf, 156 + u32 size, enum hid_report_type rtype, 157 + enum hid_class_request reqtype, 158 + u64 source, bool from_bpf) { return 0; } 159 + static inline int dispatch_hid_bpf_output_report(struct hid_device *hdev, __u8 *buf, u32 size, 160 + u64 source, bool from_bpf) { return 0; } 217 161 static inline int hid_bpf_connect_device(struct hid_device *hdev) { return 0; } 218 162 static inline void hid_bpf_disconnect_device(struct hid_device *hdev) {} 219 163 static inline void hid_bpf_destroy_device(struct hid_device *hid) {} 220 - static inline void hid_bpf_device_init(struct hid_device *hid) {} 164 + static inline int hid_bpf_device_init(struct hid_device *hid) { return 0; } 221 165 #define call_hid_bpf_rdesc_fixup(_hdev, _rdesc, _size) \ 222 166 ((u8 *)kmemdup(_rdesc, *(_size), GFP_KERNEL)) 223 167
+2 -3
samples/hid/Makefile
··· 16 16 LIBBPF_INCLUDE = $(LIBBPF_DESTDIR)/include 17 17 LIBBPF = $(LIBBPF_OUTPUT)/libbpf.a 18 18 19 - EXTRA_HEADERS := hid_bpf_attach.h 20 19 EXTRA_BPF_HEADERS := hid_bpf_helpers.h 21 20 22 21 hid_mouse-objs := hid_mouse.o ··· 206 207 LINKED_SKELS := hid_mouse.skel.h hid_surface_dial.skel.h 207 208 clean-files += $(LINKED_SKELS) 208 209 209 - hid_mouse.skel.h-deps := hid_mouse.bpf.o hid_bpf_attach.bpf.o 210 - hid_surface_dial.skel.h-deps := hid_surface_dial.bpf.o hid_bpf_attach.bpf.o 210 + hid_mouse.skel.h-deps := hid_mouse.bpf.o 211 + hid_surface_dial.skel.h-deps := hid_surface_dial.bpf.o 211 212 212 213 LINKED_BPF_SRCS := $(patsubst %.bpf.o,%.bpf.c,$(foreach skel,$(LINKED_SKELS),$($(skel)-deps))) 213 214
-18
samples/hid/hid_bpf_attach.bpf.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* Copyright (c) 2022 Benjamin Tissoires 3 - */ 4 - 5 - #include "vmlinux.h" 6 - #include <bpf/bpf_helpers.h> 7 - #include <bpf/bpf_tracing.h> 8 - #include "hid_bpf_attach.h" 9 - #include "hid_bpf_helpers.h" 10 - 11 - SEC("syscall") 12 - int attach_prog(struct attach_prog_args *ctx) 13 - { 14 - ctx->retval = hid_bpf_attach_prog(ctx->hid, 15 - ctx->prog_fd, 16 - 0); 17 - return 0; 18 - }
-14
samples/hid/hid_bpf_attach.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0-only */ 2 - /* Copyright (c) 2022 Benjamin Tissoires 3 - */ 4 - 5 - #ifndef __HID_BPF_ATTACH_H 6 - #define __HID_BPF_ATTACH_H 7 - 8 - struct attach_prog_args { 9 - int prog_fd; 10 - unsigned int hid; 11 - int retval; 12 - }; 13 - 14 - #endif /* __HID_BPF_ATTACH_H */
+21 -5
samples/hid/hid_mouse.bpf.c
··· 5 5 #include <bpf/bpf_tracing.h> 6 6 #include "hid_bpf_helpers.h" 7 7 8 - SEC("fmod_ret/hid_bpf_device_event") 9 - int BPF_PROG(hid_y_event, struct hid_bpf_ctx *hctx) 8 + static int hid_y_event(struct hid_bpf_ctx *hctx) 10 9 { 11 10 s16 y; 12 11 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */); ··· 50 51 return 0; 51 52 } 52 53 53 - SEC("fmod_ret/hid_bpf_device_event") 54 - int BPF_PROG(hid_x_event, struct hid_bpf_ctx *hctx) 54 + static int hid_x_event(struct hid_bpf_ctx *hctx) 55 55 { 56 56 s16 x; 57 57 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */); ··· 67 69 return 0; 68 70 } 69 71 70 - SEC("fmod_ret/hid_bpf_rdesc_fixup") 72 + SEC("struct_ops/hid_device_event") 73 + int BPF_PROG(hid_event, struct hid_bpf_ctx *hctx, enum hid_report_type type) 74 + { 75 + int ret = hid_y_event(hctx); 76 + 77 + if (ret) 78 + return ret; 79 + 80 + return hid_x_event(hctx); 81 + } 82 + 83 + 84 + SEC("struct_ops/hid_rdesc_fixup") 71 85 int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx) 72 86 { 73 87 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */); ··· 118 108 119 109 return 0; 120 110 } 111 + 112 + SEC(".struct_ops.link") 113 + struct hid_bpf_ops mouse_invert = { 114 + .hid_rdesc_fixup = (void *)hid_rdesc_fixup, 115 + .hid_device_event = (void *)hid_event, 116 + }; 121 117 122 118 char _license[] SEC("license") = "GPL";
+11 -28
samples/hid/hid_mouse.c
··· 29 29 #include <bpf/libbpf.h> 30 30 31 31 #include "hid_mouse.skel.h" 32 - #include "hid_bpf_attach.h" 33 32 34 33 static bool running = true; 35 34 ··· 75 76 int main(int argc, char **argv) 76 77 { 77 78 struct hid_mouse *skel; 78 - struct bpf_program *prog; 79 + struct bpf_link *link; 79 80 int err; 80 81 const char *optstr = ""; 81 82 const char *sysfs_path; 82 - int opt, hid_id, attach_fd; 83 - struct attach_prog_args args = { 84 - .retval = -1, 85 - }; 86 - DECLARE_LIBBPF_OPTS(bpf_test_run_opts, tattr, 87 - .ctx_in = &args, 88 - .ctx_size_in = sizeof(args), 89 - ); 83 + int opt, hid_id; 90 84 91 85 while ((opt = getopt(argc, argv, optstr)) != -1) { 92 86 switch (opt) { ··· 100 108 return 1; 101 109 } 102 110 103 - skel = hid_mouse__open_and_load(); 111 + skel = hid_mouse__open(); 104 112 if (!skel) { 105 113 fprintf(stderr, "%s %s:%d", __func__, __FILE__, __LINE__); 106 114 return -1; ··· 112 120 fprintf(stderr, "can not open HID device: %m\n"); 113 121 return 1; 114 122 } 115 - args.hid = hid_id; 123 + skel->struct_ops.mouse_invert->hid_id = hid_id; 116 124 117 - attach_fd = bpf_program__fd(skel->progs.attach_prog); 118 - if (attach_fd < 0) { 119 - fprintf(stderr, "can't locate attach prog: %m\n"); 125 + err = hid_mouse__load(skel); 126 + if (err < 0) { 127 + fprintf(stderr, "can not load HID-BPF program: %m\n"); 120 128 return 1; 121 129 } 122 130 123 - bpf_object__for_each_program(prog, *skel->skeleton->obj) { 124 - /* ignore syscalls */ 125 - if (bpf_program__get_type(prog) != BPF_PROG_TYPE_TRACING) 126 - continue; 127 - 128 - args.retval = -1; 129 - args.prog_fd = bpf_program__fd(prog); 130 - err = bpf_prog_test_run_opts(attach_fd, &tattr); 131 - if (err) { 132 - fprintf(stderr, "can't attach prog to hid device %d: %m (err: %d)\n", 133 - hid_id, err); 134 - return 1; 135 - } 131 + link = bpf_map__attach_struct_ops(skel->maps.mouse_invert); 132 + if (!link) { 133 + fprintf(stderr, "can not attach HID-BPF program: %m\n"); 134 + return 1; 136 135 } 137 136 138 137 signal(SIGINT, int_exit);
+8 -2
samples/hid/hid_surface_dial.bpf.c
··· 10 10 #define HID_UP_BUTTON 0x0009 11 11 #define HID_GD_WHEEL 0x0038 12 12 13 - SEC("fmod_ret/hid_bpf_device_event") 13 + SEC("struct_ops/hid_device_event") 14 14 int BPF_PROG(hid_event, struct hid_bpf_ctx *hctx) 15 15 { 16 16 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */); ··· 101 101 } 102 102 103 103 /* Convert REL_DIAL into REL_WHEEL */ 104 - SEC("fmod_ret/hid_bpf_rdesc_fixup") 104 + SEC("struct_ops/hid_rdesc_fixup") 105 105 int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx) 106 106 { 107 107 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */); ··· 129 129 130 130 return 0; 131 131 } 132 + 133 + SEC(".struct_ops.link") 134 + struct hid_bpf_ops surface_dial = { 135 + .hid_rdesc_fixup = (void *)hid_rdesc_fixup, 136 + .hid_device_event = (void *)hid_event, 137 + }; 132 138 133 139 char _license[] SEC("license") = "GPL"; 134 140 u32 _version SEC("version") = 1;
+15 -38
samples/hid/hid_surface_dial.c
··· 31 31 #include <bpf/libbpf.h> 32 32 33 33 #include "hid_surface_dial.skel.h" 34 - #include "hid_bpf_attach.h" 35 34 36 35 static bool running = true; 37 36 ··· 85 86 return (int)strtol(str_id, NULL, 16); 86 87 } 87 88 88 - static int attach_prog(struct hid_surface_dial *skel, struct bpf_program *prog, int hid_id) 89 - { 90 - struct attach_prog_args args = { 91 - .hid = hid_id, 92 - .retval = -1, 93 - }; 94 - int attach_fd, err; 95 - DECLARE_LIBBPF_OPTS(bpf_test_run_opts, tattr, 96 - .ctx_in = &args, 97 - .ctx_size_in = sizeof(args), 98 - ); 99 - 100 - attach_fd = bpf_program__fd(skel->progs.attach_prog); 101 - if (attach_fd < 0) { 102 - fprintf(stderr, "can't locate attach prog: %m\n"); 103 - return 1; 104 - } 105 - 106 - args.prog_fd = bpf_program__fd(prog); 107 - err = bpf_prog_test_run_opts(attach_fd, &tattr); 108 - if (err) { 109 - fprintf(stderr, "can't attach prog to hid device %d: %m (err: %d)\n", 110 - hid_id, err); 111 - return 1; 112 - } 113 - return 0; 114 - } 115 - 116 89 static int set_haptic(struct hid_surface_dial *skel, int hid_id) 117 90 { 118 91 struct haptic_syscall_args args = { ··· 115 144 int main(int argc, char **argv) 116 145 { 117 146 struct hid_surface_dial *skel; 118 - struct bpf_program *prog; 119 147 const char *optstr = "r:"; 148 + struct bpf_link *link; 120 149 const char *sysfs_path; 121 - int opt, hid_id, resolution = 72; 150 + int err, opt, hid_id, resolution = 72; 122 151 123 152 while ((opt = getopt(argc, argv, optstr)) != -1) { 124 153 switch (opt) { ··· 160 189 return 1; 161 190 } 162 191 163 - skel = hid_surface_dial__open_and_load(); 192 + skel = hid_surface_dial__open(); 164 193 if (!skel) { 165 194 fprintf(stderr, "%s %s:%d", __func__, __FILE__, __LINE__); 166 195 return -1; ··· 172 201 return 1; 173 202 } 174 203 204 + skel->struct_ops.surface_dial->hid_id = hid_id; 205 + 206 + err = hid_surface_dial__load(skel); 207 + if (err < 0) { 208 + fprintf(stderr, "can not load HID-BPF program: %m\n"); 209 + return 1; 210 + } 211 + 175 212 skel->data->resolution = resolution; 176 213 skel->data->physical = (int)(resolution / 72); 177 214 178 - bpf_object__for_each_program(prog, *skel->skeleton->obj) { 179 - /* ignore syscalls */ 180 - if (bpf_program__get_type(prog) != BPF_PROG_TYPE_TRACING) 181 - continue; 182 - 183 - attach_prog(skel, prog, hid_id); 215 + link = bpf_map__attach_struct_ops(skel->maps.surface_dial); 216 + if (!link) { 217 + fprintf(stderr, "can not attach HID-BPF program: %m\n"); 218 + return 1; 184 219 } 185 220 186 221 signal(SIGINT, int_exit);
+398 -28
tools/testing/selftests/hid/hid_bpf.c
··· 460 460 int hid_id; 461 461 pthread_t tid; 462 462 struct hid *skel; 463 - int hid_links[3]; /* max number of programs loaded in a single test */ 463 + struct bpf_link *hid_links[3]; /* max number of programs loaded in a single test */ 464 464 }; 465 465 static void detach_bpf(FIXTURE_DATA(hid_bpf) * self) 466 466 { ··· 470 470 close(self->hidraw_fd); 471 471 self->hidraw_fd = 0; 472 472 473 + if (!self->skel) 474 + return; 475 + 476 + hid__detach(self->skel); 477 + 473 478 for (i = 0; i < ARRAY_SIZE(self->hid_links); i++) { 474 479 if (self->hid_links[i]) 475 - close(self->hid_links[i]); 480 + bpf_link__destroy(self->hid_links[i]); 476 481 } 477 482 478 483 hid__destroy(self->skel); ··· 532 527 FIXTURE_DATA(hid_bpf) * self, 533 528 const FIXTURE_VARIANT(hid_bpf) * variant) 534 529 { 535 - int attach_fd, err = -EINVAL; 536 - struct attach_prog_args args = { 537 - .retval = -1, 538 - }; 539 - DECLARE_LIBBPF_OPTS(bpf_test_run_opts, tattr, 540 - .ctx_in = &args, 541 - .ctx_size_in = sizeof(args), 542 - ); 530 + int err = -EINVAL; 543 531 544 532 ASSERT_LE(progs_count, ARRAY_SIZE(self->hid_links)) 545 533 TH_LOG("too many programs are to be loaded"); ··· 543 545 544 546 for (int i = 0; i < progs_count; i++) { 545 547 struct bpf_program *prog; 548 + struct bpf_map *map; 549 + int *ops_hid_id; 546 550 547 551 prog = bpf_object__find_program_by_name(*self->skel->skeleton->obj, 548 552 programs[i].name); 549 553 ASSERT_OK_PTR(prog) TH_LOG("can not find program by name '%s'", programs[i].name); 550 554 551 555 bpf_program__set_autoload(prog, true); 556 + 557 + map = bpf_object__find_map_by_name(*self->skel->skeleton->obj, 558 + programs[i].name + 4); 559 + ASSERT_OK_PTR(map) TH_LOG("can not find struct_ops by name '%s'", 560 + programs[i].name + 4); 561 + 562 + /* hid_id is the first field of struct hid_bpf_ops */ 563 + ops_hid_id = bpf_map__initial_value(map, NULL); 564 + ASSERT_OK_PTR(ops_hid_id) TH_LOG("unable to retrieve struct_ops data"); 565 + 566 + *ops_hid_id = self->hid_id; 552 567 } 553 568 554 569 err = hid__load(self->skel); 555 570 ASSERT_OK(err) TH_LOG("hid_skel_load failed: %d", err); 556 571 557 - attach_fd = bpf_program__fd(self->skel->progs.attach_prog); 558 - ASSERT_GE(attach_fd, 0) TH_LOG("locate attach_prog: %d", attach_fd); 559 - 560 572 for (int i = 0; i < progs_count; i++) { 561 - struct bpf_program *prog; 573 + struct bpf_map *map; 562 574 563 - prog = bpf_object__find_program_by_name(*self->skel->skeleton->obj, 564 - programs[i].name); 565 - ASSERT_OK_PTR(prog) TH_LOG("can not find program by name '%s'", programs[i].name); 575 + map = bpf_object__find_map_by_name(*self->skel->skeleton->obj, 576 + programs[i].name + 4); 577 + ASSERT_OK_PTR(map) TH_LOG("can not find struct_ops by name '%s'", 578 + programs[i].name + 4); 566 579 567 - args.prog_fd = bpf_program__fd(prog); 568 - args.hid = self->hid_id; 569 - args.insert_head = programs[i].insert_head; 570 - err = bpf_prog_test_run_opts(attach_fd, &tattr); 571 - ASSERT_GE(args.retval, 0) 572 - TH_LOG("attach_hid(%s): %d", programs[i].name, args.retval); 573 - 574 - self->hid_links[i] = args.retval; 580 + self->hid_links[i] = bpf_map__attach_struct_ops(map); 581 + ASSERT_OK_PTR(self->hid_links[i]) TH_LOG("failed to attach struct ops '%s'", 582 + programs[i].name + 4); 575 583 } 584 + 585 + hid__attach(self->skel); 576 586 577 587 self->hidraw_fd = open_hidraw(self->dev_id); 578 588 ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw"); ··· 646 640 } 647 641 648 642 /* 643 + * Attach hid_first_event to the given uhid device, 644 + * retrieve and open the matching hidraw node, 645 + * inject one event in the uhid device, 646 + * check that the program sees it and can change the data 647 + */ 648 + TEST_F(hid_bpf, subprog_raw_event) 649 + { 650 + const struct test_program progs[] = { 651 + { .name = "hid_subprog_first_event" }, 652 + }; 653 + __u8 buf[10] = {0}; 654 + int err; 655 + 656 + LOAD_PROGRAMS(progs); 657 + 658 + /* inject one event */ 659 + buf[0] = 1; 660 + buf[1] = 42; 661 + uhid_send_event(_metadata, self->uhid_fd, buf, 6); 662 + 663 + /* read the data from hidraw */ 664 + memset(buf, 0, sizeof(buf)); 665 + err = read(self->hidraw_fd, buf, sizeof(buf)); 666 + ASSERT_EQ(err, 6) TH_LOG("read_hidraw"); 667 + ASSERT_EQ(buf[0], 1); 668 + ASSERT_EQ(buf[2], 47); 669 + 670 + /* inject another event */ 671 + memset(buf, 0, sizeof(buf)); 672 + buf[0] = 1; 673 + buf[1] = 47; 674 + uhid_send_event(_metadata, self->uhid_fd, buf, 6); 675 + 676 + /* read the data from hidraw */ 677 + memset(buf, 0, sizeof(buf)); 678 + err = read(self->hidraw_fd, buf, sizeof(buf)); 679 + ASSERT_EQ(err, 6) TH_LOG("read_hidraw"); 680 + ASSERT_EQ(buf[2], 52); 681 + } 682 + 683 + /* 649 684 * Ensures that we can attach/detach programs 650 685 */ 651 686 TEST_F(hid_bpf, test_attach_detach) ··· 695 648 { .name = "hid_first_event" }, 696 649 { .name = "hid_second_event" }, 697 650 }; 651 + struct bpf_link *link; 698 652 __u8 buf[10] = {0}; 699 - int err, link; 653 + int err, link_fd; 700 654 701 655 LOAD_PROGRAMS(progs); 702 656 703 657 link = self->hid_links[0]; 704 - ASSERT_GT(link, 0) TH_LOG("HID-BPF link not created"); 658 + ASSERT_OK_PTR(link) TH_LOG("HID-BPF link not created"); 659 + 660 + link_fd = bpf_link__fd(link); 661 + ASSERT_GE(link_fd, 0) TH_LOG("HID-BPF link FD not valid"); 705 662 706 663 /* inject one event */ 707 664 buf[0] = 1; ··· 724 673 725 674 /* pin the first program and immediately unpin it */ 726 675 #define PIN_PATH "/sys/fs/bpf/hid_first_event" 727 - err = bpf_obj_pin(link, PIN_PATH); 676 + err = bpf_obj_pin(link_fd, PIN_PATH); 728 677 ASSERT_OK(err) TH_LOG("error while calling bpf_obj_pin"); 729 678 remove(PIN_PATH); 730 679 #undef PIN_PATH ··· 924 873 ASSERT_EQ(args.retval, 2); 925 874 926 875 ASSERT_EQ(args.data[1], 2); 876 + } 877 + 878 + /* 879 + * Call hid_hw_raw_request against the given uhid device, 880 + * check that the program is called and prevents the 881 + * call to uhid. 882 + */ 883 + TEST_F(hid_bpf, test_hid_filter_raw_request_call) 884 + { 885 + const struct test_program progs[] = { 886 + { .name = "hid_test_filter_raw_request" }, 887 + }; 888 + __u8 buf[10] = {0}; 889 + int err; 890 + 891 + LOAD_PROGRAMS(progs); 892 + 893 + /* first check that we did not attach to device_event */ 894 + 895 + /* inject one event */ 896 + buf[0] = 1; 897 + buf[1] = 42; 898 + uhid_send_event(_metadata, self->uhid_fd, buf, 6); 899 + 900 + /* read the data from hidraw */ 901 + memset(buf, 0, sizeof(buf)); 902 + err = read(self->hidraw_fd, buf, sizeof(buf)); 903 + ASSERT_EQ(err, 6) TH_LOG("read_hidraw"); 904 + ASSERT_EQ(buf[0], 1); 905 + ASSERT_EQ(buf[1], 42); 906 + ASSERT_EQ(buf[2], 0) TH_LOG("leftovers_from_previous_test"); 907 + 908 + /* now check that our program is preventing hid_hw_raw_request() */ 909 + 910 + /* emit hid_hw_raw_request from hidraw */ 911 + /* Get Feature */ 912 + memset(buf, 0, sizeof(buf)); 913 + buf[0] = 0x1; /* Report Number */ 914 + err = ioctl(self->hidraw_fd, HIDIOCGFEATURE(sizeof(buf)), buf); 915 + ASSERT_LT(err, 0) TH_LOG("unexpected success while reading HIDIOCGFEATURE: %d", err); 916 + ASSERT_EQ(errno, 20) TH_LOG("unexpected error code while reading HIDIOCGFEATURE: %d", 917 + errno); 918 + 919 + /* remove our bpf program and check that we can now emit commands */ 920 + 921 + /* detach the program */ 922 + detach_bpf(self); 923 + 924 + self->hidraw_fd = open_hidraw(self->dev_id); 925 + ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw"); 926 + 927 + err = ioctl(self->hidraw_fd, HIDIOCGFEATURE(sizeof(buf)), buf); 928 + ASSERT_GE(err, 0) TH_LOG("error while reading HIDIOCGFEATURE: %d", err); 929 + } 930 + 931 + /* 932 + * Call hid_hw_raw_request against the given uhid device, 933 + * check that the program is called and can issue the call 934 + * to uhid and transform the answer. 935 + */ 936 + TEST_F(hid_bpf, test_hid_change_raw_request_call) 937 + { 938 + const struct test_program progs[] = { 939 + { .name = "hid_test_hidraw_raw_request" }, 940 + }; 941 + __u8 buf[10] = {0}; 942 + int err; 943 + 944 + LOAD_PROGRAMS(progs); 945 + 946 + /* emit hid_hw_raw_request from hidraw */ 947 + /* Get Feature */ 948 + memset(buf, 0, sizeof(buf)); 949 + buf[0] = 0x1; /* Report Number */ 950 + err = ioctl(self->hidraw_fd, HIDIOCGFEATURE(sizeof(buf)), buf); 951 + ASSERT_EQ(err, 3) TH_LOG("unexpected returned size while reading HIDIOCGFEATURE: %d", err); 952 + 953 + ASSERT_EQ(buf[0], 2); 954 + ASSERT_EQ(buf[1], 3); 955 + ASSERT_EQ(buf[2], 4); 956 + } 957 + 958 + /* 959 + * Call hid_hw_raw_request against the given uhid device, 960 + * check that the program is not making infinite loops. 961 + */ 962 + TEST_F(hid_bpf, test_hid_infinite_loop_raw_request_call) 963 + { 964 + const struct test_program progs[] = { 965 + { .name = "hid_test_infinite_loop_raw_request" }, 966 + }; 967 + __u8 buf[10] = {0}; 968 + int err; 969 + 970 + LOAD_PROGRAMS(progs); 971 + 972 + /* emit hid_hw_raw_request from hidraw */ 973 + /* Get Feature */ 974 + memset(buf, 0, sizeof(buf)); 975 + buf[0] = 0x1; /* Report Number */ 976 + err = ioctl(self->hidraw_fd, HIDIOCGFEATURE(sizeof(buf)), buf); 977 + ASSERT_EQ(err, 3) TH_LOG("unexpected returned size while reading HIDIOCGFEATURE: %d", err); 978 + } 979 + 980 + /* 981 + * Call hid_hw_output_report against the given uhid device, 982 + * check that the program is called and prevents the 983 + * call to uhid. 984 + */ 985 + TEST_F(hid_bpf, test_hid_filter_output_report_call) 986 + { 987 + const struct test_program progs[] = { 988 + { .name = "hid_test_filter_output_report" }, 989 + }; 990 + __u8 buf[10] = {0}; 991 + int err; 992 + 993 + LOAD_PROGRAMS(progs); 994 + 995 + /* first check that we did not attach to device_event */ 996 + 997 + /* inject one event */ 998 + buf[0] = 1; 999 + buf[1] = 42; 1000 + uhid_send_event(_metadata, self->uhid_fd, buf, 6); 1001 + 1002 + /* read the data from hidraw */ 1003 + memset(buf, 0, sizeof(buf)); 1004 + err = read(self->hidraw_fd, buf, sizeof(buf)); 1005 + ASSERT_EQ(err, 6) TH_LOG("read_hidraw"); 1006 + ASSERT_EQ(buf[0], 1); 1007 + ASSERT_EQ(buf[1], 42); 1008 + ASSERT_EQ(buf[2], 0) TH_LOG("leftovers_from_previous_test"); 1009 + 1010 + /* now check that our program is preventing hid_hw_output_report() */ 1011 + 1012 + buf[0] = 1; /* report ID */ 1013 + buf[1] = 2; 1014 + buf[2] = 42; 1015 + 1016 + err = write(self->hidraw_fd, buf, 3); 1017 + ASSERT_LT(err, 0) TH_LOG("unexpected success while sending hid_hw_output_report: %d", err); 1018 + ASSERT_EQ(errno, 25) TH_LOG("unexpected error code while sending hid_hw_output_report: %d", 1019 + errno); 1020 + 1021 + /* remove our bpf program and check that we can now emit commands */ 1022 + 1023 + /* detach the program */ 1024 + detach_bpf(self); 1025 + 1026 + self->hidraw_fd = open_hidraw(self->dev_id); 1027 + ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw"); 1028 + 1029 + err = write(self->hidraw_fd, buf, 3); 1030 + ASSERT_GE(err, 0) TH_LOG("error while sending hid_hw_output_report: %d", err); 1031 + } 1032 + 1033 + /* 1034 + * Call hid_hw_output_report against the given uhid device, 1035 + * check that the program is called and can issue the call 1036 + * to uhid and transform the answer. 1037 + */ 1038 + TEST_F(hid_bpf, test_hid_change_output_report_call) 1039 + { 1040 + const struct test_program progs[] = { 1041 + { .name = "hid_test_hidraw_output_report" }, 1042 + }; 1043 + __u8 buf[10] = {0}; 1044 + int err; 1045 + 1046 + LOAD_PROGRAMS(progs); 1047 + 1048 + /* emit hid_hw_output_report from hidraw */ 1049 + buf[0] = 1; /* report ID */ 1050 + buf[1] = 2; 1051 + buf[2] = 42; 1052 + 1053 + err = write(self->hidraw_fd, buf, 10); 1054 + ASSERT_EQ(err, 2) TH_LOG("unexpected returned size while sending hid_hw_output_report: %d", 1055 + err); 1056 + } 1057 + 1058 + /* 1059 + * Call hid_hw_output_report against the given uhid device, 1060 + * check that the program is not making infinite loops. 1061 + */ 1062 + TEST_F(hid_bpf, test_hid_infinite_loop_output_report_call) 1063 + { 1064 + const struct test_program progs[] = { 1065 + { .name = "hid_test_infinite_loop_output_report" }, 1066 + }; 1067 + __u8 buf[10] = {0}; 1068 + int err; 1069 + 1070 + LOAD_PROGRAMS(progs); 1071 + 1072 + /* emit hid_hw_output_report from hidraw */ 1073 + buf[0] = 1; /* report ID */ 1074 + buf[1] = 2; 1075 + buf[2] = 42; 1076 + 1077 + err = write(self->hidraw_fd, buf, 8); 1078 + ASSERT_EQ(err, 2) TH_LOG("unexpected returned size while sending hid_hw_output_report: %d", 1079 + err); 1080 + } 1081 + 1082 + /* 1083 + * Attach hid_multiply_event_wq to the given uhid device, 1084 + * retrieve and open the matching hidraw node, 1085 + * inject one event in the uhid device, 1086 + * check that the program sees it and can add extra data 1087 + */ 1088 + TEST_F(hid_bpf, test_multiply_events_wq) 1089 + { 1090 + const struct test_program progs[] = { 1091 + { .name = "hid_test_multiply_events_wq" }, 1092 + }; 1093 + __u8 buf[10] = {0}; 1094 + int err; 1095 + 1096 + LOAD_PROGRAMS(progs); 1097 + 1098 + /* inject one event */ 1099 + buf[0] = 1; 1100 + buf[1] = 42; 1101 + uhid_send_event(_metadata, self->uhid_fd, buf, 6); 1102 + 1103 + /* read the data from hidraw */ 1104 + memset(buf, 0, sizeof(buf)); 1105 + err = read(self->hidraw_fd, buf, sizeof(buf)); 1106 + ASSERT_EQ(err, 6) TH_LOG("read_hidraw"); 1107 + ASSERT_EQ(buf[0], 1); 1108 + ASSERT_EQ(buf[1], 47); 1109 + 1110 + usleep(100000); 1111 + 1112 + /* read the data from hidraw */ 1113 + memset(buf, 0, sizeof(buf)); 1114 + err = read(self->hidraw_fd, buf, sizeof(buf)); 1115 + ASSERT_EQ(err, 9) TH_LOG("read_hidraw"); 1116 + ASSERT_EQ(buf[0], 2); 1117 + ASSERT_EQ(buf[1], 3); 1118 + } 1119 + 1120 + /* 1121 + * Attach hid_multiply_event to the given uhid device, 1122 + * retrieve and open the matching hidraw node, 1123 + * inject one event in the uhid device, 1124 + * check that the program sees it and can add extra data 1125 + */ 1126 + TEST_F(hid_bpf, test_multiply_events) 1127 + { 1128 + const struct test_program progs[] = { 1129 + { .name = "hid_test_multiply_events" }, 1130 + }; 1131 + __u8 buf[10] = {0}; 1132 + int err; 1133 + 1134 + LOAD_PROGRAMS(progs); 1135 + 1136 + /* inject one event */ 1137 + buf[0] = 1; 1138 + buf[1] = 42; 1139 + uhid_send_event(_metadata, self->uhid_fd, buf, 6); 1140 + 1141 + /* read the data from hidraw */ 1142 + memset(buf, 0, sizeof(buf)); 1143 + err = read(self->hidraw_fd, buf, sizeof(buf)); 1144 + ASSERT_EQ(err, 9) TH_LOG("read_hidraw"); 1145 + ASSERT_EQ(buf[0], 2); 1146 + ASSERT_EQ(buf[1], 47); 1147 + 1148 + /* read the data from hidraw */ 1149 + memset(buf, 0, sizeof(buf)); 1150 + err = read(self->hidraw_fd, buf, sizeof(buf)); 1151 + ASSERT_EQ(err, 9) TH_LOG("read_hidraw"); 1152 + ASSERT_EQ(buf[0], 2); 1153 + ASSERT_EQ(buf[1], 52); 1154 + } 1155 + 1156 + /* 1157 + * Call hid_bpf_input_report against the given uhid device, 1158 + * check that the program is not making infinite loops. 1159 + */ 1160 + TEST_F(hid_bpf, test_hid_infinite_loop_input_report_call) 1161 + { 1162 + const struct test_program progs[] = { 1163 + { .name = "hid_test_infinite_loop_input_report" }, 1164 + }; 1165 + __u8 buf[10] = {0}; 1166 + int err; 1167 + 1168 + LOAD_PROGRAMS(progs); 1169 + 1170 + /* emit hid_hw_output_report from hidraw */ 1171 + buf[0] = 1; /* report ID */ 1172 + buf[1] = 2; 1173 + buf[2] = 42; 1174 + 1175 + uhid_send_event(_metadata, self->uhid_fd, buf, 6); 1176 + 1177 + /* read the data from hidraw */ 1178 + memset(buf, 0, sizeof(buf)); 1179 + err = read(self->hidraw_fd, buf, sizeof(buf)); 1180 + ASSERT_EQ(err, 6) TH_LOG("read_hidraw"); 1181 + ASSERT_EQ(buf[0], 1); 1182 + ASSERT_EQ(buf[1], 3); 1183 + 1184 + /* read the data from hidraw: hid_bpf_try_input_report should work exactly one time */ 1185 + memset(buf, 0, sizeof(buf)); 1186 + err = read(self->hidraw_fd, buf, sizeof(buf)); 1187 + ASSERT_EQ(err, 6) TH_LOG("read_hidraw"); 1188 + ASSERT_EQ(buf[0], 1); 1189 + ASSERT_EQ(buf[1], 4); 1190 + 1191 + /* read the data from hidraw: there should be none */ 1192 + memset(buf, 0, sizeof(buf)); 1193 + err = read(self->hidraw_fd, buf, sizeof(buf)); 1194 + ASSERT_EQ(err, -1) TH_LOG("read_hidraw"); 927 1195 } 928 1196 929 1197 /*
+370 -22
tools/testing/selftests/hid/progs/hid.c
··· 14 14 __u64 callback_check = 52; 15 15 __u64 callback2_check = 52; 16 16 17 - SEC("?fmod_ret/hid_bpf_device_event") 18 - int BPF_PROG(hid_first_event, struct hid_bpf_ctx *hid_ctx) 17 + SEC("?struct_ops/hid_device_event") 18 + int BPF_PROG(hid_first_event, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type) 19 19 { 20 20 __u8 *rw_data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 3 /* size */); 21 21 ··· 29 29 return hid_ctx->size; 30 30 } 31 31 32 - SEC("?fmod_ret/hid_bpf_device_event") 33 - int BPF_PROG(hid_second_event, struct hid_bpf_ctx *hid_ctx) 32 + SEC(".struct_ops.link") 33 + struct hid_bpf_ops first_event = { 34 + .hid_device_event = (void *)hid_first_event, 35 + .hid_id = 2, 36 + }; 37 + 38 + int __hid_subprog_first_event(struct hid_bpf_ctx *hid_ctx, enum hid_report_type type) 39 + { 40 + __u8 *rw_data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 3 /* size */); 41 + 42 + if (!rw_data) 43 + return 0; /* EPERM check */ 44 + 45 + rw_data[2] = rw_data[1] + 5; 46 + 47 + return hid_ctx->size; 48 + } 49 + 50 + SEC("?struct_ops/hid_device_event") 51 + int BPF_PROG(hid_subprog_first_event, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type) 52 + { 53 + return __hid_subprog_first_event(hid_ctx, type); 54 + } 55 + 56 + SEC(".struct_ops.link") 57 + struct hid_bpf_ops subprog_first_event = { 58 + .hid_device_event = (void *)hid_subprog_first_event, 59 + .hid_id = 2, 60 + }; 61 + 62 + SEC("?struct_ops/hid_device_event") 63 + int BPF_PROG(hid_second_event, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type) 34 64 { 35 65 __u8 *rw_data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */); 36 66 ··· 72 42 return hid_ctx->size; 73 43 } 74 44 75 - SEC("?fmod_ret/hid_bpf_device_event") 76 - int BPF_PROG(hid_change_report_id, struct hid_bpf_ctx *hid_ctx) 45 + SEC(".struct_ops.link") 46 + struct hid_bpf_ops second_event = { 47 + .hid_device_event = (void *)hid_second_event, 48 + }; 49 + 50 + SEC("?struct_ops/hid_device_event") 51 + int BPF_PROG(hid_change_report_id, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type) 77 52 { 78 53 __u8 *rw_data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 3 /* size */); 79 54 ··· 90 55 return 9; 91 56 } 92 57 93 - SEC("syscall") 94 - int attach_prog(struct attach_prog_args *ctx) 95 - { 96 - ctx->retval = hid_bpf_attach_prog(ctx->hid, 97 - ctx->prog_fd, 98 - ctx->insert_head ? HID_BPF_FLAG_INSERT_HEAD : 99 - HID_BPF_FLAG_NONE); 100 - return 0; 101 - } 58 + SEC(".struct_ops.link") 59 + struct hid_bpf_ops change_report_id = { 60 + .hid_device_event = (void *)hid_change_report_id, 61 + }; 102 62 103 63 struct hid_hw_request_syscall_args { 104 64 /* data needs to come at offset 0 so we can use it in calls */ ··· 211 181 0xc0, /* END_COLLECTION */ 212 182 }; 213 183 214 - SEC("?fmod_ret/hid_bpf_rdesc_fixup") 184 + /* 185 + * the following program is marked as sleepable (struct_ops.s). 186 + * This is not strictly mandatory but is a nice test for 187 + * sleepable struct_ops 188 + */ 189 + SEC("?struct_ops.s/hid_rdesc_fixup") 215 190 int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hid_ctx) 216 191 { 217 192 __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4096 /* size */); ··· 235 200 return sizeof(rdesc) + 73; 236 201 } 237 202 238 - SEC("?fmod_ret/hid_bpf_device_event") 239 - int BPF_PROG(hid_test_insert1, struct hid_bpf_ctx *hid_ctx) 203 + SEC(".struct_ops.link") 204 + struct hid_bpf_ops rdesc_fixup = { 205 + .hid_rdesc_fixup = (void *)hid_rdesc_fixup, 206 + }; 207 + 208 + SEC("?struct_ops/hid_device_event") 209 + int BPF_PROG(hid_test_insert1, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type) 240 210 { 241 211 __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */); 242 212 ··· 257 217 return 0; 258 218 } 259 219 260 - SEC("?fmod_ret/hid_bpf_device_event") 261 - int BPF_PROG(hid_test_insert2, struct hid_bpf_ctx *hid_ctx) 220 + SEC(".struct_ops.link") 221 + struct hid_bpf_ops test_insert1 = { 222 + .hid_device_event = (void *)hid_test_insert1, 223 + .flags = BPF_F_BEFORE, 224 + }; 225 + 226 + SEC("?struct_ops/hid_device_event") 227 + int BPF_PROG(hid_test_insert2, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type) 262 228 { 263 229 __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */); 264 230 ··· 280 234 return 0; 281 235 } 282 236 283 - SEC("?fmod_ret/hid_bpf_device_event") 284 - int BPF_PROG(hid_test_insert3, struct hid_bpf_ctx *hid_ctx) 237 + SEC(".struct_ops.link") 238 + struct hid_bpf_ops test_insert2 = { 239 + .hid_device_event = (void *)hid_test_insert2, 240 + }; 241 + 242 + SEC("?struct_ops/hid_device_event") 243 + int BPF_PROG(hid_test_insert3, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type) 285 244 { 286 245 __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */); 287 246 ··· 301 250 302 251 return 0; 303 252 } 253 + 254 + SEC(".struct_ops.link") 255 + struct hid_bpf_ops test_insert3 = { 256 + .hid_device_event = (void *)hid_test_insert3, 257 + }; 258 + 259 + SEC("?struct_ops/hid_hw_request") 260 + int BPF_PROG(hid_test_filter_raw_request, struct hid_bpf_ctx *hctx, unsigned char reportnum, 261 + enum hid_report_type rtype, enum hid_class_request reqtype, __u64 source) 262 + { 263 + return -20; 264 + } 265 + 266 + SEC(".struct_ops.link") 267 + struct hid_bpf_ops test_filter_raw_request = { 268 + .hid_hw_request = (void *)hid_test_filter_raw_request, 269 + }; 270 + 271 + static struct file *current_file; 272 + 273 + SEC("fentry/hidraw_open") 274 + int BPF_PROG(hidraw_open, struct inode *inode, struct file *file) 275 + { 276 + current_file = file; 277 + return 0; 278 + } 279 + 280 + SEC("?struct_ops.s/hid_hw_request") 281 + int BPF_PROG(hid_test_hidraw_raw_request, struct hid_bpf_ctx *hctx, unsigned char reportnum, 282 + enum hid_report_type rtype, enum hid_class_request reqtype, __u64 source) 283 + { 284 + __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 3 /* size */); 285 + int ret; 286 + 287 + if (!data) 288 + return 0; /* EPERM check */ 289 + 290 + /* check if the incoming request comes from our hidraw operation */ 291 + if (source == (__u64)current_file) { 292 + data[0] = reportnum; 293 + 294 + ret = hid_bpf_hw_request(hctx, data, 2, rtype, reqtype); 295 + if (ret != 2) 296 + return -1; 297 + data[0] = reportnum + 1; 298 + data[1] = reportnum + 2; 299 + data[2] = reportnum + 3; 300 + return 3; 301 + } 302 + 303 + return 0; 304 + } 305 + 306 + SEC(".struct_ops.link") 307 + struct hid_bpf_ops test_hidraw_raw_request = { 308 + .hid_hw_request = (void *)hid_test_hidraw_raw_request, 309 + }; 310 + 311 + SEC("?struct_ops.s/hid_hw_request") 312 + int BPF_PROG(hid_test_infinite_loop_raw_request, struct hid_bpf_ctx *hctx, unsigned char reportnum, 313 + enum hid_report_type rtype, enum hid_class_request reqtype, __u64 source) 314 + { 315 + __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 3 /* size */); 316 + int ret; 317 + 318 + if (!data) 319 + return 0; /* EPERM check */ 320 + 321 + /* always forward the request as-is to the device, hid-bpf should prevent 322 + * infinite loops. 323 + */ 324 + data[0] = reportnum; 325 + 326 + ret = hid_bpf_hw_request(hctx, data, 2, rtype, reqtype); 327 + if (ret == 2) 328 + return 3; 329 + 330 + return 0; 331 + } 332 + 333 + SEC(".struct_ops.link") 334 + struct hid_bpf_ops test_infinite_loop_raw_request = { 335 + .hid_hw_request = (void *)hid_test_infinite_loop_raw_request, 336 + }; 337 + 338 + SEC("?struct_ops/hid_hw_output_report") 339 + int BPF_PROG(hid_test_filter_output_report, struct hid_bpf_ctx *hctx, unsigned char reportnum, 340 + enum hid_report_type rtype, enum hid_class_request reqtype, __u64 source) 341 + { 342 + return -25; 343 + } 344 + 345 + SEC(".struct_ops.link") 346 + struct hid_bpf_ops test_filter_output_report = { 347 + .hid_hw_output_report = (void *)hid_test_filter_output_report, 348 + }; 349 + 350 + SEC("?struct_ops.s/hid_hw_output_report") 351 + int BPF_PROG(hid_test_hidraw_output_report, struct hid_bpf_ctx *hctx, __u64 source) 352 + { 353 + __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 3 /* size */); 354 + int ret; 355 + 356 + if (!data) 357 + return 0; /* EPERM check */ 358 + 359 + /* check if the incoming request comes from our hidraw operation */ 360 + if (source == (__u64)current_file) 361 + return hid_bpf_hw_output_report(hctx, data, 2); 362 + 363 + return 0; 364 + } 365 + 366 + SEC(".struct_ops.link") 367 + struct hid_bpf_ops test_hidraw_output_report = { 368 + .hid_hw_output_report = (void *)hid_test_hidraw_output_report, 369 + }; 370 + 371 + SEC("?struct_ops.s/hid_hw_output_report") 372 + int BPF_PROG(hid_test_infinite_loop_output_report, struct hid_bpf_ctx *hctx, __u64 source) 373 + { 374 + __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 3 /* size */); 375 + int ret; 376 + 377 + if (!data) 378 + return 0; /* EPERM check */ 379 + 380 + /* always forward the request as-is to the device, hid-bpf should prevent 381 + * infinite loops. 382 + */ 383 + 384 + ret = hid_bpf_hw_output_report(hctx, data, 2); 385 + if (ret == 2) 386 + return 2; 387 + 388 + return 0; 389 + } 390 + 391 + SEC(".struct_ops.link") 392 + struct hid_bpf_ops test_infinite_loop_output_report = { 393 + .hid_hw_output_report = (void *)hid_test_infinite_loop_output_report, 394 + }; 395 + 396 + struct elem { 397 + struct bpf_wq work; 398 + }; 399 + 400 + struct { 401 + __uint(type, BPF_MAP_TYPE_HASH); 402 + __uint(max_entries, 1); 403 + __type(key, int); 404 + __type(value, struct elem); 405 + } hmap SEC(".maps"); 406 + 407 + static int wq_cb_sleepable(void *map, int *key, struct bpf_wq *work) 408 + { 409 + __u8 buf[9] = {2, 3, 4, 5, 6, 7, 8, 9, 10}; 410 + struct hid_bpf_ctx *hid_ctx; 411 + 412 + hid_ctx = hid_bpf_allocate_context(*key); 413 + if (!hid_ctx) 414 + return 0; /* EPERM check */ 415 + 416 + hid_bpf_input_report(hid_ctx, HID_INPUT_REPORT, buf, sizeof(buf)); 417 + 418 + hid_bpf_release_context(hid_ctx); 419 + 420 + return 0; 421 + } 422 + 423 + static int test_inject_input_report_callback(int *key) 424 + { 425 + struct elem init = {}, *val; 426 + struct bpf_wq *wq; 427 + 428 + if (bpf_map_update_elem(&hmap, key, &init, 0)) 429 + return -1; 430 + 431 + val = bpf_map_lookup_elem(&hmap, key); 432 + if (!val) 433 + return -2; 434 + 435 + wq = &val->work; 436 + if (bpf_wq_init(wq, &hmap, 0) != 0) 437 + return -3; 438 + 439 + if (bpf_wq_set_callback(wq, wq_cb_sleepable, 0)) 440 + return -4; 441 + 442 + if (bpf_wq_start(wq, 0)) 443 + return -5; 444 + 445 + return 0; 446 + } 447 + 448 + SEC("?struct_ops/hid_device_event") 449 + int BPF_PROG(hid_test_multiply_events_wq, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type) 450 + { 451 + __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 9 /* size */); 452 + int hid = hid_ctx->hid->id; 453 + int ret; 454 + 455 + if (!data) 456 + return 0; /* EPERM check */ 457 + 458 + if (data[0] != 1) 459 + return 0; 460 + 461 + ret = test_inject_input_report_callback(&hid); 462 + if (ret) 463 + return ret; 464 + 465 + data[1] += 5; 466 + 467 + return 0; 468 + } 469 + 470 + SEC(".struct_ops.link") 471 + struct hid_bpf_ops test_multiply_events_wq = { 472 + .hid_device_event = (void *)hid_test_multiply_events_wq, 473 + }; 474 + 475 + SEC("?struct_ops/hid_device_event") 476 + int BPF_PROG(hid_test_multiply_events, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type) 477 + { 478 + __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 9 /* size */); 479 + __u8 buf[9]; 480 + int ret; 481 + 482 + if (!data) 483 + return 0; /* EPERM check */ 484 + 485 + if (data[0] != 1) 486 + return 0; 487 + 488 + /* 489 + * we have to use an intermediate buffer as hid_bpf_input_report 490 + * will memset data to \0 491 + */ 492 + __builtin_memcpy(buf, data, sizeof(buf)); 493 + 494 + buf[0] = 2; 495 + buf[1] += 5; 496 + ret = hid_bpf_try_input_report(hid_ctx, HID_INPUT_REPORT, buf, sizeof(buf)); 497 + if (ret < 0) 498 + return ret; 499 + 500 + /* 501 + * In real world we should reset the original buffer as data might be garbage now, 502 + * but it actually now has the content of 'buf' 503 + */ 504 + data[1] += 5; 505 + 506 + return 9; 507 + } 508 + 509 + SEC(".struct_ops.link") 510 + struct hid_bpf_ops test_multiply_events = { 511 + .hid_device_event = (void *)hid_test_multiply_events, 512 + }; 513 + 514 + SEC("?struct_ops/hid_device_event") 515 + int BPF_PROG(hid_test_infinite_loop_input_report, struct hid_bpf_ctx *hctx, 516 + enum hid_report_type report_type, __u64 source) 517 + { 518 + __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 6 /* size */); 519 + __u8 buf[6]; 520 + 521 + if (!data) 522 + return 0; /* EPERM check */ 523 + 524 + /* 525 + * we have to use an intermediate buffer as hid_bpf_input_report 526 + * will memset data to \0 527 + */ 528 + __builtin_memcpy(buf, data, sizeof(buf)); 529 + 530 + /* always forward the request as-is to the device, hid-bpf should prevent 531 + * infinite loops. 532 + * the return value is ignored so the event is passing to userspace. 533 + */ 534 + 535 + hid_bpf_try_input_report(hctx, report_type, buf, sizeof(buf)); 536 + 537 + /* each time we process the event, we increment by one data[1]: 538 + * after each successful call to hid_bpf_try_input_report, buf 539 + * has been memcopied into data by the kernel. 540 + */ 541 + data[1] += 1; 542 + 543 + return 0; 544 + } 545 + 546 + SEC(".struct_ops.link") 547 + struct hid_bpf_ops test_infinite_loop_input_report = { 548 + .hid_device_event = (void *)hid_test_infinite_loop_input_report, 549 + };
+32 -14
tools/testing/selftests/hid/progs/hid_bpf_helpers.h
··· 7 7 8 8 /* "undefine" structs and enums in vmlinux.h, because we "override" them below */ 9 9 #define hid_bpf_ctx hid_bpf_ctx___not_used 10 + #define hid_bpf_ops hid_bpf_ops___not_used 10 11 #define hid_report_type hid_report_type___not_used 11 12 #define hid_class_request hid_class_request___not_used 12 13 #define hid_bpf_attach_flags hid_bpf_attach_flags___not_used ··· 21 20 #define HID_REQ_SET_REPORT HID_REQ_SET_REPORT___not_used 22 21 #define HID_REQ_SET_IDLE HID_REQ_SET_IDLE___not_used 23 22 #define HID_REQ_SET_PROTOCOL HID_REQ_SET_PROTOCOL___not_used 24 - #define HID_BPF_FLAG_NONE HID_BPF_FLAG_NONE___not_used 25 - #define HID_BPF_FLAG_INSERT_HEAD HID_BPF_FLAG_INSERT_HEAD___not_used 26 - #define HID_BPF_FLAG_MAX HID_BPF_FLAG_MAX___not_used 27 23 28 24 #include "vmlinux.h" 29 25 30 26 #undef hid_bpf_ctx 27 + #undef hid_bpf_ops 31 28 #undef hid_report_type 32 29 #undef hid_class_request 33 30 #undef hid_bpf_attach_flags ··· 39 40 #undef HID_REQ_SET_REPORT 40 41 #undef HID_REQ_SET_IDLE 41 42 #undef HID_REQ_SET_PROTOCOL 42 - #undef HID_BPF_FLAG_NONE 43 - #undef HID_BPF_FLAG_INSERT_HEAD 44 - #undef HID_BPF_FLAG_MAX 45 43 46 44 #include <bpf/bpf_helpers.h> 47 45 #include <bpf/bpf_tracing.h> ··· 53 57 }; 54 58 55 59 struct hid_bpf_ctx { 56 - __u32 index; 57 - const struct hid_device *hid; 60 + struct hid_device *hid; 58 61 __u32 allocated_size; 59 - enum hid_report_type report_type; 60 62 union { 61 63 __s32 retval; 62 64 __s32 size; ··· 70 76 HID_REQ_SET_PROTOCOL = 0x0B, 71 77 }; 72 78 73 - enum hid_bpf_attach_flags { 74 - HID_BPF_FLAG_NONE = 0, 75 - HID_BPF_FLAG_INSERT_HEAD = _BITUL(0), 76 - HID_BPF_FLAG_MAX, 79 + struct hid_bpf_ops { 80 + int hid_id; 81 + u32 flags; 82 + struct list_head list; 83 + int (*hid_device_event)(struct hid_bpf_ctx *ctx, enum hid_report_type report_type, 84 + u64 source); 85 + int (*hid_rdesc_fixup)(struct hid_bpf_ctx *ctx); 86 + int (*hid_hw_request)(struct hid_bpf_ctx *ctx, unsigned char reportnum, 87 + enum hid_report_type rtype, enum hid_class_request reqtype, 88 + u64 source); 89 + int (*hid_hw_output_report)(struct hid_bpf_ctx *ctx, u64 source); 90 + struct hid_device *hdev; 77 91 }; 92 + 93 + #ifndef BPF_F_BEFORE 94 + #define BPF_F_BEFORE (1U << 3) 95 + #endif 78 96 79 97 /* following are kfuncs exported by HID for HID-BPF */ 80 98 extern __u8 *hid_bpf_get_data(struct hid_bpf_ctx *ctx, 81 99 unsigned int offset, 82 100 const size_t __sz) __ksym; 83 - extern int hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, u32 flags) __ksym; 84 101 extern struct hid_bpf_ctx *hid_bpf_allocate_context(unsigned int hid_id) __ksym; 85 102 extern void hid_bpf_release_context(struct hid_bpf_ctx *ctx) __ksym; 86 103 extern int hid_bpf_hw_request(struct hid_bpf_ctx *ctx, ··· 105 100 enum hid_report_type type, 106 101 __u8 *data, 107 102 size_t buf__sz) __ksym; 103 + extern int hid_bpf_try_input_report(struct hid_bpf_ctx *ctx, 104 + enum hid_report_type type, 105 + __u8 *data, 106 + size_t buf__sz) __ksym; 107 + 108 + /* bpf_wq implementation */ 109 + extern int bpf_wq_init(struct bpf_wq *wq, void *p__map, unsigned int flags) __weak __ksym; 110 + extern int bpf_wq_start(struct bpf_wq *wq, unsigned int flags) __weak __ksym; 111 + extern int bpf_wq_set_callback_impl(struct bpf_wq *wq, 112 + int (callback_fn)(void *map, int *key, struct bpf_wq *wq), 113 + unsigned int flags__k, void *aux__ign) __ksym; 114 + #define bpf_wq_set_callback(timer, cb, flags) \ 115 + bpf_wq_set_callback_impl(timer, cb, flags, NULL) 108 116 109 117 #endif /* __HID_BPF_HELPERS_H */