In 2001 augustss@NetBSD added the following hack to make USB keyboards
work in ddb(4):

        /*
         * For the console keyboard we can't deliver CTL-ALT-ESC
         * from the interrupt routine.  Doing so would start
         * polling from inside the interrupt routine and that    
         * loses bigtime.                                            
         */                                                             
        sc->sc_data = *ud;                                              
        callout_reset(&sc->sc_delay, 0, ukbd_delayed_decode, sc);       


This big hammer of delaying every input via a timeout introduced a nasty
side effect.  Since only one element can be queued, we can lose inputs
if the keyboard is too fast.

Here are some bug reports:

        https://marc.info/?l=openbsd-bugs&m=147284987417838&w=2
        https://marc.info/?l=openbsd-tech&m=142082432912041&w=1

The current code enqueues all inputs before processing them.  We could
work around this by increasing the size of the queue.  But we're only
interested in this for entering ddb(4), so I added another hook to
'struct wskbd_consops'.  This has the advantage of keeping the fix for
a USB problem inside ukbd(4).

I did not choose to generalize this hack of delaying the call to
db_enter() because it is handy to be able to enter the debugger from
interrupt context in case of interrupt storm for example.

ok?

Index: dev/hid/hidkbd.c
===================================================================
RCS file: /cvs/src/sys/dev/hid/hidkbd.c,v
retrieving revision 1.3
diff -u -p -r1.3 hidkbd.c
--- dev/hid/hidkbd.c    10 May 2017 09:48:04 -0000      1.3
+++ dev/hid/hidkbd.c    10 May 2017 12:47:06 -0000
@@ -269,19 +269,6 @@ hidkbd_input(struct hidkbd *kbd, uint8_t
                 */
                kbd->sc_data = *ud;
                timeout_add_msec(&kbd->sc_delay, 20);
-#ifdef DDB
-       } else if (kbd->sc_console_keyboard && !kbd->sc_polling) {
-               /*
-                * For the console keyboard we can't deliver CTL-ALT-ESC
-                * from the interrupt routine.  Doing so would start
-                * polling from inside the interrupt routine and that
-                * loses bigtime.
-                */
-               /* if (!timeout_pending(&kbd->sc_delay)) */ {
-                       kbd->sc_data = *ud;
-                       timeout_add(&kbd->sc_delay, 1);
-               }
-#endif
        } else {
                hidkbd_decode(kbd, ud);
        }
