diff options
author | Stuart Henderson <sthen@cvs.openbsd.org> | 2010-07-23 14:46:29 +0000 |
---|---|---|
committer | Stuart Henderson <sthen@cvs.openbsd.org> | 2010-07-23 14:46:29 +0000 |
commit | 5cb5dfab1a6e22fa3c2e713160acaccd4b514b92 (patch) | |
tree | bcef8c943cbef565e7d94891fe763208ed8e45f6 /sys/dev/usb | |
parent | c8c1eff4714d7f2b7cedddd37b39c3b9a5b13602 (diff) |
revert last commit, unbreaking the tree; was missing a macro definition
presumably from a missing commit to a header file. go ahead kettenis@ todd@
Diffstat (limited to 'sys/dev/usb')
-rw-r--r-- | sys/dev/usb/uaudio.c | 295 |
1 files changed, 65 insertions, 230 deletions
diff --git a/sys/dev/usb/uaudio.c b/sys/dev/usb/uaudio.c index fcdaf4b4ab6..3d6afce50f0 100644 --- a/sys/dev/usb/uaudio.c +++ b/sys/dev/usb/uaudio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uaudio.c,v 1.84 2010/07/23 12:17:48 jakemsr Exp $ */ +/* $OpenBSD: uaudio.c,v 1.85 2010/07/23 14:46:28 sthen Exp $ */ /* $NetBSD: uaudio.c,v 1.90 2004/10/29 17:12:53 kent Exp $ */ /* @@ -68,6 +68,7 @@ #include <dev/usb/uaudioreg.h> /* #define UAUDIO_DEBUG */ +/* #define UAUDIO_MULTIPLE_ENDPOINTS */ #ifdef UAUDIO_DEBUG #define DPRINTF(x) do { if (uaudiodebug) printf x; } while (0) #define DPRINTFN(n,x) do { if (uaudiodebug>(n)) printf x; } while (0) @@ -80,7 +81,6 @@ int uaudiodebug = 0; #define UAUDIO_NCHANBUFS 3 /* number of outstanding request */ #define UAUDIO_MIN_FRAMES 2 /* ms of sound in each request */ #define UAUDIO_MAX_FRAMES 16 -#define UAUDIO_NSYNCBUFS 3 /* number of outstanding sync requests */ #define UAUDIO_MAX_ALTS 32 /* max alt settings allowed by driver */ @@ -129,11 +129,9 @@ struct chan { u_int sample_rate; u_int bytes_per_frame; u_int max_bytes_per_frame; - u_int fraction; /* fraction/frac_denom is the extra samples/frame */ - u_int frac_denom; /* denominator for fractional samples */ + u_int fraction; /* fraction/usb_fps is the extra samples/frame */ u_int residue; /* accumulates the fractional samples */ u_int nframes; /* # of frames per transfer */ - u_int nsync_frames; /* # of frames per sync transfer */ u_int usb_fps; u_int maxpktsize; u_int reqms; /* usb request data duration, in ms */ @@ -148,8 +146,6 @@ struct chan { int altidx; /* currently used altidx */ int curchanbuf; - int cursyncbuf; - struct chanbuf { struct chan *chan; usbd_xfer_handle xfer; @@ -159,15 +155,6 @@ struct chan { u_int16_t size; } chanbufs[UAUDIO_NCHANBUFS]; - struct syncbuf { - struct chan *chan; - usbd_xfer_handle xfer; - u_char *buffer; - u_int16_t sizes[UAUDIO_MAX_FRAMES]; - u_int16_t offsets[UAUDIO_MAX_FRAMES]; - u_int16_t size; - } syncbufs[UAUDIO_NSYNCBUFS]; - struct uaudio_softc *sc; /* our softc */ }; @@ -346,9 +333,6 @@ void uaudio_chan_set_param(struct chan *, u_char *, u_char *, int); void uaudio_chan_ptransfer(struct chan *); void uaudio_chan_pintr (usbd_xfer_handle, usbd_private_handle, usbd_status); -void uaudio_chan_psync_transfer(struct chan *); -void uaudio_chan_psync_intr - (usbd_xfer_handle, usbd_private_handle, usbd_status); void uaudio_chan_rtransfer(struct chan *); void uaudio_chan_rintr @@ -1620,10 +1604,10 @@ uaudio_process_as(struct uaudio_softc *sc, const char *buf, int *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 *sync_ed; + const usb_endpoint_descriptor_audio_t *epdesc1; const struct usb_audio_streaming_endpoint_descriptor *sed; int format, chan, prec, enc, bps; - int dir, type, sync, sync_addr; + int dir, type, sync; struct as_info ai; const char *format_str; @@ -1669,21 +1653,31 @@ uaudio_process_as(struct uaudio_softc *sc, const char *buf, int *offsp, dir = UE_GET_DIR(ed->bEndpointAddress); type = UE_GET_ISO_TYPE(ed->bmAttributes); - /* Check for sync endpoint. */ + /* We can't handle endpoints that need a sync pipe yet. */ sync = FALSE; - sync_addr = 0; - if (id->bNumEndpoints > 1 && - ((dir == UE_DIR_IN && type == UE_ISO_ADAPT) || - (dir != UE_DIR_IN && type == UE_ISO_ASYNC))) - sync = TRUE; - - /* Check whether sync endpoint address is given. */ - if (ed->bLength >= USB_ENDPOINT_DESCRIPTOR_AUDIO_SIZE) { - /* bSynchAdress set to 0 indicates sync is not used. */ - if (ed->bSynchAddress == 0) - sync = FALSE; - else - sync_addr = ed->bSynchAddress; + /* bSynchAddress set to 0 indicates sync pipe is not needed. */ + if (ed->bSynchAddress != 0) { + if (dir == UE_DIR_IN && type == UE_ISO_ADAPT) { + sync = TRUE; +#ifndef UAUDIO_MULTIPLE_ENDPOINTS + printf("%s: ignored input endpoint of type adaptive\n", + sc->sc_dev.dv_xname); + return (USBD_NORMAL_COMPLETION); +#endif + } + if (dir != UE_DIR_IN && type == UE_ISO_ASYNC) { + sync = TRUE; +#ifndef UAUDIO_MULTIPLE_ENDPOINTS + printf("%s: ignored output endpoint of type async\n", + sc->sc_dev.dv_xname); + return (USBD_NORMAL_COMPLETION); +#endif + } + } + if (sync && id->bNumEndpoints < 2) { + printf("%s: sync pipe needed, but no sync endpoint given\n", + sc->sc_dev.dv_xname); + return (USBD_NORMAL_COMPLETION); } sed = (const void *)(buf + offs); @@ -1695,56 +1689,44 @@ uaudio_process_as(struct uaudio_softc *sc, const char *buf, int *offsp, if (offs > size) return (USBD_INVAL); - sync_ed = NULL; - if (sync == TRUE) { - sync_ed = (const void*)(buf + offs); - if (sync_ed->bDescriptorType != UDESC_ENDPOINT) { - printf("%s: sync ep descriptor wrong type\n", - sc->sc_dev.dv_xname); - return (USBD_NORMAL_COMPLETION); - } + epdesc1 = NULL; +#ifdef UAUDIO_MULTIPLE_ENDPOINTS + if (sync) { + epdesc1 = (const void*)(buf + offs); + if (epdesc1->bDescriptorType != UDESC_ENDPOINT) + return USBD_INVAL; DPRINTF(("uaudio_process_as: endpoint[1] bLength=%d " "bDescriptorType=%d bEndpointAddress=%d " "bmAttributes=0x%x wMaxPacketSize=%d bInterval=%d " "bRefresh=%d bSynchAddress=%d\n", - sync_ed->bLength, sync_ed->bDescriptorType, - sync_ed->bEndpointAddress, sync_ed->bmAttributes, - UGETW(sync_ed->wMaxPacketSize), sync_ed->bInterval, - sync_ed->bRefresh, sync_ed->bSynchAddress)); - offs += sync_ed->bLength; - if (offs > size) { - printf("%s: sync ep descriptor too large\n", - sc->sc_dev.dv_xname); - return (USBD_NORMAL_COMPLETION); - } - if (dir == UE_GET_DIR(sync_ed->bEndpointAddress)) { - printf("%s: sync ep wrong direction\n", + epdesc1->bLength, epdesc1->bDescriptorType, + 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) { + printf("%s: invalid endpoint: bSynchAddress=0\n", sc->sc_dev.dv_xname); - return (USBD_NORMAL_COMPLETION); + return USBD_INVAL; } - if (UE_GET_XFERTYPE(sync_ed->bmAttributes) != UE_ISOCHRONOUS) { - printf("%s: sync ep wrong xfer type\n", - sc->sc_dev.dv_xname); - return (USBD_NORMAL_COMPLETION); + if (UE_GET_XFERTYPE(epdesc1->bmAttributes) != UE_ISOCHRONOUS) { + printf("%s: invalid endpoint: bmAttributes=0x%x\n", + sc->sc_dev.dv_xname, epdesc1->bmAttributes); + return USBD_INVAL; } - if (sync_ed->bLength >= - USB_ENDPOINT_DESCRIPTOR_AUDIO_SIZE && - sync_ed->bSynchAddress != 0) { - printf("%s: sync ep bSynchAddress != 0\n", - sc->sc_dev.dv_xname); - return (USBD_NORMAL_COMPLETION); + if (epdesc1->bEndpointAddress != ed->bSynchAddress) { + printf("%s: invalid endpoint addresses: " + "ep[0]->bSynchAddress=0x%x " + "ep[1]->bEndpointAddress=0x%x\n", + sc->sc_dev.dv_xname, ed->bSynchAddress, + epdesc1->bEndpointAddress); + return USBD_INVAL; } - if (sync_addr && sync_ed->bEndpointAddress != sync_addr) { - printf("%s: sync ep address mismatch\n", - sc->sc_dev.dv_xname); - return (USBD_NORMAL_COMPLETION); - } - } - if (sync_ed != NULL && dir == UE_DIR_IN) { - printf("%s: sync pipe for recording not yet implemented\n", - sc->sc_dev.dv_xname); - return (USBD_NORMAL_COMPLETION); + /* UE_GET_ADDR(epdesc1->bEndpointAddress), and epdesc1->bRefresh */ } +#endif format = UGETW(asid->wFormatTag); chan = asf1d->bNrChannels; @@ -1807,7 +1789,7 @@ uaudio_process_as(struct uaudio_softc *sc, const char *buf, int *offsp, ai.attributes = sed->bmAttributes; ai.idesc = id; ai.edesc = ed; - ai.edesc1 = sync_ed; + ai.edesc1 = epdesc1; ai.asf1desc = asf1d; ai.sc_busy = 0; if (sc->sc_nalts < UAUDIO_MAX_ALTS) @@ -1853,7 +1835,9 @@ uaudio_identify_as(struct uaudio_softc *sc, sc->sc_nullalt = id->bAlternateSetting; break; case 1: +#ifdef UAUDIO_MULTIPLE_ENDPOINTS case 2: +#endif uaudio_process_as(sc, buf, &offs, size, id); break; default: @@ -2234,8 +2218,6 @@ uaudio_halt_out_dma(void *addr) if (sc->sc_playchan.pipe != NULL) { uaudio_chan_close(sc, &sc->sc_playchan); sc->sc_playchan.pipe = NULL; - if (sc->sc_playchan.sync_pipe != NULL) - sc->sc_playchan.sync_pipe = NULL; uaudio_chan_free_buffers(sc, &sc->sc_playchan); sc->sc_playchan.intr = NULL; } @@ -2251,8 +2233,6 @@ uaudio_halt_in_dma(void *addr) if (sc->sc_recchan.pipe != NULL) { uaudio_chan_close(sc, &sc->sc_recchan); sc->sc_recchan.pipe = NULL; - if (sc->sc_recchan.sync_pipe != NULL) - sc->sc_recchan.sync_pipe = NULL; uaudio_chan_free_buffers(sc, &sc->sc_recchan); sc->sc_recchan.intr = NULL; } @@ -2700,10 +2680,6 @@ uaudio_trigger_output(void *addr, void *start, void *end, int blksize, s = splusb(); for (i = 0; i < UAUDIO_NCHANBUFS; i++) uaudio_chan_ptransfer(ch); - if (ch->sync_pipe) { - for (i = 0; i < UAUDIO_NSYNCBUFS; i++) - uaudio_chan_psync_transfer(ch); - } splx(s); return (0); @@ -2722,10 +2698,8 @@ uaudio_chan_open(struct uaudio_softc *sc, struct chan *ch) /* Set alternate interface corresponding to the mode. */ err = usbd_set_interface(as->ifaceh, as->alt); - if (err) { - DPRINTF(("%s: usbd_set_interface failed\n", __func__)); + if (err) return (err); - } /* * If just one sampling rate is supported, @@ -2746,19 +2720,12 @@ uaudio_chan_open(struct uaudio_softc *sc, struct chan *ch) ch->sync_pipe = 0; DPRINTF(("uaudio_chan_open: create pipe to 0x%02x\n", endpt)); err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->pipe); - if (err) { - printf("%s: error creating pipe: err=%s endpt=0x%02x\n", - __func__, usbd_errstr(err), endpt); + if (err) return err; - } if (as->edesc1 != NULL) { endpt = as->edesc1->bEndpointAddress; DPRINTF(("uaudio_chan_open: create sync-pipe to 0x%02x\n", endpt)); err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->sync_pipe); - if (err) { - printf("%s: error creating sync-pipe: err=%s endpt=0x%02x\n", - __func__, usbd_errstr(err), endpt); - } } return err; } @@ -2787,7 +2754,6 @@ uaudio_chan_close(struct uaudio_softc *sc, struct chan *ch) usbd_status uaudio_chan_alloc_buffers(struct uaudio_softc *sc, struct chan *ch) { - struct as_info *as = &sc->sc_alts[ch->altidx]; usbd_xfer_handle xfer; void *buf; int i, size; @@ -2809,22 +2775,6 @@ uaudio_chan_alloc_buffers(struct uaudio_softc *sc, struct chan *ch) ch->chanbufs[i].buffer = buf; ch->chanbufs[i].chan = ch; } - if (as->edesc1 != NULL) { - size = (ch->hi_speed ? 4 : 3) * ch->nsync_frames; - for (i = 0; i < UAUDIO_NSYNCBUFS; i++) { - xfer = usbd_alloc_xfer(sc->sc_udev); - if (xfer == 0) - goto bad_sync; - ch->syncbufs[i].xfer = xfer; - buf = usbd_alloc_buffer(xfer, size); - if (buf == 0) { - i++; - goto bad_sync; - } - ch->syncbufs[i].buffer = buf; - ch->syncbufs[i].chan = ch; - } - } return (USBD_NORMAL_COMPLETION); @@ -2833,27 +2783,15 @@ bad: /* implicit buffer free */ usbd_free_xfer(ch->chanbufs[i].xfer); return (USBD_NOMEM); - -bad_sync: - while (--i >= 0) - /* implicit buffer free */ - usbd_free_xfer(ch->syncbufs[i].xfer); - return (USBD_NOMEM); - } void uaudio_chan_free_buffers(struct uaudio_softc *sc, struct chan *ch) { - struct as_info *as = &sc->sc_alts[ch->altidx]; int i; for (i = 0; i < UAUDIO_NCHANBUFS; i++) usbd_free_xfer(ch->chanbufs[i].xfer); - if (as->edesc1 != NULL) { - for (i = 0; i < UAUDIO_NSYNCBUFS; i++) - usbd_free_xfer(ch->syncbufs[i].xfer); - } } /* Called at splusb() */ @@ -2879,10 +2817,10 @@ uaudio_chan_ptransfer(struct chan *ch) for (i = 0; i < ch->nframes; i++) { size = ch->bytes_per_frame; residue += ch->fraction; - if (residue >= ch->frac_denom) { + if (residue >= ch->usb_fps) { if ((ch->sc->sc_altflags & UA_NOFRAC) == 0) size += ch->sample_size; - residue -= ch->frac_denom; + residue -= ch->usb_fps; } cb->sizes[i] = size; total += size; @@ -2965,91 +2903,6 @@ uaudio_chan_pintr(usbd_xfer_handle xfer, usbd_private_handle priv, /* Called at splusb() */ void -uaudio_chan_psync_transfer(struct chan *ch) -{ - struct syncbuf *sb; - int i, size, total = 0; - - if (ch->sc->sc_dying) - return; - - /* Pick the next sync buffer. */ - sb = &ch->syncbufs[ch->cursyncbuf]; - if (++ch->cursyncbuf >= UAUDIO_NSYNCBUFS) - ch->cursyncbuf = 0; - - size = ch->hi_speed ? 4 : 3; - for (i = 0; i < ch->nsync_frames; i++) { - sb->sizes[i] = size; - sb->offsets[i] = total; - total += size; - } - sb->size = total; - - DPRINTFN(5,("%s: transfer xfer=%p\n", __func__, sb->xfer)); - /* Fill the request */ - usbd_setup_isoc_xfer(sb->xfer, ch->sync_pipe, sb, sb->sizes, - ch->nsync_frames, USBD_NO_COPY, uaudio_chan_psync_intr); - - (void)usbd_transfer(sb->xfer); -} - -void -uaudio_chan_psync_intr(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status status) -{ - struct syncbuf *sb = priv; - struct chan *ch = sb->chan; - u_int32_t count, tmp; - u_int32_t freq, freq_w, freq_f; - int i, pos, size; - - /* Return if we are aborting. */ - if (status == USBD_CANCELLED) - return; - - usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); - DPRINTFN(5,("%s: count=%d\n", __func__, count)); - - size = ch->hi_speed ? 4 : 3; - for (i = 0; count > 0 && i < ch->nsync_frames; i++) { - if (sb->sizes[i] != size) - continue; - count -= size; - pos = sb->offsets[i]; - if (ch->hi_speed) { - /* 16.16 (12.13) -> 16.16 (12.16) */ - freq = sb->buffer[pos+3] << 24 | - sb->buffer[pos+2] << 16 | - sb->buffer[pos+1] << 8 | - sb->buffer[pos]; - } else { - /* 10.14 (10.10) -> 16.16 (10.16) */ - freq = sb->buffer[pos+2] << 18 | - sb->buffer[pos+1] << 10 | - sb->buffer[pos] << 2; - } - freq_w = (freq >> 16) & (ch->hi_speed ? 0x0fff : 0x03ff); - freq_f = freq & 0xffff; - DPRINTFN(5,("%s: freq = %d %d/%d\n", __func__, freq_w, freq_f, - ch->frac_denom)); - tmp = freq_w * ch->sample_size; - if (tmp + (freq_f ? ch->sample_size : 0) > - ch->max_bytes_per_frame) { - DPRINTF(("%s: packet size request too large: %d/%d/%d\n", - __func__, tmp, ch->max_bytes_per_frame, ch->maxpktsize)); - } else { - ch->bytes_per_frame = tmp; - ch->fraction = freq_f; - } - } - - /* start next transfer */ - uaudio_chan_psync_transfer(ch); -} - -/* Called at splusb() */ -void uaudio_chan_rtransfer(struct chan *ch) { struct chanbuf *cb; @@ -3231,24 +3084,6 @@ uaudio_chan_init(struct chan *ch, int mode, int altidx, ch->max_bytes_per_frame = ch->maxpktsize; ch->residue = 0; - ch->frac_denom = ch->usb_fps; - if (ai->edesc1 != NULL) { - /* - * The lower 16-bits of the sync request represent - * fractional samples. Scale up the fraction here once - * so all fractions are using the same denominator. - */ - ch->frac_denom = 1 << 16; - ch->fraction = (ch->fraction * ch->frac_denom) / ch->usb_fps; - - /* - * Have to set nsync_frames somewhere. We can request - * a lot of sync data; the device will reply when it's - * ready, with empty frames meaning to keep using the - * current rate. - */ - ch->nsync_frames = UAUDIO_MAX_FRAMES; - } DPRINTF(("%s: residual sample fraction: %d/%d\n", __func__, ch->fraction, ch->usb_fps)); } |