diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2013-11-01 12:05:27 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2013-11-01 12:05:27 +0000 |
commit | 1f302a5e30a7d416a32b6dfc8a3e63750069c3e5 (patch) | |
tree | dcca24cccca94c67996cc992acbbc0f63a228033 /sys/dev | |
parent | 8de4f21f9c368b1fdeaafe1e74718c25a926b29e (diff) |
Do not abuse the stack of the current process to prepend a report ID
to the report request, use malloc(9) with the appropriate size like
it is done in the synchronous version.
ok miod@
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/usb/uhidev.c | 44 | ||||
-rw-r--r-- | sys/dev/usb/uhidev.h | 6 |
2 files changed, 28 insertions, 22 deletions
diff --git a/sys/dev/usb/uhidev.c b/sys/dev/usb/uhidev.c index 341d08e2aca..0bf42b0b408 100644 --- a/sys/dev/usb/uhidev.c +++ b/sys/dev/usb/uhidev.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uhidev.c,v 1.47 2013/10/25 03:09:59 jeremy Exp $ */ +/* $OpenBSD: uhidev.c,v 1.48 2013/11/01 12:05:26 mpi Exp $ */ /* $NetBSD: uhidev.c,v 1.14 2003/03/11 16:44:00 augustss Exp $ */ /* @@ -611,27 +611,33 @@ uhidev_set_report(struct uhidev *scd, int type, void *data, int len) return retstat; } -void +usbd_status uhidev_set_report_async(struct uhidev *scd, int type, void *data, int len) { - /* XXX */ - char buf[100]; - if (scd->sc_report_id) { - buf[0] = scd->sc_report_id; - if ((uint)len > sizeof(buf) - 1) { -#ifdef DIAGNOSTIC - printf("%s: report length too large (%d)\n", - scd->sc_dev.dv_xname, len); -#endif - return; - } - memcpy(buf+1, data, len); - len++; - data = buf; - } + char *buf; + usbd_status retstat; + + if (scd->sc_report_id == 0) + return usbd_set_report_async(scd->sc_parent->sc_iface, type, + scd->sc_report_id, data, len); + + buf = malloc(len + 1, M_TEMP, M_NOWAIT); + if (buf == NULL) + return (USBD_NOMEM); + buf[0] = scd->sc_report_id; + memcpy(buf+1, data, len); + + retstat = usbd_set_report_async(scd->sc_parent->sc_iface, type, + scd->sc_report_id, buf, len + 1); - usbd_set_report_async(scd->sc_parent->sc_iface, type, - scd->sc_report_id, data, len); + /* + * 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. + */ + free(buf, M_TEMP); + + return retstat; } usbd_status diff --git a/sys/dev/usb/uhidev.h b/sys/dev/usb/uhidev.h index 8b310cad237..cbffaa744e8 100644 --- a/sys/dev/usb/uhidev.h +++ b/sys/dev/usb/uhidev.h @@ -1,4 +1,4 @@ -/* $OpenBSD: uhidev.h,v 1.13 2013/05/07 08:44:38 mpi Exp $ */ +/* $OpenBSD: uhidev.h,v 1.14 2013/11/01 12:05:26 mpi Exp $ */ /* $NetBSD: uhidev.h,v 1.3 2002/10/08 09:56:17 dan Exp $ */ /* @@ -88,7 +88,7 @@ void uhidev_get_report_desc(struct uhidev_softc *, void **, int *); int uhidev_open(struct uhidev *); void uhidev_close(struct uhidev *); int uhidev_ioctl(struct uhidev *, u_long, caddr_t, int, struct proc *); -usbd_status uhidev_set_report(struct uhidev *scd, int type, void *data,int len); -void uhidev_set_report_async(struct uhidev *scd, int type, void *data, int len); +usbd_status uhidev_set_report(struct uhidev *, int, void *, int); +usbd_status uhidev_set_report_async(struct uhidev *, int, void *, int); usbd_status uhidev_get_report(struct uhidev *scd, int type, void *data,int len); usbd_status uhidev_write(struct uhidev_softc *, void *, int); |