diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2004-10-31 12:10:53 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2004-10-31 12:10:53 +0000 |
commit | b6bf3206fb196dacf40c0e28a25f7461e115c923 (patch) | |
tree | 94996de594d941cee2071a77a0a22537b85df81b | |
parent | 7325169003f85df86e20ac2b8785c127fe247dd5 (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.c | 7 | ||||
-rw-r--r-- | sys/dev/usb/usb_subr.c | 29 | ||||
-rw-r--r-- | sys/dev/usb/usbdi_util.h | 5 |
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); |