Make an iterator abstraction for looping through all descriptors.

Move usb_get_string() and make it public.
This commit is contained in:
augustss 2004-10-23 13:26:33 +00:00
parent c1d4463c05
commit 67f0f483bd
5 changed files with 125 additions and 73 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: usb_subr.c,v 1.118 2004/09/13 12:55:49 drochner Exp $ */
/* $NetBSD: usb_subr.c,v 1.119 2004/10/23 13:26:33 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $ */
/*
@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.118 2004/09/13 12:55:49 drochner Exp $");
__KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.119 2004/10/23 13:26:33 augustss Exp $");
#include "opt_usbverbose.h"
@ -83,7 +83,6 @@ extern int usbdebug;
Static usbd_status usbd_set_config(usbd_device_handle, int);
Static void usbd_devinfo_vp(usbd_device_handle, char *, size_t, char *,
size_t, 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 *, const char *);
@ -190,51 +189,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)
{
@ -267,9 +221,15 @@ usbd_devinfo_vp(usbd_device_handle dev, char *v, size_t lv, char *p, size_t lp,
}
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;

View File

@ -1,4 +1,4 @@
/* $NetBSD: usbdi.c,v 1.104 2004/07/17 20:16:13 mycroft Exp $ */
/* $NetBSD: usbdi.c,v 1.105 2004/10/23 13:26:34 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/usbdi.c,v 1.28 1999/11/17 22:33:49 n_hibma Exp $ */
/*
@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.104 2004/07/17 20:16:13 mycroft Exp $");
__KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.105 2004/10/23 13:26:34 augustss Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -65,6 +65,7 @@ __KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.104 2004/07/17 20:16:13 mycroft Exp $");
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbdivar.h>
#include <dev/usb/usb_mem.h>
#include <dev/usb/usb_quirks.h>
#if defined(__FreeBSD__)
#include "usb_if.h"
@ -1141,6 +1142,85 @@ 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 = (uByte *)cd;
iter->end = (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 = (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) {
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)

View File

@ -1,4 +1,4 @@
/* $NetBSD: usbdi.h,v 1.63 2004/04/23 17:25:26 itojun Exp $ */
/* $NetBSD: usbdi.h,v 1.64 2004/10/23 13:26:34 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/usbdi.h,v 1.18 1999/11/17 22:33:49 n_hibma Exp $ */
/*
@ -172,6 +172,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

View File

@ -1,4 +1,4 @@
/* $NetBSD: usbdi_util.c,v 1.40 2002/07/11 21:14:36 augustss Exp $ */
/* $NetBSD: usbdi_util.c,v 1.41 2004/10/23 13:26:34 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/usbdi_util.c,v 1.14 1999/11/17 22:33:50 n_hibma Exp $ */
/*
@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: usbdi_util.c,v 1.40 2002/07/11 21:14:36 augustss Exp $");
__KERNEL_RCSID(0, "$NetBSD: usbdi_util.c,v 1.41 2004/10/23 13:26:34 augustss Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -365,8 +365,8 @@ usbd_get_hid_descriptor(usbd_interface_handle ifc)
char *p, *end;
if (idesc == NULL)
return (0);
usbd_interface2device_handle(ifc, &dev);
return (NULL);
usbd_interface2device_handle(ifc, &dev);
cdesc = usbd_get_config_descriptor(dev);
p = (char *)idesc + idesc->bLength;
@ -379,7 +379,7 @@ usbd_get_hid_descriptor(usbd_interface_handle ifc)
if (hd->bDescriptorType == UDESC_INTERFACE)
break;
}
return (0);
return (NULL);
}
usbd_status
@ -484,20 +484,19 @@ usb_detach_wakeup(device_ptr_t dv)
wakeup(dv);
}
usb_descriptor_t *
usb_find_desc(usbd_device_handle dev, int type)
const usb_descriptor_t *
usb_find_desc(usbd_device_handle dev, int type, int subtype)
{
usb_descriptor_t *desc;
usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev);
uByte *p = (uByte *)cd;
uByte *end = p + UGETW(cd->wTotalLength);
usbd_desc_iter_t iter;
const usb_descriptor_t *desc;
while (p < end) {
desc = (usb_descriptor_t *)p;
if (desc->bDescriptorType == type)
return (desc);
p += desc->bLength;
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 (NULL);
return desc;
}

View File

@ -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.30 2004/10/23 13:26:34 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/usbdi_util.h,v 1.9 1999/11/17 22:33:50 n_hibma Exp $ */
/*
@ -85,4 +85,7 @@ usbd_status usbd_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
void usb_detach_wait(device_ptr_t);
void usb_detach_wakeup(device_ptr_t);
usb_descriptor_t *usb_find_desc(usbd_device_handle dev, int type);
const usb_descriptor_t *usb_find_desc(usbd_device_handle dev, int type,
int subtype);
#define USBD_SUBTYPE_ANY (~0)