hkbd(4): Fix key repeats on multireport keyboards
Currently hkbd counts all key states to be "Up" at the start of interrupt callback. That results in generation of "Key Up" event for each key that has been downed before but is not listed in current report while is still downed. Fix that with clearing of temporary key data storage bits only for keys contained in processed report. Reported by: Greg V Obtained from: sysutils/iichid MFC after: 2 weeks
This commit is contained in:
parent
04918395f1
commit
598f0580f6
@ -143,8 +143,12 @@ struct hkbd_softc {
|
||||
struct mtx sc_mtx;
|
||||
struct task sc_task;
|
||||
struct callout sc_callout;
|
||||
/* All reported keycodes */
|
||||
bitstr_t bit_decl(sc_ndata, HKBD_NKEYCODE);
|
||||
bitstr_t bit_decl(sc_odata, HKBD_NKEYCODE);
|
||||
/* Keycodes reported in array fields only */
|
||||
bitstr_t bit_decl(sc_ndata0, HKBD_NKEYCODE);
|
||||
bitstr_t bit_decl(sc_odata0, HKBD_NKEYCODE);
|
||||
|
||||
struct thread *sc_poll_thread;
|
||||
#ifdef EVDEV_SUPPORT
|
||||
@ -520,6 +524,7 @@ hkbd_interrupt(struct hkbd_softc *sc)
|
||||
}
|
||||
|
||||
/* synchronize old data with new data */
|
||||
memcpy(sc->sc_odata0, sc->sc_ndata0, bitstr_size(HKBD_NKEYCODE));
|
||||
memcpy(sc->sc_odata, sc->sc_ndata, bitstr_size(HKBD_NKEYCODE));
|
||||
|
||||
/* check if last key is still pressed */
|
||||
@ -654,7 +659,14 @@ hkbd_intr_callback(void *context, void *data, hid_size_t len)
|
||||
}
|
||||
|
||||
/* clear temporary storage */
|
||||
memset(&sc->sc_ndata, 0, bitstr_size(HKBD_NKEYCODE));
|
||||
if (bit_test(sc->sc_loc_key_valid, 0) && id == sc->sc_id_loc_key[0]) {
|
||||
bit_foreach(sc->sc_ndata0, HKBD_NKEYCODE, i)
|
||||
bit_clear(sc->sc_ndata, i);
|
||||
memset(&sc->sc_ndata0, 0, bitstr_size(HKBD_NKEYCODE));
|
||||
}
|
||||
bit_foreach(sc->sc_ndata, HKBD_NKEYCODE, i)
|
||||
if (id == sc->sc_id_loc_key[i])
|
||||
bit_clear(sc->sc_ndata, i);
|
||||
|
||||
/* clear modifiers */
|
||||
modifiers = 0;
|
||||
@ -686,6 +698,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");
|
||||
memcpy(sc->sc_ndata0, sc->sc_odata0,
|
||||
bitstr_size(HKBD_NKEYCODE));
|
||||
memcpy(sc->sc_ndata, sc->sc_odata,
|
||||
bitstr_size(HKBD_NKEYCODE));
|
||||
return; /* ignore */
|
||||
@ -698,6 +712,7 @@ hkbd_intr_callback(void *context, void *data, hid_size_t len)
|
||||
continue;
|
||||
/* set key in bitmap */
|
||||
bit_set(sc->sc_ndata, key);
|
||||
bit_set(sc->sc_ndata0, key);
|
||||
}
|
||||
} else if (hid_get_data(buf, len, &sc->sc_loc_key[i])) {
|
||||
uint32_t key = i;
|
||||
@ -1684,6 +1699,8 @@ hkbd_clear_state(keyboard_t *kbd)
|
||||
#endif
|
||||
memset(&sc->sc_ndata, 0, bitstr_size(HKBD_NKEYCODE));
|
||||
memset(&sc->sc_odata, 0, bitstr_size(HKBD_NKEYCODE));
|
||||
memset(&sc->sc_ndata0, 0, bitstr_size(HKBD_NKEYCODE));
|
||||
memset(&sc->sc_odata0, 0, bitstr_size(HKBD_NKEYCODE));
|
||||
sc->sc_repeat_time = 0;
|
||||
sc->sc_repeat_key = 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user