diff options
| author | 2004-10-31 12:10:52 +0000 | |
|---|---|---|
| committer | 2004-10-31 12:10:52 +0000 | |
| commit | c60274faa6e28955c0c40805d30823f2d63d0822 (patch) | |
| tree | b2a15cb744493ac373badb7528420163727960d2 /sys/dev/usb/usb_subr.c | |
| parent | Simplify ldconfig handling: one single ensure_ldconfig routine that (diff) | |
| download | wireguard-openbsd-c60274faa6e28955c0c40805d30823f2d63d0822.tar.xz wireguard-openbsd-c60274faa6e28955c0c40805d30823f2d63d0822.zip | |
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.
Diffstat (limited to 'sys/dev/usb/usb_subr.c')
| -rw-r--r-- | sys/dev/usb/usb_subr.c | 29 |
1 files changed, 21 insertions, 8 deletions
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. */ |
