Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 13 Feb 2020 13:34:12 +0100
From:      Hans Petter Selasky <hps@selasky.org>
To:        "Alex V. Petrov" <alexvpetrov@gmail.com>, freebsd-usb@freebsd.org
Subject:   Re: Trouble with keyboard
Message-ID:  <06d56f8a-c6b7-0f7d-fdf6-bd6dbdba06bc@selasky.org>
In-Reply-To: <0f6f9b99-f0a8-d81b-95d3-db680f717587@gmail.com>
References:  <b030e7c2-efcc-0ed9-6491-0fe27b5f3377@gmail.com> <78038dd6-2665-fd98-64f0-75b865d96ed0@selasky.org> <c036dcda-9267-577d-629c-ecbcdade9101@selasky.org> <0f6f9b99-f0a8-d81b-95d3-db680f717587@gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------EDB4A60D84EB4322555E10AA
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit

Hi,

Can you test the attached patch?

cd /usr/src
cat ukbd.diff | patch
make buildkernel
make installkernel

--HPS

--------------EDB4A60D84EB4322555E10AA
Content-Type: text/x-patch; charset=UTF-8;
 name="ukbd.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="ukbd.diff"

Index: sys/dev/usb/input/ukbd.c
===================================================================
--- sys/dev/usb/input/ukbd.c	(revision 357854)
+++ sys/dev/usb/input/ukbd.c	(working copy)
@@ -109,27 +109,19 @@
 
 #define	UKBD_EMULATE_ATSCANCODE	       1
 #define	UKBD_DRIVER_NAME          "ukbd"
-#define	UKBD_NMOD                     8	/* units */
-#define	UKBD_NKEYCODE                 6	/* units */
-#define	UKBD_IN_BUF_SIZE  (2*(UKBD_NMOD + (2*UKBD_NKEYCODE)))	/* bytes */
-#define	UKBD_IN_BUF_FULL  ((UKBD_IN_BUF_SIZE / 2) - 1)	/* bytes */
+#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) \
+	((map)[(key) / 64] & (1ULL << ((key) % 64)))
 
