diff options
Diffstat (limited to 'sys/dev/usb/uaudio.c')
-rw-r--r-- | sys/dev/usb/uaudio.c | 371 |
1 files changed, 218 insertions, 153 deletions
diff --git a/sys/dev/usb/uaudio.c b/sys/dev/usb/uaudio.c index c93d757cf87..a7ab58c6940 100644 --- a/sys/dev/usb/uaudio.c +++ b/sys/dev/usb/uaudio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uaudio.c,v 1.7 2000/11/08 18:10:37 aaron Exp $ */ +/* $OpenBSD: uaudio.c,v 1.8 2001/01/28 09:43:41 aaron Exp $ */ /* $NetBSD: uaudio.c,v 1.29 2000/10/05 01:35:07 augustss Exp $ */ /* @@ -39,9 +39,9 @@ */ /* - * USB audio specs: http://www.teleport.com/~usb/data/Audio10.pdf - * http://www.teleport.com/~usb/data/Frmts10.pdf - * http://www.teleport.com/~usb/data/Termt10.pdf + * USB audio specs: http://www.usb.org/developers/data/devclass/audio10.pdf + * http://www.usb.org/developers/data/devclass/frmts10.pdf + * http://www.usb.org/developers/data/devclass/termt10.pdf */ #include <sys/param.h> @@ -96,6 +96,8 @@ struct mixerctl { #define MIX_SIZE(n) ((n) == MIX_SIGNED_16 || (n) == MIX_UNSIGNED_16 ? 2 : 1) #define MIX_UNSIGNED(n) ((n) == MIX_UNSIGNED_16) int minval, maxval; + u_int delta; + u_int mul; u_int8_t class; char ctlname[MAX_AUDIO_DEV_LEN]; char *ctlunit; @@ -105,6 +107,7 @@ struct mixerctl { struct as_info { u_int8_t alt; u_int8_t encoding; + usbd_interface_handle ifaceh; usb_interface_descriptor_t *idesc; usb_endpoint_descriptor_audio_t *edesc; struct usb_audio_streaming_type1_descriptor *asf1desc; @@ -115,7 +118,7 @@ struct chan { void (*intr)(void *); /* dma completion intr handler */ void *arg; /* arg for intr() */ usbd_pipe_handle pipe; - int dir; /* direction, UE_DIR_XXX */ + int dir; /* direction */ u_int sample_size; u_int sample_rate; @@ -129,6 +132,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; @@ -146,9 +151,7 @@ struct uaudio_softc { usbd_device_handle sc_udev; /* USB device */ int sc_ac_iface; /* Audio Control interface */ - int sc_as_iface; /* Audio Streaming interface */ usbd_interface_handle sc_ac_ifaceh; - usbd_interface_handle sc_as_ifaceh; struct chan sc_chan; @@ -336,7 +339,7 @@ USB_ATTACH(uaudio) usb_config_descriptor_t *cdesc; char devinfo[1024]; usbd_status err; - int i; + int i, j, found; usbd_devinfo(uaa->device, 0, devinfo); printf(": %s\n", devinfo); @@ -360,28 +363,39 @@ USB_ATTACH(uaudio) sc->sc_ac_ifaceh = uaa->iface; /* Pick up the AS interface. */ for (i = 0; i < uaa->nifaces; i++) { - if (uaa->ifaces[i] != NULL) { - id = usbd_get_interface_descriptor(uaa->ifaces[i]); - if (id != NULL && - id->bInterfaceNumber == sc->sc_as_iface) { - sc->sc_as_ifaceh = uaa->ifaces[i]; - uaa->ifaces[i] = NULL; - break; + if (uaa->ifaces[i] == NULL) + continue; + id = usbd_get_interface_descriptor(uaa->ifaces[i]); + if (id == NULL) + continue; + found = 0; + for (j = 0; j < sc->sc_nalts; j++) { + if (id->bInterfaceNumber == + sc->sc_alts[j].idesc->bInterfaceNumber) { + sc->sc_alts[j].ifaceh = uaa->ifaces[i]; + found = 1; } } + if (found) + uaa->ifaces[i] = NULL; } - if (sc->sc_as_ifaceh == NULL) { - printf("%s: missing AS interface(s)\n",USBDEVNAME(sc->sc_dev)); - USB_ATTACH_ERROR_RETURN; + for (j = 0; j < sc->sc_nalts; j++) { + if (sc->sc_alts[j].ifaceh == NULL) { + printf("%s: alt %d missing AS interface(s)\n", USBDEVNAME(sc->sc_dev), j); + USB_ATTACH_ERROR_RETURN; + } } - printf("%s: streaming interface %d, audio rev %d.%02x\n", - USBDEVNAME(sc->sc_dev), sc->sc_as_iface, + printf("%s: audio rev %d.%02x\n", + USBDEVNAME(sc->sc_dev), sc->sc_audio_rev >> 8, sc->sc_audio_rev & 0xff); 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); @@ -520,6 +534,8 @@ uaudio_find_iface(char *buf, int size, int *offsp, int subtype) void uaudio_mixer_add_ctl(struct uaudio_softc *sc, struct mixerctl *mc) { + int res; + if (sc->sc_nctls == 0) sc->sc_ctls = malloc(sizeof *mc, M_USBDEV, M_NOWAIT); else @@ -531,6 +547,7 @@ uaudio_mixer_add_ctl(struct uaudio_softc *sc, struct mixerctl *mc) return; } + mc->delta = 0; if (mc->type != MIX_ON_OFF) { /* Determine min and max values. */ mc->minval = uaudio_signext(mc->type, @@ -541,6 +558,14 @@ uaudio_mixer_add_ctl(struct uaudio_softc *sc, struct mixerctl *mc) uaudio_get(sc, GET_MAX, UT_READ_CLASS_INTERFACE, mc->wValue[0], mc->wIndex, MIX_SIZE(mc->type))); + mc->mul = mc->maxval - mc->minval; + if (mc->mul == 0) + mc->mul = 1; + res = uaudio_get(sc, GET_RES, UT_READ_CLASS_INTERFACE, + mc->wValue[0], mc->wIndex, + MIX_SIZE(mc->type)); + if (res > 0) + mc->delta = (res * 256 + mc->mul/2) / mc->mul; } else { mc->minval = 0; mc->maxval = 1; @@ -962,7 +987,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) { @@ -1057,12 +1082,16 @@ 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 0x%x\n", + printf("%s: ignored %sput endpoint of type %s\n", USBDEVNAME(sc->sc_dev), dir == UE_DIR_IN ? "in" : "out", - ed->bmAttributes & UE_ISO_TYPE); + dir == UE_DIR_IN ? "adaptive" : "async"); return (USBD_NORMAL_COMPLETION); } @@ -1078,7 +1107,7 @@ uaudio_process_as(struct uaudio_softc *sc, char *buf, int *offsp, chan = asf1d->bNrChannels; prec = asf1d->bBitResolution; if (prec != 8 && prec != 16) { -#ifdef AUDIO_DEBUG +#ifdef UAUDIO_DEBUG printf("%s: ignored setting with precision %d\n", USBDEVNAME(sc->sc_dev), prec); #endif @@ -1115,7 +1144,7 @@ uaudio_process_as(struct uaudio_softc *sc, char *buf, int *offsp, ai.asf1desc = asf1d; uaudio_add_alt(sc, &ai); sc->sc_chan.terminal = asid->bTerminalLink; /* XXX */ - sc->sc_chan.dir = dir; + sc->sc_chan.dir |= dir == UE_DIR_OUT ? AUMODE_PLAY : AUMODE_RECORD; return (USBD_NORMAL_COMPLETION); } #undef offs @@ -1136,13 +1165,14 @@ uaudio_identify_as(struct uaudio_softc *sc, usb_config_descriptor_t *cdesc) id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOSTREAM); if (id == NULL) return (USBD_INVAL); - sc->sc_as_iface = id->bInterfaceNumber; - DPRINTF(("uaudio_identify_as: AS interface is %d\n", sc->sc_as_iface)); sc->sc_chan.terminal = -1; + sc->sc_chan.dir = 0; /* Loop through all the alternate settings. */ while (offs <= size) { + DPRINTFN(2, ("uaudio_identify: interface %d\n", + id->bInterfaceNumber)); switch (id->bNumEndpoints) { case 0: DPRINTFN(2, ("uaudio_identify: AS null alt=%d\n", @@ -1153,7 +1183,7 @@ uaudio_identify_as(struct uaudio_softc *sc, usb_config_descriptor_t *cdesc) err = uaudio_process_as(sc, buf, &offs, size, id); break; default: -#ifdef AUDIO_DEBUG +#ifdef UAUDIO_DEBUG printf("%s: ignored audio interface with %d " "endpoints\n", USBDEVNAME(sc->sc_dev), id->bNumEndpoints); @@ -1172,6 +1202,10 @@ uaudio_identify_as(struct uaudio_softc *sc, usb_config_descriptor_t *cdesc) USBDEVNAME(sc->sc_dev)); return (USBD_INVAL); } +#if 0 + if (sc->sc_chan.dir == (AUMODE_PLAY | AUMODE_RECORD)) + sc->sc_props |= AUDIO_PROP_FULLDUPLEX; +#endif return (USBD_NORMAL_COMPLETION); } @@ -1336,6 +1370,7 @@ uaudio_query_devinfo(void *addr, mixer_devinfo_t *mi) mi->type = AUDIO_MIXER_VALUE; strncpy(mi->un.v.units.name, mc->ctlunit, MAX_AUDIO_DEV_LEN); mi->un.v.num_channels = mc->nchan; + mi->un.v.delta = mc->delta; break; } return (0); @@ -1353,9 +1388,9 @@ uaudio_open(void *addr, int flags) if (sc->sc_chan.terminal < 0) return (ENXIO); - if ((flags & FREAD) && sc->sc_chan.dir != UE_DIR_IN) + if ((flags & FREAD) && !(sc->sc_chan.dir & AUMODE_RECORD)) return (EACCES); - if ((flags & FWRITE) && sc->sc_chan.dir != UE_DIR_OUT) + if ((flags & FWRITE) && !(sc->sc_chan.dir & AUMODE_PLAY)) return (EACCES); sc->sc_chan.intr = 0; @@ -1563,8 +1598,8 @@ uaudio_value2bsd(struct mixerctl *mc, int val) if (mc->type == MIX_ON_OFF) val = val != 0; else - val = (uaudio_signext(mc->type, val) - mc->minval) * 256 - / (mc->maxval - mc->minval); + val = ((uaudio_signext(mc->type, val) - mc->minval) * 256 + + mc->mul/2) / mc->mul; DPRINTFN(5, ("val'=%d\n", val)); return (val); } @@ -1577,7 +1612,7 @@ uaudio_bsd2value(struct mixerctl *mc, int val) if (mc->type == MIX_ON_OFF) val = val != 0; else - val = val * (mc->maxval - mc->minval) / 256 + mc->minval; + val = (val + mc->delta/2) * mc->mul / 256 + mc->minval; DPRINTFN(5, ("val'=%d\n", val)); return (val); } @@ -1777,7 +1812,7 @@ uaudio_chan_open(struct uaudio_softc *sc, struct chan *ch) endpt, ch->sample_rate, as->alt)); /* Set alternate interface corresponding to the mode. */ - err = usbd_set_interface(sc->sc_as_ifaceh, as->alt); + err = usbd_set_interface(as->ifaceh, as->alt); if (err) return (err); @@ -1792,17 +1827,19 @@ uaudio_chan_open(struct uaudio_softc *sc, struct chan *ch) #endif DPRINTF(("uaudio_open_chan: create pipe to 0x%02x\n", endpt)); - err = usbd_open_pipe(sc->sc_as_ifaceh, endpt, 0, &ch->pipe); + err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->pipe); return (err); } void uaudio_chan_close(struct uaudio_softc *sc, struct chan *ch) { + struct as_info *as = &sc->sc_alts[sc->sc_curaltidx]; + if (sc->sc_nullalt >= 0) { DPRINTF(("uaudio_close_chan: set null alt=%d\n", sc->sc_nullalt)); - usbd_set_interface(sc->sc_as_ifaceh, sc->sc_nullalt); + usbd_set_interface(as->ifaceh, sc->sc_nullalt); } usbd_abort_pipe(ch->pipe); usbd_close_pipe(ch->pipe); @@ -1870,7 +1907,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; @@ -1973,7 +2011,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; @@ -2017,9 +2056,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 @@ -2043,7 +2090,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); } @@ -2078,14 +2125,15 @@ uaudio_chan_set_param(struct chan *ch, struct audio_params *param, int uaudio_set_params(void *addr, int setmode, int usemode, - struct audio_params *p, struct audio_params *r) + struct audio_params *play, struct audio_params *rec) { struct uaudio_softc *sc = addr; int flags = sc->sc_altflags; - int pfactor, rfactor; + int factor; int enc, i, j; - void (*pswcode)(void *, u_char *buf, int cnt); - void (*rswcode)(void *, u_char *buf, int cnt); + void (*swcode)(void *, u_char *buf, int cnt); + struct audio_params *p; + int mode; if (sc->sc_dying) return (EIO); @@ -2093,132 +2141,149 @@ uaudio_set_params(void *addr, int setmode, int usemode, if (sc->sc_chan.pipe != NULL) return (EBUSY); - pswcode = rswcode = 0; - pfactor = rfactor = 1; - enc = p->encoding; - switch (p->encoding) { - case AUDIO_ENCODING_SLINEAR_BE: - if (p->precision == 16) { - rswcode = pswcode = swap_bytes; - enc = AUDIO_ENCODING_SLINEAR_LE; - } else if (p->precision == 8 && !(flags & HAS_8)) { - pswcode = rswcode = change_sign8; - enc = AUDIO_ENCODING_ULINEAR_LE; - } - break; - case AUDIO_ENCODING_SLINEAR_LE: - if (p->precision == 8 && !(flags & HAS_8)) { - pswcode = rswcode = change_sign8; - enc = AUDIO_ENCODING_ULINEAR_LE; - } - break; - case AUDIO_ENCODING_ULINEAR_BE: - if (p->precision == 16) { - pswcode = swap_bytes_change_sign16_le; - rswcode = change_sign16_swap_bytes_le; - enc = AUDIO_ENCODING_SLINEAR_LE; - } else if (p->precision == 8 && !(flags & HAS_8U)) { - pswcode = rswcode = change_sign8; - enc = AUDIO_ENCODING_SLINEAR_LE; - } - break; - case AUDIO_ENCODING_ULINEAR_LE: - if (p->precision == 16) { - pswcode = rswcode = change_sign16_le; - enc = AUDIO_ENCODING_SLINEAR_LE; - } else if (p->precision == 8 && !(flags & HAS_8U)) { - pswcode = rswcode = change_sign8; - enc = AUDIO_ENCODING_SLINEAR_LE; - } - break; - case AUDIO_ENCODING_ULAW: - if (!(flags & HAS_MULAW)) { - if (flags & HAS_8U) { - pswcode = mulaw_to_ulinear8; - rswcode = ulinear8_to_mulaw; + for (mode = AUMODE_RECORD; mode != -1; + mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) { + if ((setmode & mode) == 0) + continue; + if ((sc->sc_chan.dir & mode) == 0) + continue; + + p = mode == AUMODE_PLAY ? play : rec; + + factor = 1; + swcode = 0; + enc = p->encoding; + switch (enc) { + case AUDIO_ENCODING_SLINEAR_BE: + if (p->precision == 16) { + swcode = swap_bytes; + enc = AUDIO_ENCODING_SLINEAR_LE; + } else if (p->precision == 8 && !(flags & HAS_8)) { + swcode = change_sign8; enc = AUDIO_ENCODING_ULINEAR_LE; - } else if (flags & HAS_8) { - pswcode = mulaw_to_slinear8; - rswcode = slinear8_to_mulaw; + } + break; + case AUDIO_ENCODING_SLINEAR_LE: + if (p->precision == 8 && !(flags & HAS_8)) { + swcode = change_sign8; + enc = AUDIO_ENCODING_ULINEAR_LE; + } + break; + case AUDIO_ENCODING_ULINEAR_BE: + if (p->precision == 16) { + if (mode == AUMODE_PLAY) + swcode = swap_bytes_change_sign16_le; + else + swcode = change_sign16_swap_bytes_le; enc = AUDIO_ENCODING_SLINEAR_LE; - } else if (flags & HAS_16) { - pswcode = mulaw_to_slinear16_le; - pfactor = 2; + } else if (p->precision == 8 && !(flags & HAS_8U)) { + swcode = change_sign8; enc = AUDIO_ENCODING_SLINEAR_LE; - /* XXX recording not handled */ - if (setmode & AUMODE_RECORD) - return (EINVAL); - } else - return (EINVAL); - } - break; - case AUDIO_ENCODING_ALAW: - if (!(flags & HAS_ALAW)) { - if (flags & HAS_8U) { - pswcode = alaw_to_ulinear8; - rswcode = ulinear8_to_alaw; - enc = AUDIO_ENCODING_ULINEAR_LE; - } else if (flags & HAS_8) { - pswcode = alaw_to_slinear8; - rswcode = slinear8_to_alaw; + } + break; + case AUDIO_ENCODING_ULINEAR_LE: + if (p->precision == 16) { + swcode = change_sign16_le; enc = AUDIO_ENCODING_SLINEAR_LE; - } else if (flags & HAS_16) { - pswcode = alaw_to_slinear16_le; - pfactor = 2; + } else if (p->precision == 8 && !(flags & HAS_8U)) { + swcode = change_sign8; enc = AUDIO_ENCODING_SLINEAR_LE; - /* XXX recording not handled */ - if (setmode & AUMODE_RECORD) + } + break; + case AUDIO_ENCODING_ULAW: + if (!(flags & HAS_MULAW)) { + if (mode == AUMODE_PLAY && + (flags & HAS_16)) { + swcode = mulaw_to_slinear16_le; + factor = 2; + enc = AUDIO_ENCODING_SLINEAR_LE; + } else if (flags & HAS_8U) { + if (mode == AUMODE_PLAY) + swcode = mulaw_to_ulinear8; + else + swcode = ulinear8_to_mulaw; + enc = AUDIO_ENCODING_ULINEAR_LE; + } else if (flags & HAS_8) { + if (mode == AUMODE_PLAY) + swcode = mulaw_to_slinear8; + else + swcode = slinear8_to_mulaw; + enc = AUDIO_ENCODING_SLINEAR_LE; + } else return (EINVAL); - } else - return (EINVAL); + } + break; + case AUDIO_ENCODING_ALAW: + if (!(flags & HAS_ALAW)) { + if (mode == AUMODE_PLAY && + (flags & HAS_16)) { + swcode = alaw_to_slinear16_le; + factor = 2; + enc = AUDIO_ENCODING_SLINEAR_LE; + } else if (flags & HAS_8U) { + if (mode == AUMODE_PLAY) + swcode = alaw_to_ulinear8; + else + swcode = ulinear8_to_alaw; + enc = AUDIO_ENCODING_ULINEAR_LE; + } else if (flags & HAS_8) { + if (mode == AUMODE_PLAY) + swcode = alaw_to_slinear8; + else + swcode = slinear8_to_alaw; + enc = AUDIO_ENCODING_SLINEAR_LE; + } else + return (EINVAL); + } + break; + default: + return (EINVAL); } - break; - default: - return (EINVAL); - } - /* XXX do some other conversions... */ - - DPRINTF(("uaudio_set_params: chan=%d prec=%d enc=%d rate=%ld\n", - p->channels, p->precision, enc, p->sample_rate)); - - for (i = 0; i < sc->sc_nalts; i++) { - struct usb_audio_streaming_type1_descriptor *a1d = - sc->sc_alts[i].asf1desc; - if (p->channels == a1d->bNrChannels && - p->precision ==a1d->bBitResolution && - enc == sc->sc_alts[i].encoding) { - if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) { - DPRINTFN(2,("uaudio_set_params: cont %d-%d\n", - UA_SAMP_LO(a1d), UA_SAMP_HI(a1d))); - if (UA_SAMP_LO(a1d) < p->sample_rate && - p->sample_rate < UA_SAMP_HI(a1d)) - goto found; - } else { - for (j = 0; j < a1d->bSamFreqType; j++) { - DPRINTFN(2,("uaudio_set_params: disc #" - "%d: %d\n", j, UA_GETSAMP(a1d, j))); - /* XXX allow for some slack */ - if (UA_GETSAMP(a1d, j) == - p->sample_rate) + /* XXX do some other conversions... */ + + DPRINTF(("uaudio_set_params: chan=%d prec=%d enc=%d rate=%ld\n", + p->channels, p->precision, enc, p->sample_rate)); + + for (i = 0; i < sc->sc_nalts; i++) { + struct usb_audio_streaming_type1_descriptor *a1d = + sc->sc_alts[i].asf1desc; + if (p->channels == a1d->bNrChannels && + p->precision == a1d->bBitResolution && + enc == sc->sc_alts[i].encoding && + (mode == AUMODE_PLAY ? UE_DIR_OUT : UE_DIR_IN) == + UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress)) { + if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) { + DPRINTFN(2,("uaudio_set_params: cont %d-%d\n", + UA_SAMP_LO(a1d), UA_SAMP_HI(a1d))); + if (UA_SAMP_LO(a1d) < p->sample_rate && + p->sample_rate < UA_SAMP_HI(a1d)) goto found; + } else { + for (j = 0; j < a1d->bSamFreqType; j++) { + DPRINTFN(2,("uaudio_set_params: disc #" + "%d: %d\n", j, UA_GETSAMP(a1d, j))); + /* XXX allow for some slack */ + if (UA_GETSAMP(a1d, j) == + p->sample_rate) + goto found; + } } } } - } - return (EINVAL); + return (EINVAL); - found: - p->sw_code = pswcode; - r->sw_code = rswcode; - p->factor = pfactor; - r->factor = rfactor; - sc->sc_curaltidx = i; + found: + p->sw_code = swcode; + p->factor = factor; + if (usemode == mode) + sc->sc_curaltidx = i; + } DPRINTF(("uaudio_set_params: use altidx=%d, altno=%d\n", sc->sc_curaltidx, sc->sc_alts[sc->sc_curaltidx].idesc->bAlternateSetting)); - return (0); + return (0); } usbd_status |