diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c index 26c10545e92e..6b11b448a34c 100644 --- a/sys/dev/usb/usb_subr.c +++ b/sys/dev/usb/usb_subr.c @@ -7,6 +7,7 @@ * $NetBSD: usb_subr.c,v 1.114 2004/06/23 02:30:52 mycroft Exp $ * $NetBSD: usb_subr.c,v 1.115 2004/06/23 05:23:19 mycroft Exp $ * $NetBSD: usb_subr.c,v 1.116 2004/06/23 06:27:54 mycroft Exp $ + * $NetBSD: usb_subr.c,v 1.119 2004/10/23 13:26:33 augustss Exp $ */ #include @@ -90,7 +91,6 @@ extern int usbdebug; Static usbd_status usbd_set_config(usbd_device_handle, int); Static void usbd_devinfo_vp(usbd_device_handle, char *, char *, int); -Static char *usbd_get_string(usbd_device_handle, int, char *); Static int usbd_getnewaddr(usbd_bus_handle bus); #if defined(__NetBSD__) Static int usbd_print(void *aux, const char *pnp); @@ -196,51 +196,6 @@ usbd_get_string_desc(usbd_device_handle dev, int sindex, int langid, return (USBD_NORMAL_COMPLETION); } -char * -usbd_get_string(usbd_device_handle dev, int si, char *buf) -{ - int swap = dev->quirks->uq_flags & UQ_SWAP_UNICODE; - usb_string_descriptor_t us; - char *s; - int i, n; - u_int16_t c; - usbd_status err; - int size; - - if (si == 0) - return (0); - if (dev->quirks->uq_flags & UQ_NO_STRINGS) - return (0); - if (dev->langid == USBD_NOLANG) { - /* Set up default language */ - err = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us, - &size); - if (err || size < 4) { - dev->langid = 0; /* Well, just pick something 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, &size); - if (err) - return (0); - s = buf; - n = size / 2 - 1; - for (i = 0; i < n; i++) { - c = UGETW(us.bString[i]); - /* Convert from Unicode, handle buggy strings. */ - if ((c & 0xff00) == 0) - *s++ = c; - else if ((c & 0x00ff) == 0 && swap) - *s++ = c >> 8; - else - *s++ = '?'; - } - *s++ = 0; - return (buf); -} - Static void usbd_trim_spaces(char *p) { @@ -272,9 +227,15 @@ usbd_devinfo_vp(usbd_device_handle dev, char *v, char *p, int usedev) } if (usedev) { - vendor = usbd_get_string(dev, udd->iManufacturer, v); + if (usbd_get_string(dev, udd->iManufacturer, v)) + vendor = NULL; + else + vendor = v; usbd_trim_spaces(vendor); - product = usbd_get_string(dev, udd->iProduct, p); + if (usbd_get_string(dev, udd->iProduct, p)) + product = NULL; + else + product = p; usbd_trim_spaces(product); if (vendor && !*vendor) vendor = NULL; diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c index 9a571dc1b106..adefde3057d9 100644 --- a/sys/dev/usb/usbdi.c +++ b/sys/dev/usb/usbdi.c @@ -1,4 +1,4 @@ -/* $NetBSD: usbdi.c,v 1.104 2004/07/17 20:16:13 mycroft Exp $ */ +/* $NetBSD: usbdi.c,v 1.106 2004/10/24 12:52:40 augustss Exp $ */ #include __FBSDID("$FreeBSD$"); @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include #include #if defined(__NetBSD__) || defined(__OpenBSD__) +#include #include #elif defined(__FreeBSD__) #include @@ -62,6 +63,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #if defined(__FreeBSD__) #include "usb_if.h" @@ -1154,6 +1156,86 @@ usb_match_device(const struct usb_devno *tbl, u_int nentries, u_int sz, return (NULL); } + +void +usb_desc_iter_init(usbd_device_handle dev, usbd_desc_iter_t *iter) +{ + const usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev); + + iter->cur = (const uByte *)cd; + iter->end = (const uByte *)cd + UGETW(cd->wTotalLength); +} + +const usb_descriptor_t * +usb_desc_iter_next(usbd_desc_iter_t *iter) +{ + const usb_descriptor_t *desc; + + if (iter->cur + sizeof(usb_descriptor_t) >= iter->end) { + if (iter->cur != iter->end) + printf("usb_desc_iter_next: bad descriptor\n"); + return NULL; + } + desc = (const usb_descriptor_t *)iter->cur; + if (desc->bLength == 0) { + printf("usb_desc_iter_next: descriptor length = 0\n"); + return NULL; + } + iter->cur += desc->bLength; + if (iter->cur > iter->end) { + printf("usb_desc_iter_next: descriptor length too large\n"); + return NULL; + } + return desc; +} + +usbd_status +usbd_get_string(usbd_device_handle dev, int si, char *buf) +{ + int swap = dev->quirks->uq_flags & UQ_SWAP_UNICODE; + usb_string_descriptor_t us; + char *s; + int i, n; + u_int16_t c; + usbd_status err; + int size; + + buf[0] = '\0'; + if (si == 0) + return (USBD_INVAL); + if (dev->quirks->uq_flags & UQ_NO_STRINGS) + return (USBD_STALLED); + if (dev->langid == USBD_NOLANG) { + /* Set up default language */ + err = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us, + &size); + if (err || size < 4) { + DPRINTFN(-1,("usbd_get_string: getting lang failed, using 0\n")); + dev->langid = 0; /* Well, just pick something 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, &size); + if (err) + return (err); + s = buf; + n = size / 2 - 1; + for (i = 0; i < n; i++) { + c = UGETW(us.bString[i]); + /* Convert from Unicode, handle buggy strings. */ + if ((c & 0xff00) == 0) + *s++ = c; + else if ((c & 0x00ff) == 0 && swap) + *s++ = c >> 8; + else + *s++ = '?'; + } + *s++ = 0; + return (USBD_NORMAL_COMPLETION); +} + #if defined(__FreeBSD__) int usbd_driver_load(module_t mod, int what, void *arg) diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h index 4e062bb7d3bb..b238b17631b6 100644 --- a/sys/dev/usb/usbdi.h +++ b/sys/dev/usb/usbdi.h @@ -170,6 +170,16 @@ usbd_status usbd_reload_device_desc(usbd_device_handle); int usbd_ratecheck(struct timeval *last); +usbd_status usbd_get_string(usbd_device_handle dev, int si, char *buf); + +/* An iterator for descriptors. */ +typedef struct { + const uByte *cur; + const uByte *end; +} usbd_desc_iter_t; +void usb_desc_iter_init(usbd_device_handle dev, usbd_desc_iter_t *iter); +const usb_descriptor_t *usb_desc_iter_next(usbd_desc_iter_t *iter); + /* * The usb_task structs form a queue of things to run in the USB event * thread. Normally this is just device discovery when a connect/disconnect diff --git a/sys/dev/usb/usbdi_util.c b/sys/dev/usb/usbdi_util.c index e18c6d38e9f9..b275778203dd 100644 --- a/sys/dev/usb/usbdi_util.c +++ b/sys/dev/usb/usbdi_util.c @@ -1,4 +1,4 @@ -/* $NetBSD: usbdi_util.c,v 1.36 2001/11/13 06:24:57 lukem Exp $ */ +/* $NetBSD: usbdi_util.c,v 1.42 2004/12/03 08:53:40 augustss Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -222,6 +222,25 @@ usbd_set_port_feature(usbd_device_handle dev, int port, int sel) return (usbd_do_request(dev, &req, 0)); } +usbd_status +usbd_get_protocol(usbd_interface_handle iface, u_int8_t *report) +{ + usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface); + usbd_device_handle dev; + usb_device_request_t req; + + DPRINTFN(4, ("usbd_get_protocol: iface=%p, endpt=%d\n", + iface, id->bInterfaceNumber)); + if (id == NULL) + return (USBD_IOERROR); + usbd_interface2device_handle(iface, &dev); + req.bmRequestType = UT_READ_CLASS_INTERFACE; + req.bRequest = UR_GET_PROTOCOL; + USETW(req.wValue, 0); + USETW(req.wIndex, id->bInterfaceNumber); + USETW(req.wLength, 1); + return (usbd_do_request(dev, &req, report)); +} usbd_status usbd_set_protocol(usbd_interface_handle iface, int report) @@ -291,8 +310,8 @@ usbd_get_report(usbd_interface_handle iface, int type, int id, void *data, usbd_device_handle dev; usb_device_request_t req; - DPRINTFN(4, ("usbd_set_report: len=%d\n", len)); - if (id == 0) + DPRINTFN(4, ("usbd_get_report: len=%d\n", len)); + if (ifd == NULL) return (USBD_IOERROR); usbd_interface2device_handle(iface, &dev); req.bmRequestType = UT_READ_CLASS_INTERFACE; @@ -346,7 +365,7 @@ usbd_get_hid_descriptor(usbd_interface_handle ifc) char *p, *end; if (idesc == NULL) - return (0); + return (NULL); usbd_interface2device_handle(ifc, &dev); cdesc = usbd_get_config_descriptor(dev); @@ -360,7 +379,7 @@ usbd_get_hid_descriptor(usbd_interface_handle ifc) if (hd->bDescriptorType == UDESC_INTERFACE) break; } - return (0); + return (NULL); } usbd_status @@ -432,7 +451,7 @@ usbd_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe, splx(s); return (err); } - error = tsleep(xfer, PZERO | PCATCH, lbl, 0); + error = tsleep((caddr_t)xfer, PZERO | PCATCH, lbl, 0); splx(s); if (error) { DPRINTF(("usbd_bulk_transfer: tsleep=%d\n", error)); @@ -506,3 +525,20 @@ usb_detach_wakeup(device_ptr_t dv) DPRINTF(("usb_detach_wakeup: for %s\n", USBDEVPTRNAME(dv))); wakeup(dv); } + +const usb_descriptor_t * +usb_find_desc(usbd_device_handle dev, int type, int subtype) +{ + usbd_desc_iter_t iter; + const usb_descriptor_t *desc; + + usb_desc_iter_init(dev, &iter); + for (;;) { + desc = usb_desc_iter_next(&iter); + if (!desc || (desc->bDescriptorType == type && + (subtype == USBD_SUBTYPE_ANY || + subtype == desc->bDescriptorSubtype))) + break; + } + return desc; +} diff --git a/sys/dev/usb/usbdi_util.h b/sys/dev/usb/usbdi_util.h index 51e052f712f8..82ea13b1c303 100644 --- a/sys/dev/usb/usbdi_util.h +++ b/sys/dev/usb/usbdi_util.h @@ -1,4 +1,4 @@ -/* $NetBSD: usbdi_util.h,v 1.29 2004/06/23 02:30:52 mycroft Exp $ */ +/* $NetBSD: usbdi_util.h,v 1.31 2004/12/03 08:53:40 augustss Exp $ */ /* $FreeBSD$ */ /*- @@ -54,6 +54,7 @@ usbd_status usbd_set_port_feature(usbd_device_handle dev, int, int); usbd_status usbd_clear_port_feature(usbd_device_handle, int, int); usbd_status usbd_get_device_status(usbd_device_handle, usb_status_t *); usbd_status usbd_get_hub_status(usbd_device_handle, usb_hub_status_t *); +usbd_status usbd_get_protocol(usbd_interface_handle dev, u_int8_t *report); usbd_status usbd_set_protocol(usbd_interface_handle dev, int report); usbd_status usbd_get_report_descriptor(usbd_device_handle dev, int ifcno, int size, void *d); @@ -88,3 +89,7 @@ usbd_status usbd_intr_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe, void usb_detach_wait(device_ptr_t); void usb_detach_wakeup(device_ptr_t); +const usb_descriptor_t *usb_find_desc(usbd_device_handle dev, int type, + int subtype); +#define USBD_SUBTYPE_ANY (~0) +