+#define	MOD_EJECT	0x01
+#define	MOD_FN		0x02
+
 struct ukbd_data {
-	uint16_t	modifiers;
-#define	MOD_CONTROL_L	0x01
-#define	MOD_CONTROL_R	0x10
-#define	MOD_SHIFT_L	0x02
-#define	MOD_SHIFT_R	0x20
-#define	MOD_ALT_L	0x04
-#define	MOD_ALT_R	0x40
-#define	MOD_WIN_L	0x08
-#define	MOD_WIN_R	0x80
-/* internal */
-#define	MOD_EJECT	0x0100
-#define	MOD_FN		0x0200
-	uint8_t	keycode[UKBD_NKEYCODE];
+	uint64_t bitmap[howmany(UKBD_NKEYCODE, 64)];
 };
 
 enum {
@@ -144,17 +136,10 @@
 	keymap_t sc_keymap;
 	accentmap_t sc_accmap;
 	fkeytab_t sc_fkeymap[UKBD_NFKEY];
+	uint64_t sc_loc_key_valid[howmany(UKBD_NKEYCODE, 64)];
 	struct hid_location sc_loc_apple_eject;
 	struct hid_location sc_loc_apple_fn;
-	struct hid_location sc_loc_ctrl_l;
-	struct hid_location sc_loc_ctrl_r;
-	struct hid_location sc_loc_shift_l;
-	struct hid_location sc_loc_shift_r;
-	struct hid_location sc_loc_alt_l;
-	struct hid_location sc_loc_alt_r;
-	struct hid_location sc_loc_win_l;
-	struct hid_location sc_loc_win_r;
-	struct hid_location sc_loc_events;
+	struct hid_location sc_loc_key[UKBD_NKEYCODE];
 	struct hid_location sc_loc_numlock;
 	struct hid_location sc_loc_capslock;
 	struct hid_location sc_loc_scrolllock;
@@ -172,8 +157,7 @@
 
 	sbintime_t sc_co_basetime;
 	int	sc_delay;
-	uint32_t sc_ntime[UKBD_NKEYCODE];
-	uint32_t sc_otime[UKBD_NKEYCODE];
+	uint32_t sc_repeat_time;
 	uint32_t sc_input[UKBD_IN_BUF_SIZE];	/* input buffer */
 	uint32_t sc_time_ms;
 	uint32_t sc_composed_char;	/* composed char code, if non-zero */
@@ -191,15 +175,6 @@
 #define	UKBD_FLAG_APPLE_EJECT	0x00000040
 #define	UKBD_FLAG_APPLE_FN	0x00000080
 #define	UKBD_FLAG_APPLE_SWAP	0x00000100
-#define	UKBD_FLAG_CTRL_L	0x00000400
-#define	UKBD_FLAG_CTRL_R	0x00000800
-#define	UKBD_FLAG_SHIFT_L	0x00001000
-#define	UKBD_FLAG_SHIFT_R	0x00002000
-#define	UKBD_FLAG_ALT_L		0x00004000
-#define	UKBD_FLAG_ALT_R		0x00008000
-#define	UKBD_FLAG_WIN_L		0x00010000
-#define	UKBD_FLAG_WIN_R		0x00020000
-#define	UKBD_FLAG_EVENTS	0x00040000
 #define	UKBD_FLAG_NUMLOCK	0x00080000
 #define	UKBD_FLAG_CAPSLOCK	0x00100000
 #define	UKBD_FLAG_SCROLLLOCK 	0x00200000
@@ -214,7 +189,6 @@
 	uint16_t sc_inputs;
 	uint16_t sc_inputhead;
 	uint16_t sc_inputtail;
-	uint16_t sc_modifiers;
 
 	uint8_t	sc_leds;		/* store for async led requests */
 	uint8_t	sc_iface_index;
@@ -221,24 +195,17 @@
 	uint8_t	sc_iface_no;
 	uint8_t sc_id_apple_eject;
 	uint8_t sc_id_apple_fn;
-	uint8_t sc_id_ctrl_l;
-	uint8_t sc_id_ctrl_r;
-	uint8_t sc_id_shift_l;
-	uint8_t sc_id_shift_r;
-	uint8_t sc_id_alt_l;
-	uint8_t sc_id_alt_r;
-	uint8_t sc_id_win_l;
-	uint8_t sc_id_win_r;
-	uint8_t sc_id_event;
+	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_events;
 	uint8_t sc_kbd_id;
+	uint8_t sc_repeat_key;
 
 	uint8_t sc_buffer[UKBD_BUFFER_SIZE];
 };
 
+#define	KEY_NONE	  0x00
 #define	KEY_ERROR	  0x01
 
 #define	KEY_PRESS	  0
@@ -259,22 +226,8 @@
 #define	UKBD_UNLOCK()	USB_MTX_UNLOCK(&Giant)
 #define	UKBD_LOCK_ASSERT()	USB_MTX_ASSERT(&Giant, MA_OWNED)
 
-struct ukbd_mods {
-	uint32_t mask, key;
-};
+#define	NN 0				/* no translation */
 
-static const struct ukbd_mods ukbd_mods[UKBD_NMOD] = {
-	{MOD_CONTROL_L, 0xe0},
-	{MOD_CONTROL_R, 0xe4},
-	{MOD_SHIFT_L, 0xe1},
-	{MOD_SHIFT_R, 0xe5},
-	{MOD_ALT_L, 0xe2},
-	{MOD_ALT_R, 0xe6},
-	{MOD_WIN_L, 0xe3},
-	{MOD_WIN_R, 0xe7},
-};
-
-#define	NN 0				/* no translation */
 /*
  * Translate USB keycodes to AT keyboard scancodes.
  */
@@ -347,8 +300,8 @@
 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, int);
-static int	ukbd_key2scan(struct ukbd_softc *, int, int, int);
+static uint32_t	ukbd_atkeycode(int, const uint64_t *);
+static int	ukbd_key2scan(struct ukbd_softc *, int, const uint64_t *, int);
 #endif
 static uint32_t	ukbd_read_char(keyboard_t *, int);
 static void	ukbd_clear_state(keyboard_t *);
@@ -371,16 +324,26 @@
 };
 #endif
 
