From owner-svn-src-all@freebsd.org Sun Aug 21 18:37:22 2016 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id EE3F9BC1B85; Sun, 21 Aug 2016 18:37:22 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id CA6D81EEC; Sun, 21 Aug 2016 18:37:22 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u7LIbMEH020766; Sun, 21 Aug 2016 18:37:22 GMT (envelope-from hselasky@FreeBSD.org) Received: (from hselasky@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u7LIbM1t020765; Sun, 21 Aug 2016 18:37:22 GMT (envelope-from hselasky@FreeBSD.org) Message-Id: <201608211837.u7LIbM1t020765@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: hselasky set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky Date: Sun, 21 Aug 2016 18:37:22 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r304571 - head/sys/dev/usb/input X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 21 Aug 2016 18:37:23 -0000 Author: hselasky Date: Sun Aug 21 18:37:21 2016 New Revision: 304571 URL: https://svnweb.freebsd.org/changeset/base/304571 Log: 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. Tested by: Bruce Evans MFC after: 1 week Modified: head/sys/dev/usb/input/ukbd.c Modified: head/sys/dev/usb/input/ukbd.c ============================================================================== --- head/sys/dev/usb/input/ukbd.c Sun Aug 21 18:12:49 2016 (r304570) +++ head/sys/dev/usb/input/ukbd.c Sun Aug 21 18:37:21 2016 (r304571) @@ -108,7 +108,7 @@ SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, pollr #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 */ @@ -129,7 +129,8 @@ struct ukbd_data { }; enum { - UKBD_INTR_DT, + UKBD_INTR_DT_0, + UKBD_INTR_DT_1, UKBD_CTRL_LED, UKBD_N_TRANSFER, }; @@ -478,7 +479,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) @@ -954,7 +956,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, @@ -1201,9 +1212,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)); @@ -1295,11 +1323,13 @@ ukbd_attach(device_t dev) rate = 1000 / rate; /* set new polling interval in ms */ - usbd_xfer_set_interval(sc->sc_xfer[UKBD_INTR_DT], rate); + usbd_xfer_set_interval(sc->sc_xfer[UKBD_INTR_DT_0], rate); + usbd_xfer_set_interval(sc->sc_xfer[UKBD_INTR_DT_1], rate); } #endif /* 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 */ @@ -1325,7 +1355,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)); @@ -1979,7 +2010,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) {