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>