-static uint8_t
+static bool
 ukbd_any_key_pressed(struct ukbd_softc *sc)
 {
-	uint8_t i;
-	uint8_t j;
+	bool ret = false;
+	unsigned i;
 
-	for (j = i = 0; i < UKBD_NKEYCODE; i++)
-		j |= sc->sc_odata.keycode[i];
+	for (i = 0; i != howmany(UKBD_NKEYCODE, 64); i++)
+		ret |= (sc->sc_odata.bitmap[i] != 0);
+	return (ret);
+}
 
-	return (j ? 1 : 0);
+static bool
+ukbd_any_key_valid(struct ukbd_softc *sc)
+{
+	bool ret = false;
+	unsigned i;
+
+	for (i = 0; i != howmany(UKBD_NKEYCODE, 64); i++)
+		ret |= (sc->sc_loc_key_valid[i] != 0);
+	return (ret);
 }
 
 static void
@@ -522,99 +485,64 @@
 static void
 ukbd_interrupt(struct ukbd_softc *sc)
 {
-	uint32_t n_mod;
-	uint32_t o_mod;
-	uint32_t now = sc->sc_time_ms;
-	int32_t dtime;
-	uint8_t key;
-	uint8_t i;
-	uint8_t j;
+	const uint32_t now = sc->sc_time_ms;
+	unsigned key;
+	bool old_keys;
 
 	UKBD_LOCK_ASSERT();
 
-	if (sc->sc_ndata.keycode[0] == KEY_ERROR)
-		return;
+	old_keys = ukbd_any_key_pressed(sc);
 
-	n_mod = sc->sc_ndata.modifiers;
-	o_mod = sc->sc_odata.modifiers;
-	if (n_mod != o_mod) {
-		for (i = 0; i < UKBD_NMOD; i++) {
-			if ((n_mod & ukbd_mods[i].mask) !=
-			    (o_mod & ukbd_mods[i].mask)) {
-				ukbd_put_key(sc, ukbd_mods[i].key |
-				    ((n_mod & ukbd_mods[i].mask) ?
-				    KEY_PRESS : KEY_RELEASE));
-			}
-		}
-	}
-	/* Check for released keys. */
-	for (i = 0; i < UKBD_NKEYCODE; i++) {
-		key = sc->sc_odata.keycode[i];
-		if (key == 0) {
-			continue;
-		}
-		for (j = 0; j < UKBD_NKEYCODE; j++) {
-			if (sc->sc_ndata.keycode[j] == 0) {
-				continue;
-			}
-			if (key == sc->sc_ndata.keycode[j]) {
-				goto rfound;
-			}
-		}
-		ukbd_put_key(sc, key | KEY_RELEASE);
-rfound:	;
-	}
+	/* Check for key changes */
+	for (key = 0; key < UKBD_NKEYCODE; key++) {
+		const uint64_t delta =
+		    sc->sc_odata.bitmap[key / 64] ^
+		    sc->sc_ndata.bitmap[key / 64];
+		const uint64_t mask =
+		    1ULL << (key % 64);
 
-	/* Check for pressed keys. */
-	for (i = 0; i < UKBD_NKEYCODE; i++) {
-		key = sc->sc_ndata.keycode[i];
-		if (key == 0) {
-			continue;
-		}
-		sc->sc_ntime[i] = now + sc->sc_kbd.kb_delay1;
-		for (j = 0; j < UKBD_NKEYCODE; j++) {
-			if (sc->sc_odata.keycode[j] == 0) {
-				continue;
-			}
-			if (key == sc->sc_odata.keycode[j]) {
+		if (mask == 1 && delta == 0) {
+			key += 63;
+			continue;	/* skip empty areas */
+		} else if (delta & mask) {
+			if (sc->sc_odata.bitmap[key / 64] & mask) {
+				ukbd_put_key(sc, key | KEY_RELEASE);
 
-				/* key is still pressed */
+				/* clear repeating key, if any */
+				if (sc->sc_repeat_key == key)
+					sc->sc_repeat_key = 0;
+			} else {
+				ukbd_put_key(sc, key | KEY_PRESS);
 
-				sc->sc_ntime[i] = sc->sc_otime[j];
-				dtime = (sc->sc_otime[j] - now);
-
-				if (dtime > 0) {
-					/* time has not elapsed */
-					goto pfound;
-				}
-				sc->sc_ntime[i] = now + sc->sc_kbd.kb_delay2;
-				break;
+				/* set repeat time for last key */
+				sc->sc_repeat_time = now + sc->sc_kbd.kb_delay1;
+				sc->sc_repeat_key = key;
 			}
 		}
-		if (j == UKBD_NKEYCODE) {
-			/* New key - set initial delay and [re]start timer */
-			sc->sc_co_basetime = sbinuptime();
-			sc->sc_delay = sc->sc_kbd.kb_delay1;
-			ukbd_start_timer(sc);
-		}
-		ukbd_put_key(sc, key | KEY_PRESS);
+	}
 
-		/*
-                 * If any other key is presently down, force its repeat to be
-                 * well in the future (100s).  This makes the last key to be
-                 * pressed do the autorepeat.
-                 */
-		for (j = 0; j != UKBD_NKEYCODE; j++) {
-			if (j != i)
-				sc->sc_ntime[j] = now + (100 * 1000);
+	/* synchronize old data with new data */
+	sc->sc_odata = sc->sc_ndata;
+	
+	/* check if last key is still pressed */
+	if (sc->sc_repeat_key != 0) {
+		const int32_t dtime = (sc->sc_repeat_time - now);
+
+		/* check if time has elapsed */
+		if (dtime < 0) {
+			ukbd_put_key(sc, sc->sc_repeat_key | KEY_PRESS);
+			sc->sc_repeat_time = now + sc->sc_kbd.kb_delay2;
 		}
-pfound:	;
 	}
 
-	sc->sc_odata = sc->sc_ndata;
+	/* check for first new key and set initial delay and [re]start timer */
+	if (old_keys == false && ukbd_any_key_pressed(sc) == true) {
+		sc->sc_co_basetime = sbinuptime();
+		sc->sc_delay = sc->sc_kbd.kb_delay1;
+		ukbd_start_timer(sc);
+	}
 
-	memcpy(sc->sc_otime, sc->sc_ntime, sizeof(sc->sc_otime));
-
+	/* wakeup keyboard system */
 	ukbd_event_keyinput(sc);
 }
 
@@ -664,8 +592,9 @@
 	}
 }
 
-static uint8_t
-ukbd_apple_fn(uint8_t keycode) {
+static uint32_t
+ukbd_apple_fn(uint32_t keycode)
+{
 	switch (keycode) {
 	case 0x28: return 0x49; /* RETURN -> INSERT */
 	case 0x2a: return 0x4c; /* BACKSPACE -> DEL */
@@ -677,8 +606,9 @@
 	}
 }
 
-static uint8_t
-ukbd_apple_swap(uint8_t keycode) {
+static uint32_t
+ukbd_apple_swap(uint32_t keycode)
+{
 	switch (keycode) {
 	case 0x35: return 0x64;
 	case 0x64: return 0x35;
@@ -691,9 +621,10 @@
 {
 	struct ukbd_softc *sc = usbd_xfer_softc(xfer);
 	struct usb_page_cache *pc;
-	uint8_t i;
-	uint8_t offset;
+	uint32_t i;
 	uint8_t id;
+	uint8_t modifiers;
+	int offset;
 	int len;
 
 	UKBD_LOCK_ASSERT();
@@ -733,117 +664,72 @@
 		/* clear temporary storage */
 		memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata));
 
+		/* 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))
-				sc->sc_modifiers |= MOD_EJECT;
-			else
-				sc->sc_modifiers &= ~MOD_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))
-				sc->sc_modifiers |= MOD_FN;
-			else
-				sc->sc_modifiers &= ~MOD_FN;
+				modifiers |= MOD_FN;
 		}
-		if ((sc->sc_flags & UKBD_FLAG_CTRL_L) &&
-		    (id == sc->sc_id_ctrl_l)) {
-			if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_ctrl_l))
-			  sc->	sc_modifiers |= MOD_CONTROL_L;
-			else
-			  sc->	sc_modifiers &= ~MOD_CONTROL_L;
-		}
-		if ((sc->sc_flags & UKBD_FLAG_CTRL_R) &&
-		    (id == sc->sc_id_ctrl_r)) {
-			if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_ctrl_r))
-				sc->sc_modifiers |= MOD_CONTROL_R;
-			else
-				sc->sc_modifiers &= ~MOD_CONTROL_R;
-		}
-		if ((sc->sc_flags & UKBD_FLAG_SHIFT_L) &&
-		    (id == sc->sc_id_shift_l)) {
-			if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_shift_l))
-				sc->sc_modifiers |= MOD_SHIFT_L;
-			else
-				sc->sc_modifiers &= ~MOD_SHIFT_L;
-		}
-		if ((sc->sc_flags & UKBD_FLAG_SHIFT_R) &&
-		    (id == sc->sc_id_shift_r)) {
-			if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_shift_r))
-				sc->sc_modifiers |= MOD_SHIFT_R;
-			else
-				sc->sc_modifiers &= ~MOD_SHIFT_R;
-		}
-		if ((sc->sc_flags & UKBD_FLAG_ALT_L) &&
-		    (id == sc->sc_id_alt_l)) {
-			if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_alt_l))
-				sc->sc_modifiers |= MOD_ALT_L;
-			else
-				sc->sc_modifiers &= ~MOD_ALT_L;
-		}
-		if ((sc->sc_flags & UKBD_FLAG_ALT_R) &&
-		    (id == sc->sc_id_alt_r)) {
-			if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_alt_r))
-				sc->sc_modifiers |= MOD_ALT_R;
-			else
-				sc->sc_modifiers &= ~MOD_ALT_R;
-		}
-		if ((sc->sc_flags & UKBD_FLAG_WIN_L) &&
-		    (id == sc->sc_id_win_l)) {
-			if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_win_l))
-				sc->sc_modifiers |= MOD_WIN_L;
-			else
-				sc->sc_modifiers &= ~MOD_WIN_L;
-		}
-		if ((sc->sc_flags & UKBD_FLAG_WIN_R) &&
-		    (id == sc->sc_id_win_r)) {
-			if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_win_r))
-				sc->sc_modifiers |= MOD_WIN_R;
-			else
-				sc->sc_modifiers &= ~MOD_WIN_R;
-		}
 
-		sc->sc_ndata.modifiers = sc->sc_modifiers;
+		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 ((sc->sc_flags & UKBD_FLAG_EVENTS) &&
-		    (id == sc->sc_id_events)) {
-			i = sc->sc_loc_events.count;
-			if (i > UKBD_NKEYCODE)
-				i = UKBD_NKEYCODE;
-			if (i > len)
-				i = len;
-			while (i--) {
-				sc->sc_ndata.keycode[i] =
-				    hid_get_data(sc->sc_buffer + i, len - i,
-				    &sc->sc_loc_events);
+			if (mask == 1 && valid == 0) {
+				i += 63;
+				continue;	/* skip empty areas */
+			} else if (id != sc->sc_id_loc_key[i]) {
+				continue;	/* invalid HID ID */
+			} else if (~valid & mask) {
+				continue;	/* location is not valid */
+			} else if (i == 0) {
+				offset = sc->sc_loc_key[0].count;
+				if (offset < 0 || offset > len)
+					offset = len;
+				while (offset--) {
+					uint32_t key =
+					    hid_get_data(sc->sc_buffer + offset, len - offset,
+					    &sc->sc_loc_key[i]);
+					if (modifiers & MOD_FN)
+						key = ukbd_apple_fn(key);
+					if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP)
+						key = ukbd_apple_swap(key);
+					if (key == KEY_NONE || key == KEY_ERROR || key >= UKBD_NKEYCODE)
+						continue;
+					/* set key in bitmap */
+					sc->sc_ndata.bitmap[key / 64] |= 1ULL << (key % 64);
+				}
+			} else if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_key[i])) {
+				uint32_t key = i;
+
+				if (modifiers & MOD_FN)
+					key = ukbd_apple_fn(key);
+				if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP)
+					key = ukbd_apple_swap(key);
+				if (key == KEY_NONE || key == KEY_ERROR || key >= UKBD_NKEYCODE)
+					continue;
+				/* set key in bitmap */
+				sc->sc_ndata.bitmap[key / 64] |= 1ULL << (key % 64);
 			}
 		}
