Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102765886
D30486.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D30486.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D30486: usbhid(4): Add second set of USB transfers to work in polled mode.
Attached
Detach File
Event Timeline
Log In to Comment