summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2004-10-31 12:10:53 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2004-10-31 12:10:53 +0000
commitb6bf3206fb196dacf40c0e28a25f7461e115c923 (patch)
tree94996de594d941cee2071a77a0a22537b85df81b
parent7325169003f85df86e20ac2b8785c127fe247dd5 (diff)
from netbsd via freebsd via jsg@
usbdi_util.h (1.29), uhid.c (1.62), ugen.c (1.68), usb_subr.c (1.114) Yes, some devices return incorrect lengths in their string descriptors. Rather than losing, do what Windows does: just request the maximum size, and allow a shorter response. Obsoletes the need for UQ_NO_STRINGS, and therefore these "quirks" are removed. usb_subr.c (1.116) In the "seemed like a good idea until I found the fatal flaw" department... Attempting to read a maximum-size string descriptor causes my kue device to go completely apeshit. So, go back to the original method, but allow the device to return a shorter string than it claimed.
-rw-r--r--sys/dev/usb/ugen.c7
-rw-r--r--sys/dev/usb/usb_subr.c29
-rw-r--r--sys/dev/usb/usbdi_util.h5
3 files changed, 29 insertions, 12 deletions
diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c
index b7f955fd601..777c2916cdd 100644
--- a/sys/dev/usb/ugen.c
+++ b/sys/dev/usb/ugen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ugen.c,v 1.30 2004/07/21 00:01:07 dlg Exp $ */
+/* $OpenBSD: ugen.c,v 1.31 2004/10/31 12:10:52 dlg Exp $ */
/* $NetBSD: ugen.c,v 1.63 2002/11/26 18:49:48 christos Exp $ */
/* $FreeBSD: src/sys/dev/usb/ugen.c,v 1.26 1999/11/17 22:33:41 n_hibma Exp $ */
@@ -1227,12 +1227,15 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd,
return (error);
}
case USB_GET_STRING_DESC:
+ {
+ int len;
si = (struct usb_string_desc *)addr;
err = usbd_get_string_desc(sc->sc_udev, si->usd_string_index,
- si->usd_language_id, &si->usd_desc);
+ si->usd_language_id, &si->usd_desc, &len);
if (err)
return (EINVAL);
break;
+ }
case USB_DO_REQUEST:
{
struct usb_ctl_request *ur = (void *)addr;
diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c
index 2e6895ee421..c2c68e52b9a 100644
--- a/sys/dev/usb/usb_subr.c
+++ b/sys/dev/usb/usb_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: usb_subr.c,v 1.28 2004/08/30 03:06:48 drahn Exp $ */
+/* $OpenBSD: usb_subr.c,v 1.29 2004/10/31 12:10:52 dlg Exp $ */
/* $NetBSD: usb_subr.c,v 1.103 2003/01/10 11:19:13 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $ */
@@ -150,7 +150,7 @@ usbd_errstr(usbd_status err)
usbd_status
usbd_get_string_desc(usbd_device_handle dev, int sindex, int langid,
- usb_string_descriptor_t *sdesc)
+ usb_string_descriptor_t *sdesc, int *sizep)
{
usb_device_request_t req;
usbd_status err;
@@ -166,11 +166,22 @@ usbd_get_string_desc(usbd_device_handle dev, int sindex, int langid,
if (err)
return (err);
- if (actlen < 1)
+ if (actlen < 2)
return (USBD_SHORT_XFER);
USETW(req.wLength, sdesc->bLength); /* the whole string */
- return (usbd_do_request(dev, &req, sdesc));
+ err = usbd_do_request_flags(dev, &req, sdesc, USBD_SHORT_XFER_OK,
+ &actlen, USBD_DEFAULT_TIMEOUT);
+ if (err)
+ return (err);
+
+ if (actlen != sdesc->bLength) {
+ DPRINTFN(-1, ("usbd_get_string_desc: expected %d, got %d\n",
+ sdesc->bLength, actlen));
+ }
+
+ *sizep = actlen;
+ return (USBD_NORMAL_COMPLETION);
}
char *
@@ -182,6 +193,7 @@ usbd_get_string(usbd_device_handle dev, int si, char *buf)
int i, n;
u_int16_t c;
usbd_status err;
+ int size;
if (si == 0)
return (0);
@@ -189,19 +201,20 @@ usbd_get_string(usbd_device_handle dev, int si, char *buf)
return (0);
if (dev->langid == USBD_NOLANG) {
/* Set up default language */
- err = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us);
- if (err || us.bLength < 4) {
+ err = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us,
+ &size);
+ if (err || size < 4) {
dev->langid = 0; /* Well, just pick English then */
} else {
/* Pick the first language as the default. */
dev->langid = UGETW(us.bString[0]);
}
}
- err = usbd_get_string_desc(dev, si, dev->langid, &us);
+ err = usbd_get_string_desc(dev, si, dev->langid, &us, &size);
if (err)
return (0);
s = buf;
- n = us.bLength / 2 - 1;
+ n = size / 2 - 1;
for (i = 0; i < n; i++) {
c = UGETW(us.bString[i]);
/* Convert from Unicode, handle buggy strings. */
diff --git a/sys/dev/usb/usbdi_util.h b/sys/dev/usb/usbdi_util.h
index 71d40301b67..020e034d1cd 100644
--- a/sys/dev/usb/usbdi_util.h
+++ b/sys/dev/usb/usbdi_util.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: usbdi_util.h,v 1.13 2004/07/21 00:01:08 dlg Exp $ */
+/* $OpenBSD: usbdi_util.h,v 1.14 2004/10/31 12:10:52 dlg Exp $ */
/* $NetBSD: usbdi_util.h,v 1.28 2002/07/11 21:14:36 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/usbdi_util.h,v 1.9 1999/11/17 22:33:50 n_hibma Exp $ */
@@ -71,7 +71,8 @@ usbd_status usbd_read_report_desc(usbd_interface_handle ifc, void **descp,
int *sizep, usb_malloc_type mem);
usbd_status usbd_get_config(usbd_device_handle dev, u_int8_t *conf);
usbd_status usbd_get_string_desc(usbd_device_handle dev, int sindex,
- int langid,usb_string_descriptor_t *sdesc);
+ int langid,usb_string_descriptor_t *sdesc,
+ int *sizep);
void usbd_delay_ms(usbd_device_handle, u_int);