git: 510b003ff412 - stable/13 - hkbd(4): Fix key repeats on multireport keyboards

Vladimir Kondratyev wulf at FreeBSD.org
Thu Sep 23 01:04:00 UTC 2021


The branch stable/13 has been updated by wulf:

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

commit 510b003ff41291599cab3e45d463f3a3bf77d6eb
Author:     Vladimir Kondratyev <wulf at FreeBSD.org>
AuthorDate: 2021-09-09 21:40:13 +0000
Commit:     Vladimir Kondratyev <wulf at FreeBSD.org>
CommitDate: 2021-09-23 00:58:58 +0000

    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
    
    (cherry picked from commit 598f0580f6822e2492231d055f49465a5b55d270)
---
 sys/dev/hid/hkbd.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/sys/dev/hid/hkbd.c b/sys/dev/hid/hkbd.c
index 65e8b9446e9d..bfd8e12df746 100644
--- a/sys/dev/hid/hkbd.c
+++ b/sys/dev/hid/hkbd.c
@@ -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;
 }


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