-
 #ifdef USB_DEBUG
-		DPRINTF("modifiers = 0x%04x\n", (int)sc->sc_modifiers);
+		DPRINTF("modifiers = 0x%04x\n", modifiers);
 		for (i = 0; i < UKBD_NKEYCODE; i++) {
-			if (sc->sc_ndata.keycode[i]) {
-				DPRINTF("[%d] = 0x%02x\n",
-				    (int)i, (int)sc->sc_ndata.keycode[i]);
-			}
+			const uint64_t valid = sc->sc_ndata.bitmap[i / 64];
+			const uint64_t mask = 1ULL << (i % 64);
+
+			if (valid & mask)
+				DPRINTF("Key 0x%02x pressed\n", i);
 		}
 #endif
-		if (sc->sc_modifiers & MOD_FN) {
-			for (i = 0; i < UKBD_NKEYCODE; i++) {
-				sc->sc_ndata.keycode[i] = 
-				    ukbd_apple_fn(sc->sc_ndata.keycode[i]);
-			}
-		}
-
-		if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP) {
-			for (i = 0; i < UKBD_NKEYCODE; i++) {
-				sc->sc_ndata.keycode[i] = 
-				    ukbd_apple_swap(sc->sc_ndata.keycode[i]);
-			}
-		}
-
 		ukbd_interrupt(sc);
 
 	case USB_ST_SETUP:
