git: b93f6bfca343 - main - hid: Port ukbd to HID and attach to build

Vladimir Kondratyev wulf at FreeBSD.org
Thu Jan 7 23:20:51 UTC 2021


The branch main has been updated by wulf:

URL: https://cgit.FreeBSD.org/src/commit/?id=b93f6bfca34363f9c285e3e027fbfd4032b02b64

commit b93f6bfca34363f9c285e3e027fbfd4032b02b64
Author:     Vladimir Kondratyev <wulf at FreeBSD.org>
AuthorDate: 2020-10-12 19:52:29 +0000
Commit:     Vladimir Kondratyev <wulf at 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 ***


More information about the dev-commits-src-all mailing list