Add an asynchronous version of uhidev_get_report(), from David Higgs
authormpi <mpi@openbsd.org>
Fri, 9 Jan 2015 12:07:50 +0000 (12:07 +0000)
committermpi <mpi@openbsd.org>
Fri, 9 Jan 2015 12:07:50 +0000 (12:07 +0000)
with some tweaks.

Nothing use it for the moment, but upcoming upd(4) improvements need
it.

sys/dev/usb/uhidev.c
sys/dev/usb/uhidev.h
sys/dev/usb/usbdi.c
sys/dev/usb/usbdi.h

index 7144b5f..777218c 100644 (file)
@@ -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 $     */
 
 /*
 #include <sys/ioctl.h>
 #include <sys/conf.h>
 
+#include <machine/bus.h>
+
 #include <dev/usb/usb.h>
 #include <dev/usb/usbhid.h>
 
 #include <dev/usb/usbdevs.h>
 #include <dev/usb/usbdi.h>
 #include <dev/usb/usbdi_util.h>
+#include <dev/usb/usbdivar.h>
 #include <dev/usb/hid.h>
 #include <dev/usb/usb_quirks.h>
 
@@ -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)
 {
index 434cc76..ad00e8f 100644 (file)
@@ -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);
index c461d70..e875158 100644 (file)
@@ -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);
index a4c1539..b91697b 100644 (file)
@@ -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(