diff options
| author | 2015-01-22 10:27:47 +0000 | |
|---|---|---|
| committer | 2015-01-22 10:27:47 +0000 | |
| commit | 4f731aad272daa2f3d9eb51ecdfabce8b1271b49 (patch) | |
| tree | e34e4e3b1fd7951a3b287504e46de6cdb21b9f49 /sys/dev/usb/uhidev.c | |
| parent | Use correct error type and remove unused interface pointer. (diff) | |
| download | wireguard-openbsd-4f731aad272daa2f3d9eb51ecdfabce8b1271b49.tar.xz wireguard-openbsd-4f731aad272daa2f3d9eb51ecdfabce8b1271b49.zip | |
Reduce the number of intermediate buffers by pre-allocating DMA buffers
in the report functions instead of letting the stack do it magically for
us.
Reviewed and tested by David Higgs, thanks!
Diffstat (limited to 'sys/dev/usb/uhidev.c')
| -rw-r--r-- | sys/dev/usb/uhidev.c | 73 |
1 files changed, 41 insertions, 32 deletions
diff --git a/sys/dev/usb/uhidev.c b/sys/dev/usb/uhidev.c index 46ca3e52b02..27e1e60de68 100644 --- a/sys/dev/usb/uhidev.c +++ b/sys/dev/usb/uhidev.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uhidev.c,v 1.68 2015/01/09 12:09:51 mpi Exp $ */ +/* $OpenBSD: uhidev.c,v 1.69 2015/01/22 10:27:47 mpi Exp $ */ /* $NetBSD: uhidev.c,v 1.14 2003/03/11 16:44:00 augustss Exp $ */ /* @@ -671,18 +671,30 @@ int uhidev_set_report_async(struct uhidev_softc *sc, int type, int id, void *data, int len) { + struct usbd_xfer *xfer; usb_device_request_t req; - char *buf = data; int actlen = len; + char *buf; + + xfer = usbd_alloc_xfer(sc->sc_udev); + if (xfer == NULL) + return (-1); + + if (id > 0) + len++; + + buf = usbd_alloc_buffer(xfer, len); + if (buf == NULL) { + usbd_free_xfer(xfer); + return (-1); + } /* Prepend the reportID. */ if (id > 0) { - len++; - buf = malloc(len, M_TEMP, M_NOWAIT); - if (buf == NULL) - return (-1); buf[0] = id; memcpy(buf + 1, data, len - 1); + } else { + memcpy(buf, data, len); } req.bmRequestType = UT_WRITE_CLASS_INTERFACE; @@ -691,17 +703,9 @@ uhidev_set_report_async(struct uhidev_softc *sc, int type, int id, void *data, USETW(req.wIndex, sc->sc_ifaceno); USETW(req.wLength, len); - if (usbd_do_request_async(sc->sc_udev, &req, buf, NULL, NULL)) + if (usbd_request_async(xfer, &req, NULL, NULL)) actlen = -1; - /* - * Since report requests are write-only it is safe to free - * the buffer right after submitting the transfer because - * it won't be used afterward. - */ - if (id > 0) - free(buf, M_TEMP, len); - return (actlen); } @@ -750,11 +754,11 @@ uhidev_get_report_async_cb(struct usbd_xfer *xfer, void *priv, usbd_status err) if (info->id > 0) { len--; memcpy(info->data, xfer->buffer + 1, len); + } else { + memcpy(info->data, xfer->buffer, len); } } info->callback(info->priv, info->id, info->data, len); - if (info->id > 0) - free(xfer->buffer, M_TEMP, xfer->length); free(info, M_TEMP, sizeof(*info)); usbd_free_xfer(xfer); } @@ -763,42 +767,47 @@ int uhidev_get_report_async(struct uhidev_softc *sc, int type, int id, void *data, int len, void *priv, void (*callback)(void *, int, void *, int)) { + struct usbd_xfer *xfer; usb_device_request_t req; struct uhidev_async_info *info; - char *buf = data; int actlen = len; + char *buf; + + xfer = usbd_alloc_xfer(sc->sc_udev); + if (xfer == NULL) + return (-1); + + if (id > 0) + len++; + + buf = usbd_alloc_buffer(xfer, len); + if (buf == NULL) { + usbd_free_xfer(xfer); + return (-1); + } info = malloc(sizeof(*info), M_TEMP, M_NOWAIT); - if (info == NULL) + if (info == NULL) { + usbd_free_xfer(xfer); return (-1); + } info->callback = callback; info->priv = priv; info->data = data; info->id = id; - if (id > 0) { - len++; - buf = malloc(len, M_TEMP, M_NOWAIT|M_ZERO); - if (buf == NULL) { - free(info, M_TEMP, sizeof(*info)); - return (-1); - } - } - req.bmRequestType = UT_READ_CLASS_INTERFACE; req.bRequest = UR_GET_REPORT; USETW2(req.wValue, type, id); USETW(req.wIndex, sc->sc_ifaceno); USETW(req.wLength, len); - if (usbd_do_request_async(sc->sc_udev, &req, buf, priv, - uhidev_get_report_async_cb)) { + if (usbd_request_async(xfer, &req, priv, uhidev_get_report_async_cb)) { free(info, M_TEMP, sizeof(*info)); - if (id > 0) - free(buf, M_TEMP, len); actlen = -1; } + return (actlen); } |
