On 13/02/15(Fri) 00:28, David Higgs wrote:
> I guess nobody else has tried calling uhidev_get_report_async() yet.  :)
> 
> First I was getting a NULL pointer deref in the uhidev async callback.
> Then I realized that due to USBD_NO_COPY, xfer->buffer was always
> NULL.  Next, I tried to use the DMA buffer, but I ended up in DDB in a
> very cryptic way.  I believe this is because the DMA buffer isn't
> available when the callback is invoked.
> 
> For the async callback to get a valid dmabuf, it needs to be invoked
> prior to usb_freemem() in usbd_transfer_complete().  The xfer->status
> determination would need to move up too.  I'd do this myself but I
> don't understand the logic and ordering of pipe->repeat stuff, and am
> concerned about unintentionally breaking other devices.
> 
> This is partially my fault, because I "tested" the original diff that
> added the USBD_NO_COPY semantics to verify that it didn't break my
> synchronous code paths, but hadn't yet written anything for upd(4) to
> check the async ones.

Does the diff below help?

Index: uhidev.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/uhidev.c,v
retrieving revision 1.69
diff -u -p -r1.69 uhidev.c
--- uhidev.c    22 Jan 2015 10:27:47 -0000      1.69
+++ uhidev.c    13 Feb 2015 05:58:06 -0000
@@ -55,6 +55,7 @@
 #include <dev/usb/usbdivar.h>
 #include <dev/usb/hid.h>
 #include <dev/usb/usb_quirks.h>
+#include <dev/usb/usb_mem.h>
 
 #include <dev/usb/uhidev.h>
 
@@ -747,15 +748,17 @@ void
 uhidev_get_report_async_cb(struct usbd_xfer *xfer, void *priv, usbd_status err)
 {
        struct uhidev_async_info *info = priv;
+       char *buffer;
        int len = -1;
 
        if (err == USBD_NORMAL_COMPLETION || err == USBD_SHORT_XFER) {
+               buffer = KERNADDR(&xfer->dmabuf, 0);
                len = xfer->actlen;
                if (info->id > 0) {
                        len--;
-                       memcpy(info->data, xfer->buffer + 1, len);
+                       memcpy(info->data, buffer + 1, len);
                } else {
-                       memcpy(info->data, xfer->buffer, len);
+                       memcpy(info->data, buffer, len);
                }
        }
        info->callback(info->priv, info->id, info->data, len);

Reply via email to