summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2013-11-01 12:05:27 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2013-11-01 12:05:27 +0000
commit1f302a5e30a7d416a32b6dfc8a3e63750069c3e5 (patch)
treedcca24cccca94c67996cc992acbbc0f63a228033 /sys/dev
parent8de4f21f9c368b1fdeaafe1e74718c25a926b29e (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.c44
-rw-r--r--sys/dev/usb/uhidev.h6
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);