Index: dev/wscons/wskbd.c
===================================================================
RCS file: /cvs/src/sys/dev/wscons/wskbd.c,v
retrieving revision 1.86
diff -u -p -r1.86 wskbd.c
--- dev/wscons/wskbd.c  30 Apr 2017 16:45:46 -0000      1.86
+++ dev/wscons/wskbd.c  10 May 2017 12:48:48 -0000
@@ -211,6 +211,7 @@ void        update_modifier(struct wskbd_intern
 int    internal_command(struct wskbd_softc *, u_int *, keysym_t, keysym_t);
 int    wskbd_translate(struct wskbd_internal *, u_int, int);
 int    wskbd_enable(struct wskbd_softc *, int);
+void   wskbd_debugger(struct wskbd_softc *);
 #if NWSDISPLAY > 0
 void   change_displayparam(struct wskbd_softc *, int, int, int);
 #endif
@@ -1503,8 +1504,7 @@ internal_command(struct wskbd_softc *sc,
 
 #ifdef DDB
        if (ksym == KS_Cmd_Debugger) {
-               if (sc->sc_isconsole && db_console)
-                       db_enter();
+               wskbd_debugger(sc);
                /* discard this key (ddb discarded command modifiers) */
                *type = WSCONS_EVENT_KEY_UP;
                return (1);
@@ -1541,8 +1541,7 @@ internal_command(struct wskbd_softc *sc,
                switch (kbd_reset) {
 #ifdef DDB
                case 2:
-                       if (sc->sc_isconsole && db_console)
-                               db_enter();
+                       wskbd_debugger(sc);
                        /* discard this key (ddb discarded command modifiers) */
                        *type = WSCONS_EVENT_KEY_UP;
                        break;
@@ -1821,4 +1820,18 @@ wskbd_translate(struct wskbd_internal *i
 
        id->t_symbols[0] = res;
        return (1);
+}
+
+void
+wskbd_debugger(struct wskbd_softc *sc)
+{
+#ifdef DDB
+       if (sc->sc_isconsole && db_console) {
+               if (sc->id->t_consops->debugger != NULL) {
+                       (*sc->id->t_consops->debugger)
+                               (sc->id->t_consaccesscookie);
+               } else
+                       db_enter();
+       }
+#endif
 }
Index: dev/wscons/wskbdvar.h
===================================================================
RCS file: /cvs/src/sys/dev/wscons/wskbdvar.h,v
retrieving revision 1.2
diff -u -p -r1.2 wskbdvar.h
--- dev/wscons/wskbdvar.h       14 Mar 2002 01:27:03 -0000      1.2
+++ dev/wscons/wskbdvar.h       10 May 2017 12:43:42 -0000
@@ -58,6 +58,7 @@ struct wskbd_consops {
        void    (*getc)(void *, u_int *, int *);
        void    (*pollc)(void *, int);
        void    (*bell)(void *, u_int, u_int, u_int);
+       void    (*debugger)(void *);
 };
 
 /*
Index: dev/usb/ukbd.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/ukbd.c,v
retrieving revision 1.77
diff -u -p -r1.77 ukbd.c
--- dev/usb/ukbd.c      11 Mar 2017 11:55:03 -0000      1.77
+++ dev/usb/ukbd.c      10 May 2017 12:55:54 -0000
@@ -130,26 +130,30 @@ struct ukbd_softc {
 #define sc_ledsize             sc_hdev.sc_osize
 
        struct hidkbd           sc_kbd;
-
        int                     sc_spl;
-
        struct hid_location     sc_apple_fn;
-
        void                    (*sc_munge)(void *, uint8_t *, u_int);
+
+#ifdef DDB
+       struct timeout          sc_ddb; /* for entering DDB */
+#endif
 };
 
 void   ukbd_cngetc(void *, u_int *, int *);
 void   ukbd_cnpollc(void *, int);
 void   ukbd_cnbell(void *, u_int, u_int, u_int);
+void   ukbd_debugger(void *);
 
 const struct wskbd_consops ukbd_consops = {
        ukbd_cngetc,
        ukbd_cnpollc,
        ukbd_cnbell,
+       ukbd_debugger,
 };
 
 void   ukbd_intr(struct uhidev *addr, void *ibuf, u_int len);
 
+void   ukbd_db_enter(void *);
 int    ukbd_enable(void *, int);
 void   ukbd_set_leds(void *, int);
 int    ukbd_ioctl(void *, u_long, caddr_t, int, struct proc *);
@@ -322,6 +326,10 @@ ukbd_attach(struct device *parent, struc
        ukbd_set_leds(sc, 0);
 
        hidkbd_attach_wskbd(kbd, layout, &ukbd_accessops);
+
+#ifdef DDB
+       timeout_set(&sc->sc_ddb, ukbd_db_enter, sc);
+#endif
 }
 
 int
@@ -447,6 +455,28 @@ ukbd_cnbell(void *v, u_int pitch, u_int 
 {
        hidkbd_bell(pitch, period, volume, 1);
 }
+
+#ifdef DDB
+void
+ukbd_debugger(void *v)
+{
+       struct ukbd_softc *sc = v;
+
+       /*
+        * For the console keyboard we can't deliver CTL-ALT-ESC
+        * from the interrupt routine.  Doing so would start
+        * polling from inside the interrupt routine and that
+        * loses bigtime.
+        */
+       timeout_add(&sc->sc_ddb, 1);
+}
+
+void
+ukbd_db_enter(void *xsc)
+{
+       db_enter();
+}
+#endif
 
 int
 ukbd_cnattach(void)

Reply via email to