diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist --- a/etc/mtree/BSD.include.dist +++ b/etc/mtree/BSD.include.dist @@ -54,6 +54,8 @@ .. firewire .. + hid + .. hwpmc .. hyperv diff --git a/include/Makefile b/include/Makefile --- a/include/Makefile +++ b/include/Makefile @@ -159,7 +159,7 @@ done; \ fi .endfor -.for i in ${LDIRS} ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/evdev:Ndev/hyperv:Ndev/pci:Ndev/veriexec} ${LSUBSUBDIRS} +.for i in ${LDIRS} ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/evdev:Ndev/hid:Ndev/hyperv:Ndev/pci:Ndev/veriexec} ${LSUBSUBDIRS} cd ${SRCTOP}/sys; \ ${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 $i/*.h \ ${SDESTDIR}${INCLUDEDIR}/$i @@ -179,6 +179,9 @@ ${SDESTDIR}${INCLUDEDIR}/dev/evdev; \ ${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 uinput.h \ ${SDESTDIR}${INCLUDEDIR}/dev/evdev + cd ${SRCTOP}/sys/dev/hid; \ + ${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 hid.h \ + ${SDESTDIR}${INCLUDEDIR}/dev/hid cd ${SRCTOP}/sys/dev/hyperv/include; \ ${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 hyperv.h \ ${SDESTDIR}${INCLUDEDIR}/dev/hyperv @@ -262,7 +265,7 @@ ${INSTALL_SYMLINK} ${TAG_ARGS} ../../../sys/$i/$$h ${SDESTDIR}${INCLUDEDIR}/$i; \ done .endfor -.for i in ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/evdev:Ndev/hyperv:Ndev/pci:Ndev/veriexec} +.for i in ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/evdev:Ndev/hid:Ndev/hyperv:Ndev/pci:Ndev/veriexec} cd ${SRCTOP}/sys/$i; \ for h in *.h; do \ ${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/$i/$$h ${SDESTDIR}${INCLUDEDIR}/$i; \ @@ -283,6 +286,11 @@ ln -fs ../../../../sys/dev/evdev/$$h \ ${SDESTDIR}${INCLUDEDIR}/dev/evdev; \ done + cd ${SRCTOP}/sys/dev/hid; \ + for h in hid.h; do \ + ln -fs ../../../../sys/dev/hid/$$h \ + ${SDESTDIR}${INCLUDEDIR}/dev/hid; \ + done cd ${SRCTOP}/sys/dev/hyperv/include; \ for h in hyperv.h; do \ ${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/dev/hyperv/include/$$h \ diff --git a/share/man/man4/atp.4 b/share/man/man4/atp.4 --- a/share/man/man4/atp.4 +++ b/share/man/man4/atp.4 @@ -38,6 +38,7 @@ your kernel configuration file: .Bd -ragged -offset indent .Cd "device atp" +.Cd "device hid" .Cd "device usb" .Ed .Pp diff --git a/share/man/man4/ucycom.4 b/share/man/man4/ucycom.4 --- a/share/man/man4/ucycom.4 +++ b/share/man/man4/ucycom.4 @@ -39,6 +39,7 @@ kernel configuration file: .Bd -ragged -offset indent .Cd "device usb" +.Cd "device hid" .Cd "device ucom" .Cd "device ucycom" .Ed diff --git a/share/man/man4/ugold.4 b/share/man/man4/ugold.4 --- a/share/man/man4/ugold.4 +++ b/share/man/man4/ugold.4 @@ -28,6 +28,7 @@ your kernel configuration file: .Bd -ragged -offset indent .Cd "device usb" +.Cd "device hid" .Cd "device ugold" .Ed .Pp diff --git a/share/man/man4/uhid.4 b/share/man/man4/uhid.4 --- a/share/man/man4/uhid.4 +++ b/share/man/man4/uhid.4 @@ -41,6 +41,8 @@ kernel configuration file: .Bd -ragged -offset indent .Cd "device uhid" +.Cd "device hid" +.Cd "device usb" .Ed .Pp Alternatively, to load the driver as a diff --git a/share/man/man4/ukbd.4 b/share/man/man4/ukbd.4 --- a/share/man/man4/ukbd.4 +++ b/share/man/man4/ukbd.4 @@ -36,6 +36,8 @@ kernel configuration file: .Bd -ragged -offset indent .Cd "device ukbd" +.Cd "device hid" +.Cd "device usb" .Ed .Pp Alternatively, to load the driver as a diff --git a/share/man/man4/ums.4 b/share/man/man4/ums.4 --- a/share/man/man4/ums.4 +++ b/share/man/man4/ums.4 @@ -36,6 +36,7 @@ kernel configuration file: .Bd -ragged -offset indent .Cd "device ums" +.Cd "device hid" .Cd "device uhci" .Cd "device ohci" .Cd "device usb" diff --git a/share/man/man4/wmt.4 b/share/man/man4/wmt.4 --- a/share/man/man4/wmt.4 +++ b/share/man/man4/wmt.4 @@ -36,6 +36,7 @@ .Bd -ragged -offset indent .Cd "device wmt" .Cd "device usb" +.Cd "device hid" .Cd "device evdev" .Ed .Pp diff --git a/share/man/man4/wsp.4 b/share/man/man4/wsp.4 --- a/share/man/man4/wsp.4 +++ b/share/man/man4/wsp.4 @@ -35,6 +35,7 @@ your kernel configuration file: .Bd -ragged -offset indent .Cd "device wsp" +.Cd "device hid" .Cd "device usb" .Ed .Pp diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -380,3 +380,6 @@ options EVDEV_SUPPORT # evdev support in legacy drivers device evdev # input event device support device uinput # install /dev/uinput cdev + +# HID support +device hid # Generic HID support diff --git a/sys/arm/conf/EFIKA_MX b/sys/arm/conf/EFIKA_MX --- a/sys/arm/conf/EFIKA_MX +++ b/sys/arm/conf/EFIKA_MX @@ -116,6 +116,9 @@ device wlan_tkip # 802.11 TKIP support device wlan_amrr # AMRR transmit rate control algorithm +# HID support +device hid # Generic HID support + # Flattened Device Tree options FDT # Configure using FDT/DTB data options FDT_DTB_STATIC diff --git a/sys/arm/conf/GENERIC b/sys/arm/conf/GENERIC --- a/sys/arm/conf/GENERIC +++ b/sys/arm/conf/GENERIC @@ -280,6 +280,9 @@ # Thermal sensors device aw_thermal # Allwinner Thermal Sensor Controller +# HID support +device hid # Generic HID support + # Flattened Device Tree options FDT # Configure using FDT/DTB data makeoptions MODULES_EXTRA+="dtb/allwinner" diff --git a/sys/arm/conf/IMX53 b/sys/arm/conf/IMX53 --- a/sys/arm/conf/IMX53 +++ b/sys/arm/conf/IMX53 @@ -113,6 +113,9 @@ #device mmc # SD/MMC protocol #device mmcsd # SDCard disk device +# HID support +device hid # Generic HID support + # Flattened Device Tree options FDT # Configure using FDT/DTB data diff --git a/sys/arm/conf/IMX6 b/sys/arm/conf/IMX6 --- a/sys/arm/conf/IMX6 +++ b/sys/arm/conf/IMX6 @@ -106,6 +106,9 @@ #device wlan_tkip # 802.11 TKIP support #device wlan_amrr # AMRR transmit rate control algorithm +# HID support +device hid # Generic HID support + device vt device kbdmux device ukbd diff --git a/sys/arm/conf/RPI-B b/sys/arm/conf/RPI-B --- a/sys/arm/conf/RPI-B +++ b/sys/arm/conf/RPI-B @@ -89,6 +89,9 @@ device fdt_pinctrl +# HID support +device hid # Generic HID support + # Flattened Device Tree options FDT # Configure using FDT/DTB data # Note: DTB is normally loaded and modified by RPi boot loader, then diff --git a/sys/arm/conf/TEGRA124 b/sys/arm/conf/TEGRA124 --- a/sys/arm/conf/TEGRA124 +++ b/sys/arm/conf/TEGRA124 @@ -130,6 +130,9 @@ #device sound #device snd_hda +# HID support +device hid # Generic HID support + # Flattened Device Tree options FDT # Configure using FDT/DTB data device fdt_pinctrl diff --git a/sys/arm/conf/VYBRID b/sys/arm/conf/VYBRID --- a/sys/arm/conf/VYBRID +++ b/sys/arm/conf/VYBRID @@ -103,5 +103,8 @@ device kbdmux device ukbd +# HID support +device hid # Generic HID support + # Flattened Device Tree options FDT # Configure using FDT/DTB data diff --git a/sys/arm64/conf/GENERIC b/sys/arm64/conf/GENERIC --- a/sys/arm64/conf/GENERIC +++ b/sys/arm64/conf/GENERIC @@ -369,3 +369,6 @@ # DTBs makeoptions MODULES_EXTRA="dtb/allwinner dtb/freescale dtb/imx8 dtb/mv dtb/rockchip dtb/rpi" + +# HID support +device hid # Generic HID support diff --git a/sys/conf/files b/sys/conf/files --- a/sys/conf/files +++ b/sys/conf/files @@ -1815,6 +1815,7 @@ dev/gpio/gpiobus_if.m optional gpio dev/gpio/gpiopps.c optional gpiopps fdt dev/gpio/ofw_gpiobus.c optional fdt gpio +dev/hid/hid.c optional hid dev/hifn/hifn7751.c optional hifn dev/hptiop/hptiop.c optional hptiop scbus dev/hwpmc/hwpmc_logging.c optional hwpmc diff --git a/sys/dev/hid/hid.h b/sys/dev/hid/hid.h new file mode 100644 --- /dev/null +++ b/sys/dev/hid/hid.h @@ -0,0 +1,247 @@ +/* $FreeBSD$ */ +/*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD + * + * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. + * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved. + * Copyright (c) 1998 Lennart Augustsson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _HID_HID_H_ +#define _HID_HID_H_ + +/* Usage pages */ +#define HUP_UNDEFINED 0x0000 +#define HUP_GENERIC_DESKTOP 0x0001 +#define HUP_SIMULATION 0x0002 +#define HUP_VR_CONTROLS 0x0003 +#define HUP_SPORTS_CONTROLS 0x0004 +#define HUP_GAMING_CONTROLS 0x0005 +#define HUP_KEYBOARD 0x0007 +#define HUP_LEDS 0x0008 +#define HUP_BUTTON 0x0009 +#define HUP_ORDINALS 0x000a +#define HUP_TELEPHONY 0x000b +#define HUP_CONSUMER 0x000c +#define HUP_DIGITIZERS 0x000d +#define HUP_PHYSICAL_IFACE 0x000e +#define HUP_UNICODE 0x0010 +#define HUP_ALPHANUM_DISPLAY 0x0014 +#define HUP_MONITOR 0x0080 +#define HUP_MONITOR_ENUM_VAL 0x0081 +#define HUP_VESA_VC 0x0082 +#define HUP_VESA_CMD 0x0083 +#define HUP_POWER 0x0084 +#define HUP_BATTERY_SYSTEM 0x0085 +#define HUP_BARCODE_SCANNER 0x008b +#define HUP_SCALE 0x008c +#define HUP_CAMERA_CONTROL 0x0090 +#define HUP_ARCADE 0x0091 +#define HUP_MICROSOFT 0xff00 + +/* Usages, generic desktop */ +#define HUG_POINTER 0x0001 +#define HUG_MOUSE 0x0002 +#define HUG_JOYSTICK 0x0004 +#define HUG_GAME_PAD 0x0005 +#define HUG_KEYBOARD 0x0006 +#define HUG_KEYPAD 0x0007 +#define HUG_X 0x0030 +#define HUG_Y 0x0031 +#define HUG_Z 0x0032 +#define HUG_RX 0x0033 +#define HUG_RY 0x0034 +#define HUG_RZ 0x0035 +#define HUG_SLIDER 0x0036 +#define HUG_DIAL 0x0037 +#define HUG_WHEEL 0x0038 +#define HUG_HAT_SWITCH 0x0039 +#define HUG_COUNTED_BUFFER 0x003a +#define HUG_BYTE_COUNT 0x003b +#define HUG_MOTION_WAKEUP 0x003c +#define HUG_VX 0x0040 +#define HUG_VY 0x0041 +#define HUG_VZ 0x0042 +#define HUG_VBRX 0x0043 +#define HUG_VBRY 0x0044 +#define HUG_VBRZ 0x0045 +#define HUG_VNO 0x0046 +#define HUG_TWHEEL 0x0048 /* M$ Wireless Intellimouse Wheel */ +#define HUG_SYSTEM_CONTROL 0x0080 +#define HUG_SYSTEM_POWER_DOWN 0x0081 +#define HUG_SYSTEM_SLEEP 0x0082 +#define HUG_SYSTEM_WAKEUP 0x0083 +#define HUG_SYSTEM_CONTEXT_MENU 0x0084 +#define HUG_SYSTEM_MAIN_MENU 0x0085 +#define HUG_SYSTEM_APP_MENU 0x0086 +#define HUG_SYSTEM_MENU_HELP 0x0087 +#define HUG_SYSTEM_MENU_EXIT 0x0088 +#define HUG_SYSTEM_MENU_SELECT 0x0089 +#define HUG_SYSTEM_MENU_RIGHT 0x008a +#define HUG_SYSTEM_MENU_LEFT 0x008b +#define HUG_SYSTEM_MENU_UP 0x008c +#define HUG_SYSTEM_MENU_DOWN 0x008d +#define HUG_APPLE_EJECT 0x00b8 + +/* Usages Digitizers */ +#define HUD_UNDEFINED 0x0000 +#define HUD_DIGITIZER 0x0001 +#define HUD_PEN 0x0002 +#define HUD_TOUCHSCREEN 0x0004 +#define HUD_TOUCHPAD 0x0005 +#define HUD_CONFIG 0x000e +#define HUD_FINGER 0x0022 +#define HUD_TIP_PRESSURE 0x0030 +#define HUD_BARREL_PRESSURE 0x0031 +#define HUD_IN_RANGE 0x0032 +#define HUD_TOUCH 0x0033 +#define HUD_UNTOUCH 0x0034 +#define HUD_TAP 0x0035 +#define HUD_QUALITY 0x0036 +#define HUD_DATA_VALID 0x0037 +#define HUD_TRANSDUCER_INDEX 0x0038 +#define HUD_TABLET_FKEYS 0x0039 +#define HUD_PROGRAM_CHANGE_KEYS 0x003a +#define HUD_BATTERY_STRENGTH 0x003b +#define HUD_INVERT 0x003c +#define HUD_X_TILT 0x003d +#define HUD_Y_TILT 0x003e +#define HUD_AZIMUTH 0x003f +#define HUD_ALTITUDE 0x0040 +#define HUD_TWIST 0x0041 +#define HUD_TIP_SWITCH 0x0042 +#define HUD_SEC_TIP_SWITCH 0x0043 +#define HUD_BARREL_SWITCH 0x0044 +#define HUD_ERASER 0x0045 +#define HUD_TABLET_PICK 0x0046 +#define HUD_CONFIDENCE 0x0047 +#define HUD_WIDTH 0x0048 +#define HUD_HEIGHT 0x0049 +#define HUD_CONTACTID 0x0051 +#define HUD_INPUT_MODE 0x0052 +#define HUD_DEVICE_INDEX 0x0053 +#define HUD_CONTACTCOUNT 0x0054 +#define HUD_CONTACT_MAX 0x0055 +#define HUD_SCAN_TIME 0x0056 +#define HUD_SURFACE_SWITCH 0x0057 +#define HUD_BUTTONS_SWITCH 0x0058 +#define HUD_BUTTON_TYPE 0x0059 +#define HUD_LATENCY_MODE 0x0060 + +/* Usages, Consumer */ +#define HUC_AC_PAN 0x0238 + +#define HID_USAGE2(p,u) (((p) << 16) | (u)) + +#define UHID_INPUT_REPORT 0x01 +#define UHID_OUTPUT_REPORT 0x02 +#define UHID_FEATURE_REPORT 0x03 + +/* Bits in the input/output/feature items */ +#define HIO_CONST 0x001 +#define HIO_VARIABLE 0x002 +#define HIO_RELATIVE 0x004 +#define HIO_WRAP 0x008 +#define HIO_NONLINEAR 0x010 +#define HIO_NOPREF 0x020 +#define HIO_NULLSTATE 0x040 +#define HIO_VOLATILE 0x080 +#define HIO_BUFBYTES 0x100 + +/* Units of Measure */ +#define HUM_CENTIMETER 0x11 +#define HUM_RADIAN 0x12 +#define HUM_INCH 0x13 +#define HUM_DEGREE 0x14 + +#if defined(_KERNEL) || defined(_STANDALONE) + +#define HID_ITEM_MAXUSAGE 4 + +enum hid_kind { + hid_input, hid_output, hid_feature, hid_collection, hid_endcollection +}; + +struct hid_location { + uint32_t size; + uint32_t count; + uint32_t pos; +}; + +struct hid_item { + /* Global */ + int32_t _usage_page; + int32_t logical_minimum; + int32_t logical_maximum; + int32_t physical_minimum; + int32_t physical_maximum; + int32_t unit_exponent; + int32_t unit; + int32_t report_ID; + /* Local */ + int nusages; + union { + int32_t usage; + int32_t usages[HID_ITEM_MAXUSAGE]; + }; + int32_t usage_minimum; + int32_t usage_maximum; + int32_t designator_index; + int32_t designator_minimum; + int32_t designator_maximum; + int32_t string_index; + int32_t string_minimum; + int32_t string_maximum; + int32_t set_delimiter; + /* Misc */ + int32_t collection; + int collevel; + enum hid_kind kind; + uint32_t flags; + /* Location */ + struct hid_location loc; +}; + +/* prototypes from "usb_hid.c" */ + +struct hid_data *hid_start_parse(const void *d, usb_size_t len, int kindset); +void hid_end_parse(struct hid_data *s); +int hid_get_item(struct hid_data *s, struct hid_item *h); +int hid_report_size(const void *buf, usb_size_t len, enum hid_kind k, + uint8_t *id); +int hid_locate(const void *desc, usb_size_t size, int32_t usage, + enum hid_kind kind, uint8_t index, struct hid_location *loc, + uint32_t *flags, uint8_t *id); +int32_t hid_get_data(const uint8_t *buf, usb_size_t len, + struct hid_location *loc); +uint32_t hid_get_data_unsigned(const uint8_t *buf, usb_size_t len, + struct hid_location *loc); +void hid_put_data_unsigned(uint8_t *buf, usb_size_t len, + struct hid_location *loc, unsigned int value); +int hid_is_collection(const void *desc, usb_size_t size, int32_t usage); +int32_t hid_item_resolution(struct hid_item *hi); +int hid_is_mouse(const void *d_ptr, uint16_t d_len); +int hid_is_keyboard(const void *d_ptr, uint16_t d_len); +#endif /* _KERNEL || _STANDALONE */ +#endif /* _HID_HID_H_ */ diff --git a/sys/dev/hid/hid.c b/sys/dev/hid/hid.c new file mode 100644 --- /dev/null +++ b/sys/dev/hid/hid.c @@ -0,0 +1,932 @@ +/* $FreeBSD$ */ +/* $NetBSD: hid.c,v 1.17 2001/11/13 06:24:53 lukem Exp $ */ +/*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD + * + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Lennart Augustsson (lennart@augustsson.net) at + * Carlstedt Research & Technology. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef USB_GLOBAL_INCLUDE_FILE +#include USB_GLOBAL_INCLUDE_FILE +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define USB_DEBUG_VAR usb_debug + +#include +#include +#include +#include +#include +#endif /* USB_GLOBAL_INCLUDE_FILE */ + +static void hid_clear_local(struct hid_item *); +static uint8_t hid_get_byte(struct hid_data *s, const uint16_t wSize); + +#define MAXUSAGE 64 +#define MAXPUSH 4 +#define MAXID 16 +#define MAXLOCCNT 2048 + +struct hid_pos_data { + int32_t rid; + uint32_t pos; +}; + +struct hid_data { + const uint8_t *start; + const uint8_t *end; + const uint8_t *p; + struct hid_item cur[MAXPUSH]; + struct hid_pos_data last_pos[MAXID]; + int32_t usages_min[MAXUSAGE]; + int32_t usages_max[MAXUSAGE]; + int32_t usage_last; /* last seen usage */ + uint32_t loc_size; /* last seen size */ + uint32_t loc_count; /* last seen count */ + uint32_t ncount; /* end usage item count */ + uint32_t icount; /* current usage item count */ + uint8_t kindset; /* we have 5 kinds so 8 bits are enough */ + uint8_t pushlevel; /* current pushlevel */ + uint8_t nusage; /* end "usages_min/max" index */ + uint8_t iusage; /* current "usages_min/max" index */ + uint8_t ousage; /* current "usages_min/max" offset */ + uint8_t susage; /* usage set flags */ +}; + +/*------------------------------------------------------------------------* + * hid_clear_local + *------------------------------------------------------------------------*/ +static void +hid_clear_local(struct hid_item *c) +{ + + c->loc.count = 0; + c->loc.size = 0; + c->nusages = 0; + memset(c->usages, 0, sizeof(c->usages)); + c->usage_minimum = 0; + c->usage_maximum = 0; + c->designator_index = 0; + c->designator_minimum = 0; + c->designator_maximum = 0; + c->string_index = 0; + c->string_minimum = 0; + c->string_maximum = 0; + c->set_delimiter = 0; +} + +static void +hid_switch_rid(struct hid_data *s, struct hid_item *c, int32_t next_rID) +{ + uint8_t i; + + /* check for same report ID - optimise */ + + if (c->report_ID == next_rID) + return; + + /* save current position for current rID */ + + if (c->report_ID == 0) { + i = 0; + } else { + for (i = 1; i != MAXID; i++) { + if (s->last_pos[i].rid == c->report_ID) + break; + if (s->last_pos[i].rid == 0) + break; + } + } + if (i != MAXID) { + s->last_pos[i].rid = c->report_ID; + s->last_pos[i].pos = c->loc.pos; + } + + /* store next report ID */ + + c->report_ID = next_rID; + + /* lookup last position for next rID */ + + if (next_rID == 0) { + i = 0; + } else { + for (i = 1; i != MAXID; i++) { + if (s->last_pos[i].rid == next_rID) + break; + if (s->last_pos[i].rid == 0) + break; + } + } + if (i != MAXID) { + s->last_pos[i].rid = next_rID; + c->loc.pos = s->last_pos[i].pos; + } else { + DPRINTF("Out of RID entries, position is set to zero!\n"); + c->loc.pos = 0; + } +} + +/*------------------------------------------------------------------------* + * hid_start_parse + *------------------------------------------------------------------------*/ +struct hid_data * +hid_start_parse(const void *d, usb_size_t len, int kindset) +{ + struct hid_data *s; + + if ((kindset-1) & kindset) { + DPRINTFN(0, "Only one bit can be " + "set in the kindset\n"); + return (NULL); + } + + s = malloc(sizeof *s, M_TEMP, M_WAITOK | M_ZERO); + s->start = s->p = d; + s->end = ((const uint8_t *)d) + len; + s->kindset = kindset; + return (s); +} + +/*------------------------------------------------------------------------* + * hid_end_parse + *------------------------------------------------------------------------*/ +void +hid_end_parse(struct hid_data *s) +{ + if (s == NULL) + return; + + free(s, M_TEMP); +} + +/*------------------------------------------------------------------------* + * get byte from HID descriptor + *------------------------------------------------------------------------*/ +static uint8_t +hid_get_byte(struct hid_data *s, const uint16_t wSize) +{ + const uint8_t *ptr; + uint8_t retval; + + ptr = s->p; + + /* check if end is reached */ + if (ptr == s->end) + return (0); + + /* read out a byte */ + retval = *ptr; + + /* check if data pointer can be advanced by "wSize" bytes */ + if ((s->end - ptr) < wSize) + ptr = s->end; + else + ptr += wSize; + + /* update pointer */ + s->p = ptr; + + return (retval); +} + +/*------------------------------------------------------------------------* + * hid_get_item + *------------------------------------------------------------------------*/ +int +hid_get_item(struct hid_data *s, struct hid_item *h) +{ + struct hid_item *c; + unsigned int bTag, bType, bSize; + uint32_t oldpos; + int32_t mask; + int32_t dval; + + if (s == NULL) + return (0); + + c = &s->cur[s->pushlevel]; + + top: + /* check if there is an array of items */ + if (s->icount < s->ncount) { + /* get current usage */ + if (s->iusage < s->nusage) { + dval = s->usages_min[s->iusage] + s->ousage; + c->usage = dval; + s->usage_last = dval; + if (dval == s->usages_max[s->iusage]) { + s->iusage ++; + s->ousage = 0; + } else { + s->ousage ++; + } + } else { + DPRINTFN(1, "Using last usage\n"); + dval = s->usage_last; + } + c->nusages = 1; + /* array type HID item may have multiple usages */ + while ((c->flags & HIO_VARIABLE) == 0 && s->ousage == 0 && + s->iusage < s->nusage && c->nusages < HID_ITEM_MAXUSAGE) + c->usages[c->nusages++] = s->usages_min[s->iusage++]; + if ((c->flags & HIO_VARIABLE) == 0 && s->ousage == 0 && + s->iusage < s->nusage) + DPRINTFN(0, "HID_ITEM_MAXUSAGE should be increased " + "up to %hhu to parse the HID report descriptor\n", + s->nusage); + s->icount ++; + /* + * Only copy HID item, increment position and return + * if correct kindset! + */ + if (s->kindset & (1 << c->kind)) { + *h = *c; + DPRINTFN(1, "%u,%u,%u\n", h->loc.pos, + h->loc.size, h->loc.count); + c->loc.pos += c->loc.size * c->loc.count; + return (1); + } + } + + /* reset state variables */ + s->icount = 0; + s->ncount = 0; + s->iusage = 0; + s->nusage = 0; + s->susage = 0; + s->ousage = 0; + hid_clear_local(c); + + /* get next item */ + while (s->p != s->end) { + bSize = hid_get_byte(s, 1); + if (bSize == 0xfe) { + /* long item */ + bSize = hid_get_byte(s, 1); + bSize |= hid_get_byte(s, 1) << 8; + bTag = hid_get_byte(s, 1); + bType = 0xff; /* XXX what should it be */ + } else { + /* short item */ + bTag = bSize >> 4; + bType = (bSize >> 2) & 3; + bSize &= 3; + if (bSize == 3) + bSize = 4; + } + switch (bSize) { + case 0: + dval = 0; + mask = 0; + break; + case 1: + dval = (int8_t)hid_get_byte(s, 1); + mask = 0xFF; + break; + case 2: + dval = hid_get_byte(s, 1); + dval |= hid_get_byte(s, 1) << 8; + dval = (int16_t)dval; + mask = 0xFFFF; + break; + case 4: + dval = hid_get_byte(s, 1); + dval |= hid_get_byte(s, 1) << 8; + dval |= hid_get_byte(s, 1) << 16; + dval |= hid_get_byte(s, 1) << 24; + mask = 0xFFFFFFFF; + break; + default: + dval = hid_get_byte(s, bSize); + DPRINTFN(0, "bad length %u (data=0x%02x)\n", + bSize, dval); + continue; + } + + switch (bType) { + case 0: /* Main */ + switch (bTag) { + case 8: /* Input */ + c->kind = hid_input; + ret: + c->flags = dval; + c->loc.count = s->loc_count; + c->loc.size = s->loc_size; + + if (c->flags & HIO_VARIABLE) { + /* range check usage count */ + if (c->loc.count > MAXLOCCNT) { + DPRINTFN(0, "Number of " + "items(%u) truncated to %u\n", + (unsigned)(c->loc.count), + MAXLOCCNT); + s->ncount = MAXLOCCNT; + } else + s->ncount = c->loc.count; + + /* + * The "top" loop will return + * one and one item: + */ + c->loc.count = 1; + } else { + s->ncount = 1; + } + goto top; + + case 9: /* Output */ + c->kind = hid_output; + goto ret; + case 10: /* Collection */ + c->kind = hid_collection; + c->collection = dval; + c->collevel++; + c->usage = s->usage_last; + c->nusages = 1; + *h = *c; + return (1); + case 11: /* Feature */ + c->kind = hid_feature; + goto ret; + case 12: /* End collection */ + c->kind = hid_endcollection; + if (c->collevel == 0) { + DPRINTFN(0, "invalid end collection\n"); + return (0); + } + c->collevel--; + *h = *c; + return (1); + default: + DPRINTFN(0, "Main bTag=%d\n", bTag); + break; + } + break; + case 1: /* Global */ + switch (bTag) { + case 0: + c->_usage_page = dval << 16; + break; + case 1: + c->logical_minimum = dval; + break; + case 2: + c->logical_maximum = dval; + break; + case 3: + c->physical_minimum = dval; + break; + case 4: + c->physical_maximum = dval; + break; + case 5: + c->unit_exponent = dval; + break; + case 6: + c->unit = dval; + break; + case 7: + /* mask because value is unsigned */ + s->loc_size = dval & mask; + break; + case 8: + hid_switch_rid(s, c, dval & mask); + break; + case 9: + /* mask because value is unsigned */ + s->loc_count = dval & mask; + break; + case 10: /* Push */ + /* stop parsing, if invalid push level */ + if ((s->pushlevel + 1) >= MAXPUSH) { + DPRINTFN(0, "Cannot push item @ %d\n", s->pushlevel); + return (0); + } + s->pushlevel ++; + s->cur[s->pushlevel] = *c; + /* store size and count */ + c->loc.size = s->loc_size; + c->loc.count = s->loc_count; + /* update current item pointer */ + c = &s->cur[s->pushlevel]; + break; + case 11: /* Pop */ + /* stop parsing, if invalid push level */ + if (s->pushlevel == 0) { + DPRINTFN(0, "Cannot pop item @ 0\n"); + return (0); + } + s->pushlevel --; + /* preserve position */ + oldpos = c->loc.pos; + c = &s->cur[s->pushlevel]; + /* restore size and count */ + s->loc_size = c->loc.size; + s->loc_count = c->loc.count; + /* set default item location */ + c->loc.pos = oldpos; + c->loc.size = 0; + c->loc.count = 0; + break; + default: + DPRINTFN(0, "Global bTag=%d\n", bTag); + break; + } + break; + case 2: /* Local */ + switch (bTag) { + case 0: + if (bSize != 4) + dval = (dval & mask) | c->_usage_page; + + /* set last usage, in case of a collection */ + s->usage_last = dval; + + if (s->nusage < MAXUSAGE) { + s->usages_min[s->nusage] = dval; + s->usages_max[s->nusage] = dval; + s->nusage ++; + } else { + DPRINTFN(0, "max usage reached\n"); + } + + /* clear any pending usage sets */ + s->susage = 0; + break; + case 1: + s->susage |= 1; + + if (bSize != 4) + dval = (dval & mask) | c->_usage_page; + c->usage_minimum = dval; + + goto check_set; + case 2: + s->susage |= 2; + + if (bSize != 4) + dval = (dval & mask) | c->_usage_page; + c->usage_maximum = dval; + + check_set: + if (s->susage != 3) + break; + + /* sanity check */ + if ((s->nusage < MAXUSAGE) && + (c->usage_minimum <= c->usage_maximum)) { + /* add usage range */ + s->usages_min[s->nusage] = + c->usage_minimum; + s->usages_max[s->nusage] = + c->usage_maximum; + s->nusage ++; + } else { + DPRINTFN(0, "Usage set dropped\n"); + } + s->susage = 0; + break; + case 3: + c->designator_index = dval; + break; + case 4: + c->designator_minimum = dval; + break; + case 5: + c->designator_maximum = dval; + break; + case 7: + c->string_index = dval; + break; + case 8: + c->string_minimum = dval; + break; + case 9: + c->string_maximum = dval; + break; + case 10: + c->set_delimiter = dval; + break; + default: + DPRINTFN(0, "Local bTag=%d\n", bTag); + break; + } + break; + default: + DPRINTFN(0, "default bType=%d\n", bType); + break; + } + } + return (0); +} + +/*------------------------------------------------------------------------* + * hid_report_size + *------------------------------------------------------------------------*/ +int +hid_report_size(const void *buf, usb_size_t len, enum hid_kind k, uint8_t *id) +{ + struct hid_data *d; + struct hid_item h; + uint32_t temp; + uint32_t hpos; + uint32_t lpos; + uint8_t any_id; + + any_id = 0; + hpos = 0; + lpos = 0xFFFFFFFF; + + for (d = hid_start_parse(buf, len, 1 << k); hid_get_item(d, &h);) { + if (h.kind == k) { + /* check for ID-byte presence */ + if ((h.report_ID != 0) && !any_id) { + if (id != NULL) + *id = h.report_ID; + any_id = 1; + } + /* compute minimum */ + if (lpos > h.loc.pos) + lpos = h.loc.pos; + /* compute end position */ + temp = h.loc.pos + (h.loc.size * h.loc.count); + /* compute maximum */ + if (hpos < temp) + hpos = temp; + } + } + hid_end_parse(d); + + /* safety check - can happen in case of currupt descriptors */ + if (lpos > hpos) + temp = 0; + else + temp = hpos - lpos; + + /* check for ID byte */ + if (any_id) + temp += 8; + else if (id != NULL) + *id = 0; + + /* return length in bytes rounded up */ + return ((temp + 7) / 8); +} + +/*------------------------------------------------------------------------* + * hid_locate + *------------------------------------------------------------------------*/ +int +hid_locate(const void *desc, usb_size_t size, int32_t u, enum hid_kind k, + uint8_t index, struct hid_location *loc, uint32_t *flags, uint8_t *id) +{ + struct hid_data *d; + struct hid_item h; + int i; + + for (d = hid_start_parse(desc, size, 1 << k); hid_get_item(d, &h);) { + for (i = 0; i < h.nusages; i++) { + if (h.kind == k && h.usages[i] == u) { + if (index--) + break; + if (loc != NULL) + *loc = h.loc; + if (flags != NULL) + *flags = h.flags; + if (id != NULL) + *id = h.report_ID; + hid_end_parse(d); + return (1); + } + } + } + if (loc != NULL) + loc->size = 0; + if (flags != NULL) + *flags = 0; + if (id != NULL) + *id = 0; + hid_end_parse(d); + return (0); +} + +/*------------------------------------------------------------------------* + * hid_get_data + *------------------------------------------------------------------------*/ +static uint32_t +hid_get_data_sub(const uint8_t *buf, usb_size_t len, struct hid_location *loc, + int is_signed) +{ + uint32_t hpos = loc->pos; + uint32_t hsize = loc->size; + uint32_t data; + uint32_t rpos; + uint8_t n; + + DPRINTFN(11, "hid_get_data: loc %d/%d\n", hpos, hsize); + + /* Range check and limit */ + if (hsize == 0) + return (0); + if (hsize > 32) + hsize = 32; + + /* Get data in a safe way */ + data = 0; + rpos = (hpos / 8); + n = (hsize + 7) / 8; + rpos += n; + while (n--) { + rpos--; + if (rpos < len) + data |= buf[rpos] << (8 * n); + } + + /* Correctly shift down data */ + data = (data >> (hpos % 8)); + n = 32 - hsize; + + /* Mask and sign extend in one */ + if (is_signed != 0) + data = (int32_t)((int32_t)data << n) >> n; + else + data = (uint32_t)((uint32_t)data << n) >> n; + + DPRINTFN(11, "hid_get_data: loc %d/%d = %lu\n", + loc->pos, loc->size, (long)data); + return (data); +} + +int32_t +hid_get_data(const uint8_t *buf, usb_size_t len, struct hid_location *loc) +{ + return (hid_get_data_sub(buf, len, loc, 1)); +} + +uint32_t +hid_get_data_unsigned(const uint8_t *buf, usb_size_t len, struct hid_location *loc) +{ + return (hid_get_data_sub(buf, len, loc, 0)); +} + +/*------------------------------------------------------------------------* + * hid_put_data + *------------------------------------------------------------------------*/ +void +hid_put_data_unsigned(uint8_t *buf, usb_size_t len, + struct hid_location *loc, unsigned int value) +{ + uint32_t hpos = loc->pos; + uint32_t hsize = loc->size; + uint64_t data; + uint64_t mask; + uint32_t rpos; + uint8_t n; + + DPRINTFN(11, "hid_put_data: loc %d/%d = %u\n", hpos, hsize, value); + + /* Range check and limit */ + if (hsize == 0) + return; + if (hsize > 32) + hsize = 32; + + /* Put data in a safe way */ + rpos = (hpos / 8); + n = (hsize + 7) / 8; + data = ((uint64_t)value) << (hpos % 8); + mask = ((1ULL << hsize) - 1ULL) << (hpos % 8); + rpos += n; + while (n--) { + rpos--; + if (rpos < len) { + buf[rpos] &= ~(mask >> (8 * n)); + buf[rpos] |= (data >> (8 * n)); + } + } +} + +/*------------------------------------------------------------------------* + * hid_is_collection + *------------------------------------------------------------------------*/ +int +hid_is_collection(const void *desc, usb_size_t size, int32_t usage) +{ + struct hid_data *hd; + struct hid_item hi; + int err; + + hd = hid_start_parse(desc, size, hid_input); + if (hd == NULL) + return (0); + + while ((err = hid_get_item(hd, &hi))) { + if (hi.kind == hid_collection && + hi.usage == usage) + break; + } + hid_end_parse(hd); + return (err); +} + +/*------------------------------------------------------------------------* + * calculate HID item resolution. unit/mm for distances, unit/rad for angles + *------------------------------------------------------------------------*/ +int32_t +hid_item_resolution(struct hid_item *hi) +{ + /* + * hid unit scaling table according to HID Usage Table Review + * Request 39 Tbl 17 http://www.usb.org/developers/hidpage/HUTRR39b.pdf + */ + static const int64_t scale[0x10][2] = { + [0x00] = { 1, 1 }, + [0x01] = { 1, 10 }, + [0x02] = { 1, 100 }, + [0x03] = { 1, 1000 }, + [0x04] = { 1, 10000 }, + [0x05] = { 1, 100000 }, + [0x06] = { 1, 1000000 }, + [0x07] = { 1, 10000000 }, + [0x08] = { 100000000, 1 }, + [0x09] = { 10000000, 1 }, + [0x0A] = { 1000000, 1 }, + [0x0B] = { 100000, 1 }, + [0x0C] = { 10000, 1 }, + [0x0D] = { 1000, 1 }, + [0x0E] = { 100, 1 }, + [0x0F] = { 10, 1 }, + }; + int64_t logical_size; + int64_t physical_size; + int64_t multiplier; + int64_t divisor; + int64_t resolution; + + switch (hi->unit) { + case HUM_CENTIMETER: + multiplier = 1; + divisor = 10; + break; + case HUM_INCH: + multiplier = 10; + divisor = 254; + break; + case HUM_RADIAN: + multiplier = 1; + divisor = 1; + break; + case HUM_DEGREE: + multiplier = 573; + divisor = 10; + break; + default: + return (0); + } + + if ((hi->logical_maximum <= hi->logical_minimum) || + (hi->physical_maximum <= hi->physical_minimum) || + (hi->unit_exponent < 0) || (hi->unit_exponent >= nitems(scale))) + return (0); + + logical_size = (int64_t)hi->logical_maximum - + (int64_t)hi->logical_minimum; + physical_size = (int64_t)hi->physical_maximum - + (int64_t)hi->physical_minimum; + /* Round to ceiling */ + resolution = logical_size * multiplier * scale[hi->unit_exponent][0] / + (physical_size * divisor * scale[hi->unit_exponent][1]); + + if (resolution > INT32_MAX) + return (0); + + return (resolution); +} + +/*------------------------------------------------------------------------* + * hid_is_mouse + * + * This function will decide if a USB descriptor belongs to a USB mouse. + * + * Return values: + * Zero: Not a USB mouse. + * Else: Is a USB mouse. + *------------------------------------------------------------------------*/ +int +hid_is_mouse(const void *d_ptr, uint16_t d_len) +{ + struct hid_data *hd; + struct hid_item hi; + int mdepth; + int found; + + hd = hid_start_parse(d_ptr, d_len, 1 << hid_input); + if (hd == NULL) + return (0); + + mdepth = 0; + found = 0; + + while (hid_get_item(hd, &hi)) { + switch (hi.kind) { + case hid_collection: + if (mdepth != 0) + mdepth++; + else if (hi.collection == 1 && + hi.usage == + HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)) + mdepth++; + break; + case hid_endcollection: + if (mdepth != 0) + mdepth--; + break; + case hid_input: + if (mdepth == 0) + break; + if (hi.usage == + HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) && + (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE) + found++; + if (hi.usage == + HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) && + (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE) + found++; + break; + default: + break; + } + } + hid_end_parse(hd); + return (found); +} + +/*------------------------------------------------------------------------* + * hid_is_keyboard + * + * This function will decide if a USB descriptor belongs to a USB keyboard. + * + * Return values: + * Zero: Not a USB keyboard. + * Else: Is a USB keyboard. + *------------------------------------------------------------------------*/ +int +hid_is_keyboard(const void *d_ptr, uint16_t d_len) +{ + if (hid_is_collection(d_ptr, d_len, + HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD))) + return (1); + return (0); +} + +MODULE_VERSION(hid, 1); diff --git a/sys/dev/hid/hidrdesc.h b/sys/dev/hid/hidrdesc.h new file mode 100644 --- /dev/null +++ b/sys/dev/hid/hidrdesc.h @@ -0,0 +1,370 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2000 Nick Hibma + * All rights reserved. + * + * Copyright (c) 2005 Ed Schouten + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + * + * This file contains replacements for broken HID report descriptors. + */ + +#define HID_GRAPHIRE_REPORT_DESCR(...) \ + 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */\ + 0x09, 0x01, /* USAGE (Digitizer) */\ + 0xa1, 0x01, /* COLLECTION (Application) */\ + 0x85, 0x02, /* REPORT_ID (2) */\ + 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */\ + 0x09, 0x01, /* USAGE (Digitizer) */\ + 0xa1, 0x00, /* COLLECTION (Physical) */\ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */\ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */\ + 0x09, 0x33, /* USAGE (Touch) */\ + 0x95, 0x01, /* REPORT_COUNT (1) */\ + 0x75, 0x01, /* REPORT_SIZE (1) */\ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ + 0x09, 0x44, /* USAGE (Barrel Switch) */\ + 0x95, 0x02, /* REPORT_COUNT (2) */\ + 0x75, 0x01, /* REPORT_SIZE (1) */\ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ + 0x09, 0x00, /* USAGE (Undefined) */\ + 0x95, 0x02, /* REPORT_COUNT (2) */\ + 0x75, 0x01, /* REPORT_SIZE (1) */\ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */\ + 0x09, 0x3c, /* USAGE (Invert) */\ + 0x95, 0x01, /* REPORT_COUNT (1) */\ + 0x75, 0x01, /* REPORT_SIZE (1) */\ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ + 0x09, 0x38, /* USAGE (Transducer Index) */\ + 0x95, 0x01, /* REPORT_COUNT (1) */\ + 0x75, 0x01, /* REPORT_SIZE (1) */\ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ + 0x09, 0x32, /* USAGE (In Range) */\ + 0x95, 0x01, /* REPORT_COUNT (1) */\ + 0x75, 0x01, /* REPORT_SIZE (1) */\ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */\ + 0x09, 0x30, /* USAGE (X) */\ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */\ + 0x26, 0xde, 0x27, /* LOGICAL_MAXIMUM (10206) */\ + 0x95, 0x01, /* REPORT_COUNT (1) */\ + 0x75, 0x10, /* REPORT_SIZE (16) */\ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ + 0x09, 0x31, /* USAGE (Y) */\ + 0x26, 0xfe, 0x1c, /* LOGICAL_MAXIMUM (7422) */\ + 0x95, 0x01, /* REPORT_COUNT (1) */\ + 0x75, 0x10, /* REPORT_SIZE (16) */\ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ + 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */\ + 0x09, 0x30, /* USAGE (Tip Pressure) */\ + 0x26, 0xff, 0x01, /* LOGICAL_MAXIMUM (511) */\ + 0x95, 0x01, /* REPORT_COUNT (1) */\ + 0x75, 0x10, /* REPORT_SIZE (16) */\ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ + 0xc0, /* END_COLLECTION */\ + 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */\ + 0x09, 0x00, /* USAGE (Undefined) */\ + 0x85, 0x02, /* REPORT_ID (2) */\ + 0x95, 0x01, /* REPORT_COUNT (1) */\ + 0xb1, 0x02, /* FEATURE (Data,Var,Abs) */\ + 0x09, 0x00, /* USAGE (Undefined) */\ + 0x85, 0x03, /* REPORT_ID (3) */\ + 0x95, 0x01, /* REPORT_COUNT (1) */\ + 0xb1, 0x02, /* FEATURE (Data,Var,Abs) */\ + 0xc0, /* END_COLLECTION */\ + +#define HID_GRAPHIRE3_4X5_REPORT_DESCR(...) \ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */\ + 0x09, 0x02, /* USAGE (Mouse) */\ + 0xa1, 0x01, /* COLLECTION (Application) */\ + 0x85, 0x01, /* REPORT_ID (1) */\ + 0x09, 0x01, /* USAGE (Pointer) */\ + 0xa1, 0x00, /* COLLECTION (Physical) */\ + 0x05, 0x09, /* USAGE_PAGE (Button) */\ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */\ + 0x29, 0x03, /* USAGE_MAXIMUM (Button 3) */\ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */\ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */\ + 0x95, 0x03, /* REPORT_COUNT (3) */\ + 0x75, 0x01, /* REPORT_SIZE (1) */\ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ + 0x95, 0x01, /* REPORT_COUNT (1) */\ + 0x75, 0x05, /* REPORT_SIZE (5) */\ + 0x81, 0x01, /* INPUT (Cnst,Ary,Abs) */\ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */\ + 0x09, 0x30, /* USAGE (X) */\ + 0x09, 0x31, /* USAGE (Y) */\ + 0x09, 0x38, /* USAGE (Wheel) */\ + 0x15, 0x81, /* LOGICAL_MINIMUM (-127) */\ + 0x25, 0x7f, /* LOGICAL_MAXIMUM (127) */\ + 0x75, 0x08, /* REPORT_SIZE (8) */\ + 0x95, 0x03, /* REPORT_COUNT (3) */\ + 0x81, 0x06, /* INPUT (Data,Var,Rel) */\ + 0xc0, /* END_COLLECTION */\ + 0xc0, /* END_COLLECTION */\ + 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */\ + 0x09, 0x01, /* USAGE (Pointer) */\ + 0xa1, 0x01, /* COLLECTION (Applicaption) */\ + 0x85, 0x02, /* REPORT_ID (2) */\ + 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */\ + 0x09, 0x01, /* USAGE (Digitizer) */\ + 0xa1, 0x00, /* COLLECTION (Physical) */\ + 0x09, 0x33, /* USAGE (Touch) */\ + 0x09, 0x44, /* USAGE (Barrel Switch) */\ + 0x09, 0x44, /* USAGE (Barrel Switch) */\ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */\ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */\ + 0x75, 0x01, /* REPORT_SIZE (1) */\ + 0x95, 0x03, /* REPORT_COUNT (3) */\ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ + 0x75, 0x01, /* REPORT_SIZE (1) */\ + 0x95, 0x02, /* REPORT_COUNT (2) */\ + 0x81, 0x01, /* INPUT (Cnst,Ary,Abs) */\ + 0x09, 0x3c, /* USAGE (Invert) */\ + 0x09, 0x38, /* USAGE (Transducer Index) */\ + 0x09, 0x32, /* USAGE (In Range) */\ + 0x75, 0x01, /* REPORT_SIZE (1) */\ + 0x95, 0x03, /* REPORT_COUNT (3) */\ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */\ + 0x09, 0x30, /* USAGE (X) */\ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */\ + 0x26, 0xde, 0x27, /* LOGICAL_MAXIMUM (10206) */\ + 0x75, 0x10, /* REPORT_SIZE (16) */\ + 0x95, 0x01, /* REPORT_COUNT (1) */\ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ + 0x09, 0x31, /* USAGE (Y) */\ + 0x26, 0xfe, 0x1c, /* LOGICAL_MAXIMUM (7422) */\ + 0x75, 0x10, /* REPORT_SIZE (16) */\ + 0x95, 0x01, /* REPORT_COUNT (1) */\ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ + 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */\ + 0x09, 0x30, /* USAGE (Tip Pressure) */\ + 0x26, 0xff, 0x01, /* LOGICAL_MAXIMUM (511) */\ + 0x75, 0x10, /* REPORT_SIZE (16) */\ + 0x95, 0x01, /* REPORT_COUNT (1) */\ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ + 0xc0, /* END_COLLECTION */\ + 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */\ + 0x09, 0x00, /* USAGE (Undefined) */\ + 0x85, 0x02, /* REPORT_ID (2) */\ + 0x95, 0x01, /* REPORT_COUNT (1) */\ + 0xb1, 0x02, /* FEATURE (Data,Var,Abs) */\ + 0x09, 0x00, /* USAGE (Undefined) */\ + 0x85, 0x03, /* REPORT_ID (3) */\ + 0x95, 0x01, /* REPORT_COUNT (1) */\ + 0xb1, 0x02, /* FEATURE (Data,Var,Abs) */\ + 0xc0 /* END_COLLECTION */\ + +/* + * The descriptor has no output report format, thus preventing you from + * controlling the LEDs and the built-in rumblers. + */ +#define HID_XB360GP_REPORT_DESCR(...) \ + 0x05, 0x01, /* USAGE PAGE (Generic Desktop) */\ + 0x09, 0x05, /* USAGE (Gamepad) */\ + 0xa1, 0x01, /* COLLECTION (Application) */\ + /* Unused */\ + 0x75, 0x08, /* REPORT SIZE (8) */\ + 0x95, 0x01, /* REPORT COUNT (1) */\ + 0x81, 0x01, /* INPUT (Constant) */\ + /* Byte count */\ + 0x75, 0x08, /* REPORT SIZE (8) */\ + 0x95, 0x01, /* REPORT COUNT (1) */\ + 0x05, 0x01, /* USAGE PAGE (Generic Desktop) */\ + 0x09, 0x3b, /* USAGE (Byte Count) */\ + 0x81, 0x01, /* INPUT (Constant) */\ + /* D-Pad */\ + 0x05, 0x01, /* USAGE PAGE (Generic Desktop) */\ + 0x09, 0x01, /* USAGE (Pointer) */\ + 0xa1, 0x00, /* COLLECTION (Physical) */\ + 0x75, 0x01, /* REPORT SIZE (1) */\ + 0x15, 0x00, /* LOGICAL MINIMUM (0) */\ + 0x25, 0x01, /* LOGICAL MAXIMUM (1) */\ + 0x35, 0x00, /* PHYSICAL MINIMUM (0) */\ + 0x45, 0x01, /* PHYSICAL MAXIMUM (1) */\ + 0x95, 0x04, /* REPORT COUNT (4) */\ + 0x05, 0x01, /* USAGE PAGE (Generic Desktop) */\ + 0x09, 0x90, /* USAGE (D-Pad Up) */\ + 0x09, 0x91, /* USAGE (D-Pad Down) */\ + 0x09, 0x93, /* USAGE (D-Pad Left) */\ + 0x09, 0x92, /* USAGE (D-Pad Right) */\ + 0x81, 0x02, /* INPUT (Data, Variable, Absolute) */\ + 0xc0, /* END COLLECTION */\ + /* Buttons 5-11 */\ + 0x75, 0x01, /* REPORT SIZE (1) */\ + 0x15, 0x00, /* LOGICAL MINIMUM (0) */\ + 0x25, 0x01, /* LOGICAL MAXIMUM (1) */\ + 0x35, 0x00, /* PHYSICAL MINIMUM (0) */\ + 0x45, 0x01, /* PHYSICAL MAXIMUM (1) */\ + 0x95, 0x07, /* REPORT COUNT (7) */\ + 0x05, 0x09, /* USAGE PAGE (Button) */\ + 0x09, 0x08, /* USAGE (Button 8) */\ + 0x09, 0x07, /* USAGE (Button 7) */\ + 0x09, 0x09, /* USAGE (Button 9) */\ + 0x09, 0x0a, /* USAGE (Button 10) */\ + 0x09, 0x05, /* USAGE (Button 5) */\ + 0x09, 0x06, /* USAGE (Button 6) */\ + 0x09, 0x0b, /* USAGE (Button 11) */\ + 0x81, 0x02, /* INPUT (Data, Variable, Absolute) */\ + /* Unused */\ + 0x75, 0x01, /* REPORT SIZE (1) */\ + 0x95, 0x01, /* REPORT COUNT (1) */\ + 0x81, 0x01, /* INPUT (Constant) */\ + /* Buttons 1-4 */\ + 0x75, 0x01, /* REPORT SIZE (1) */\ + 0x15, 0x00, /* LOGICAL MINIMUM (0) */\ + 0x25, 0x01, /* LOGICAL MAXIMUM (1) */\ + 0x35, 0x00, /* PHYSICAL MINIMUM (0) */\ + 0x45, 0x01, /* PHYSICAL MAXIMUM (1) */\ + 0x95, 0x04, /* REPORT COUNT (4) */\ + 0x05, 0x09, /* USAGE PAGE (Button) */\ + 0x19, 0x01, /* USAGE MINIMUM (Button 1) */\ + 0x29, 0x04, /* USAGE MAXIMUM (Button 4) */\ + 0x81, 0x02, /* INPUT (Data, Variable, Absolute) */\ + /* Triggers */\ + 0x75, 0x08, /* REPORT SIZE (8) */\ + 0x15, 0x00, /* LOGICAL MINIMUM (0) */\ + 0x26, 0xff, 0x00, /* LOGICAL MAXIMUM (255) */\ + 0x35, 0x00, /* PHYSICAL MINIMUM (0) */\ + 0x46, 0xff, 0x00, /* PHYSICAL MAXIMUM (255) */\ + 0x95, 0x02, /* REPORT SIZE (2) */\ + 0x05, 0x01, /* USAGE PAGE (Generic Desktop) */\ + 0x09, 0x32, /* USAGE (Z) */\ + 0x09, 0x35, /* USAGE (Rz) */\ + 0x81, 0x02, /* INPUT (Data, Variable, Absolute) */\ + /* Sticks */\ + 0x75, 0x10, /* REPORT SIZE (16) */\ + 0x16, 0x00, 0x80, /* LOGICAL MINIMUM (-32768) */\ + 0x26, 0xff, 0x7f, /* LOGICAL MAXIMUM (32767) */\ + 0x36, 0x00, 0x80, /* PHYSICAL MINIMUM (-32768) */\ + 0x46, 0xff, 0x7f, /* PHYSICAL MAXIMUM (32767) */\ + 0x95, 0x04, /* REPORT COUNT (4) */\ + 0x05, 0x01, /* USAGE PAGE (Generic Desktop) */\ + 0x09, 0x30, /* USAGE (X) */\ + 0x09, 0x31, /* USAGE (Y) */\ + 0x09, 0x33, /* USAGE (Rx) */\ + 0x09, 0x34, /* USAGE (Ry) */\ + 0x81, 0x02, /* INPUT (Data, Variable, Absolute) */\ + /* Unused */\ + 0x75, 0x30, /* REPORT SIZE (48) */\ + 0x95, 0x01, /* REPORT COUNT (1) */\ + 0x81, 0x01, /* INPUT (Constant) */\ + 0xc0 /* END COLLECTION */\ + +/* Fixed report descriptor for Super Nintendo gamepads */ +#define HID_SNES_REPORT_DESCR(...) \ + 0x05, 0x01, /* Usage Page (Desktop), */\ + 0x09, 0x04, /* Usage (Joystik), */\ + 0xA1, 0x01, /* Collection (Application), */\ + 0xA1, 0x02, /* Collection (Logical), */\ + 0x14, /* Logical Minimum (0), */\ + 0x75, 0x08, /* Report Size (8), */\ + 0x95, 0x03, /* Report Count (3), */\ + 0x81, 0x01, /* Input (Constant), */\ + 0x26, 0xFF, 0x00, /* Logical Maximum (255), */\ + 0x95, 0x02, /* Report Count (2), */\ + 0x09, 0x30, /* Usage (X), */\ + 0x09, 0x31, /* Usage (Y), */\ + 0x81, 0x02, /* Input (Variable), */\ + 0x75, 0x01, /* Report Size (1), */\ + 0x95, 0x04, /* Report Count (4), */\ + 0x81, 0x01, /* Input (Constant), */\ + 0x25, 0x01, /* Logical Maximum (1), */\ + 0x95, 0x0A, /* Report Count (10), */\ + 0x05, 0x09, /* Usage Page (Button), */\ + 0x19, 0x01, /* Usage Minimum (01h), */\ + 0x29, 0x0A, /* Usage Maximum (0Ah), */\ + 0x81, 0x02, /* Input (Variable), */\ + 0x95, 0x0A, /* Report Count (10), */\ + 0x81, 0x01, /* Input (Constant), */\ + 0xC0, /* End Collection, */\ + 0xC0 /* End Collection */ + +/* HID mouse boot protocol descriptor */ +#define HID_MOUSE_BOOTPROTO_DESCR(...) \ + 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */\ + 0x09, 0x02, /* Usage (Mouse) */\ + 0xA1, 0x01, /* Collection (Application) */\ + 0x09, 0x01, /* Usage (Pointer) */\ + 0xA1, 0x00, /* Collection (Physical) */\ + 0x95, 0x03, /* Report Count (3) */\ + 0x75, 0x01, /* Report Size (1) */\ + 0x05, 0x09, /* Usage Page (Button) */\ + 0x19, 0x01, /* Usage Minimum (0x01) */\ + 0x29, 0x03, /* Usage Maximum (0x03) */\ + 0x15, 0x00, /* Logical Minimum (0) */\ + 0x25, 0x01, /* Logical Maximum (1) */\ + 0x81, 0x02, /* Input (Data,Var,Abs) */\ + 0x95, 0x01, /* Report Count (1) */\ + 0x75, 0x05, /* Report Size (5) */\ + 0x81, 0x03, /* Input (Const) */\ + 0x75, 0x08, /* Report Size (8) */\ + 0x95, 0x02, /* Report Count (2) */\ + 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */\ + 0x09, 0x30, /* Usage (X) */\ + 0x09, 0x31, /* Usage (Y) */\ + 0x15, 0x81, /* Logical Minimum (-127) */\ + 0x25, 0x7F, /* Logical Maximum (127) */\ + 0x81, 0x06, /* Input (Data,Var,Rel) */\ + 0xC0, /* End Collection */\ + 0xC0, /* End Collection */ + +/* HID keyboard boot protocol descriptor */ +#define HID_KBD_BOOTPROTO_DESCR(...) \ + 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */\ + 0x09, 0x06, /* Usage (Keyboard) */\ + 0xA1, 0x01, /* Collection (Application) */\ + 0x05, 0x07, /* Usage Page (Kbrd/Keypad) */\ + 0x19, 0xE0, /* Usage Minimum (0xE0) */\ + 0x29, 0xE7, /* Usage Maximum (0xE7) */\ + 0x15, 0x00, /* Logical Minimum (0) */\ + 0x25, 0x01, /* Logical Maximum (1) */\ + 0x75, 0x01, /* Report Size (1) */\ + 0x95, 0x08, /* Report Count (8) */\ + 0x81, 0x02, /* Input (Data,Var,Abs) */\ + 0x95, 0x01, /* Report Count (1) */\ + 0x75, 0x08, /* Report Size (8) */\ + 0x81, 0x01, /* Input (Const,Array,Abs) */\ + 0x95, 0x03, /* Report Count (3) */\ + 0x75, 0x01, /* Report Size (1) */\ + 0x05, 0x08, /* Usage Page (LEDs) */\ + 0x19, 0x01, /* Usage Minimum (Num Lock) */\ + 0x29, 0x03, /* Usage Maximum (Scroll Lock) */\ + 0x91, 0x02, /* Output (Data,Var,Abs) */\ + 0x95, 0x05, /* Report Count (5) */\ + 0x75, 0x01, /* Report Size (1) */\ + 0x91, 0x01, /* Output (Const,Array,Abs) */\ + 0x95, 0x06, /* Report Count (6) */\ + 0x75, 0x08, /* Report Size (8) */\ + 0x15, 0x00, /* Logical Minimum (0) */\ + 0x26, 0xFF, 0x00, /* Logical Maximum (255) */\ + 0x05, 0x07, /* Usage Page (Kbrd/Keypad) */\ + 0x19, 0x00, /* Usage Minimum (0x00) */\ + 0x2A, 0xFF, 0x00, /* Usage Maximum (0xFF) */\ + 0x81, 0x00, /* Input (Data,Array,Abs) */\ + 0xC0, /* End Collection */ diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c --- a/sys/dev/sound/usb/uaudio.c +++ b/sys/dev/sound/usb/uaudio.c @@ -6210,6 +6210,7 @@ DRIVER_MODULE_ORDERED(uaudio, uhub, uaudio_driver, uaudio_devclass, NULL, 0, SI_ORDER_ANY); MODULE_DEPEND(uaudio, usb, 1, 1, 1); MODULE_DEPEND(uaudio, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); +MODULE_DEPEND(uaudio, hid, 1, 1, 1); MODULE_VERSION(uaudio, 1); USB_PNP_HOST_INFO(uaudio_devs); USB_PNP_HOST_INFO(uaudio_vendor_midi); diff --git a/sys/dev/usb/input/atp.c b/sys/dev/usb/input/atp.c --- a/sys/dev/usb/input/atp.c +++ b/sys/dev/usb/input/atp.c @@ -2633,6 +2633,7 @@ DRIVER_MODULE(atp, uhub, atp_driver, atp_devclass, NULL, 0); MODULE_DEPEND(atp, usb, 1, 1, 1); +MODULE_DEPEND(atp, hid, 1, 1, 1); MODULE_VERSION(atp, 1); USB_PNP_HOST_INFO(fg_devs); USB_PNP_HOST_INFO(wsp_devs); diff --git a/sys/dev/usb/input/uhid.c b/sys/dev/usb/input/uhid.c --- a/sys/dev/usb/input/uhid.c +++ b/sys/dev/usb/input/uhid.c @@ -907,5 +907,6 @@ DRIVER_MODULE(uhid, uhub, uhid_driver, uhid_devclass, NULL, 0); MODULE_DEPEND(uhid, usb, 1, 1, 1); +MODULE_DEPEND(uhid, hid, 1, 1, 1); MODULE_VERSION(uhid, 1); USB_PNP_HOST_INFO(uhid_devs); diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c --- a/sys/dev/usb/input/ukbd.c +++ b/sys/dev/usb/input/ukbd.c @@ -2185,6 +2185,7 @@ DRIVER_MODULE(ukbd, uhub, ukbd_driver, ukbd_devclass, ukbd_driver_load, 0); MODULE_DEPEND(ukbd, usb, 1, 1, 1); +MODULE_DEPEND(ukbd, hid, 1, 1, 1); #ifdef EVDEV_SUPPORT MODULE_DEPEND(ukbd, evdev, 1, 1, 1); #endif diff --git a/sys/dev/usb/input/ums.c b/sys/dev/usb/input/ums.c --- a/sys/dev/usb/input/ums.c +++ b/sys/dev/usb/input/ums.c @@ -1213,6 +1213,7 @@ DRIVER_MODULE(ums, uhub, ums_driver, ums_devclass, NULL, 0); MODULE_DEPEND(ums, usb, 1, 1, 1); +MODULE_DEPEND(ums, hid, 1, 1, 1); #ifdef EVDEV_SUPPORT MODULE_DEPEND(ums, evdev, 1, 1, 1); #endif diff --git a/sys/dev/usb/input/usb_rdesc.h b/sys/dev/usb/input/usb_rdesc.h --- a/sys/dev/usb/input/usb_rdesc.h +++ b/sys/dev/usb/input/usb_rdesc.h @@ -1,11 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2000 Nick Hibma - * All rights reserved. - * - * Copyright (c) 2005 Ed Schouten - * All rights reserved. + * Copyright (c) 2020 Vladimir Kondratyev * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,277 +26,14 @@ * * $FreeBSD$ * - * This file contains replacements for broken HID report descriptors. + * This a proxy file for replacements for broken HID report descriptors. */ -#define UHID_GRAPHIRE_REPORT_DESCR(...) \ - 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */\ - 0x09, 0x01, /* USAGE (Digitizer) */\ - 0xa1, 0x01, /* COLLECTION (Application) */\ - 0x85, 0x02, /* REPORT_ID (2) */\ - 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */\ - 0x09, 0x01, /* USAGE (Digitizer) */\ - 0xa1, 0x00, /* COLLECTION (Physical) */\ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */\ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */\ - 0x09, 0x33, /* USAGE (Touch) */\ - 0x95, 0x01, /* REPORT_COUNT (1) */\ - 0x75, 0x01, /* REPORT_SIZE (1) */\ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ - 0x09, 0x44, /* USAGE (Barrel Switch) */\ - 0x95, 0x02, /* REPORT_COUNT (2) */\ - 0x75, 0x01, /* REPORT_SIZE (1) */\ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ - 0x09, 0x00, /* USAGE (Undefined) */\ - 0x95, 0x02, /* REPORT_COUNT (2) */\ - 0x75, 0x01, /* REPORT_SIZE (1) */\ - 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */\ - 0x09, 0x3c, /* USAGE (Invert) */\ - 0x95, 0x01, /* REPORT_COUNT (1) */\ - 0x75, 0x01, /* REPORT_SIZE (1) */\ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ - 0x09, 0x38, /* USAGE (Transducer Index) */\ - 0x95, 0x01, /* REPORT_COUNT (1) */\ - 0x75, 0x01, /* REPORT_SIZE (1) */\ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ - 0x09, 0x32, /* USAGE (In Range) */\ - 0x95, 0x01, /* REPORT_COUNT (1) */\ - 0x75, 0x01, /* REPORT_SIZE (1) */\ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */\ - 0x09, 0x30, /* USAGE (X) */\ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */\ - 0x26, 0xde, 0x27, /* LOGICAL_MAXIMUM (10206) */\ - 0x95, 0x01, /* REPORT_COUNT (1) */\ - 0x75, 0x10, /* REPORT_SIZE (16) */\ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ - 0x09, 0x31, /* USAGE (Y) */\ - 0x26, 0xfe, 0x1c, /* LOGICAL_MAXIMUM (7422) */\ - 0x95, 0x01, /* REPORT_COUNT (1) */\ - 0x75, 0x10, /* REPORT_SIZE (16) */\ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ - 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */\ - 0x09, 0x30, /* USAGE (Tip Pressure) */\ - 0x26, 0xff, 0x01, /* LOGICAL_MAXIMUM (511) */\ - 0x95, 0x01, /* REPORT_COUNT (1) */\ - 0x75, 0x10, /* REPORT_SIZE (16) */\ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ - 0xc0, /* END_COLLECTION */\ - 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */\ - 0x09, 0x00, /* USAGE (Undefined) */\ - 0x85, 0x02, /* REPORT_ID (2) */\ - 0x95, 0x01, /* REPORT_COUNT (1) */\ - 0xb1, 0x02, /* FEATURE (Data,Var,Abs) */\ - 0x09, 0x00, /* USAGE (Undefined) */\ - 0x85, 0x03, /* REPORT_ID (3) */\ - 0x95, 0x01, /* REPORT_COUNT (1) */\ - 0xb1, 0x02, /* FEATURE (Data,Var,Abs) */\ - 0xc0, /* END_COLLECTION */\ - -#define UHID_GRAPHIRE3_4X5_REPORT_DESCR(...) \ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */\ - 0x09, 0x02, /* USAGE (Mouse) */\ - 0xa1, 0x01, /* COLLECTION (Application) */\ - 0x85, 0x01, /* REPORT_ID (1) */\ - 0x09, 0x01, /* USAGE (Pointer) */\ - 0xa1, 0x00, /* COLLECTION (Physical) */\ - 0x05, 0x09, /* USAGE_PAGE (Button) */\ - 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */\ - 0x29, 0x03, /* USAGE_MAXIMUM (Button 3) */\ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */\ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */\ - 0x95, 0x03, /* REPORT_COUNT (3) */\ - 0x75, 0x01, /* REPORT_SIZE (1) */\ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ - 0x95, 0x01, /* REPORT_COUNT (1) */\ - 0x75, 0x05, /* REPORT_SIZE (5) */\ - 0x81, 0x01, /* INPUT (Cnst,Ary,Abs) */\ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */\ - 0x09, 0x30, /* USAGE (X) */\ - 0x09, 0x31, /* USAGE (Y) */\ - 0x09, 0x38, /* USAGE (Wheel) */\ - 0x15, 0x81, /* LOGICAL_MINIMUM (-127) */\ - 0x25, 0x7f, /* LOGICAL_MAXIMUM (127) */\ - 0x75, 0x08, /* REPORT_SIZE (8) */\ - 0x95, 0x03, /* REPORT_COUNT (3) */\ - 0x81, 0x06, /* INPUT (Data,Var,Rel) */\ - 0xc0, /* END_COLLECTION */\ - 0xc0, /* END_COLLECTION */\ - 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */\ - 0x09, 0x01, /* USAGE (Pointer) */\ - 0xa1, 0x01, /* COLLECTION (Applicaption) */\ - 0x85, 0x02, /* REPORT_ID (2) */\ - 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */\ - 0x09, 0x01, /* USAGE (Digitizer) */\ - 0xa1, 0x00, /* COLLECTION (Physical) */\ - 0x09, 0x33, /* USAGE (Touch) */\ - 0x09, 0x44, /* USAGE (Barrel Switch) */\ - 0x09, 0x44, /* USAGE (Barrel Switch) */\ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */\ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */\ - 0x75, 0x01, /* REPORT_SIZE (1) */\ - 0x95, 0x03, /* REPORT_COUNT (3) */\ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ - 0x75, 0x01, /* REPORT_SIZE (1) */\ - 0x95, 0x02, /* REPORT_COUNT (2) */\ - 0x81, 0x01, /* INPUT (Cnst,Ary,Abs) */\ - 0x09, 0x3c, /* USAGE (Invert) */\ - 0x09, 0x38, /* USAGE (Transducer Index) */\ - 0x09, 0x32, /* USAGE (In Range) */\ - 0x75, 0x01, /* REPORT_SIZE (1) */\ - 0x95, 0x03, /* REPORT_COUNT (3) */\ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */\ - 0x09, 0x30, /* USAGE (X) */\ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */\ - 0x26, 0xde, 0x27, /* LOGICAL_MAXIMUM (10206) */\ - 0x75, 0x10, /* REPORT_SIZE (16) */\ - 0x95, 0x01, /* REPORT_COUNT (1) */\ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ - 0x09, 0x31, /* USAGE (Y) */\ - 0x26, 0xfe, 0x1c, /* LOGICAL_MAXIMUM (7422) */\ - 0x75, 0x10, /* REPORT_SIZE (16) */\ - 0x95, 0x01, /* REPORT_COUNT (1) */\ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ - 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */\ - 0x09, 0x30, /* USAGE (Tip Pressure) */\ - 0x26, 0xff, 0x01, /* LOGICAL_MAXIMUM (511) */\ - 0x75, 0x10, /* REPORT_SIZE (16) */\ - 0x95, 0x01, /* REPORT_COUNT (1) */\ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */\ - 0xc0, /* END_COLLECTION */\ - 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */\ - 0x09, 0x00, /* USAGE (Undefined) */\ - 0x85, 0x02, /* REPORT_ID (2) */\ - 0x95, 0x01, /* REPORT_COUNT (1) */\ - 0xb1, 0x02, /* FEATURE (Data,Var,Abs) */\ - 0x09, 0x00, /* USAGE (Undefined) */\ - 0x85, 0x03, /* REPORT_ID (3) */\ - 0x95, 0x01, /* REPORT_COUNT (1) */\ - 0xb1, 0x02, /* FEATURE (Data,Var,Abs) */\ - 0xc0 /* END_COLLECTION */\ - -/* - * The descriptor has no output report format, thus preventing you from - * controlling the LEDs and the built-in rumblers. - */ -#define UHID_XB360GP_REPORT_DESCR(...) \ - 0x05, 0x01, /* USAGE PAGE (Generic Desktop) */\ - 0x09, 0x05, /* USAGE (Gamepad) */\ - 0xa1, 0x01, /* COLLECTION (Application) */\ - /* Unused */\ - 0x75, 0x08, /* REPORT SIZE (8) */\ - 0x95, 0x01, /* REPORT COUNT (1) */\ - 0x81, 0x01, /* INPUT (Constant) */\ - /* Byte count */\ - 0x75, 0x08, /* REPORT SIZE (8) */\ - 0x95, 0x01, /* REPORT COUNT (1) */\ - 0x05, 0x01, /* USAGE PAGE (Generic Desktop) */\ - 0x09, 0x3b, /* USAGE (Byte Count) */\ - 0x81, 0x01, /* INPUT (Constant) */\ - /* D-Pad */\ - 0x05, 0x01, /* USAGE PAGE (Generic Desktop) */\ - 0x09, 0x01, /* USAGE (Pointer) */\ - 0xa1, 0x00, /* COLLECTION (Physical) */\ - 0x75, 0x01, /* REPORT SIZE (1) */\ - 0x15, 0x00, /* LOGICAL MINIMUM (0) */\ - 0x25, 0x01, /* LOGICAL MAXIMUM (1) */\ - 0x35, 0x00, /* PHYSICAL MINIMUM (0) */\ - 0x45, 0x01, /* PHYSICAL MAXIMUM (1) */\ - 0x95, 0x04, /* REPORT COUNT (4) */\ - 0x05, 0x01, /* USAGE PAGE (Generic Desktop) */\ - 0x09, 0x90, /* USAGE (D-Pad Up) */\ - 0x09, 0x91, /* USAGE (D-Pad Down) */\ - 0x09, 0x93, /* USAGE (D-Pad Left) */\ - 0x09, 0x92, /* USAGE (D-Pad Right) */\ - 0x81, 0x02, /* INPUT (Data, Variable, Absolute) */\ - 0xc0, /* END COLLECTION */\ - /* Buttons 5-11 */\ - 0x75, 0x01, /* REPORT SIZE (1) */\ - 0x15, 0x00, /* LOGICAL MINIMUM (0) */\ - 0x25, 0x01, /* LOGICAL MAXIMUM (1) */\ - 0x35, 0x00, /* PHYSICAL MINIMUM (0) */\ - 0x45, 0x01, /* PHYSICAL MAXIMUM (1) */\ - 0x95, 0x07, /* REPORT COUNT (7) */\ - 0x05, 0x09, /* USAGE PAGE (Button) */\ - 0x09, 0x08, /* USAGE (Button 8) */\ - 0x09, 0x07, /* USAGE (Button 7) */\ - 0x09, 0x09, /* USAGE (Button 9) */\ - 0x09, 0x0a, /* USAGE (Button 10) */\ - 0x09, 0x05, /* USAGE (Button 5) */\ - 0x09, 0x06, /* USAGE (Button 6) */\ - 0x09, 0x0b, /* USAGE (Button 11) */\ - 0x81, 0x02, /* INPUT (Data, Variable, Absolute) */\ - /* Unused */\ - 0x75, 0x01, /* REPORT SIZE (1) */\ - 0x95, 0x01, /* REPORT COUNT (1) */\ - 0x81, 0x01, /* INPUT (Constant) */\ - /* Buttons 1-4 */\ - 0x75, 0x01, /* REPORT SIZE (1) */\ - 0x15, 0x00, /* LOGICAL MINIMUM (0) */\ - 0x25, 0x01, /* LOGICAL MAXIMUM (1) */\ - 0x35, 0x00, /* PHYSICAL MINIMUM (0) */\ - 0x45, 0x01, /* PHYSICAL MAXIMUM (1) */\ - 0x95, 0x04, /* REPORT COUNT (4) */\ - 0x05, 0x09, /* USAGE PAGE (Button) */\ - 0x19, 0x01, /* USAGE MINIMUM (Button 1) */\ - 0x29, 0x04, /* USAGE MAXIMUM (Button 4) */\ - 0x81, 0x02, /* INPUT (Data, Variable, Absolute) */\ - /* Triggers */\ - 0x75, 0x08, /* REPORT SIZE (8) */\ - 0x15, 0x00, /* LOGICAL MINIMUM (0) */\ - 0x26, 0xff, 0x00, /* LOGICAL MAXIMUM (255) */\ - 0x35, 0x00, /* PHYSICAL MINIMUM (0) */\ - 0x46, 0xff, 0x00, /* PHYSICAL MAXIMUM (255) */\ - 0x95, 0x02, /* REPORT SIZE (2) */\ - 0x05, 0x01, /* USAGE PAGE (Generic Desktop) */\ - 0x09, 0x32, /* USAGE (Z) */\ - 0x09, 0x35, /* USAGE (Rz) */\ - 0x81, 0x02, /* INPUT (Data, Variable, Absolute) */\ - /* Sticks */\ - 0x75, 0x10, /* REPORT SIZE (16) */\ - 0x16, 0x00, 0x80, /* LOGICAL MINIMUM (-32768) */\ - 0x26, 0xff, 0x7f, /* LOGICAL MAXIMUM (32767) */\ - 0x36, 0x00, 0x80, /* PHYSICAL MINIMUM (-32768) */\ - 0x46, 0xff, 0x7f, /* PHYSICAL MAXIMUM (32767) */\ - 0x95, 0x04, /* REPORT COUNT (4) */\ - 0x05, 0x01, /* USAGE PAGE (Generic Desktop) */\ - 0x09, 0x30, /* USAGE (X) */\ - 0x09, 0x31, /* USAGE (Y) */\ - 0x09, 0x33, /* USAGE (Rx) */\ - 0x09, 0x34, /* USAGE (Ry) */\ - 0x81, 0x02, /* INPUT (Data, Variable, Absolute) */\ - /* Unused */\ - 0x75, 0x30, /* REPORT SIZE (48) */\ - 0x95, 0x01, /* REPORT COUNT (1) */\ - 0x81, 0x01, /* INPUT (Constant) */\ - 0xc0 /* END COLLECTION */\ +#include -/* Fixed report descriptor for Super Nintendo gamepads */ -#define UHID_SNES_REPORT_DESCR(...) \ - 0x05, 0x01, /* Usage Page (Desktop), */\ - 0x09, 0x04, /* Usage (Joystik), */\ - 0xA1, 0x01, /* Collection (Application), */\ - 0xA1, 0x02, /* Collection (Logical), */\ - 0x14, /* Logical Minimum (0), */\ - 0x75, 0x08, /* Report Size (8), */\ - 0x95, 0x03, /* Report Count (3), */\ - 0x81, 0x01, /* Input (Constant), */\ - 0x26, 0xFF, 0x00, /* Logical Maximum (255), */\ - 0x95, 0x02, /* Report Count (2), */\ - 0x09, 0x30, /* Usage (X), */\ - 0x09, 0x31, /* Usage (Y), */\ - 0x81, 0x02, /* Input (Variable), */\ - 0x75, 0x01, /* Report Size (1), */\ - 0x95, 0x04, /* Report Count (4), */\ - 0x81, 0x01, /* Input (Constant), */\ - 0x25, 0x01, /* Logical Maximum (1), */\ - 0x95, 0x0A, /* Report Count (10), */\ - 0x05, 0x09, /* Usage Page (Button), */\ - 0x19, 0x01, /* Usage Minimum (01h), */\ - 0x29, 0x0A, /* Usage Maximum (0Ah), */\ - 0x81, 0x02, /* Input (Variable), */\ - 0x95, 0x0A, /* Report Count (10), */\ - 0x81, 0x01, /* Input (Constant), */\ - 0xC0, /* End Collection, */\ - 0xC0 /* End Collection */ +#define UHID_GRAPHIRE_REPORT_DESCR HID_GRAPHIRE_REPORT_DESCR +#define UHID_GRAPHIRE3_4X5_REPORT_DESCR HID_GRAPHIRE3_4X5_REPORT_DESCR +#define UHID_XB360GP_REPORT_DESCR HID_XB360GP_REPORT_DESCR +#define UHID_SNES_REPORT_DESCR HID_SNES_REPORT_DESCR +#define UHID_MOUSE_BOOTPROTO_DESCR HID_MOUSE_BOOTPROTO_DESCR +#define UHID_KBD_BOOTPROTO_DESCR HID_KBD_BOOTPROTO_DESCR diff --git a/sys/dev/usb/input/wmt.c b/sys/dev/usb/input/wmt.c --- a/sys/dev/usb/input/wmt.c +++ b/sys/dev/usb/input/wmt.c @@ -1072,6 +1072,7 @@ DRIVER_MODULE(wmt, uhub, wmt_driver, wmt_devclass, NULL, 0); MODULE_DEPEND(wmt, usb, 1, 1, 1); +MODULE_DEPEND(wmt, hid, 1, 1, 1); MODULE_DEPEND(wmt, evdev, 1, 1, 1); MODULE_VERSION(wmt, 1); USB_PNP_HOST_INFO(wmt_devs); diff --git a/sys/dev/usb/input/wsp.c b/sys/dev/usb/input/wsp.c --- a/sys/dev/usb/input/wsp.c +++ b/sys/dev/usb/input/wsp.c @@ -1403,5 +1403,6 @@ DRIVER_MODULE(wsp, uhub, wsp_driver, wsp_devclass, NULL, 0); MODULE_DEPEND(wsp, usb, 1, 1, 1); +MODULE_DEPEND(wsp, hid, 1, 1, 1); MODULE_VERSION(wsp, 1); USB_PNP_HOST_INFO(wsp_devs); diff --git a/sys/dev/usb/misc/ugold.c b/sys/dev/usb/misc/ugold.c --- a/sys/dev/usb/misc/ugold.c +++ b/sys/dev/usb/misc/ugold.c @@ -142,6 +142,7 @@ DRIVER_MODULE(ugold, uhub, ugold_driver, ugold_devclass, NULL, NULL); MODULE_DEPEND(ugold, usb, 1, 1, 1); +MODULE_DEPEND(ugold, hid, 1, 1, 1); MODULE_VERSION(ugold, 1); USB_PNP_HOST_INFO(ugold_devs); diff --git a/sys/dev/usb/serial/ucycom.c b/sys/dev/usb/serial/ucycom.c --- a/sys/dev/usb/serial/ucycom.c +++ b/sys/dev/usb/serial/ucycom.c @@ -185,6 +185,7 @@ DRIVER_MODULE(ucycom, uhub, ucycom_driver, ucycom_devclass, NULL, 0); MODULE_DEPEND(ucycom, ucom, 1, 1, 1); MODULE_DEPEND(ucycom, usb, 1, 1, 1); +MODULE_DEPEND(ucycom, hid, 1, 1, 1); MODULE_VERSION(ucycom, 1); USB_PNP_HOST_INFO(ucycom_devs); diff --git a/sys/dev/usb/usb_hid.c b/sys/dev/usb/usb_hid.c --- a/sys/dev/usb/usb_hid.c +++ b/sys/dev/usb/usb_hid.c @@ -68,717 +68,6 @@ #include #endif /* USB_GLOBAL_INCLUDE_FILE */ -static void hid_clear_local(struct hid_item *); -static uint8_t hid_get_byte(struct hid_data *s, const uint16_t wSize); - -#define MAXUSAGE 64 -#define MAXPUSH 4 -#define MAXID 16 -#define MAXLOCCNT 2048 - -struct hid_pos_data { - int32_t rid; - uint32_t pos; -}; - -struct hid_data { - const uint8_t *start; - const uint8_t *end; - const uint8_t *p; - struct hid_item cur[MAXPUSH]; - struct hid_pos_data last_pos[MAXID]; - int32_t usages_min[MAXUSAGE]; - int32_t usages_max[MAXUSAGE]; - int32_t usage_last; /* last seen usage */ - uint32_t loc_size; /* last seen size */ - uint32_t loc_count; /* last seen count */ - uint32_t ncount; /* end usage item count */ - uint32_t icount; /* current usage item count */ - uint8_t kindset; /* we have 5 kinds so 8 bits are enough */ - uint8_t pushlevel; /* current pushlevel */ - uint8_t nusage; /* end "usages_min/max" index */ - uint8_t iusage; /* current "usages_min/max" index */ - uint8_t ousage; /* current "usages_min/max" offset */ - uint8_t susage; /* usage set flags */ -}; - -/*------------------------------------------------------------------------* - * hid_clear_local - *------------------------------------------------------------------------*/ -static void -hid_clear_local(struct hid_item *c) -{ - - c->loc.count = 0; - c->loc.size = 0; - c->nusages = 0; - memset(c->usages, 0, sizeof(c->usages)); - c->usage_minimum = 0; - c->usage_maximum = 0; - c->designator_index = 0; - c->designator_minimum = 0; - c->designator_maximum = 0; - c->string_index = 0; - c->string_minimum = 0; - c->string_maximum = 0; - c->set_delimiter = 0; -} - -static void -hid_switch_rid(struct hid_data *s, struct hid_item *c, int32_t next_rID) -{ - uint8_t i; - - /* check for same report ID - optimise */ - - if (c->report_ID == next_rID) - return; - - /* save current position for current rID */ - - if (c->report_ID == 0) { - i = 0; - } else { - for (i = 1; i != MAXID; i++) { - if (s->last_pos[i].rid == c->report_ID) - break; - if (s->last_pos[i].rid == 0) - break; - } - } - if (i != MAXID) { - s->last_pos[i].rid = c->report_ID; - s->last_pos[i].pos = c->loc.pos; - } - - /* store next report ID */ - - c->report_ID = next_rID; - - /* lookup last position for next rID */ - - if (next_rID == 0) { - i = 0; - } else { - for (i = 1; i != MAXID; i++) { - if (s->last_pos[i].rid == next_rID) - break; - if (s->last_pos[i].rid == 0) - break; - } - } - if (i != MAXID) { - s->last_pos[i].rid = next_rID; - c->loc.pos = s->last_pos[i].pos; - } else { - DPRINTF("Out of RID entries, position is set to zero!\n"); - c->loc.pos = 0; - } -} - -/*------------------------------------------------------------------------* - * hid_start_parse - *------------------------------------------------------------------------*/ -struct hid_data * -hid_start_parse(const void *d, usb_size_t len, int kindset) -{ - struct hid_data *s; - - if ((kindset-1) & kindset) { - DPRINTFN(0, "Only one bit can be " - "set in the kindset\n"); - return (NULL); - } - - s = malloc(sizeof *s, M_TEMP, M_WAITOK | M_ZERO); - s->start = s->p = d; - s->end = ((const uint8_t *)d) + len; - s->kindset = kindset; - return (s); -} - -/*------------------------------------------------------------------------* - * hid_end_parse - *------------------------------------------------------------------------*/ -void -hid_end_parse(struct hid_data *s) -{ - if (s == NULL) - return; - - free(s, M_TEMP); -} - -/*------------------------------------------------------------------------* - * get byte from HID descriptor - *------------------------------------------------------------------------*/ -static uint8_t -hid_get_byte(struct hid_data *s, const uint16_t wSize) -{ - const uint8_t *ptr; - uint8_t retval; - - ptr = s->p; - - /* check if end is reached */ - if (ptr == s->end) - return (0); - - /* read out a byte */ - retval = *ptr; - - /* check if data pointer can be advanced by "wSize" bytes */ - if ((s->end - ptr) < wSize) - ptr = s->end; - else - ptr += wSize; - - /* update pointer */ - s->p = ptr; - - return (retval); -} - -/*------------------------------------------------------------------------* - * hid_get_item - *------------------------------------------------------------------------*/ -int -hid_get_item(struct hid_data *s, struct hid_item *h) -{ - struct hid_item *c; - unsigned int bTag, bType, bSize; - uint32_t oldpos; - int32_t mask; - int32_t dval; - - if (s == NULL) - return (0); - - c = &s->cur[s->pushlevel]; - - top: - /* check if there is an array of items */ - if (s->icount < s->ncount) { - /* get current usage */ - if (s->iusage < s->nusage) { - dval = s->usages_min[s->iusage] + s->ousage; - c->usage = dval; - s->usage_last = dval; - if (dval == s->usages_max[s->iusage]) { - s->iusage ++; - s->ousage = 0; - } else { - s->ousage ++; - } - } else { - DPRINTFN(1, "Using last usage\n"); - dval = s->usage_last; - } - c->nusages = 1; - /* array type HID item may have multiple usages */ - while ((c->flags & HIO_VARIABLE) == 0 && s->ousage == 0 && - s->iusage < s->nusage && c->nusages < HID_ITEM_MAXUSAGE) - c->usages[c->nusages++] = s->usages_min[s->iusage++]; - if ((c->flags & HIO_VARIABLE) == 0 && s->ousage == 0 && - s->iusage < s->nusage) - DPRINTFN(0, "HID_ITEM_MAXUSAGE should be increased " - "up to %hhu to parse the HID report descriptor\n", - s->nusage); - s->icount ++; - /* - * Only copy HID item, increment position and return - * if correct kindset! - */ - if (s->kindset & (1 << c->kind)) { - *h = *c; - DPRINTFN(1, "%u,%u,%u\n", h->loc.pos, - h->loc.size, h->loc.count); - c->loc.pos += c->loc.size * c->loc.count; - return (1); - } - } - - /* reset state variables */ - s->icount = 0; - s->ncount = 0; - s->iusage = 0; - s->nusage = 0; - s->susage = 0; - s->ousage = 0; - hid_clear_local(c); - - /* get next item */ - while (s->p != s->end) { - bSize = hid_get_byte(s, 1); - if (bSize == 0xfe) { - /* long item */ - bSize = hid_get_byte(s, 1); - bSize |= hid_get_byte(s, 1) << 8; - bTag = hid_get_byte(s, 1); - bType = 0xff; /* XXX what should it be */ - } else { - /* short item */ - bTag = bSize >> 4; - bType = (bSize >> 2) & 3; - bSize &= 3; - if (bSize == 3) - bSize = 4; - } - switch (bSize) { - case 0: - dval = 0; - mask = 0; - break; - case 1: - dval = (int8_t)hid_get_byte(s, 1); - mask = 0xFF; - break; - case 2: - dval = hid_get_byte(s, 1); - dval |= hid_get_byte(s, 1) << 8; - dval = (int16_t)dval; - mask = 0xFFFF; - break; - case 4: - dval = hid_get_byte(s, 1); - dval |= hid_get_byte(s, 1) << 8; - dval |= hid_get_byte(s, 1) << 16; - dval |= hid_get_byte(s, 1) << 24; - mask = 0xFFFFFFFF; - break; - default: - dval = hid_get_byte(s, bSize); - DPRINTFN(0, "bad length %u (data=0x%02x)\n", - bSize, dval); - continue; - } - - switch (bType) { - case 0: /* Main */ - switch (bTag) { - case 8: /* Input */ - c->kind = hid_input; - ret: - c->flags = dval; - c->loc.count = s->loc_count; - c->loc.size = s->loc_size; - - if (c->flags & HIO_VARIABLE) { - /* range check usage count */ - if (c->loc.count > MAXLOCCNT) { - DPRINTFN(0, "Number of " - "items(%u) truncated to %u\n", - (unsigned)(c->loc.count), - MAXLOCCNT); - s->ncount = MAXLOCCNT; - } else - s->ncount = c->loc.count; - - /* - * The "top" loop will return - * one and one item: - */ - c->loc.count = 1; - } else { - s->ncount = 1; - } - goto top; - - case 9: /* Output */ - c->kind = hid_output; - goto ret; - case 10: /* Collection */ - c->kind = hid_collection; - c->collection = dval; - c->collevel++; - c->usage = s->usage_last; - c->nusages = 1; - *h = *c; - return (1); - case 11: /* Feature */ - c->kind = hid_feature; - goto ret; - case 12: /* End collection */ - c->kind = hid_endcollection; - if (c->collevel == 0) { - DPRINTFN(0, "invalid end collection\n"); - return (0); - } - c->collevel--; - *h = *c; - return (1); - default: - DPRINTFN(0, "Main bTag=%d\n", bTag); - break; - } - break; - case 1: /* Global */ - switch (bTag) { - case 0: - c->_usage_page = dval << 16; - break; - case 1: - c->logical_minimum = dval; - break; - case 2: - c->logical_maximum = dval; - break; - case 3: - c->physical_minimum = dval; - break; - case 4: - c->physical_maximum = dval; - break; - case 5: - c->unit_exponent = dval; - break; - case 6: - c->unit = dval; - break; - case 7: - /* mask because value is unsigned */ - s->loc_size = dval & mask; - break; - case 8: - hid_switch_rid(s, c, dval & mask); - break; - case 9: - /* mask because value is unsigned */ - s->loc_count = dval & mask; - break; - case 10: /* Push */ - /* stop parsing, if invalid push level */ - if ((s->pushlevel + 1) >= MAXPUSH) { - DPRINTFN(0, "Cannot push item @ %d\n", s->pushlevel); - return (0); - } - s->pushlevel ++; - s->cur[s->pushlevel] = *c; - /* store size and count */ - c->loc.size = s->loc_size; - c->loc.count = s->loc_count; - /* update current item pointer */ - c = &s->cur[s->pushlevel]; - break; - case 11: /* Pop */ - /* stop parsing, if invalid push level */ - if (s->pushlevel == 0) { - DPRINTFN(0, "Cannot pop item @ 0\n"); - return (0); - } - s->pushlevel --; - /* preserve position */ - oldpos = c->loc.pos; - c = &s->cur[s->pushlevel]; - /* restore size and count */ - s->loc_size = c->loc.size; - s->loc_count = c->loc.count; - /* set default item location */ - c->loc.pos = oldpos; - c->loc.size = 0; - c->loc.count = 0; - break; - default: - DPRINTFN(0, "Global bTag=%d\n", bTag); - break; - } - break; - case 2: /* Local */ - switch (bTag) { - case 0: - if (bSize != 4) - dval = (dval & mask) | c->_usage_page; - - /* set last usage, in case of a collection */ - s->usage_last = dval; - - if (s->nusage < MAXUSAGE) { - s->usages_min[s->nusage] = dval; - s->usages_max[s->nusage] = dval; - s->nusage ++; - } else { - DPRINTFN(0, "max usage reached\n"); - } - - /* clear any pending usage sets */ - s->susage = 0; - break; - case 1: - s->susage |= 1; - - if (bSize != 4) - dval = (dval & mask) | c->_usage_page; - c->usage_minimum = dval; - - goto check_set; - case 2: - s->susage |= 2; - - if (bSize != 4) - dval = (dval & mask) | c->_usage_page; - c->usage_maximum = dval; - - check_set: - if (s->susage != 3) - break; - - /* sanity check */ - if ((s->nusage < MAXUSAGE) && - (c->usage_minimum <= c->usage_maximum)) { - /* add usage range */ - s->usages_min[s->nusage] = - c->usage_minimum; - s->usages_max[s->nusage] = - c->usage_maximum; - s->nusage ++; - } else { - DPRINTFN(0, "Usage set dropped\n"); - } - s->susage = 0; - break; - case 3: - c->designator_index = dval; - break; - case 4: - c->designator_minimum = dval; - break; - case 5: - c->designator_maximum = dval; - break; - case 7: - c->string_index = dval; - break; - case 8: - c->string_minimum = dval; - break; - case 9: - c->string_maximum = dval; - break; - case 10: - c->set_delimiter = dval; - break; - default: - DPRINTFN(0, "Local bTag=%d\n", bTag); - break; - } - break; - default: - DPRINTFN(0, "default bType=%d\n", bType); - break; - } - } - return (0); -} - -/*------------------------------------------------------------------------* - * hid_report_size - *------------------------------------------------------------------------*/ -int -hid_report_size(const void *buf, usb_size_t len, enum hid_kind k, uint8_t *id) -{ - struct hid_data *d; - struct hid_item h; - uint32_t temp; - uint32_t hpos; - uint32_t lpos; - uint8_t any_id; - - any_id = 0; - hpos = 0; - lpos = 0xFFFFFFFF; - - for (d = hid_start_parse(buf, len, 1 << k); hid_get_item(d, &h);) { - if (h.kind == k) { - /* check for ID-byte presence */ - if ((h.report_ID != 0) && !any_id) { - if (id != NULL) - *id = h.report_ID; - any_id = 1; - } - /* compute minimum */ - if (lpos > h.loc.pos) - lpos = h.loc.pos; - /* compute end position */ - temp = h.loc.pos + (h.loc.size * h.loc.count); - /* compute maximum */ - if (hpos < temp) - hpos = temp; - } - } - hid_end_parse(d); - - /* safety check - can happen in case of currupt descriptors */ - if (lpos > hpos) - temp = 0; - else - temp = hpos - lpos; - - /* check for ID byte */ - if (any_id) - temp += 8; - else if (id != NULL) - *id = 0; - - /* return length in bytes rounded up */ - return ((temp + 7) / 8); -} - -/*------------------------------------------------------------------------* - * hid_locate - *------------------------------------------------------------------------*/ -int -hid_locate(const void *desc, usb_size_t size, int32_t u, enum hid_kind k, - uint8_t index, struct hid_location *loc, uint32_t *flags, uint8_t *id) -{ - struct hid_data *d; - struct hid_item h; - int i; - - for (d = hid_start_parse(desc, size, 1 << k); hid_get_item(d, &h);) { - for (i = 0; i < h.nusages; i++) { - if (h.kind == k && h.usages[i] == u) { - if (index--) - break; - if (loc != NULL) - *loc = h.loc; - if (flags != NULL) - *flags = h.flags; - if (id != NULL) - *id = h.report_ID; - hid_end_parse(d); - return (1); - } - } - } - if (loc != NULL) - loc->size = 0; - if (flags != NULL) - *flags = 0; - if (id != NULL) - *id = 0; - hid_end_parse(d); - return (0); -} - -/*------------------------------------------------------------------------* - * hid_get_data - *------------------------------------------------------------------------*/ -static uint32_t -hid_get_data_sub(const uint8_t *buf, usb_size_t len, struct hid_location *loc, - int is_signed) -{ - uint32_t hpos = loc->pos; - uint32_t hsize = loc->size; - uint32_t data; - uint32_t rpos; - uint8_t n; - - DPRINTFN(11, "hid_get_data: loc %d/%d\n", hpos, hsize); - - /* Range check and limit */ - if (hsize == 0) - return (0); - if (hsize > 32) - hsize = 32; - - /* Get data in a safe way */ - data = 0; - rpos = (hpos / 8); - n = (hsize + 7) / 8; - rpos += n; - while (n--) { - rpos--; - if (rpos < len) - data |= buf[rpos] << (8 * n); - } - - /* Correctly shift down data */ - data = (data >> (hpos % 8)); - n = 32 - hsize; - - /* Mask and sign extend in one */ - if (is_signed != 0) - data = (int32_t)((int32_t)data << n) >> n; - else - data = (uint32_t)((uint32_t)data << n) >> n; - - DPRINTFN(11, "hid_get_data: loc %d/%d = %lu\n", - loc->pos, loc->size, (long)data); - return (data); -} - -int32_t -hid_get_data(const uint8_t *buf, usb_size_t len, struct hid_location *loc) -{ - return (hid_get_data_sub(buf, len, loc, 1)); -} - -uint32_t -hid_get_data_unsigned(const uint8_t *buf, usb_size_t len, struct hid_location *loc) -{ - return (hid_get_data_sub(buf, len, loc, 0)); -} - -/*------------------------------------------------------------------------* - * hid_put_data - *------------------------------------------------------------------------*/ -void -hid_put_data_unsigned(uint8_t *buf, usb_size_t len, - struct hid_location *loc, unsigned int value) -{ - uint32_t hpos = loc->pos; - uint32_t hsize = loc->size; - uint64_t data; - uint64_t mask; - uint32_t rpos; - uint8_t n; - - DPRINTFN(11, "hid_put_data: loc %d/%d = %u\n", hpos, hsize, value); - - /* Range check and limit */ - if (hsize == 0) - return; - if (hsize > 32) - hsize = 32; - - /* Put data in a safe way */ - rpos = (hpos / 8); - n = (hsize + 7) / 8; - data = ((uint64_t)value) << (hpos % 8); - mask = ((1ULL << hsize) - 1ULL) << (hpos % 8); - rpos += n; - while (n--) { - rpos--; - if (rpos < len) { - buf[rpos] &= ~(mask >> (8 * n)); - buf[rpos] |= (data >> (8 * n)); - } - } -} - -/*------------------------------------------------------------------------* - * hid_is_collection - *------------------------------------------------------------------------*/ -int -hid_is_collection(const void *desc, usb_size_t size, int32_t usage) -{ - struct hid_data *hd; - struct hid_item hi; - int err; - - hd = hid_start_parse(desc, size, hid_input); - if (hd == NULL) - return (0); - - while ((err = hid_get_item(hd, &hi))) { - if (hi.kind == hid_collection && - hi.usage == usage) - break; - } - hid_end_parse(hd); - return (err); -} - /*------------------------------------------------------------------------* * hid_get_descriptor_from_usb * @@ -863,153 +152,3 @@ } return (USB_ERR_NORMAL_COMPLETION); } - -/*------------------------------------------------------------------------* - * calculate HID item resolution. unit/mm for distances, unit/rad for angles - *------------------------------------------------------------------------*/ -int32_t -hid_item_resolution(struct hid_item *hi) -{ - /* - * hid unit scaling table according to HID Usage Table Review - * Request 39 Tbl 17 http://www.usb.org/developers/hidpage/HUTRR39b.pdf - */ - static const int64_t scale[0x10][2] = { - [0x00] = { 1, 1 }, - [0x01] = { 1, 10 }, - [0x02] = { 1, 100 }, - [0x03] = { 1, 1000 }, - [0x04] = { 1, 10000 }, - [0x05] = { 1, 100000 }, - [0x06] = { 1, 1000000 }, - [0x07] = { 1, 10000000 }, - [0x08] = { 100000000, 1 }, - [0x09] = { 10000000, 1 }, - [0x0A] = { 1000000, 1 }, - [0x0B] = { 100000, 1 }, - [0x0C] = { 10000, 1 }, - [0x0D] = { 1000, 1 }, - [0x0E] = { 100, 1 }, - [0x0F] = { 10, 1 }, - }; - int64_t logical_size; - int64_t physical_size; - int64_t multiplier; - int64_t divisor; - int64_t resolution; - - switch (hi->unit) { - case HUM_CENTIMETER: - multiplier = 1; - divisor = 10; - break; - case HUM_INCH: - multiplier = 10; - divisor = 254; - break; - case HUM_RADIAN: - multiplier = 1; - divisor = 1; - break; - case HUM_DEGREE: - multiplier = 573; - divisor = 10; - break; - default: - return (0); - } - - if ((hi->logical_maximum <= hi->logical_minimum) || - (hi->physical_maximum <= hi->physical_minimum) || - (hi->unit_exponent < 0) || (hi->unit_exponent >= nitems(scale))) - return (0); - - logical_size = (int64_t)hi->logical_maximum - - (int64_t)hi->logical_minimum; - physical_size = (int64_t)hi->physical_maximum - - (int64_t)hi->physical_minimum; - /* Round to ceiling */ - resolution = logical_size * multiplier * scale[hi->unit_exponent][0] / - (physical_size * divisor * scale[hi->unit_exponent][1]); - - if (resolution > INT32_MAX) - return (0); - - return (resolution); -} - -/*------------------------------------------------------------------------* - * hid_is_mouse - * - * This function will decide if a USB descriptor belongs to a USB mouse. - * - * Return values: - * Zero: Not a USB mouse. - * Else: Is a USB mouse. - *------------------------------------------------------------------------*/ -int -hid_is_mouse(const void *d_ptr, uint16_t d_len) -{ - struct hid_data *hd; - struct hid_item hi; - int mdepth; - int found; - - hd = hid_start_parse(d_ptr, d_len, 1 << hid_input); - if (hd == NULL) - return (0); - - mdepth = 0; - found = 0; - - while (hid_get_item(hd, &hi)) { - switch (hi.kind) { - case hid_collection: - if (mdepth != 0) - mdepth++; - else if (hi.collection == 1 && - hi.usage == - HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)) - mdepth++; - break; - case hid_endcollection: - if (mdepth != 0) - mdepth--; - break; - case hid_input: - if (mdepth == 0) - break; - if (hi.usage == - HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) && - (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE) - found++; - if (hi.usage == - HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) && - (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE) - found++; - break; - default: - break; - } - } - hid_end_parse(hd); - return (found); -} - -/*------------------------------------------------------------------------* - * hid_is_keyboard - * - * This function will decide if a USB descriptor belongs to a USB keyboard. - * - * Return values: - * Zero: Not a USB keyboard. - * Else: Is a USB keyboard. - *------------------------------------------------------------------------*/ -int -hid_is_keyboard(const void *d_ptr, uint16_t d_len) -{ - if (hid_is_collection(d_ptr, d_len, - HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD))) - return (1); - return (0); -} diff --git a/sys/dev/usb/usbhid.h b/sys/dev/usb/usbhid.h --- a/sys/dev/usb/usbhid.h +++ b/sys/dev/usb/usbhid.h @@ -31,6 +31,8 @@ #ifndef _USB_HID_H_ #define _USB_HID_H_ +#include + #ifndef USB_GLOBAL_INCLUDE_FILE #include #endif @@ -61,224 +63,14 @@ #define USB_HID_DESCRIPTOR_SIZE(n) (9+((n)*3)) -/* Usage pages */ -#define HUP_UNDEFINED 0x0000 -#define HUP_GENERIC_DESKTOP 0x0001 -#define HUP_SIMULATION 0x0002 -#define HUP_VR_CONTROLS 0x0003 -#define HUP_SPORTS_CONTROLS 0x0004 -#define HUP_GAMING_CONTROLS 0x0005 -#define HUP_KEYBOARD 0x0007 -#define HUP_LEDS 0x0008 -#define HUP_BUTTON 0x0009 -#define HUP_ORDINALS 0x000a -#define HUP_TELEPHONY 0x000b -#define HUP_CONSUMER 0x000c -#define HUP_DIGITIZERS 0x000d -#define HUP_PHYSICAL_IFACE 0x000e -#define HUP_UNICODE 0x0010 -#define HUP_ALPHANUM_DISPLAY 0x0014 -#define HUP_MONITOR 0x0080 -#define HUP_MONITOR_ENUM_VAL 0x0081 -#define HUP_VESA_VC 0x0082 -#define HUP_VESA_CMD 0x0083 -#define HUP_POWER 0x0084 -#define HUP_BATTERY_SYSTEM 0x0085 -#define HUP_BARCODE_SCANNER 0x008b -#define HUP_SCALE 0x008c -#define HUP_CAMERA_CONTROL 0x0090 -#define HUP_ARCADE 0x0091 -#define HUP_MICROSOFT 0xff00 - -/* Usages, generic desktop */ -#define HUG_POINTER 0x0001 -#define HUG_MOUSE 0x0002 -#define HUG_JOYSTICK 0x0004 -#define HUG_GAME_PAD 0x0005 -#define HUG_KEYBOARD 0x0006 -#define HUG_KEYPAD 0x0007 -#define HUG_X 0x0030 -#define HUG_Y 0x0031 -#define HUG_Z 0x0032 -#define HUG_RX 0x0033 -#define HUG_RY 0x0034 -#define HUG_RZ 0x0035 -#define HUG_SLIDER 0x0036 -#define HUG_DIAL 0x0037 -#define HUG_WHEEL 0x0038 -#define HUG_HAT_SWITCH 0x0039 -#define HUG_COUNTED_BUFFER 0x003a -#define HUG_BYTE_COUNT 0x003b -#define HUG_MOTION_WAKEUP 0x003c -#define HUG_VX 0x0040 -#define HUG_VY 0x0041 -#define HUG_VZ 0x0042 -#define HUG_VBRX 0x0043 -#define HUG_VBRY 0x0044 -#define HUG_VBRZ 0x0045 -#define HUG_VNO 0x0046 -#define HUG_TWHEEL 0x0048 /* M$ Wireless Intellimouse Wheel */ -#define HUG_SYSTEM_CONTROL 0x0080 -#define HUG_SYSTEM_POWER_DOWN 0x0081 -#define HUG_SYSTEM_SLEEP 0x0082 -#define HUG_SYSTEM_WAKEUP 0x0083 -#define HUG_SYSTEM_CONTEXT_MENU 0x0084 -#define HUG_SYSTEM_MAIN_MENU 0x0085 -#define HUG_SYSTEM_APP_MENU 0x0086 -#define HUG_SYSTEM_MENU_HELP 0x0087 -#define HUG_SYSTEM_MENU_EXIT 0x0088 -#define HUG_SYSTEM_MENU_SELECT 0x0089 -#define HUG_SYSTEM_MENU_RIGHT 0x008a -#define HUG_SYSTEM_MENU_LEFT 0x008b -#define HUG_SYSTEM_MENU_UP 0x008c -#define HUG_SYSTEM_MENU_DOWN 0x008d -#define HUG_APPLE_EJECT 0x00b8 - -/* Usages Digitizers */ -#define HUD_UNDEFINED 0x0000 -#define HUD_DIGITIZER 0x0001 -#define HUD_PEN 0x0002 -#define HUD_TOUCHSCREEN 0x0004 -#define HUD_TOUCHPAD 0x0005 -#define HUD_CONFIG 0x000e -#define HUD_FINGER 0x0022 -#define HUD_TIP_PRESSURE 0x0030 -#define HUD_BARREL_PRESSURE 0x0031 -#define HUD_IN_RANGE 0x0032 -#define HUD_TOUCH 0x0033 -#define HUD_UNTOUCH 0x0034 -#define HUD_TAP 0x0035 -#define HUD_QUALITY 0x0036 -#define HUD_DATA_VALID 0x0037 -#define HUD_TRANSDUCER_INDEX 0x0038 -#define HUD_TABLET_FKEYS 0x0039 -#define HUD_PROGRAM_CHANGE_KEYS 0x003a -#define HUD_BATTERY_STRENGTH 0x003b -#define HUD_INVERT 0x003c -#define HUD_X_TILT 0x003d -#define HUD_Y_TILT 0x003e -#define HUD_AZIMUTH 0x003f -#define HUD_ALTITUDE 0x0040 -#define HUD_TWIST 0x0041 -#define HUD_TIP_SWITCH 0x0042 -#define HUD_SEC_TIP_SWITCH 0x0043 -#define HUD_BARREL_SWITCH 0x0044 -#define HUD_ERASER 0x0045 -#define HUD_TABLET_PICK 0x0046 -#define HUD_CONFIDENCE 0x0047 -#define HUD_WIDTH 0x0048 -#define HUD_HEIGHT 0x0049 -#define HUD_CONTACTID 0x0051 -#define HUD_INPUT_MODE 0x0052 -#define HUD_DEVICE_INDEX 0x0053 -#define HUD_CONTACTCOUNT 0x0054 -#define HUD_CONTACT_MAX 0x0055 -#define HUD_SCAN_TIME 0x0056 -#define HUD_SURFACE_SWITCH 0x0057 -#define HUD_BUTTONS_SWITCH 0x0058 -#define HUD_BUTTON_TYPE 0x0059 -#define HUD_LATENCY_MODE 0x0060 - -/* Usages, Consumer */ -#define HUC_AC_PAN 0x0238 - -#define HID_USAGE2(p,u) (((p) << 16) | (u)) - -#define UHID_INPUT_REPORT 0x01 -#define UHID_OUTPUT_REPORT 0x02 -#define UHID_FEATURE_REPORT 0x03 - -/* Bits in the input/output/feature items */ -#define HIO_CONST 0x001 -#define HIO_VARIABLE 0x002 -#define HIO_RELATIVE 0x004 -#define HIO_WRAP 0x008 -#define HIO_NONLINEAR 0x010 -#define HIO_NOPREF 0x020 -#define HIO_NULLSTATE 0x040 -#define HIO_VOLATILE 0x080 -#define HIO_BUFBYTES 0x100 - -/* Units of Measure */ -#define HUM_CENTIMETER 0x11 -#define HUM_RADIAN 0x12 -#define HUM_INCH 0x13 -#define HUM_DEGREE 0x14 - #if defined(_KERNEL) || defined(_STANDALONE) struct usb_config_descriptor; -#define HID_ITEM_MAXUSAGE 4 - -enum hid_kind { - hid_input, hid_output, hid_feature, hid_collection, hid_endcollection -}; - -struct hid_location { - uint32_t size; - uint32_t count; - uint32_t pos; -}; - -struct hid_item { - /* Global */ - int32_t _usage_page; - int32_t logical_minimum; - int32_t logical_maximum; - int32_t physical_minimum; - int32_t physical_maximum; - int32_t unit_exponent; - int32_t unit; - int32_t report_ID; - /* Local */ - int nusages; - union { - int32_t usage; - int32_t usages[HID_ITEM_MAXUSAGE]; - }; - int32_t usage_minimum; - int32_t usage_maximum; - int32_t designator_index; - int32_t designator_minimum; - int32_t designator_maximum; - int32_t string_index; - int32_t string_minimum; - int32_t string_maximum; - int32_t set_delimiter; - /* Misc */ - int32_t collection; - int collevel; - enum hid_kind kind; - uint32_t flags; - /* Location */ - struct hid_location loc; -}; - -/* prototypes from "usb_hid.c" */ - -struct hid_data *hid_start_parse(const void *d, usb_size_t len, int kindset); -void hid_end_parse(struct hid_data *s); -int hid_get_item(struct hid_data *s, struct hid_item *h); -int hid_report_size(const void *buf, usb_size_t len, enum hid_kind k, - uint8_t *id); -int hid_locate(const void *desc, usb_size_t size, int32_t usage, - enum hid_kind kind, uint8_t index, struct hid_location *loc, - uint32_t *flags, uint8_t *id); -int32_t hid_get_data(const uint8_t *buf, usb_size_t len, - struct hid_location *loc); -uint32_t hid_get_data_unsigned(const uint8_t *buf, usb_size_t len, - struct hid_location *loc); -void hid_put_data_unsigned(uint8_t *buf, usb_size_t len, - struct hid_location *loc, unsigned int value); -int hid_is_collection(const void *desc, usb_size_t size, int32_t usage); struct usb_hid_descriptor *hid_get_descriptor_from_usb( struct usb_config_descriptor *cd, struct usb_interface_descriptor *id); usb_error_t usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx, void **descp, uint16_t *sizep, struct malloc_type *mem, uint8_t iface_index); -int32_t hid_item_resolution(struct hid_item *hi); -int hid_is_mouse(const void *d_ptr, uint16_t d_len); -int hid_is_keyboard(const void *d_ptr, uint16_t d_len); #endif /* _KERNEL || _STANDALONE */ #endif /* _USB_HID_H_ */ diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -348,3 +348,6 @@ options EVDEV_SUPPORT # evdev support in legacy drivers device evdev # input event device support device uinput # install /dev/uinput cdev + +# HID support +device hid # Generic HID support diff --git a/sys/mips/conf/ERL b/sys/mips/conf/ERL --- a/sys/mips/conf/ERL +++ b/sys/mips/conf/ERL @@ -212,3 +212,6 @@ # PMC support #device hwpmc + +# HID support +device hid # Generic HID support diff --git a/sys/mips/conf/JZ4780 b/sys/mips/conf/JZ4780 --- a/sys/mips/conf/JZ4780 +++ b/sys/mips/conf/JZ4780 @@ -109,5 +109,8 @@ device umass # Disks/Mass storage - Requires scbus and da device ums # Mouse +# HID support +device hid # Generic HID support + # FDT support options FDT diff --git a/sys/mips/conf/OCTEON1 b/sys/mips/conf/OCTEON1 --- a/sys/mips/conf/OCTEON1 +++ b/sys/mips/conf/OCTEON1 @@ -237,3 +237,6 @@ # PMC support #device hwpmc + +# HID support +device hid # Generic HID support diff --git a/sys/modules/Makefile b/sys/modules/Makefile --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -129,6 +129,7 @@ ${_glxiic} \ ${_glxsb} \ gpio \ + hid \ hifn \ ${_hpt27xx} \ ${_hptiop} \ diff --git a/sys/modules/hid/Makefile b/sys/modules/hid/Makefile new file mode 100644 --- /dev/null +++ b/sys/modules/hid/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +SUBDIR = \ + hid + +.include diff --git a/sys/modules/hid/hid/Makefile b/sys/modules/hid/hid/Makefile new file mode 100644 --- /dev/null +++ b/sys/modules/hid/hid/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +.PATH: ${SRCTOP}/sys/dev/hid + +KMOD= hid +SRCS= hid.c +SRCS+= opt_usb.h + +.include diff --git a/sys/powerpc/conf/GENERIC b/sys/powerpc/conf/GENERIC --- a/sys/powerpc/conf/GENERIC +++ b/sys/powerpc/conf/GENERIC @@ -240,3 +240,5 @@ device virtio_scsi # VirtIO SCSI device device virtio_balloon # VirtIO Memory Balloon device +# HID support +device hid # Generic HID support diff --git a/sys/powerpc/conf/GENERIC64 b/sys/powerpc/conf/GENERIC64 --- a/sys/powerpc/conf/GENERIC64 +++ b/sys/powerpc/conf/GENERIC64 @@ -270,3 +270,5 @@ device virtio_scsi # VirtIO SCSI device device virtio_balloon # VirtIO Memory Balloon device +# HID support +device hid # Generic HID support diff --git a/sys/powerpc/conf/GENERIC64LE b/sys/powerpc/conf/GENERIC64LE --- a/sys/powerpc/conf/GENERIC64LE +++ b/sys/powerpc/conf/GENERIC64LE @@ -251,3 +251,5 @@ device virtio_scsi # VirtIO SCSI device device virtio_balloon # VirtIO Memory Balloon device +# HID support +device hid # Generic HID support diff --git a/sys/powerpc/conf/MPC85XX b/sys/powerpc/conf/MPC85XX --- a/sys/powerpc/conf/MPC85XX +++ b/sys/powerpc/conf/MPC85XX @@ -117,3 +117,6 @@ device videomode device vt device fbd + +# HID support +device hid # Generic HID support diff --git a/sys/powerpc/conf/MPC85XXSPE b/sys/powerpc/conf/MPC85XXSPE --- a/sys/powerpc/conf/MPC85XXSPE +++ b/sys/powerpc/conf/MPC85XXSPE @@ -118,3 +118,6 @@ device videomode device vt device fbd + +# HID support +device hid # Generic HID support diff --git a/sys/powerpc/conf/QORIQ64 b/sys/powerpc/conf/QORIQ64 --- a/sys/powerpc/conf/QORIQ64 +++ b/sys/powerpc/conf/QORIQ64 @@ -120,3 +120,6 @@ options KBD_INSTALL_CDEV device ukbd device ums + +# HID support +device hid # Generic HID support