Date: Thu, 7 Jan 2021 23:20:50 GMT From: Vladimir Kondratyev <wulf@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: b93f6bfca343 - main - hid: Port ukbd to HID and attach to build Message-ID: <202101072320.107NKo1o063115@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by wulf: URL: https://cgit.FreeBSD.org/src/commit/?id=b93f6bfca34363f9c285e3e027fbfd4032b02b64 commit b93f6bfca34363f9c285e3e027fbfd4032b02b64 Author: Vladimir Kondratyev <wulf@FreeBSD.org> AuthorDate: 2020-10-12 19:52:29 +0000 Commit: Vladimir Kondratyev <wulf@FreeBSD.org> CommitDate: 2021-01-07 23:18:43 +0000 hid: Port ukbd to HID and attach to build Reviewed by: hselasky Differential revision: https://reviews.freebsd.org/D27991 --- share/man/man4/Makefile | 1 + share/man/man4/hkbd.4 | 59 +- sys/conf/files | 3 +- sys/conf/options | 1 + sys/dev/hid/hkbd.c | 1354 ++++++++++++++++++----------------------- sys/modules/hid/Makefile | 1 + sys/modules/hid/hkbd/Makefile | 10 + 7 files changed, 628 insertions(+), 801 deletions(-) diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index c92c8f50545f..4fd816804062 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -183,6 +183,7 @@ MAN= aac.4 \ hidbus.4 \ hidquirk.4 \ hifn.4 \ + hkbd.4 \ hmt.4 \ hpet.4 \ ${_hpt27xx.4} \ diff --git a/share/man/man4/hkbd.4 b/share/man/man4/hkbd.4 index f443f51ce8e1..400bf1d989cd 100644 --- a/share/man/man4/hkbd.4 +++ b/share/man/man4/hkbd.4 @@ -24,37 +24,41 @@ .\" .\" $FreeBSD$ .\" -.Dd April 24, 2018 -.Dt UKBD 4 +.Dd September 12, 2020 +.Dt HKBD 4 .Os .Sh NAME -.Nm ukbd -.Nd USB keyboard driver +.Nm hkbd +.Nd HID keyboard driver .Sh SYNOPSIS To compile this driver into the kernel, place the following line in your kernel configuration file: .Bd -ragged -offset indent -.Cd "device ukbd" +.Cd "device hkbd" .Cd "device hid" -.Cd "device usb" +.Cd "device hidbus" +.Cd "device evdev" +.Cd "options EVDEV_SUPPORT" .Ed .Pp Alternatively, to load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent -ukbd_load="YES" +hkbd_load="YES" .Ed .Sh DESCRIPTION The .Nm -driver provides support for keyboards that attach to the USB port. -.Xr usb 4 +driver provides support for keyboards that attach to the HID transport +backend. +.Xr hid 4 , +.Xr hidbus 4 , and one of -.Xr uhci 4 +.Xr iichid 4 or -.Xr ohci 4 +.Xr usbhid 4 must be configured in the kernel as well. .Sh CONFIGURATION By default, the keyboard subsystem does not create the appropriate devices yet. @@ -63,12 +67,12 @@ config file: .Pp .Dl "options KBD_INSTALL_CDEV" .Pp -If both an AT keyboard USB keyboards are used at the same time, the +If both an AT keyboard HID keyboards are used at the same time, the AT keyboard will appear as .Pa kbd0 in .Pa /dev . -The USB keyboards will be +The HID keyboards will be .Pa kbd1 , kbd2 , etc. You can see some information about the keyboard with the following command: @@ -87,19 +91,19 @@ You can swap console keyboards by using the command .Pp .Dl "kbdcontrol -k /dev/kbd1" .Pp -From this point on, the first USB keyboard will be the keyboard +From this point on, the first HID keyboard will be the keyboard to be used by the console. .Pp -If you want to use a USB keyboard as your default and not use an AT keyboard at +If you want to use a HID keyboard as your default and not use an AT keyboard at all, you will have to remove the .Cd "device atkbd" line from the kernel configuration file. Because of the device initialization order, -the USB keyboard will be detected +the HID keyboard will be detected .Em after the console driver initializes itself and you have to explicitly tell the console -driver to use the existence of the USB keyboard. +driver to use the existence of the HID keyboard. This can be done in one of the following two ways. .Pp @@ -107,7 +111,7 @@ Run the following command as a part of system initialization: .Pp .Dl "kbdcontrol -k /dev/kbd0 < /dev/ttyv0 > /dev/null" .Pp -(Note that as the USB keyboard is the only keyboard, it is accessed as +(Note that as the HID keyboard is the only keyboard, it is accessed as .Pa /dev/kbd0 ) or otherwise tell the console driver to periodically look for a keyboard by setting a flag in the kernel configuration file: @@ -123,8 +127,8 @@ initialized at boot time. Make the keyboards available through a character device in .Pa /dev . .Pp -.D1 Cd options UKBD_DFLT_KEYMAP -.D1 Cd makeoptions UKBD_DFLT_KEYMAP=fr.iso +.D1 Cd options HKBD_DFLT_KEYMAP +.D1 Cd makeoptions HKBD_DFLT_KEYMAP=fr.iso .Pp The above lines will put the French ISO keymap in the ukbd driver. You can specify any keymap in @@ -145,28 +149,31 @@ variables and .Xr loader 8 tunables: .Bl -tag -width indent -.It Va hw.usb.ukbd.debug +.It Va hw.hid.hkbd.debug Debug output level, where 0 is debugging disabled and larger values increase debug message verbosity. Default is 0. .El .Sh FILES -.Bl -tag -width ".Pa /dev/kbd*" -compact +.Bl -tag -width ".Pa /dev/input/event*" -compact .It Pa /dev/kbd* blocking device nodes +.It Pa /dev/input/event* +input event device nodes. .El .Sh EXAMPLES -.D1 Cd "device ukbd" +.D1 Cd "device hkbd" .Pp Add the .Nm driver to the kernel. .Sh SEE ALSO .Xr kbdcontrol 1 , -.Xr ohci 4 , +.Xr hid 4 , +.Xr hidbus 4 , +.Xr iichid 4 , .Xr syscons 4 , -.Xr uhci 4 , -.Xr usb 4 , +.Xr usbhid 4 , .Xr vt 4 , .Xr config 8 .Sh AUTHORS diff --git a/sys/conf/files b/sys/conf/files index 13dd93d9d2cd..71d78778d500 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1820,6 +1820,7 @@ dev/hid/hid.c optional hid dev/hid/hid_if.m optional hid dev/hid/hidbus.c optional hidbus dev/hid/hidquirk.c optional hid +dev/hid/hkbd.c optional hkbd dev/hid/hmt.c optional hmt hconf dev/hifn/hifn7751.c optional hifn dev/hptiop/hptiop.c optional hptiop scbus @@ -2327,7 +2328,7 @@ dev/ixgbe/ixgbe_dcb_82599.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/jedec_dimm/jedec_dimm.c optional jedec_dimm smbus dev/jme/if_jme.c optional jme pci -dev/kbd/kbd.c optional atkbd | pckbd | sc | ukbd | vt +dev/kbd/kbd.c optional atkbd | pckbd | sc | ukbd | vt | hkbd dev/kbdmux/kbdmux.c optional kbdmux dev/ksyms/ksyms.c optional ksyms dev/le/am7990.c optional le diff --git a/sys/conf/options b/sys/conf/options index 48b7f362a80a..789def58cb48 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -1019,3 +1019,4 @@ LINDEBUGFS HID_DEBUG opt_hid.h IICHID_DEBUG opt_hid.h IICHID_SAMPLING opt_hid.h +HKBD_DFLT_KEYMAP opt_hkbd.h diff --git a/sys/dev/hid/hkbd.c b/sys/dev/hid/hkbd.c index 0edacbefcbfc..321a51734664 100644 --- a/sys/dev/hid/hkbd.c +++ b/sys/dev/hid/hkbd.c @@ -39,7 +39,7 @@ __FBSDID("$FreeBSD$"); */ #include "opt_kbd.h" -#include "opt_ukbd.h" +#include "opt_hkbd.h" #include "opt_evdev.h" #include <sys/stdint.h> @@ -61,18 +61,14 @@ __FBSDID("$FreeBSD$"); #include <sys/malloc.h> #include <sys/priv.h> #include <sys/proc.h> +#include <sys/kdb.h> +#include <sys/epoch.h> +#define HID_DEBUG_VAR hkbd_debug #include <dev/hid/hid.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbhid.h> - -#define USB_DEBUG_VAR ukbd_debug -#include <dev/usb/usb_debug.h> - -#include <dev/usb/quirk/usb_quirk.h> +#include <dev/hid/hidbus.h> +#include <dev/hid/hidquirk.h> +#include <dev/hid/hidrdesc.h> #ifdef EVDEV_SUPPORT #include <dev/evdev/input.h> @@ -86,7 +82,7 @@ __FBSDID("$FreeBSD$"); #include <dev/kbd/kbdreg.h> /* the initial key map, accent map and fkey strings */ -#if defined(UKBD_DFLT_KEYMAP) && !defined(KLD_MODULE) +#if defined(HKBD_DFLT_KEYMAP) && !defined(KLD_MODULE) #define KBD_DFLT_KEYMAP #include "ukbdmap.h" #endif @@ -94,67 +90,60 @@ __FBSDID("$FreeBSD$"); /* the following file must be included after "ukbdmap.h" */ #include <dev/kbd/kbdtables.h> -#ifdef USB_DEBUG -static int ukbd_debug = 0; -static int ukbd_no_leds = 0; -static int ukbd_pollrate = 0; - -static SYSCTL_NODE(_hw_usb, OID_AUTO, ukbd, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, - "USB keyboard"); -SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, debug, CTLFLAG_RWTUN, - &ukbd_debug, 0, "Debug level"); -SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, no_leds, CTLFLAG_RWTUN, - &ukbd_no_leds, 0, "Disables setting of keyboard leds"); -SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, pollrate, CTLFLAG_RWTUN, - &ukbd_pollrate, 0, "Force this polling rate, 1-1000Hz"); +#ifdef HID_DEBUG +static int hkbd_debug = 0; +static int hkbd_no_leds = 0; + +static SYSCTL_NODE(_hw_hid, OID_AUTO, hkbd, CTLFLAG_RW, 0, "USB keyboard"); +SYSCTL_INT(_hw_hid_hkbd, OID_AUTO, debug, CTLFLAG_RWTUN, + &hkbd_debug, 0, "Debug level"); +SYSCTL_INT(_hw_hid_hkbd, OID_AUTO, no_leds, CTLFLAG_RWTUN, + &hkbd_no_leds, 0, "Disables setting of keyboard leds"); #endif -#define UKBD_EMULATE_ATSCANCODE 1 -#define UKBD_DRIVER_NAME "ukbd" -#define UKBD_NKEYCODE 256 /* units */ -#define UKBD_IN_BUF_SIZE (4 * UKBD_NKEYCODE) /* scancodes */ -#define UKBD_IN_BUF_FULL ((UKBD_IN_BUF_SIZE / 2) - 1) /* scancodes */ -#define UKBD_NFKEY (sizeof(fkey_tab)/sizeof(fkey_tab[0])) /* units */ -#define UKBD_BUFFER_SIZE 64 /* bytes */ -#define UKBD_KEY_PRESSED(map, key) ({ \ - CTASSERT((key) >= 0 && (key) < UKBD_NKEYCODE); \ +#define INPUT_EPOCH global_epoch_preempt + +#define HKBD_EMULATE_ATSCANCODE 1 +#define HKBD_DRIVER_NAME "hkbd" +#define HKBD_NKEYCODE 256 /* units */ +#define HKBD_IN_BUF_SIZE (4 * HKBD_NKEYCODE) /* scancodes */ +#define HKBD_IN_BUF_FULL ((HKBD_IN_BUF_SIZE / 2) - 1) /* scancodes */ +#define HKBD_NFKEY (sizeof(fkey_tab)/sizeof(fkey_tab[0])) /* units */ +#define HKBD_BUFFER_SIZE 64 /* bytes */ +#define HKBD_KEY_PRESSED(map, key) ({ \ + CTASSERT((key) >= 0 && (key) < HKBD_NKEYCODE); \ ((map)[(key) / 64] & (1ULL << ((key) % 64))); \ }) #define MOD_EJECT 0x01 #define MOD_FN 0x02 -struct ukbd_data { - uint64_t bitmap[howmany(UKBD_NKEYCODE, 64)]; -}; +#define MOD_MIN 0xe0 +#define MOD_MAX 0xe7 -enum { - UKBD_INTR_DT_0, - UKBD_INTR_DT_1, - UKBD_CTRL_LED, - UKBD_N_TRANSFER, +struct hkbd_data { + uint64_t bitmap[howmany(HKBD_NKEYCODE, 64)]; }; -struct ukbd_softc { +struct hkbd_softc { + device_t sc_dev; + keyboard_t sc_kbd; keymap_t sc_keymap; accentmap_t sc_accmap; - fkeytab_t sc_fkeymap[UKBD_NFKEY]; - uint64_t sc_loc_key_valid[howmany(UKBD_NKEYCODE, 64)]; + fkeytab_t sc_fkeymap[HKBD_NFKEY]; + uint64_t sc_loc_key_valid[howmany(HKBD_NKEYCODE, 64)]; struct hid_location sc_loc_apple_eject; struct hid_location sc_loc_apple_fn; - struct hid_location sc_loc_key[UKBD_NKEYCODE]; + struct hid_location sc_loc_key[HKBD_NKEYCODE]; struct hid_location sc_loc_numlock; struct hid_location sc_loc_capslock; struct hid_location sc_loc_scrolllock; - struct usb_callout sc_callout; - struct ukbd_data sc_ndata; - struct ukbd_data sc_odata; + struct callout sc_callout; + struct hkbd_data sc_ndata; + struct hkbd_data sc_odata; struct thread *sc_poll_thread; - struct usb_device *sc_udev; - struct usb_interface *sc_iface; - struct usb_xfer *sc_xfer[UKBD_N_TRANSFER]; #ifdef EVDEV_SUPPORT struct evdev_dev *sc_evdev; #endif @@ -162,26 +151,25 @@ struct ukbd_softc { sbintime_t sc_co_basetime; int sc_delay; uint32_t sc_repeat_time; - uint32_t sc_input[UKBD_IN_BUF_SIZE]; /* input buffer */ + uint32_t sc_input[HKBD_IN_BUF_SIZE]; /* input buffer */ uint32_t sc_time_ms; uint32_t sc_composed_char; /* composed char code, if non-zero */ -#ifdef UKBD_EMULATE_ATSCANCODE +#ifdef HKBD_EMULATE_ATSCANCODE uint32_t sc_buffered_char[2]; #endif uint32_t sc_flags; /* flags */ -#define UKBD_FLAG_COMPOSE 0x00000001 -#define UKBD_FLAG_POLLING 0x00000002 -#define UKBD_FLAG_SET_LEDS 0x00000004 -#define UKBD_FLAG_ATTACHED 0x00000010 -#define UKBD_FLAG_GONE 0x00000020 - -#define UKBD_FLAG_HID_MASK 0x003fffc0 -#define UKBD_FLAG_APPLE_EJECT 0x00000040 -#define UKBD_FLAG_APPLE_FN 0x00000080 -#define UKBD_FLAG_APPLE_SWAP 0x00000100 -#define UKBD_FLAG_NUMLOCK 0x00080000 -#define UKBD_FLAG_CAPSLOCK 0x00100000 -#define UKBD_FLAG_SCROLLLOCK 0x00200000 +#define HKBD_FLAG_COMPOSE 0x00000001 +#define HKBD_FLAG_POLLING 0x00000002 +#define HKBD_FLAG_ATTACHED 0x00000010 +#define HKBD_FLAG_GONE 0x00000020 + +#define HKBD_FLAG_HID_MASK 0x003fffc0 +#define HKBD_FLAG_APPLE_EJECT 0x00000040 +#define HKBD_FLAG_APPLE_FN 0x00000080 +#define HKBD_FLAG_APPLE_SWAP 0x00000100 +#define HKBD_FLAG_NUMLOCK 0x00080000 +#define HKBD_FLAG_CAPSLOCK 0x00100000 +#define HKBD_FLAG_SCROLLLOCK 0x00200000 int sc_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */ int sc_state; /* shift/lock key state */ @@ -194,19 +182,16 @@ struct ukbd_softc { uint16_t sc_inputhead; uint16_t sc_inputtail; - uint8_t sc_leds; /* store for async led requests */ uint8_t sc_iface_index; uint8_t sc_iface_no; uint8_t sc_id_apple_eject; uint8_t sc_id_apple_fn; - uint8_t sc_id_loc_key[UKBD_NKEYCODE]; - uint8_t sc_id_numlock; - uint8_t sc_id_capslock; - uint8_t sc_id_scrolllock; + uint8_t sc_id_loc_key[HKBD_NKEYCODE]; + uint8_t sc_id_leds; uint8_t sc_kbd_id; uint8_t sc_repeat_key; - uint8_t sc_buffer[UKBD_BUFFER_SIZE]; + uint8_t sc_buffer[HKBD_BUFFER_SIZE]; }; #define KEY_NONE 0x00 @@ -226,9 +211,18 @@ struct ukbd_softc { SCAN_PREFIX_CTL | SCAN_PREFIX_SHIFT) #define SCAN_CHAR(c) ((c) & 0x7f) -#define UKBD_LOCK() USB_MTX_LOCK(&Giant) -#define UKBD_UNLOCK() USB_MTX_UNLOCK(&Giant) -#define UKBD_LOCK_ASSERT() USB_MTX_ASSERT(&Giant, MA_OWNED) +#define HKBD_LOCK() do { \ + if (!HID_IN_POLLING_MODE()) \ + mtx_lock(&Giant); \ +} while (0) +#define HKBD_UNLOCK() do { \ + if (!HID_IN_POLLING_MODE()) \ + mtx_unlock(&Giant); \ +} while (0) +#define HKBD_LOCK_ASSERT() do { \ + if (!HID_IN_POLLING_MODE()) \ + mtx_assert(&Giant, MA_OWNED); \ +} while (0) #define NN 0 /* no translation */ /* @@ -247,7 +241,7 @@ struct ukbd_softc { * 0x90: Kana * 0x91: Eisu */ -static const uint8_t ukbd_trtab[256] = { +static const uint8_t hkbd_trtab[256] = { 0, 0, 0, 0, 30, 48, 46, 32, /* 00 - 07 */ 18, 33, 34, 35, 23, 36, 37, 38, /* 08 - 0F */ 50, 49, 24, 25, 16, 19, 31, 20, /* 10 - 17 */ @@ -282,82 +276,68 @@ static const uint8_t ukbd_trtab[256] = { NN, NN, NN, NN, NN, NN, NN, NN, /* F8 - FF */ }; -static const uint8_t ukbd_boot_desc[] = { - 0x05, 0x01, 0x09, 0x06, 0xa1, - 0x01, 0x05, 0x07, 0x19, 0xe0, - 0x29, 0xe7, 0x15, 0x00, 0x25, - 0x01, 0x75, 0x01, 0x95, 0x08, - 0x81, 0x02, 0x95, 0x01, 0x75, - 0x08, 0x81, 0x01, 0x95, 0x03, - 0x75, 0x01, 0x05, 0x08, 0x19, - 0x01, 0x29, 0x03, 0x91, 0x02, - 0x95, 0x05, 0x75, 0x01, 0x91, - 0x01, 0x95, 0x06, 0x75, 0x08, - 0x15, 0x00, 0x26, 0xff, 0x00, - 0x05, 0x07, 0x19, 0x00, 0x2a, - 0xff, 0x00, 0x81, 0x00, 0xc0 -}; +static const uint8_t hkbd_boot_desc[] = { HID_KBD_BOOTPROTO_DESCR() }; /* prototypes */ -static void ukbd_timeout(void *); -static void ukbd_set_leds(struct ukbd_softc *, uint8_t); -static int ukbd_set_typematic(keyboard_t *, int); -#ifdef UKBD_EMULATE_ATSCANCODE -static uint32_t ukbd_atkeycode(int, const uint64_t *); -static int ukbd_key2scan(struct ukbd_softc *, int, const uint64_t *, int); +static void hkbd_timeout(void *); +static int hkbd_set_leds(struct hkbd_softc *, uint8_t); +static int hkbd_set_typematic(keyboard_t *, int); +#ifdef HKBD_EMULATE_ATSCANCODE +static uint32_t hkbd_atkeycode(int, const uint64_t *); +static int hkbd_key2scan(struct hkbd_softc *, int, const uint64_t *, int); #endif -static uint32_t ukbd_read_char(keyboard_t *, int); -static void ukbd_clear_state(keyboard_t *); -static int ukbd_ioctl(keyboard_t *, u_long, caddr_t); -static int ukbd_enable(keyboard_t *); -static int ukbd_disable(keyboard_t *); -static void ukbd_interrupt(struct ukbd_softc *); -static void ukbd_event_keyinput(struct ukbd_softc *); - -static device_probe_t ukbd_probe; -static device_attach_t ukbd_attach; -static device_detach_t ukbd_detach; -static device_resume_t ukbd_resume; +static uint32_t hkbd_read_char(keyboard_t *, int); +static void hkbd_clear_state(keyboard_t *); +static int hkbd_ioctl(keyboard_t *, u_long, caddr_t); +static int hkbd_enable(keyboard_t *); +static int hkbd_disable(keyboard_t *); +static void hkbd_interrupt(struct hkbd_softc *); +static void hkbd_event_keyinput(struct hkbd_softc *); + +static device_probe_t hkbd_probe; +static device_attach_t hkbd_attach; +static device_detach_t hkbd_detach; +static device_resume_t hkbd_resume; #ifdef EVDEV_SUPPORT -static evdev_event_t ukbd_ev_event; +static evdev_event_t hkbd_ev_event; -static const struct evdev_methods ukbd_evdev_methods = { - .ev_event = ukbd_ev_event, +static const struct evdev_methods hkbd_evdev_methods = { + .ev_event = hkbd_ev_event, }; #endif static bool -ukbd_any_key_pressed(struct ukbd_softc *sc) +hkbd_any_key_pressed(struct hkbd_softc *sc) { bool ret = false; unsigned i; - for (i = 0; i != howmany(UKBD_NKEYCODE, 64); i++) + for (i = 0; i != howmany(HKBD_NKEYCODE, 64); i++) ret |= (sc->sc_odata.bitmap[i] != 0); return (ret); } static bool -ukbd_any_key_valid(struct ukbd_softc *sc) +hkbd_any_key_valid(struct hkbd_softc *sc) { bool ret = false; unsigned i; - for (i = 0; i != howmany(UKBD_NKEYCODE, 64); i++) + for (i = 0; i != howmany(HKBD_NKEYCODE, 64); i++) ret |= (sc->sc_loc_key_valid[i] != 0); return (ret); } static bool -ukbd_is_modifier_key(uint32_t key) +hkbd_is_modifier_key(uint32_t key) { - return (key >= 0xe0 && key <= 0xe7); + return (key >= MOD_MIN && key <= MOD_MAX); } static void -ukbd_start_timer(struct ukbd_softc *sc) +hkbd_start_timer(struct hkbd_softc *sc) { sbintime_t delay, now, prec; @@ -377,15 +357,16 @@ ukbd_start_timer(struct ukbd_softc *sc) /* This is rarely called, so prefer precision to efficiency. */ prec = qmin(delay >> 7, SBT_1MS * 10); - usb_callout_reset_sbt(&sc->sc_callout, sc->sc_co_basetime, prec, - ukbd_timeout, sc, C_ABSOLUTE); + if (!HID_IN_POLLING_MODE()) + callout_reset_sbt(&sc->sc_callout, sc->sc_co_basetime, prec, + hkbd_timeout, sc, C_ABSOLUTE); } static void -ukbd_put_key(struct ukbd_softc *sc, uint32_t key) +hkbd_put_key(struct hkbd_softc *sc, uint32_t key) { - UKBD_LOCK_ASSERT(); + HKBD_LOCK_ASSERT(); DPRINTF("0x%02x (%d) %s\n", key, key, (key & KEY_RELEASE) ? "released" : "pressed"); @@ -396,11 +377,11 @@ ukbd_put_key(struct ukbd_softc *sc, uint32_t key) evdev_hid2key(KEY_INDEX(key)), !(key & KEY_RELEASE)); #endif - if (sc->sc_inputs < UKBD_IN_BUF_SIZE) { + if (sc->sc_inputs < HKBD_IN_BUF_SIZE) { sc->sc_input[sc->sc_inputtail] = key; ++(sc->sc_inputs); ++(sc->sc_inputtail); - if (sc->sc_inputtail >= UKBD_IN_BUF_SIZE) { + if (sc->sc_inputtail >= HKBD_IN_BUF_SIZE) { sc->sc_inputtail = 0; } } else { @@ -409,15 +390,15 @@ ukbd_put_key(struct ukbd_softc *sc, uint32_t key) } static void -ukbd_do_poll(struct ukbd_softc *sc, uint8_t wait) +hkbd_do_poll(struct hkbd_softc *sc, uint8_t wait) { - UKBD_LOCK_ASSERT(); - KASSERT((sc->sc_flags & UKBD_FLAG_POLLING) != 0, - ("ukbd_do_poll called when not polling\n")); + HKBD_LOCK_ASSERT(); + KASSERT((sc->sc_flags & HKBD_FLAG_POLLING) != 0, + ("hkbd_do_poll called when not polling\n")); DPRINTFN(2, "polling\n"); - if (USB_IN_POLLING_MODE_FUNC() == 0) { + if (!HID_IN_POLLING_MODE()) { /* * In this context the kernel is polling for input, * but the USB subsystem works in normal interrupt-driven @@ -438,10 +419,10 @@ ukbd_do_poll(struct ukbd_softc *sc, uint8_t wait) } while (sc->sc_inputs == 0) { - usbd_transfer_poll(sc->sc_xfer, UKBD_N_TRANSFER); + hidbus_intr_poll(sc->sc_dev); /* Delay-optimised support for repetition of keys */ - if (ukbd_any_key_pressed(sc)) { + if (hkbd_any_key_pressed(sc)) { /* a key is pressed - need timekeeping */ DELAY(1000); @@ -449,7 +430,7 @@ ukbd_do_poll(struct ukbd_softc *sc, uint8_t wait) sc->sc_time_ms += 1; } - ukbd_interrupt(sc); + hkbd_interrupt(sc); if (!wait) break; @@ -457,24 +438,17 @@ ukbd_do_poll(struct ukbd_softc *sc, uint8_t wait) } static int32_t -ukbd_get_key(struct ukbd_softc *sc, uint8_t wait) +hkbd_get_key(struct hkbd_softc *sc, uint8_t wait) { int32_t c; - UKBD_LOCK_ASSERT(); - KASSERT((USB_IN_POLLING_MODE_FUNC() == 0) || - (sc->sc_flags & UKBD_FLAG_POLLING) != 0, + HKBD_LOCK_ASSERT(); + KASSERT(!HID_IN_POLLING_MODE() || + (sc->sc_flags & HKBD_FLAG_POLLING) != 0, ("not polling in kdb or panic\n")); - if (sc->sc_inputs == 0 && - (sc->sc_flags & UKBD_FLAG_GONE) == 0) { - /* start transfer, if not already started */ - usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT_0]); - usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT_1]); - } - - if (sc->sc_flags & UKBD_FLAG_POLLING) - ukbd_do_poll(sc, wait); + if (sc->sc_flags & HKBD_FLAG_POLLING) + hkbd_do_poll(sc, wait); if (sc->sc_inputs == 0) { c = -1; @@ -482,7 +456,7 @@ ukbd_get_key(struct ukbd_softc *sc, uint8_t wait) c = sc->sc_input[sc->sc_inputhead]; --(sc->sc_inputs); ++(sc->sc_inputhead); - if (sc->sc_inputhead >= UKBD_IN_BUF_SIZE) { + if (sc->sc_inputhead >= HKBD_IN_BUF_SIZE) { sc->sc_inputhead = 0; } } @@ -490,53 +464,54 @@ ukbd_get_key(struct ukbd_softc *sc, uint8_t wait) } static void -ukbd_interrupt(struct ukbd_softc *sc) +hkbd_interrupt(struct hkbd_softc *sc) { const uint32_t now = sc->sc_time_ms; unsigned key; - UKBD_LOCK_ASSERT(); + HKBD_LOCK_ASSERT(); - /* Check for modifier key changes first */ - for (key = 0xe0; key != 0xe8; key++) { + /* Check for key changes, the order is: + * 1. Modifier keys down + * 2. Regular keys up/down + * 3. Modifier keys up + * + * This allows devices which send events changing the state of + * both a modifier key and a regular key, to be correctly + * translated. */ + for (key = MOD_MIN; key <= MOD_MAX; key++) { const uint64_t mask = 1ULL << (key % 64); - const uint64_t delta = - sc->sc_odata.bitmap[key / 64] ^ - sc->sc_ndata.bitmap[key / 64]; - if (delta & mask) { - if (sc->sc_odata.bitmap[key / 64] & mask) - ukbd_put_key(sc, key | KEY_RELEASE); - else - ukbd_put_key(sc, key | KEY_PRESS); + if (!(sc->sc_odata.bitmap[key / 64] & mask) && + (sc->sc_ndata.bitmap[key / 64] & mask)) { + hkbd_put_key(sc, key | KEY_PRESS); } } - - /* Check for key changes */ - for (key = 0; key != UKBD_NKEYCODE; key++) { + for (key = 0; key != HKBD_NKEYCODE; key++) { const uint64_t mask = 1ULL << (key % 64); const uint64_t delta = sc->sc_odata.bitmap[key / 64] ^ sc->sc_ndata.bitmap[key / 64]; + if (hkbd_is_modifier_key(key)) + continue; + if (mask == 1 && delta == 0) { key += 63; continue; /* skip empty areas */ - } else if (ukbd_is_modifier_key(key)) { - continue; } else if (delta & mask) { if (sc->sc_odata.bitmap[key / 64] & mask) { - ukbd_put_key(sc, key | KEY_RELEASE); + hkbd_put_key(sc, key | KEY_RELEASE); /* clear repeating key, if any */ if (sc->sc_repeat_key == key) sc->sc_repeat_key = 0; } else { - ukbd_put_key(sc, key | KEY_PRESS); + hkbd_put_key(sc, key | KEY_PRESS); sc->sc_co_basetime = sbinuptime(); sc->sc_delay = sc->sc_kbd.kb_delay1; - ukbd_start_timer(sc); + hkbd_start_timer(sc); /* set repeat time for last key */ sc->sc_repeat_time = now + sc->sc_kbd.kb_delay1; @@ -544,6 +519,14 @@ ukbd_interrupt(struct ukbd_softc *sc) } } } + for (key = MOD_MIN; key <= MOD_MAX; key++) { + const uint64_t mask = 1ULL << (key % 64); + + if ((sc->sc_odata.bitmap[key / 64] & mask) && + !(sc->sc_ndata.bitmap[key / 64] & mask)) { + hkbd_put_key(sc, key | KEY_RELEASE); + } + } /* synchronize old data with new data */ sc->sc_odata = sc->sc_ndata; @@ -554,7 +537,7 @@ ukbd_interrupt(struct ukbd_softc *sc) /* check if time has elapsed */ if (dtime <= 0) { - ukbd_put_key(sc, sc->sc_repeat_key | KEY_PRESS); + hkbd_put_key(sc, sc->sc_repeat_key | KEY_PRESS); sc->sc_repeat_time = now + sc->sc_kbd.kb_delay2; } } @@ -565,17 +548,17 @@ ukbd_interrupt(struct ukbd_softc *sc) #endif /* wakeup keyboard system */ - ukbd_event_keyinput(sc); + hkbd_event_keyinput(sc); } static void -ukbd_event_keyinput(struct ukbd_softc *sc) +hkbd_event_keyinput(struct hkbd_softc *sc) { int c; - UKBD_LOCK_ASSERT(); + HKBD_LOCK_ASSERT(); - if ((sc->sc_flags & UKBD_FLAG_POLLING) != 0) + if ((sc->sc_flags & HKBD_FLAG_POLLING) != 0) return; if (sc->sc_inputs == 0) @@ -589,33 +572,36 @@ ukbd_event_keyinput(struct ukbd_softc *sc) } else { /* read and discard the input, no one is waiting for it */ do { - c = ukbd_read_char(&sc->sc_kbd, 0); + c = hkbd_read_char(&sc->sc_kbd, 0); } while (c != NOKEY); } } static void -ukbd_timeout(void *arg) +hkbd_timeout(void *arg) { - struct ukbd_softc *sc = arg; + struct hkbd_softc *sc = arg; + struct epoch_tracker et; - UKBD_LOCK_ASSERT(); + HKBD_LOCK_ASSERT(); sc->sc_time_ms += sc->sc_delay; sc->sc_delay = 0; - ukbd_interrupt(sc); + epoch_enter_preempt(INPUT_EPOCH, &et); + hkbd_interrupt(sc); + epoch_exit_preempt(INPUT_EPOCH, &et); /* Make sure any leftover key events gets read out */ - ukbd_event_keyinput(sc); + hkbd_event_keyinput(sc); - if (ukbd_any_key_pressed(sc) || (sc->sc_inputs != 0)) { - ukbd_start_timer(sc); + if (hkbd_any_key_pressed(sc) || (sc->sc_inputs != 0)) { + hkbd_start_timer(sc); } } static uint32_t -ukbd_apple_fn(uint32_t keycode) +hkbd_apple_fn(uint32_t keycode) { switch (keycode) { case 0x28: return 0x49; /* RETURN -> INSERT */ @@ -629,7 +615,7 @@ ukbd_apple_fn(uint32_t keycode) } static uint32_t -ukbd_apple_swap(uint32_t keycode) +hkbd_apple_swap(uint32_t keycode) { switch (keycode) { case 0x35: return 0x64; @@ -639,347 +625,141 @@ ukbd_apple_swap(uint32_t keycode) } static void -ukbd_intr_callback(struct usb_xfer *xfer, usb_error_t error) +hkbd_intr_callback(void *context, void *data, hid_size_t len) { - struct ukbd_softc *sc = usbd_xfer_softc(xfer); - struct usb_page_cache *pc; + struct hkbd_softc *sc = context; + uint8_t *buf = data; uint32_t i; - uint8_t id; + uint8_t id = 0; uint8_t modifiers; int offset; - int len; - UKBD_LOCK_ASSERT(); + HKBD_LOCK_ASSERT(); - usbd_xfer_status(xfer, &len, NULL, NULL, NULL); - pc = usbd_xfer_get_frame(xfer, 0); + DPRINTF("actlen=%d bytes\n", len); - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - DPRINTF("actlen=%d bytes\n", len); + if (len == 0) { + DPRINTF("zero length data\n"); + return; + } + if (sc->sc_kbd_id != 0) { + /* check and remove HID ID byte */ + id = buf[0]; + buf++; + len--; if (len == 0) { DPRINTF("zero length data\n"); - goto tr_setup; + return; } + } - if (sc->sc_kbd_id != 0) { - /* check and remove HID ID byte */ - usbd_copy_out(pc, 0, &id, 1); - offset = 1; - len--; - if (len == 0) { - DPRINTF("zero length data\n"); - goto tr_setup; - } - } else { - offset = 0; - id = 0; - } - - if (len > UKBD_BUFFER_SIZE) - len = UKBD_BUFFER_SIZE; - - /* get data */ - usbd_copy_out(pc, offset, sc->sc_buffer, len); - - /* clear temporary storage */ - memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata)); + /* clear temporary storage */ + memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata)); - /* clear modifiers */ - modifiers = 0; + /* clear modifiers */ + modifiers = 0; - /* scan through HID data */ - if ((sc->sc_flags & UKBD_FLAG_APPLE_EJECT) && - (id == sc->sc_id_apple_eject)) { - if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_apple_eject)) - modifiers |= MOD_EJECT; - } - if ((sc->sc_flags & UKBD_FLAG_APPLE_FN) && - (id == sc->sc_id_apple_fn)) { - if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_apple_fn)) - modifiers |= MOD_FN; - } + /* scan through HID data */ + if ((sc->sc_flags & HKBD_FLAG_APPLE_EJECT) && + (id == sc->sc_id_apple_eject)) { + if (hid_get_data(buf, len, &sc->sc_loc_apple_eject)) + modifiers |= MOD_EJECT; + } + if ((sc->sc_flags & HKBD_FLAG_APPLE_FN) && + (id == sc->sc_id_apple_fn)) { + if (hid_get_data(buf, len, &sc->sc_loc_apple_fn)) + modifiers |= MOD_FN; + } - for (i = 0; i != UKBD_NKEYCODE; i++) { - const uint64_t valid = sc->sc_loc_key_valid[i / 64]; - const uint64_t mask = 1ULL << (i % 64); - - if (mask == 1 && valid == 0) { - i += 63; - continue; /* skip empty areas */ - } else if (~valid & mask) { - continue; /* location is not valid */ - } else if (id != sc->sc_id_loc_key[i]) { - continue; /* invalid HID ID */ - } else if (i == 0) { - struct hid_location tmp_loc = sc->sc_loc_key[0]; - /* range check array size */ - if (tmp_loc.count > UKBD_NKEYCODE) - tmp_loc.count = UKBD_NKEYCODE; - while (tmp_loc.count--) { - uint32_t key = - hid_get_udata(sc->sc_buffer, len, &tmp_loc); - /* advance to next location */ *** 1579 LINES SKIPPED ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202101072320.107NKo1o063115>