From 3541a1e38c63c01fd011130e727a19efa30fd874 Mon Sep 17 00:00:00 2001 From: mpi Date: Fri, 9 Jan 2015 12:07:50 +0000 Subject: [PATCH] Add an asynchronous version of uhidev_get_report(), from David Higgs with some tweaks. Nothing use it for the moment, but upcoming upd(4) improvements need it. --- sys/dev/usb/uhidev.c | 80 ++++++++++++++++++++++++++++++++++++++++++-- sys/dev/usb/uhidev.h | 4 ++- sys/dev/usb/usbdi.c | 12 ++++--- sys/dev/usb/usbdi.h | 4 +-- 4 files changed, 90 insertions(+), 10 deletions(-) diff --git a/sys/dev/usb/uhidev.c b/sys/dev/usb/uhidev.c index 7144b5f7094..777218c5fd8 100644 --- a/sys/dev/usb/uhidev.c +++ b/sys/dev/usb/uhidev.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uhidev.c,v 1.66 2014/12/13 21:05:33 doug Exp $ */ +/* $OpenBSD: uhidev.c,v 1.67 2015/01/09 12:07:50 mpi Exp $ */ /* $NetBSD: uhidev.c,v 1.14 2003/03/11 16:44:00 augustss Exp $ */ /* @@ -44,12 +44,15 @@ #include #include +#include + #include #include #include #include #include +#include #include #include @@ -72,6 +75,13 @@ int uhidevdebug = 0; #define DPRINTFN(n,x) #endif +struct uhidev_async_info { + void (*callback)(void *priv, int id, void *data, int len); + void *priv; + void *data; + int id; +}; + void uhidev_intr(struct usbd_xfer *, void *, usbd_status); int uhidev_maxrepid(void *buf, int len); @@ -83,6 +93,9 @@ void uhidev_attach(struct device *, struct device *, void *); int uhidev_detach(struct device *, int); int uhidev_activate(struct device *, int); +void uhidev_get_report_async_cb(struct usbd_xfer *xfer, void *priv, + usbd_status status); + struct cfdriver uhidev_cd = { NULL, "uhidev", DV_DULL }; @@ -678,7 +691,7 @@ 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)) + if (usbd_do_request_async(sc->sc_udev, &req, buf, NULL, NULL)) actlen = -1; /* @@ -726,6 +739,69 @@ uhidev_get_report(struct uhidev_softc *sc, int type, int id, void *data, return (actlen); } +void +uhidev_get_report_async_cb(struct usbd_xfer *xfer, void *priv, usbd_status err) +{ + struct uhidev_async_info *info = priv; + int len = -1; + + if (err == USBD_NORMAL_COMPLETION || err == USBD_SHORT_XFER) { + len = xfer->actlen; + if (info->id > 0) { + len--; + memcpy(info->data, xfer->buffer + 1, 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); +} + +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)) +{ + usb_device_request_t req; + struct uhidev_async_info *info; + char *buf = data; + int actlen = len; + + info = malloc(sizeof(*info), M_TEMP, M_NOWAIT); + if (info == NULL) + 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)) { + free(info, M_TEMP, sizeof(*info)); + if (id > 0) + free(buf, M_TEMP, len); + actlen = -1; + } + return (actlen); +} + usbd_status uhidev_write(struct uhidev_softc *sc, void *data, int len) { diff --git a/sys/dev/usb/uhidev.h b/sys/dev/usb/uhidev.h index 434cc76a1fb..ad00e8f8bf7 100644 --- a/sys/dev/usb/uhidev.h +++ b/sys/dev/usb/uhidev.h @@ -1,4 +1,4 @@ -/* $OpenBSD: uhidev.h,v 1.21 2014/12/11 18:39:27 mpi Exp $ */ +/* $OpenBSD: uhidev.h,v 1.22 2015/01/09 12:07:50 mpi Exp $ */ /* $NetBSD: uhidev.h,v 1.3 2002/10/08 09:56:17 dan Exp $ */ /* @@ -91,4 +91,6 @@ int uhidev_ioctl(struct uhidev *, u_long, caddr_t, int, struct proc *); int uhidev_set_report(struct uhidev_softc *, int, int, void *, int); int uhidev_set_report_async(struct uhidev_softc *, int, int, void *, int); int uhidev_get_report(struct uhidev_softc *, int, int, void *, int); +int uhidev_get_report_async(struct uhidev_softc *, int, int, void *, int, + void *, void (*)(void *, int, void *, int)); usbd_status uhidev_write(struct uhidev_softc *, void *, int); diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c index c461d70c787..e875158358e 100644 --- a/sys/dev/usb/usbdi.c +++ b/sys/dev/usb/usbdi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: usbdi.c,v 1.75 2014/11/01 00:41:33 mpi Exp $ */ +/* $OpenBSD: usbdi.c,v 1.76 2015/01/09 12:07:50 mpi Exp $ */ /* $NetBSD: usbdi.c,v 1.103 2002/09/27 15:37:38 provos Exp $ */ /* $FreeBSD: src/sys/dev/usb/usbdi.c,v 1.28 1999/11/17 22:33:49 n_hibma Exp $ */ @@ -596,7 +596,7 @@ usbd_clear_endpoint_stall_async(struct usbd_pipe *pipe) USETW(req.wValue, UF_ENDPOINT_HALT); USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress); USETW(req.wLength, 0); - err = usbd_do_request_async(dev, &req, 0); + err = usbd_do_request_async(dev, &req, 0, 0, 0); return (err); } @@ -979,7 +979,7 @@ usbd_do_request_async_cb(struct usbd_xfer *xfer, void *priv, */ usbd_status usbd_do_request_async(struct usbd_device *dev, usb_device_request_t *req, - void *data) + void *data, void *priv, usbd_callback callback) { struct usbd_xfer *xfer; usbd_status err; @@ -987,8 +987,10 @@ usbd_do_request_async(struct usbd_device *dev, usb_device_request_t *req, xfer = usbd_alloc_xfer(dev); if (xfer == NULL) return (USBD_NOMEM); - usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req, - data, UGETW(req->wLength), 0, usbd_do_request_async_cb); + if (callback == NULL) + callback = usbd_do_request_async_cb; + usbd_setup_default_xfer(xfer, dev, priv, USBD_DEFAULT_TIMEOUT, req, + data, UGETW(req->wLength), 0, callback); err = usbd_transfer(xfer); if (err != USBD_IN_PROGRESS) { usbd_free_xfer(xfer); diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h index a4c15393f76..b91697b2fc8 100644 --- a/sys/dev/usb/usbdi.h +++ b/sys/dev/usb/usbdi.h @@ -1,4 +1,4 @@ -/* $OpenBSD: usbdi.h,v 1.63 2014/08/10 11:18:57 mpi Exp $ */ +/* $OpenBSD: usbdi.h,v 1.64 2015/01/09 12:07:50 mpi Exp $ */ /* $NetBSD: usbdi.h,v 1.62 2002/07/11 21:14:35 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/usbdi.h,v 1.18 1999/11/17 22:33:49 n_hibma Exp $ */ @@ -122,7 +122,7 @@ usbd_status usbd_open_pipe_intr(struct usbd_interface *iface, u_int8_t address, usbd_status usbd_do_request(struct usbd_device *pipe, usb_device_request_t *req, void *data); usbd_status usbd_do_request_async(struct usbd_device *pipe, - usb_device_request_t *req, void *data); + usb_device_request_t *req, void *data, void *priv, usbd_callback callback); usbd_status usbd_do_request_flags(struct usbd_device *pipe, usb_device_request_t *req, void *data, u_int16_t flags, int*, u_int32_t); usb_interface_descriptor_t *usbd_get_interface_descriptor( -- 2.20.1