NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/55919: Creative HP-BTW3 (BT-W3) USB audio device has another descriptor layout
The following reply was made to PR kern/55919; it has been noted by GNATS.
From: Ryo ONODERA <ryo%tetera.org@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc:
Subject: Re: kern/55919: Creative HP-BTW3 (BT-W3) USB audio device has
another descriptor layout
Date: Sat, 30 Jan 2021 04:51:16 +0900
Hi,
I have rewrite my patch.
As far as I understand correctly, the order of descriptors is not
specified in spec,
https://usb.org/sites/default/files/audio10.pdf .
My patch is here:
http://www.ryoon.net/~ryoon/sys-dev-uaudio.c-2.diff
Index: sys/dev/usb/uaudio.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/uaudio.c,v
retrieving revision 1.168
diff -u -r1.168 uaudio.c
--- sys/dev/usb/uaudio.c 10 Jan 2021 15:50:16 -0000 1.168
+++ sys/dev/usb/uaudio.c 29 Jan 2021 19:36:18 -0000
@@ -1532,52 +1532,63 @@
int size, const usb_interface_descriptor_t *id)
#define offs (*offsp)
{
- const struct usb_audio_streaming_interface_descriptor *asid;
- const struct usb_audio_streaming_type1_descriptor *asf1d;
- const usb_endpoint_descriptor_audio_t *ed;
- const usb_endpoint_descriptor_audio_t *epdesc1;
- const struct usb_audio_streaming_endpoint_descriptor *sed;
+ const struct usb_audio_streaming_interface_descriptor *asid = NULL;
+ const struct usb_audio_streaming_type1_descriptor *asf1d = NULL;
+ const usb_endpoint_descriptor_audio_t *ed = NULL;
+ const usb_endpoint_descriptor_audio_t *epdesc1 = NULL;
+ const struct usb_audio_streaming_endpoint_descriptor *sed = NULL;
+ const usb_descriptor_t *desc = NULL;
int format, chan __unused, prec, enc;
int dir, type, sync;
struct as_info ai;
const char *format_str __unused;
- asid = (const void *)(tbuf + offs);
- if (asid->bDescriptorType != UDESC_CS_INTERFACE ||
- asid->bDescriptorSubtype != AS_GENERAL)
+ while (offs < size) {
+ desc = (const void *)(tbuf + offs);
+
+ if (desc->bDescriptorType == UDESC_CS_INTERFACE &&
+ desc->bDescriptorSubtype == AS_GENERAL) {
+ asid = (const void *)desc;
+ offs += asid->bLength;
+ } else if (desc->bDescriptorType == UDESC_CS_INTERFACE &&
+ desc->bDescriptorSubtype == FORMAT_TYPE) {
+ asf1d = (const void *)desc;
+ offs += asf1d->bLength;
+ } else if (desc->bDescriptorType == UDESC_ENDPOINT) {
+ ed = (const void *)desc;
+ offs += ed->bLength;
+ } else if (desc->bDescriptorType == UDESC_CS_ENDPOINT &&
+ desc->bDescriptorSubtype == AS_GENERAL) {
+ sed = (const void *)desc;
+ offs += sed->bLength;
+ } else if (ed != NULL && id->bNumEndpoints > 1 &&
+ desc->bDescriptorType == UDESC_ENDPOINT) {
+ epdesc1 = (const void*)desc;
+ offs += epdesc1->bLength;
+ } else
+ break;
+ }
+
+ if (asid == NULL || asf1d == NULL || ed == NULL || sed == NULL ||
+ (id->bNumEndpoints > 1 && epdesc1 == NULL))
return USBD_INVAL;
+
+ format = UGETW(asid->wFormatTag);
DPRINTF("asid: bTerminalLink=%d wFormatTag=%d\n",
asid->bTerminalLink, UGETW(asid->wFormatTag));
- offs += asid->bLength;
- if (offs > size)
- return USBD_INVAL;
-
- asf1d = (const void *)(tbuf + offs);
- if (asf1d->bDescriptorType != UDESC_CS_INTERFACE ||
- asf1d->bDescriptorSubtype != FORMAT_TYPE)
- return USBD_INVAL;
- offs += asf1d->bLength;
- if (offs > size)
- return USBD_INVAL;
if (asf1d->bFormatType != FORMAT_TYPE_I) {
aprint_normal_dev(sc->sc_dev,
- "ignored setting with type %d format\n", UGETW(asid->wFormatTag));
+ "ignored setting with type %d format\n", format);
return USBD_NORMAL_COMPLETION;
}
- ed = (const void *)(tbuf + offs);
- if (ed->bDescriptorType != UDESC_ENDPOINT)
- return USBD_INVAL;
DPRINTF("endpoint[0] bLength=%d bDescriptorType=%d "
"bEndpointAddress=%d bmAttributes=%#x wMaxPacketSize=%d "
"bInterval=%d bRefresh=%d bSynchAddress=%d\n",
ed->bLength, ed->bDescriptorType, ed->bEndpointAddress,
ed->bmAttributes, UGETW(ed->wMaxPacketSize),
ed->bInterval, ed->bRefresh, ed->bSynchAddress);
- offs += ed->bLength;
- if (offs > size)
- return USBD_INVAL;
if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
return USBD_INVAL;
@@ -1606,14 +1617,7 @@
#endif
}
- sed = (const void *)(tbuf + offs);
- if (sed->bDescriptorType != UDESC_CS_ENDPOINT ||
- sed->bDescriptorSubtype != AS_GENERAL)
- return USBD_INVAL;
DPRINTF(" streadming_endpoint: offset=%d bLength=%d\n", offs, sed->bLength);
- offs += sed->bLength;
- if (offs > size)
- return USBD_INVAL;
#ifdef UAUDIO_MULTIPLE_ENDPOINTS
if (sync && id->bNumEndpoints <= 1) {
@@ -1627,11 +1631,7 @@
"non sync-pipe endpoint but multiple endpoints\n");
return USBD_INVAL;
}
- epdesc1 = NULL;
if (id->bNumEndpoints > 1) {
- epdesc1 = (const void*)(tbuf + offs);
- if (epdesc1->bDescriptorType != UDESC_ENDPOINT)
- return USBD_INVAL;
DPRINTF("endpoint[1] bLength=%d "
"bDescriptorType=%d bEndpointAddress=%d "
"bmAttributes=%#x wMaxPacketSize=%d bInterval=%d "
@@ -1640,9 +1640,6 @@
epdesc1->bEndpointAddress, epdesc1->bmAttributes,
UGETW(epdesc1->wMaxPacketSize), epdesc1->bInterval,
epdesc1->bRefresh, epdesc1->bSynchAddress);
- offs += epdesc1->bLength;
- if (offs > size)
- return USBD_INVAL;
if (epdesc1->bSynchAddress != 0) {
aprint_error_dev(sc->sc_dev,
"invalid endpoint: bSynchAddress=0\n");
@@ -1665,7 +1662,6 @@
/* UE_GET_ADDR(epdesc1->bEndpointAddress), and epdesc1->bRefresh */
}
- format = UGETW(asid->wFormatTag);
chan = asf1d->bNrChannels;
prec = asf1d->bBitResolution;
if (prec != 8 && prec != 16 && prec != 24) {
--
Ryo ONODERA // ryo%tetera.org@localhost
PGP fingerprint = 82A2 DC91 76E0 A10A 8ABB FD1B F404 27FA C7D1 15F3
Home |
Main Index |
Thread Index |
Old Index