From 20d1ae1adbca724b9d7ae88edd71ea502a999630 Mon Sep 17 00:00:00 2001 From: augustss Date: Thu, 28 Dec 2000 11:56:22 +0000 Subject: [PATCH] Add two more quirks: UQ_AU_NO_FRAC for audio devices that cannot handle adjustment for fractional sample size. UQ_AU_INP_ASYNC for input devices that claim to be adaptive, but are in fact asynchronous (an easy mistake to make unless you read the specs carefully :) --- sys/dev/usb/uaudio.c | 31 +++++++++++++++++++++++++------ sys/dev/usb/usb_quirks.c | 7 +++++-- sys/dev/usb/usb_quirks.h | 6 ++++-- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/sys/dev/usb/uaudio.c b/sys/dev/usb/uaudio.c index 061691aa834a..e2b61095e376 100644 --- a/sys/dev/usb/uaudio.c +++ b/sys/dev/usb/uaudio.c @@ -1,4 +1,4 @@ -/* $NetBSD: uaudio.c,v 1.30 2000/12/28 01:01:42 augustss Exp $ */ +/* $NetBSD: uaudio.c,v 1.31 2000/12/28 11:56:22 augustss Exp $ */ /* * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -128,6 +128,8 @@ struct chan { int blksize; /* chunk size to report up */ int transferred; /* transferred bytes not reported up */ + char nofrac; /* don't do sample rate adjustment */ + int curchanbuf; struct chanbuf { struct chan *chan; @@ -381,6 +383,9 @@ USB_ATTACH(uaudio) sc->sc_chan.sc = sc; + if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_FRAC) + sc->sc_chan.nofrac = 1; + DPRINTF(("uaudio_attach: doing audio_attach_mi\n")); #if defined(__OpenBSD__) audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev); @@ -961,7 +966,7 @@ uaudio_add_extension(struct uaudio_softc *sc, usb_descriptor_t *v, DPRINTFN(2,("uaudio_add_extension: bUnitId=%d bNrInPins=%d\n", d->bUnitId, d->bNrInPins)); - if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_NO_XU) + if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_XU) return; if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) { @@ -1056,6 +1061,10 @@ uaudio_process_as(struct uaudio_softc *sc, char *buf, int *offsp, dir = UE_GET_DIR(ed->bEndpointAddress); type = UE_GET_ISO_TYPE(ed->bmAttributes); + if ((usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_INP_ASYNC) && + dir == UE_DIR_IN && type == UE_ISO_ADAPT) + type = UE_ISO_ASYNC; + /* We can't handle endpoints that need a sync pipe. */ if (dir == UE_DIR_IN ? type == UE_ISO_ADAPT : type == UE_ISO_ASYNC) { printf("%s: ignored %sput endpoint of type %s\n", @@ -1869,7 +1878,8 @@ uaudio_chan_ptransfer(struct chan *ch) size = ch->bytes_per_frame; residue += ch->fraction; if (residue >= USB_FRAMES_PER_SECOND) { - size += ch->sample_size; + if (!ch->nofrac) + size += ch->sample_size; residue -= USB_FRAMES_PER_SECOND; } cb->sizes[i] = size; @@ -1972,7 +1982,8 @@ uaudio_chan_rtransfer(struct chan *ch) size = ch->bytes_per_frame; residue += ch->fraction; if (residue >= USB_FRAMES_PER_SECOND) { - size += ch->sample_size; + if (!ch->nofrac) + size += ch->sample_size; residue -= USB_FRAMES_PER_SECOND; } cb->sizes[i] = size; @@ -2016,9 +2027,17 @@ uaudio_chan_rintr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); DPRINTFN(5,("uaudio_chan_rintr: count=%d, transferred=%d\n", count, ch->transferred)); + + if (count < cb->size) { + /* if the device fails to keep up, copy last byte */ + u_char b = count ? cb->buffer[count-1] : 0; + while (count < cb->size) + cb->buffer[count++] = b; + } + #ifdef DIAGNOSTIC if (count != cb->size) { - printf("uaudio_chan_pintr: count(%d) != size(%d)\n", + printf("uaudio_chan_rintr: count(%d) != size(%d)\n", count, cb->size); } #endif @@ -2042,7 +2061,7 @@ uaudio_chan_rintr(usbd_xfer_handle xfer, usbd_private_handle priv, s = splaudio(); while (ch->transferred >= ch->blksize) { ch->transferred -= ch->blksize; - DPRINTFN(5,("uaudio_chan_pintr: call %p(%p)\n", + DPRINTFN(5,("uaudio_chan_rintr: call %p(%p)\n", ch->intr, ch->arg)); ch->intr(ch->arg); } diff --git a/sys/dev/usb/usb_quirks.c b/sys/dev/usb/usb_quirks.c index c8cf847e0fd8..e2d6df456c3e 100644 --- a/sys/dev/usb/usb_quirks.c +++ b/sys/dev/usb/usb_quirks.c @@ -1,4 +1,4 @@ -/* $NetBSD: usb_quirks.c,v 1.33 2000/12/11 05:41:00 augustss Exp $ */ +/* $NetBSD: usb_quirks.c,v 1.34 2000/12/28 11:56:23 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/usb_quirks.c,v 1.13 1999/11/17 22:33:47 n_hibma Exp $ */ /* @@ -64,7 +64,7 @@ Static struct usbd_quirk_entry { { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_SERIAL1, 0x101, { UQ_NO_STRINGS }}, { USB_VENDOR_WACOM, USB_PRODUCT_WACOM_CT0405U, 0x101, { UQ_NO_STRINGS }}, { USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2, { UQ_BAD_ADC }}, - { USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2, { UQ_NO_XU }}, + { USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2, { UQ_AU_NO_XU }}, { USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ADA70, 0x103, { UQ_BAD_ADC }}, { USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ASC495, 0x000, { UQ_BAD_AUDIO }}, { USB_VENDOR_QTRONIX, USB_PRODUCT_QTRONIX_980N, 0x110, { UQ_SPUR_BUT_UP }}, @@ -76,6 +76,9 @@ Static struct usbd_quirk_entry { { USB_VENDOR_TI, USB_PRODUCT_TI_UTUSB41, 0x110, { UQ_POWER_CLAIM }}, { USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_320U, 0x000, { UQ_NO_STRINGS }}, + { USB_VENDOR_TELEX, USB_PRODUCT_TELEX_MIC1, 0x009, { UQ_AU_NO_FRAC }}, + { USB_VENDOR_SILICONPORTALS, USB_PRODUCT_SILICONPORTALS_YAPPHONE, + 0x100, { UQ_AU_INP_ASYNC }}, { 0, 0, 0, { 0 } } }; diff --git a/sys/dev/usb/usb_quirks.h b/sys/dev/usb/usb_quirks.h index e3718249feec..a02f58a7ed0f 100644 --- a/sys/dev/usb/usb_quirks.h +++ b/sys/dev/usb/usb_quirks.h @@ -1,4 +1,4 @@ -/* $NetBSD: usb_quirks.h,v 1.16 2000/12/11 05:41:00 augustss Exp $ */ +/* $NetBSD: usb_quirks.h,v 1.17 2000/12/28 11:56:23 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/usb_quirks.h,v 1.9 1999/11/12 23:31:03 n_hibma Exp $ */ /* @@ -48,8 +48,10 @@ struct usbd_quirks { #define UQ_BUS_POWERED 0x0020 /* device is bus powered, despite claim */ #define UQ_BAD_AUDIO 0x0040 /* device claims audio class, but isn't */ #define UQ_SPUR_BUT_UP 0x0080 /* spurious mouse button up events */ -#define UQ_NO_XU 0x0100 /* audio device has broken extension unit */ +#define UQ_AU_NO_XU 0x0100 /* audio device has broken extension unit */ #define UQ_POWER_CLAIM 0x0200 /* hub lies about power status */ +#define UQ_AU_NO_FRAC 0x0400 /* don't adjust for fractional samples */ +#define UQ_AU_INP_ASYNC 0x0800 /* input is async despite claim of adaptive */ }; extern struct usbd_quirks usbd_no_quirk;