@@ -1072,10 +958,14 @@
 ukbd_parse_hid(struct ukbd_softc *sc, const uint8_t *ptr, uint32_t len)
 {
 	uint32_t flags;
+	uint32_t key;
 
 	/* reset detected bits */
 	sc->sc_flags &= ~UKBD_FLAG_HID_MASK;
 
+	/* reset detected keys */
+	memset(sc->sc_loc_key_valid, 0, sizeof(sc->sc_loc_key_valid));
+
 	/* check if there is an ID byte */
 	sc->sc_kbd_size = hid_report_size(ptr, len,
 	    hid_input, &sc->sc_kbd_id);
@@ -1098,84 +988,34 @@
 			sc->sc_flags |= UKBD_FLAG_APPLE_FN;
 		DPRINTFN(1, "Found Apple FN-key\n");
 	}
-	/* figure out some keys */
-	if (hid_locate(ptr, len,
-	    HID_USAGE2(HUP_KEYBOARD, 0xE0),
-	    hid_input, 0, &sc->sc_loc_ctrl_l, &flags,
-	    &sc->sc_id_ctrl_l)) {
-		if (flags & HIO_VARIABLE)
-			sc->sc_flags |= UKBD_FLAG_CTRL_L;
-		DPRINTFN(1, "Found left control\n");
-	}
-	if (hid_locate(ptr, len,
-	    HID_USAGE2(HUP_KEYBOARD, 0xE4),
-	    hid_input, 0, &sc->sc_loc_ctrl_r, &flags,
-	    &sc->sc_id_ctrl_r)) {
-		if (flags & HIO_VARIABLE)
-			sc->sc_flags |= UKBD_FLAG_CTRL_R;
-		DPRINTFN(1, "Found right control\n");
-	}
-	if (hid_locate(ptr, len,
-	    HID_USAGE2(HUP_KEYBOARD, 0xE1),
-	    hid_input, 0, &sc->sc_loc_shift_l, &flags,
-	    &sc->sc_id_shift_l)) {
-		if (flags & HIO_VARIABLE)
-			sc->sc_flags |= UKBD_FLAG_SHIFT_L;
-		DPRINTFN(1, "Found left shift\n");
-	}
-	if (hid_locate(ptr, len,
-	    HID_USAGE2(HUP_KEYBOARD, 0xE5),
-	    hid_input, 0, &sc->sc_loc_shift_r, &flags,
-	    &sc->sc_id_shift_r)) {
-		if (flags & HIO_VARIABLE)
-			sc->sc_flags |= UKBD_FLAG_SHIFT_R;
-		DPRINTFN(1, "Found right shift\n");
-	}
-	if (hid_locate(ptr, len,
-	    HID_USAGE2(HUP_KEYBOARD, 0xE2),
-	    hid_input, 0, &sc->sc_loc_alt_l, &flags,
-	    &sc->sc_id_alt_l)) {
-		if (flags & HIO_VARIABLE)
-			sc->sc_flags |= UKBD_FLAG_ALT_L;
-		DPRINTFN(1, "Found left alt\n");
-	}
-	if (hid_locate(ptr, len,
-	    HID_USAGE2(HUP_KEYBOARD, 0xE6),
-	    hid_input, 0, &sc->sc_loc_alt_r, &flags,
-	    &sc->sc_id_alt_r)) {
-		if (flags & HIO_VARIABLE)
-			sc->sc_flags |= UKBD_FLAG_ALT_R;
-		DPRINTFN(1, "Found right alt\n");
-	}
-	if (hid_locate(ptr, len,
-	    HID_USAGE2(HUP_KEYBOARD, 0xE3),
-	    hid_input, 0, &sc->sc_loc_win_l, &flags,
-	    &sc->sc_id_win_l)) {
-		if (flags & HIO_VARIABLE)
-			sc->sc_flags |= UKBD_FLAG_WIN_L;
-		DPRINTFN(1, "Found left GUI\n");
-	}
-	if (hid_locate(ptr, len,
-	    HID_USAGE2(HUP_KEYBOARD, 0xE7),
-	    hid_input, 0, &sc->sc_loc_win_r, &flags,
-	    &sc->sc_id_win_r)) {
-		if (flags & HIO_VARIABLE)
-			sc->sc_flags |= UKBD_FLAG_WIN_R;
-		DPRINTFN(1, "Found right GUI\n");
-	}
+
 	/* figure out event buffer */
 	if (hid_locate(ptr, len,
 	    HID_USAGE2(HUP_KEYBOARD, 0x00),
-	    hid_input, 0, &sc->sc_loc_events, &flags,
-	    &sc->sc_id_events)) {
+	    hid_input, 0, &sc->sc_loc_key[0], &flags,
+	    &sc->sc_id_loc_key[0])) {
 		if (flags & HIO_VARIABLE) {
 			DPRINTFN(1, "Ignoring keyboard event control\n");
 		} else {
-			sc->sc_flags |= UKBD_FLAG_EVENTS;
+			sc->sc_loc_key_valid[0] |= 1;
 			DPRINTFN(1, "Found keyboard event array\n");
 		}
 	}
 
