On Friday, February 13, 2015, Martin Pieuchot <mpieuc...@nolizard.org>
wrote:

> 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?


> Partially but not enough.  I had already figured out that I needed that
to solve the NULL pointer dereference.  See my 2nd paragraph above.

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