Author: hselasky
Date: Fri Sep  9 06:41:16 2016
New Revision: 305646
URL: https://svnweb.freebsd.org/changeset/base/305646

Log:
  MFC r304571:
  Make the UKBD USB transfers double buffered and set them up one by one,
  so they are memory independent which allows for handling panics
  triggered by the keyboard driver itself, typically via CTRL+ALT+ESC
  sequences. Or if the USB keyboard driver was processing a key at the
  moment of panic. Allow UKBD to be attached while keyboard polling is active.

Modified:
  stable/9/sys/dev/usb/input/ukbd.c
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/dev/usb/input/ukbd.c
==============================================================================
--- stable/9/sys/dev/usb/input/ukbd.c   Fri Sep  9 06:38:13 2016        
(r305645)
+++ stable/9/sys/dev/usb/input/ukbd.c   Fri Sep  9 06:41:16 2016        
(r305646)
@@ -107,7 +107,7 @@ TUNABLE_INT("hw.usb.ukbd.no_leds", &ukbd
 #define        UKBD_NMOD                     8 /* units */
 #define        UKBD_NKEYCODE                 6 /* units */
 #define        UKBD_IN_BUF_SIZE  (2*(UKBD_NMOD + (2*UKBD_NKEYCODE)))   /* 
bytes */
-#define        UKBD_IN_BUF_FULL  (UKBD_IN_BUF_SIZE / 2)        /* bytes */
+#define        UKBD_IN_BUF_FULL  ((UKBD_IN_BUF_SIZE / 2) - 1)  /* bytes */
 #define        UKBD_NFKEY        (sizeof(fkey_tab)/sizeof(fkey_tab[0]))        
/* units */
 #define        UKBD_BUFFER_SIZE              64        /* bytes */
 
@@ -128,7 +128,8 @@ struct ukbd_data {
 };
 
 enum {
-       UKBD_INTR_DT,
+       UKBD_INTR_DT_0,
+       UKBD_INTR_DT_1,
        UKBD_CTRL_LED,
        UKBD_N_TRANSFER,
 };
@@ -477,7 +478,8 @@ ukbd_get_key(struct ukbd_softc *sc, uint
        if (sc->sc_inputs == 0 &&
            (sc->sc_flags & UKBD_FLAG_GONE) == 0) {
                /* start transfer, if not already started */
-               usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT]);
+               usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT_0]);
+               usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT_1]);
        }
 
        if (sc->sc_flags & UKBD_FLAG_POLLING)
@@ -953,7 +955,16 @@ ukbd_set_leds_callback(struct usb_xfer *
 
 static const struct usb_config ukbd_config[UKBD_N_TRANSFER] = {
 
-       [UKBD_INTR_DT] = {
+       [UKBD_INTR_DT_0] = {
+               .type = UE_INTERRUPT,
+               .endpoint = UE_ADDR_ANY,
+               .direction = UE_DIR_IN,
+               .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+               .bufsize = 0,   /* use wMaxPacketSize */
+               .callback = &ukbd_intr_callback,
+       },
+
+       [UKBD_INTR_DT_1] = {
                .type = UE_INTERRUPT,
                .endpoint = UE_ADDR_ANY,
                .direction = UE_DIR_IN,
@@ -1198,9 +1209,26 @@ ukbd_attach(device_t dev)
 
        usb_callout_init_mtx(&sc->sc_callout, &Giant, 0);
 
+#ifdef UKBD_NO_POLLING
        err = usbd_transfer_setup(uaa->device,
            &uaa->info.bIfaceIndex, sc->sc_xfer, ukbd_config,
            UKBD_N_TRANSFER, sc, &Giant);
+#else
+       /*
+        * Setup the UKBD USB transfers one by one, so they are memory
+        * independent which allows for handling panics triggered by
+        * the keyboard driver itself, typically via CTRL+ALT+ESC
+        * sequences. Or if the USB keyboard driver was processing a
+        * key at the moment of panic.
+        */
+       for (n = 0; n != UKBD_N_TRANSFER; n++) {
+               err = usbd_transfer_setup(uaa->device,
+                   &uaa->info.bIfaceIndex, sc->sc_xfer + n, ukbd_config + n,
+                   1, sc, &Giant);
+               if (err)
+                       break;
+       }
+#endif
 
        if (err) {
                DPRINTF("error=%s\n", usbd_errstr(err));
@@ -1283,7 +1311,8 @@ ukbd_attach(device_t dev)
        }
 
        /* start the keyboard */
-       usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT]);
+       usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT_0]);
+       usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT_1]);
 
        return (0);                     /* success */
 
@@ -1309,7 +1338,8 @@ ukbd_detach(device_t dev)
        /* kill any stuck keys */
        if (sc->sc_flags & UKBD_FLAG_ATTACHED) {
                /* stop receiving events from the USB keyboard */
-               usbd_transfer_stop(sc->sc_xfer[UKBD_INTR_DT]);
+               usbd_transfer_stop(sc->sc_xfer[UKBD_INTR_DT_0]);
+               usbd_transfer_stop(sc->sc_xfer[UKBD_INTR_DT_1]);
 
                /* release all leftover keys, if any */
                memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata));
@@ -1974,7 +2004,7 @@ ukbd_poll(keyboard_t *kbd, int on)
         */
        if (on)
                sc->sc_polling++;
-       else
+       else if (sc->sc_polling > 0)
                sc->sc_polling--;
 
        if (sc->sc_polling != 0) {
_______________________________________________
svn-src-stable-9@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-9
To unsubscribe, send any mail to "svn-src-stable-9-unsubscr...@freebsd.org"

Reply via email to