Page MenuHomeFreeBSD

D30486.diff
No OneTemporary

D30486.diff

diff --git a/sys/dev/hid/hid_if.m b/sys/dev/hid/hid_if.m
--- a/sys/dev/hid/hid_if.m
+++ b/sys/dev/hid/hid_if.m
@@ -44,8 +44,8 @@
# rdesc is pointer to structire containing requested maximal sizes of input,
# output and feature reports. It is used by hardware transport drivers
# to determine sizes of internal buffers.
-# This function returns zero upon success. A non-zero return value indicates
-# failure.
+# This function can be subsequently called with intr parameter set to NULL
+# to request intr_poll method support for transport driver.
#
METHOD void intr_setup {
device_t dev;
@@ -76,8 +76,9 @@
};
#
-# The following function gets called from the HID keyboard driver
-# when the system has paniced.
+# The following function gets called from the HID keyboard driver when
+# the system has paniced. intr_setup method with NULL passed as intr parameter
+# must be called once before to let transport driver to be prepared.
#
METHOD void intr_poll {
device_t dev;
diff --git a/sys/dev/hid/hidbus.c b/sys/dev/hid/hidbus.c
--- a/sys/dev/hid/hidbus.c
+++ b/sys/dev/hid/hidbus.c
@@ -457,6 +457,9 @@
break;
case HIDBUS_IVAR_FLAGS:
tlc->flags = value;
+ if ((value & HIDBUS_FLAG_CAN_POLL) != 0)
+ HID_INTR_SETUP(
+ device_get_parent(bus), NULL, NULL, NULL);
break;
case HIDBUS_IVAR_DRIVER_INFO:
tlc->driver_info = value;
diff --git a/sys/dev/iicbus/iichid.c b/sys/dev/iicbus/iichid.c
--- a/sys/dev/iicbus/iichid.c
+++ b/sys/dev/iicbus/iichid.c
@@ -782,6 +782,9 @@
{
struct iichid_softc *sc;
+ if (intr == NULL)
+ return;
+
sc = device_get_softc(dev);
/*
* Do not rely on wMaxInputLength, as some devices may set it to
diff --git a/sys/dev/usb/input/usbhid.c b/sys/dev/usb/input/usbhid.c
--- a/sys/dev/usb/input/usbhid.c
+++ b/sys/dev/usb/input/usbhid.c
@@ -67,6 +67,7 @@
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbhid.h>
+#include <dev/usb/usb_core.h>
#define USB_DEBUG_VAR usbhid_debug
#include <dev/usb/usb_debug.h>
@@ -85,6 +86,8 @@
&usbhid_debug, 0, "Debug level");
#endif
+/* Second set of USB transfers for polling mode */
+#define POLL_XFER(xfer) ((xfer) + USBHID_N_TRANSFER)
enum {
USBHID_INTR_OUT_DT,
USBHID_INTR_IN_DT,
@@ -123,8 +126,9 @@
struct mtx sc_mtx;
struct usb_config sc_config[USBHID_N_TRANSFER];
- struct usb_xfer *sc_xfer[USBHID_N_TRANSFER];
- struct usbhid_xfer_ctx sc_xfer_ctx[USBHID_N_TRANSFER];
+ struct usb_xfer *sc_xfer[POLL_XFER(USBHID_N_TRANSFER)];
+ struct usbhid_xfer_ctx sc_xfer_ctx[POLL_XFER(USBHID_N_TRANSFER)];
+ bool sc_can_poll;
struct usb_device *sc_udev;
uint8_t sc_iface_no;
@@ -317,6 +321,8 @@
static inline int
usbhid_xfer_check_len(struct usbhid_softc* sc, int xfer_idx, hid_size_t len)
{
+ if (USB_IN_POLLING_MODE_FUNC())
+ xfer_idx = POLL_XFER(xfer_idx);
if (sc->sc_xfer[xfer_idx] == NULL)
return (ENODEV);
if (len > usbd_xfer_max_len(sc->sc_xfer[xfer_idx]))
@@ -333,6 +339,39 @@
bool nowrite;
int error;
+ nowrite = hid_test_quirk(&sc->sc_hw, HQ_NOWRITE);
+
+ /*
+ * Setup the USB transfers one by one, so they are memory independent
+ * which allows for handling panics triggered by the HID drivers
+ * itself, typically by hkbd via CTRL+ALT+ESC sequences. Or if the HID
+ * keyboard driver was processing a key at the moment of panic.
+ */
+ if (intr == NULL) {
+ if (sc->sc_can_poll)
+ return;
+ for (n = 0; n != USBHID_N_TRANSFER; n++) {
+ if (nowrite && n == USBHID_INTR_OUT_DT)
+ continue;
+ error = usbd_transfer_setup(sc->sc_udev,
+ &sc->sc_iface_index, sc->sc_xfer + POLL_XFER(n),
+ sc->sc_config + n, 1,
+ (void *)(sc->sc_xfer_ctx + POLL_XFER(n)),
+ &sc->sc_mtx);
+ if (error)
+ DPRINTF("xfer %d setup error=%s\n", n,
+ usbd_errstr(error));
+ }
+ mtx_lock(&sc->sc_mtx);
+ if (sc->sc_xfer[USBHID_INTR_IN_DT] != NULL &&
+ sc->sc_xfer[USBHID_INTR_IN_DT]->flags_int.started)
+ usbd_transfer_start(
+ sc->sc_xfer[POLL_XFER(USBHID_INTR_IN_DT)]);
+ mtx_unlock(&sc->sc_mtx);
+ sc->sc_can_poll = true;
+ return;
+ }
+
sc->sc_intr_handler = intr;
sc->sc_intr_ctx = context;
bcopy(usbhid_config, sc->sc_config, sizeof(usbhid_config));
@@ -344,14 +383,6 @@
sc->sc_config[USBHID_CTRL_DT].bufsize =
MAX(rdesc->isize, MAX(rdesc->osize, rdesc->fsize));
- nowrite = hid_test_quirk(&sc->sc_hw, HQ_NOWRITE);
-
- /*
- * Setup the USB transfers one by one, so they are memory independent
- * which allows for handling panics triggered by the HID drivers
- * itself, typically by hkbd via CTRL+ALT+ESC sequences. Or if the HID
- * keyboard driver was processing a key at the moment of panic.
- */
for (n = 0; n != USBHID_N_TRANSFER; n++) {
if (nowrite && n == USBHID_INTR_OUT_DT)
continue;
@@ -378,6 +409,10 @@
struct usbhid_softc* sc = device_get_softc(dev);
usbd_transfer_unsetup(sc->sc_xfer, USBHID_N_TRANSFER);
+ if (sc->sc_can_poll)
+ usbd_transfer_unsetup(
+ sc->sc_xfer, POLL_XFER(USBHID_N_TRANSFER));
+ sc->sc_can_poll = false;
free(sc->sc_intr_buf, M_USBDEV);
}
@@ -397,7 +432,16 @@
.cb_ctx = sc,
.buf = sc->sc_intr_buf,
};
+ sc->sc_xfer_ctx[POLL_XFER(USBHID_INTR_IN_DT)] = (struct usbhid_xfer_ctx) {
+ .req.intr.maxlen =
+ usbd_xfer_max_len(sc->sc_xfer[USBHID_INTR_IN_DT]),
+ .cb = usbhid_intr_handler_cb,
+ .cb_ctx = sc,
+ .buf = sc->sc_intr_buf,
+ };
usbd_transfer_start(sc->sc_xfer[USBHID_INTR_IN_DT]);
+ if (sc->sc_can_poll)
+ usbd_transfer_start(sc->sc_xfer[POLL_XFER(USBHID_INTR_IN_DT)]);
mtx_unlock(&sc->sc_mtx);
return (0);
@@ -410,6 +454,8 @@
usbd_transfer_drain(sc->sc_xfer[USBHID_INTR_IN_DT]);
usbd_transfer_drain(sc->sc_xfer[USBHID_INTR_OUT_DT]);
+ if (sc->sc_can_poll)
+ usbd_transfer_drain(sc->sc_xfer[POLL_XFER(USBHID_INTR_IN_DT)]);
return (0);
}
@@ -419,7 +465,9 @@
{
struct usbhid_softc* sc = device_get_softc(dev);
+ MPASS(sc->sc_can_poll);
usbd_transfer_poll(sc->sc_xfer + USBHID_INTR_IN_DT, 1);
+ usbd_transfer_poll(sc->sc_xfer + POLL_XFER(USBHID_INTR_IN_DT), 1);
}
/*
@@ -430,12 +478,13 @@
union usbhid_device_request *req, void *buf)
{
int error, timeout;
- struct usbhid_xfer_ctx *xfer_ctx, save;
+ struct usbhid_xfer_ctx *xfer_ctx;
xfer_ctx = sc->sc_xfer_ctx + xfer_idx;
if (USB_IN_POLLING_MODE_FUNC()) {
- save = *xfer_ctx;
+ xfer_ctx = POLL_XFER(xfer_ctx);
+ xfer_idx = POLL_XFER(xfer_idx);
} else {
mtx_lock(&sc->sc_mtx);
++xfer_ctx->waiters;
@@ -473,9 +522,7 @@
if (error == 0)
*req = xfer_ctx->req;
- if (USB_IN_POLLING_MODE_FUNC()) {
- *xfer_ctx = save;
- } else {
+ if (!USB_IN_POLLING_MODE_FUNC()) {
xfer_ctx->influx = false;
if (xfer_ctx->waiters != 0)
wakeup_one(&xfer_ctx->waiters);

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 17, 9:16 PM (21 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14684774
Default Alt Text
D30486.diff (6 KB)

Event Timeline