Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb Summary: Introduce a keyboard event ring buffer ...



details:   https://anonhg.NetBSD.org/src/rev/641f8af4e0f2
branches:  trunk
changeset: 746344:641f8af4e0f2
user:      tih <tih%NetBSD.org@localhost>
date:      Sun Mar 29 10:46:10 2020 +0000

description:
Summary: Introduce a keyboard event ring buffer for USB console keyboards

For the console keyboard, events must be handled separately from the
interrupt handler, because of the possibility that the user chooses to
drop into DDB by use of the designated key combination.  This delayed
handling is tied to the HZ clock through the callout(9) mechanism,
meaning that another keyboard event arriving within 10ms of the
previous one might overwrite its predecessor before it's handled.
This causes dropped events for fast typists - and the situation gets
worse with modern, programmable, keyboards.

This patch introduces a ring buffer in the ukbd_softc data structure,
so that multiple pending events may be safely stored.

diffstat:

 sys/dev/usb/ukbd.c |  29 ++++++++++++++++++++++-------
 1 files changed, 22 insertions(+), 7 deletions(-)

diffs (79 lines):

diff -r e53224cbffea -r 641f8af4e0f2 sys/dev/usb/ukbd.c
--- a/sys/dev/usb/ukbd.c        Sun Mar 29 10:25:28 2020 +0000
+++ b/sys/dev/usb/ukbd.c        Sun Mar 29 10:46:10 2020 +0000
@@ -1,4 +1,4 @@
-/*      $NetBSD: ukbd.c,v 1.145 2020/03/14 02:35:33 christos Exp $        */
+/*      $NetBSD: ukbd.c,v 1.146 2020/03/29 10:46:10 tih Exp $        */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ukbd.c,v 1.145 2020/03/14 02:35:33 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ukbd.c,v 1.146 2020/03/29 10:46:10 tih Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ddb.h"
@@ -258,7 +258,9 @@
        int sc_console_keyboard;        /* we are the console keyboard */
 
        struct callout sc_delay;        /* for quirk handling */
-       struct ukbd_data sc_data;       /* for quirk handling */
+#define MAXPENDING 32
+       struct ukbd_data sc_data[MAXPENDING];
+       size_t sc_data_w, sc_data_r;
 
        struct hid_location sc_apple_fn;
        struct hid_location sc_numloc;
@@ -475,6 +477,9 @@
 
        callout_init(&sc->sc_delay, 0);
 
+       sc->sc_data_w = 0;
+       sc->sc_data_r = 0;
+
        usb_init_task(&sc->sc_ledtask, ukbd_set_leds_task, sc, 0);
 
        /* Flash the leds; no real purpose, just shows we're alive. */
@@ -686,8 +691,14 @@
                 * generate a key up followed by a key down for the same
                 * key after about 10 ms.
                 * We avoid this bug by holding off decoding for 20 ms.
+                * Note that this comes at a cost: we deliberately overwrite
+                * the data for any keyboard event that is followed by
+                * another one within this time window.
                 */
-               sc->sc_data = *ud;
+               if (sc->sc_data_w == sc->sc_data_r) {
+                       sc->sc_data_w = (sc->sc_data_w + 1) % MAXPENDING;
+               }
+               sc->sc_data[sc->sc_data_w] = *ud;
                callout_reset(&sc->sc_delay, hz / 50, ukbd_delayed_decode, sc);
 #ifdef DDB
        } else if (sc->sc_console_keyboard && !(sc->sc_flags & FLAG_POLLING)) {
@@ -697,8 +708,9 @@
                 * polling from inside the interrupt routine and that
                 * loses bigtime.
                 */
-               sc->sc_data = *ud;
-               callout_reset(&sc->sc_delay, 1, ukbd_delayed_decode, sc);
+               sc->sc_data_w = (sc->sc_data_w + 1) % MAXPENDING;
+               sc->sc_data[sc->sc_data_w] = *ud;
+               callout_reset(&sc->sc_delay, 0, ukbd_delayed_decode, sc);
 #endif
        } else {
                ukbd_decode(sc, ud);
@@ -710,7 +722,10 @@
 {
        struct ukbd_softc *sc = addr;
 
-       ukbd_decode(sc, &sc->sc_data);
+       while (sc->sc_data_r != sc->sc_data_w) {
+               sc->sc_data_r = (sc->sc_data_r + 1) % MAXPENDING;
+               ukbd_decode(sc, &sc->sc_data[sc->sc_data_r]);
+       }
 }
 
 void



Home | Main Index | Thread Index | Old Index