hkbd(4): Use bitstring(3) KPI for key bitmaps processing.
No functional changes intended. MFC after: 2 weeks
This commit is contained in:
parent
3ef9023f93
commit
04918395f1
@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/kdb.h>
|
||||
#include <sys/epoch.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#include <sys/bitstring.h>
|
||||
|
||||
#include <machine/atomic.h>
|
||||
|
||||
@ -116,7 +117,7 @@ SYSCTL_INT(_hw_hid_hkbd, OID_AUTO, no_leds, CTLFLAG_RWTUN,
|
||||
#define HKBD_BUFFER_SIZE 64 /* bytes */
|
||||
#define HKBD_KEY_PRESSED(map, key) ({ \
|
||||
CTASSERT((key) >= 0 && (key) < HKBD_NKEYCODE); \
|
||||
((map)[(key) / 64] & (1ULL << ((key) % 64))); \
|
||||
bit_test(map, key); \
|
||||
})
|
||||
|
||||
#define MOD_EJECT 0x01
|
||||
@ -125,10 +126,6 @@ SYSCTL_INT(_hw_hid_hkbd, OID_AUTO, no_leds, CTLFLAG_RWTUN,
|
||||
#define MOD_MIN 0xe0
|
||||
#define MOD_MAX 0xe7
|
||||
|
||||
struct hkbd_data {
|
||||
uint64_t bitmap[howmany(HKBD_NKEYCODE, 64)];
|
||||
};
|
||||
|
||||
struct hkbd_softc {
|
||||
device_t sc_dev;
|
||||
|
||||
@ -136,7 +133,7 @@ struct hkbd_softc {
|
||||
keymap_t sc_keymap;
|
||||
accentmap_t sc_accmap;
|
||||
fkeytab_t sc_fkeymap[HKBD_NFKEY];
|
||||
uint64_t sc_loc_key_valid[howmany(HKBD_NKEYCODE, 64)];
|
||||
bitstr_t bit_decl(sc_loc_key_valid, HKBD_NKEYCODE);
|
||||
struct hid_location sc_loc_apple_eject;
|
||||
struct hid_location sc_loc_apple_fn;
|
||||
struct hid_location sc_loc_key[HKBD_NKEYCODE];
|
||||
@ -146,8 +143,8 @@ struct hkbd_softc {
|
||||
struct mtx sc_mtx;
|
||||
struct task sc_task;
|
||||
struct callout sc_callout;
|
||||
struct hkbd_data sc_ndata;
|
||||
struct hkbd_data sc_odata;
|
||||
bitstr_t bit_decl(sc_ndata, HKBD_NKEYCODE);
|
||||
bitstr_t bit_decl(sc_odata, HKBD_NKEYCODE);
|
||||
|
||||
struct thread *sc_poll_thread;
|
||||
#ifdef EVDEV_SUPPORT
|
||||
@ -328,23 +325,19 @@ static const struct evdev_methods hkbd_evdev_methods = {
|
||||
static bool
|
||||
hkbd_any_key_pressed(struct hkbd_softc *sc)
|
||||
{
|
||||
bool ret = false;
|
||||
unsigned i;
|
||||
int result;
|
||||
|
||||
for (i = 0; i != howmany(HKBD_NKEYCODE, 64); i++)
|
||||
ret |= (sc->sc_odata.bitmap[i] != 0);
|
||||
return (ret);
|
||||
bit_ffs(sc->sc_odata, HKBD_NKEYCODE, &result);
|
||||
return (result != -1);
|
||||
}
|
||||
|
||||
static bool
|
||||
hkbd_any_key_valid(struct hkbd_softc *sc)
|
||||
{
|
||||
bool ret = false;
|
||||
unsigned i;
|
||||
int result;
|
||||
|
||||
for (i = 0; i != howmany(HKBD_NKEYCODE, 64); i++)
|
||||
ret |= (sc->sc_loc_key_valid[i] != 0);
|
||||
return (ret);
|
||||
bit_ffs(sc->sc_loc_key_valid, HKBD_NKEYCODE, &result);
|
||||
return (result != -1);
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -487,65 +480,47 @@ hkbd_interrupt(struct hkbd_softc *sc)
|
||||
|
||||
HKBD_LOCK_ASSERT(sc);
|
||||
|
||||
/* Check for key changes, the order is:
|
||||
* 1. Modifier keys down
|
||||
* 2. Regular keys up/down
|
||||
* 3. Modifier keys up
|
||||
/*
|
||||
* Check for key changes, the order is:
|
||||
* 1. Regular keys up
|
||||
* 2. Modifier keys up
|
||||
* 3. Modifier keys down
|
||||
* 4. Regular keys down
|
||||
*
|
||||
* 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);
|
||||
|
||||
if (!(sc->sc_odata.bitmap[key / 64] & mask) &&
|
||||
(sc->sc_ndata.bitmap[key / 64] & mask)) {
|
||||
hkbd_put_key(sc, key | KEY_PRESS);
|
||||
}
|
||||
}
|
||||
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))
|
||||
bit_foreach(sc->sc_odata, HKBD_NKEYCODE, key) {
|
||||
if (hkbd_is_modifier_key(key) || bit_test(sc->sc_ndata, key))
|
||||
continue;
|
||||
hkbd_put_key(sc, key | KEY_RELEASE);
|
||||
|
||||
if (mask == 1 && delta == 0) {
|
||||
key += 63;
|
||||
continue; /* skip empty areas */
|
||||
} else if (delta & mask) {
|
||||
if (sc->sc_odata.bitmap[key / 64] & mask) {
|
||||
hkbd_put_key(sc, key | KEY_RELEASE);
|
||||
|
||||
/* clear repeating key, if any */
|
||||
if (sc->sc_repeat_key == key)
|
||||
sc->sc_repeat_key = 0;
|
||||
} else {
|
||||
hkbd_put_key(sc, key | KEY_PRESS);
|
||||
|
||||
sc->sc_co_basetime = sbinuptime();
|
||||
sc->sc_delay = sc->sc_kbd.kb_delay1;
|
||||
hkbd_start_timer(sc);
|
||||
|
||||
/* set repeat time for last key */
|
||||
sc->sc_repeat_time = now + sc->sc_kbd.kb_delay1;
|
||||
sc->sc_repeat_key = key;
|
||||
}
|
||||
}
|
||||
/* clear repeating key, if any */
|
||||
if (sc->sc_repeat_key == key)
|
||||
sc->sc_repeat_key = 0;
|
||||
}
|
||||
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)) {
|
||||
bit_foreach_at(sc->sc_odata, MOD_MIN, MOD_MAX + 1, key)
|
||||
if (!bit_test(sc->sc_ndata, key))
|
||||
hkbd_put_key(sc, key | KEY_RELEASE);
|
||||
}
|
||||
bit_foreach_at(sc->sc_ndata, MOD_MIN, MOD_MAX + 1, key)
|
||||
if (!bit_test(sc->sc_odata, key))
|
||||
hkbd_put_key(sc, key | KEY_PRESS);
|
||||
bit_foreach(sc->sc_ndata, HKBD_NKEYCODE, key) {
|
||||
if (hkbd_is_modifier_key(key) || bit_test(sc->sc_odata, key))
|
||||
continue;
|
||||
hkbd_put_key(sc, key | KEY_PRESS);
|
||||
|
||||
sc->sc_co_basetime = sbinuptime();
|
||||
sc->sc_delay = sc->sc_kbd.kb_delay1;
|
||||
hkbd_start_timer(sc);
|
||||
|
||||
/* set repeat time for last key */
|
||||
sc->sc_repeat_time = now + sc->sc_kbd.kb_delay1;
|
||||
sc->sc_repeat_key = key;
|
||||
}
|
||||
|
||||
/* synchronize old data with new data */
|
||||
sc->sc_odata = sc->sc_ndata;
|
||||
memcpy(sc->sc_odata, sc->sc_ndata, bitstr_size(HKBD_NKEYCODE));
|
||||
|
||||
/* check if last key is still pressed */
|
||||
if (sc->sc_repeat_key != 0) {
|
||||
@ -679,7 +654,7 @@ hkbd_intr_callback(void *context, void *data, hid_size_t len)
|
||||
}
|
||||
|
||||
/* clear temporary storage */
|
||||
memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata));
|
||||
memset(&sc->sc_ndata, 0, bitstr_size(HKBD_NKEYCODE));
|
||||
|
||||
/* clear modifiers */
|
||||
modifiers = 0;
|
||||
@ -696,16 +671,8 @@ hkbd_intr_callback(void *context, void *data, hid_size_t len)
|
||||
modifiers |= MOD_FN;
|
||||
}
|
||||
|
||||
for (i = 0; i != HKBD_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]) {
|
||||
bit_foreach(sc->sc_loc_key_valid, HKBD_NKEYCODE, i) {
|
||||
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];
|
||||
@ -719,7 +686,8 @@ hkbd_intr_callback(void *context, void *data, hid_size_t len)
|
||||
tmp_loc.pos += tmp_loc.size;
|
||||
if (key == KEY_ERROR) {
|
||||
DPRINTF("KEY_ERROR\n");
|
||||
sc->sc_ndata = sc->sc_odata;
|
||||
memcpy(sc->sc_ndata, sc->sc_odata,
|
||||
bitstr_size(HKBD_NKEYCODE));
|
||||
return; /* ignore */
|
||||
}
|
||||
if (modifiers & MOD_FN)
|
||||
@ -729,7 +697,7 @@ hkbd_intr_callback(void *context, void *data, hid_size_t len)
|
||||
if (key == KEY_NONE || key >= HKBD_NKEYCODE)
|
||||
continue;
|
||||
/* set key in bitmap */
|
||||
sc->sc_ndata.bitmap[key / 64] |= 1ULL << (key % 64);
|
||||
bit_set(sc->sc_ndata, key);
|
||||
}
|
||||
} else if (hid_get_data(buf, len, &sc->sc_loc_key[i])) {
|
||||
uint32_t key = i;
|
||||
@ -741,18 +709,13 @@ hkbd_intr_callback(void *context, void *data, hid_size_t len)
|
||||
if (key == KEY_NONE || key == KEY_ERROR || key >= HKBD_NKEYCODE)
|
||||
continue;
|
||||
/* set key in bitmap */
|
||||
sc->sc_ndata.bitmap[key / 64] |= 1ULL << (key % 64);
|
||||
bit_set(sc->sc_ndata, key);
|
||||
}
|
||||
}
|
||||
#ifdef HID_DEBUG
|
||||
DPRINTF("modifiers = 0x%04x\n", modifiers);
|
||||
for (i = 0; i != HKBD_NKEYCODE; 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);
|
||||
}
|
||||
bit_foreach(sc->sc_ndata, HKBD_NKEYCODE, i)
|
||||
DPRINTF("Key 0x%02x pressed\n", i);
|
||||
#endif
|
||||
hkbd_interrupt(sc);
|
||||
}
|
||||
@ -795,7 +758,7 @@ hkbd_parse_hid(struct hkbd_softc *sc, const uint8_t *ptr, uint32_t len,
|
||||
sc->sc_flags &= ~HKBD_FLAG_HID_MASK;
|
||||
|
||||
/* reset detected keys */
|
||||
memset(sc->sc_loc_key_valid, 0, sizeof(sc->sc_loc_key_valid));
|
||||
memset(sc->sc_loc_key_valid, 0, bitstr_size(HKBD_NKEYCODE));
|
||||
|
||||
/* check if there is an ID byte */
|
||||
sc->sc_kbd_size = hid_report_size_max(ptr, len,
|
||||
@ -828,7 +791,7 @@ hkbd_parse_hid(struct hkbd_softc *sc, const uint8_t *ptr, uint32_t len,
|
||||
if (flags & HIO_VARIABLE) {
|
||||
DPRINTFN(1, "Ignoring keyboard event control\n");
|
||||
} else {
|
||||
sc->sc_loc_key_valid[0] |= 1;
|
||||
bit_set(sc->sc_loc_key_valid, 0);
|
||||
DPRINTFN(1, "Found keyboard event array\n");
|
||||
}
|
||||
}
|
||||
@ -840,8 +803,7 @@ hkbd_parse_hid(struct hkbd_softc *sc, const uint8_t *ptr, uint32_t len,
|
||||
hid_input, tlc_index, 0, &sc->sc_loc_key[key], &flags,
|
||||
&sc->sc_id_loc_key[key], NULL)) {
|
||||
if (flags & HIO_VARIABLE) {
|
||||
sc->sc_loc_key_valid[key / 64] |=
|
||||
1ULL << (key % 64);
|
||||
bit_set(sc->sc_loc_key_valid, key);
|
||||
DPRINTFN(1, "Found key 0x%02x\n", key);
|
||||
}
|
||||
}
|
||||
@ -1057,7 +1019,7 @@ hkbd_detach(device_t dev)
|
||||
hidbus_intr_stop(dev);
|
||||
|
||||
/* release all leftover keys, if any */
|
||||
memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata));
|
||||
memset(&sc->sc_ndata, 0, bitstr_size(HKBD_NKEYCODE));
|
||||
|
||||
/* process releasing of all keys */
|
||||
HKBD_LOCK(sc);
|
||||
@ -1305,11 +1267,11 @@ hkbd_read(keyboard_t *kbd, int wait)
|
||||
++(kbd->kb_count);
|
||||
|
||||
#ifdef HKBD_EMULATE_ATSCANCODE
|
||||
keycode = hkbd_atkeycode(usbcode, sc->sc_ndata.bitmap);
|
||||
keycode = hkbd_atkeycode(usbcode, sc->sc_ndata);
|
||||
if (keycode == NN) {
|
||||
return -1;
|
||||
}
|
||||
return (hkbd_key2scan(sc, keycode, sc->sc_ndata.bitmap,
|
||||
return (hkbd_key2scan(sc, keycode, sc->sc_ndata,
|
||||
(usbcode & KEY_RELEASE)));
|
||||
#else /* !HKBD_EMULATE_ATSCANCODE */
|
||||
return (usbcode);
|
||||
@ -1375,13 +1337,13 @@ hkbd_read_char_locked(keyboard_t *kbd, int wait)
|
||||
|
||||
#ifdef HKBD_EMULATE_ATSCANCODE
|
||||
/* USB key index -> key code -> AT scan code */
|
||||
keycode = hkbd_atkeycode(usbcode, sc->sc_ndata.bitmap);
|
||||
keycode = hkbd_atkeycode(usbcode, sc->sc_ndata);
|
||||
if (keycode == NN) {
|
||||
return (NOKEY);
|
||||
}
|
||||
/* return an AT scan code for the K_RAW mode */
|
||||
if (sc->sc_mode == K_RAW) {
|
||||
return (hkbd_key2scan(sc, keycode, sc->sc_ndata.bitmap,
|
||||
return (hkbd_key2scan(sc, keycode, sc->sc_ndata,
|
||||
(usbcode & KEY_RELEASE)));
|
||||
}
|
||||
#else /* !HKBD_EMULATE_ATSCANCODE */
|
||||
@ -1720,8 +1682,8 @@ hkbd_clear_state(keyboard_t *kbd)
|
||||
sc->sc_buffered_char[0] = 0;
|
||||
sc->sc_buffered_char[1] = 0;
|
||||
#endif
|
||||
memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata));
|
||||
memset(&sc->sc_odata, 0, sizeof(sc->sc_odata));
|
||||
memset(&sc->sc_ndata, 0, bitstr_size(HKBD_NKEYCODE));
|
||||
memset(&sc->sc_odata, 0, bitstr_size(HKBD_NKEYCODE));
|
||||
sc->sc_repeat_time = 0;
|
||||
sc->sc_repeat_key = 0;
|
||||
}
|
||||
@ -1865,7 +1827,7 @@ hkbd_set_typematic(keyboard_t *kbd, int code)
|
||||
|
||||
#ifdef HKBD_EMULATE_ATSCANCODE
|
||||
static uint32_t
|
||||
hkbd_atkeycode(int usbcode, const uint64_t *bitmap)
|
||||
hkbd_atkeycode(int usbcode, const bitstr_t *bitmap)
|
||||
{
|
||||
uint32_t keycode;
|
||||
|
||||
@ -1892,7 +1854,7 @@ hkbd_atkeycode(int usbcode, const uint64_t *bitmap)
|
||||
}
|
||||
|
||||
static int
|
||||
hkbd_key2scan(struct hkbd_softc *sc, int code, const uint64_t *bitmap, int up)
|
||||
hkbd_key2scan(struct hkbd_softc *sc, int code, const bitstr_t *bitmap, int up)
|
||||
{
|
||||
static const int scan[] = {
|
||||
/* 89 */
|
||||
|
Loading…
Reference in New Issue
Block a user