+	/* figure out the keys */
+	for (key = 1; key != UKBD_NKEYCODE; key++) {
+		if (hid_locate(ptr, len,
+		    HID_USAGE2(HUP_KEYBOARD, key),
+		    hid_input, 0, &sc->sc_loc_key[key], &flags,
+		    &sc->sc_id_loc_key[key])) {
+			if (flags & HIO_VARIABLE) {
+				sc->sc_loc_key_valid[key / 64] |=
+				    1ULL << (key % 64);
+				DPRINTFN(1, "Found key 0x%02x\n", key);
+			}
+		}
+	}
+
 	/* figure out leds on keyboard */
 	sc->sc_led_size = hid_report_size(ptr, len,
 	    hid_output, NULL);
@@ -1301,7 +1141,7 @@
 
 	/* check if we should use the boot protocol */
 	if (usb_test_quirk(uaa, UQ_KBD_BOOTPROTO) ||
-	    (err != 0) || (!(sc->sc_flags & UKBD_FLAG_EVENTS))) {
+	    (err != 0) || ukbd_any_key_valid(sc) == false) {
 
 		DPRINTF("Forcing boot protocol\n");
 
@@ -1660,11 +1500,11 @@
 	++(kbd->kb_count);
 
 #ifdef UKBD_EMULATE_ATSCANCODE
-	keycode = ukbd_atkeycode(usbcode, sc->sc_ndata.modifiers);
+	keycode = ukbd_atkeycode(usbcode, sc->sc_ndata.bitmap);
 	if (keycode == NN) {
 		return -1;
 	}
-	return (ukbd_key2scan(sc, keycode, sc->sc_ndata.modifiers,
+	return (ukbd_key2scan(sc, keycode, sc->sc_ndata.bitmap,
 	    (usbcode & KEY_RELEASE)));
 #else					/* !UKBD_EMULATE_ATSCANCODE */
 	return (usbcode);
@@ -1731,13 +1571,13 @@
 
 #ifdef UKBD_EMULATE_ATSCANCODE
 	/* USB key index -> key code -> AT scan code */
-	keycode = ukbd_atkeycode(usbcode, sc->sc_ndata.modifiers);
+	keycode = ukbd_atkeycode(usbcode, sc->sc_ndata.bitmap);
 	if (keycode == NN) {
 		return (NOKEY);
 	}
 	/* return an AT scan code for the K_RAW mode */
 	if (sc->sc_mode == K_RAW) {
-		return (ukbd_key2scan(sc, keycode, sc->sc_ndata.modifiers,
+		return (ukbd_key2scan(sc, keycode, sc->sc_ndata.bitmap,
 		    (usbcode & KEY_RELEASE)));
 	}
 #else					/* !UKBD_EMULATE_ATSCANCODE */
@@ -2061,8 +1901,8 @@
 #endif
 	memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata));
 	memset(&sc->sc_odata, 0, sizeof(sc->sc_odata));
-	memset(&sc->sc_ntime, 0, sizeof(sc->sc_ntime));
-	memset(&sc->sc_otime, 0, sizeof(sc->sc_otime));
+	sc->sc_repeat_time = 0;
+	sc->sc_repeat_key = 0;
 }
 
 /* save the internal state, not used */
@@ -2149,11 +1989,12 @@
 
 #ifdef UKBD_EMULATE_ATSCANCODE
 static uint32_t
-ukbd_atkeycode(int usbcode, int shift)
+ukbd_atkeycode(int usbcode, const uint64_t *bitmap)
 {
 	uint32_t keycode;
 
 	keycode = ukbd_trtab[KEY_INDEX(usbcode)];
+
 	/*
 	 * Translate Alt-PrintScreen to SysRq.
 	 *
@@ -2168,13 +2009,14 @@
 	 * is routine.
 	 */
 	if ((keycode == 0x5c || keycode == 0x7e) &&
-	    shift & (MOD_ALT_L | MOD_ALT_R))
+	    (UKBD_KEY_PRESSED(bitmap, 0xe2 /* ALT-L */) ||
+	     UKBD_KEY_PRESSED(bitmap, 0xe6 /* ALT-R */)))
 		return (0x54);
 	return (keycode);
 }
 
 static int
-ukbd_key2scan(struct ukbd_softc *sc, int code, int shift, int up)
+ukbd_key2scan(struct ukbd_softc *sc, int code, const uint64_t *bitmap, int up)
 {
 	static const int scan[] = {
 		/* 89 */
@@ -2234,12 +2076,17 @@
 		code = scan[code - 89];
 	}
 	/* PrintScreen */
-	if (code == 0x137 && (!(shift & (MOD_CONTROL_L | MOD_CONTROL_R |
-	    MOD_SHIFT_L | MOD_SHIFT_R)))) {
+	if (code == 0x137 && (!(
+	    UKBD_KEY_PRESSED(bitmap, 0xe0 /* CTRL-L */) ||
+	    UKBD_KEY_PRESSED(bitmap, 0xe4 /* CTRL-R */) ||
+	    UKBD_KEY_PRESSED(bitmap, 0xe1 /* SHIFT-L */) ||
+	    UKBD_KEY_PRESSED(bitmap, 0xe5 /* SHIFT-R */)))) {
 		code |= SCAN_PREFIX_SHIFT;
 	}
 	/* Pause/Break */
-	if ((code == 0x146) && (!(shift & (MOD_CONTROL_L | MOD_CONTROL_R)))) {
+	if ((code == 0x146) && (!(
+	    UKBD_KEY_PRESSED(bitmap, 0xe0 /* CTRL-L */) ||
+	    UKBD_KEY_PRESSED(bitmap, 0xe4 /* CTRL-R */)))) {
 		code = (0x45 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL);
 	}
 	code |= (up ? SCAN_RELEASE : SCAN_PRESS);

--------------EDB4A60D84EB4322555E10AA--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?06d56f8a-c6b7-0f7d-fdf6-bd6dbdba06bc>