[BACK]Return to uaudio.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / usb

Annotation of src/sys/dev/usb/uaudio.c, Revision 1.41.2.1

1.41.2.1! nathanw     1: /*     $NetBSD: uaudio.c,v 1.41 2001/01/23 14:04:13 augustss Exp $     */
1.1       augustss    2:
                      3: /*
                      4:  * Copyright (c) 1999 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
1.5       augustss    7:  * This code is derived from software contributed to The NetBSD Foundation
1.24      augustss    8:  * by Lennart Augustsson (lennart@augustsson.net) at
1.5       augustss    9:  * Carlstedt Research & Technology.
1.1       augustss   10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *        This product includes software developed by the NetBSD
                     22:  *        Foundation, Inc. and its contributors.
                     23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     24:  *    contributors may be used to endorse or promote products derived
                     25:  *    from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37:  * POSSIBILITY OF SUCH DAMAGE.
                     38:  */
                     39:
                     40: /*
1.32      augustss   41:  * USB audio specs: http://www.usb.org/developers/data/devclass/audio10.pdf
                     42:  *                  http://www.usb.org/developers/data/devclass/frmts10.pdf
                     43:  *                  http://www.usb.org/developers/data/devclass/termt10.pdf
1.1       augustss   44:  */
                     45:
                     46: #include <sys/param.h>
                     47: #include <sys/systm.h>
                     48: #include <sys/kernel.h>
                     49: #include <sys/malloc.h>
                     50: #include <sys/device.h>
                     51: #include <sys/ioctl.h>
                     52: #include <sys/tty.h>
                     53: #include <sys/file.h>
1.40      augustss   54: #include <sys/reboot.h>                /* for bootverbose */
1.1       augustss   55: #include <sys/select.h>
                     56: #include <sys/proc.h>
                     57: #include <sys/vnode.h>
                     58: #include <sys/device.h>
                     59: #include <sys/poll.h>
                     60:
                     61: #include <sys/audioio.h>
                     62: #include <dev/audio_if.h>
                     63: #include <dev/mulaw.h>
                     64: #include <dev/auconv.h>
                     65:
                     66: #include <dev/usb/usb.h>
                     67: #include <dev/usb/usbdi.h>
                     68: #include <dev/usb/usbdi_util.h>
                     69: #include <dev/usb/usb_quirks.h>
                     70:
                     71: #include <dev/usb/uaudioreg.h>
                     72:
1.4       augustss   73: #ifdef UAUDIO_DEBUG
1.1       augustss   74: #define DPRINTF(x)     if (uaudiodebug) logprintf x
                     75: #define DPRINTFN(n,x)  if (uaudiodebug>(n)) logprintf x
                     76: int    uaudiodebug = 0;
                     77: #else
                     78: #define DPRINTF(x)
                     79: #define DPRINTFN(n,x)
                     80: #endif
                     81:
1.22      augustss   82: #define UAUDIO_NCHANBUFS 6     /* number of outstanding request */
1.1       augustss   83: #define UAUDIO_NFRAMES   20    /* ms of sound in each request */
                     84:
                     85:
                     86: #define MIX_MAX_CHAN 8
                     87: struct mixerctl {
                     88:        u_int16_t       wValue[MIX_MAX_CHAN]; /* using nchan */
                     89:        u_int16_t       wIndex;
                     90:        u_int8_t        nchan;
                     91:        u_int8_t        type;
                     92: #define MIX_ON_OFF     1
                     93: #define MIX_SIGNED_16  2
                     94: #define MIX_UNSIGNED_16        3
                     95: #define MIX_SIGNED_8   4
                     96: #define MIX_SIZE(n) ((n) == MIX_SIGNED_16 || (n) == MIX_UNSIGNED_16 ? 2 : 1)
                     97: #define MIX_UNSIGNED(n) ((n) == MIX_UNSIGNED_16)
1.34      augustss   98:        int             minval, maxval;
                     99:        u_int           delta;
                    100:        u_int           mul;
1.1       augustss  101:        u_int8_t        class;
                    102:        char            ctlname[MAX_AUDIO_DEV_LEN];
                    103:        char            *ctlunit;
                    104: };
                    105: #define MAKE(h,l) (((h) << 8) | (l))
                    106:
                    107: struct as_info {
                    108:        u_int8_t        alt;
                    109:        u_int8_t        encoding;
1.37      mycroft   110:        usbd_interface_handle   ifaceh;
1.1       augustss  111:        usb_interface_descriptor_t *idesc;
                    112:        usb_endpoint_descriptor_audio_t *edesc;
                    113:        struct usb_audio_streaming_type1_descriptor *asf1desc;
                    114: };
                    115:
                    116: struct chan {
                    117:        int     terminal;       /* terminal id */
1.26      augustss  118:        void    (*intr)(void *);        /* dma completion intr handler */
1.1       augustss  119:        void    *arg;           /* arg for intr() */
                    120:        usbd_pipe_handle pipe;
1.35      mycroft   121:        int     dir;            /* direction */
1.1       augustss  122:
                    123:        u_int   sample_size;
                    124:        u_int   sample_rate;
                    125:        u_int   bytes_per_frame;
                    126:        u_int   fraction;       /* fraction/1000 is the extra samples/frame */
                    127:        u_int   residue;        /* accumulates the fractional samples */
                    128:
                    129:        u_char  *start;         /* upper layer buffer start */
                    130:        u_char  *end;           /* upper layer buffer end */
                    131:        u_char  *cur;           /* current position in upper layer buffer */
                    132:        int     blksize;        /* chunk size to report up */
                    133:        int     transferred;    /* transferred bytes not reported up */
                    134:
1.31      augustss  135:        char    nofrac;         /* don't do sample rate adjustment */
                    136:
1.1       augustss  137:        int     curchanbuf;
                    138:        struct chanbuf {
                    139:                struct chan         *chan;
1.9       augustss  140:                usbd_xfer_handle xfer;
1.1       augustss  141:                u_char              *buffer;
                    142:                u_int16_t           sizes[UAUDIO_NFRAMES];
                    143:                u_int16_t           size;
                    144:        } chanbufs[UAUDIO_NCHANBUFS];
1.8       augustss  145:
                    146:        struct uaudio_softc *sc; /* our softc */
1.1       augustss  147: };
                    148:
                    149: struct uaudio_softc {
                    150:        USBBASEDEVICE sc_dev;           /* base device */
                    151:        usbd_device_handle sc_udev;     /* USB device */
                    152:
                    153:        int     sc_ac_iface;    /* Audio Control interface */
                    154:        usbd_interface_handle   sc_ac_ifaceh;
                    155:
1.5       augustss  156:        struct chan sc_chan;
1.1       augustss  157:
                    158:        int     sc_curaltidx;
                    159:
                    160:        int     sc_nullalt;
                    161:
1.7       augustss  162:        int     sc_audio_rev;
                    163:
1.1       augustss  164:        struct as_info *sc_alts;
                    165:        int     sc_nalts;
                    166:        int     sc_props;
                    167:
                    168:        int     sc_altflags;
                    169: #define HAS_8     0x01
                    170: #define HAS_16    0x02
                    171: #define HAS_8U    0x04
                    172: #define HAS_ALAW  0x08
                    173: #define HAS_MULAW 0x10
                    174:
                    175:        struct mixerctl *sc_ctls;
                    176:        int     sc_nctls;
                    177:
                    178:        device_ptr_t sc_audiodev;
                    179:        char    sc_dying;
                    180: };
                    181:
                    182: #define UAC_OUTPUT 0
                    183: #define UAC_INPUT  1
                    184: #define UAC_EQUAL  2
                    185:
1.26      augustss  186: Static usbd_status     uaudio_identify_ac(struct uaudio_softc *sc,
                    187:                                           usb_config_descriptor_t *cdesc);
                    188: Static usbd_status     uaudio_identify_as(struct uaudio_softc *sc,
                    189:                                           usb_config_descriptor_t *cdesc);
                    190: Static usbd_status     uaudio_process_as(struct uaudio_softc *sc,
1.9       augustss  191:                            char *buf, int *offsp, int size,
1.26      augustss  192:                            usb_interface_descriptor_t *id);
1.1       augustss  193:
1.26      augustss  194: Static void            uaudio_add_alt(struct uaudio_softc *sc,
                    195:                                       struct as_info *ai);
1.1       augustss  196:
1.26      augustss  197: Static usb_interface_descriptor_t *uaudio_find_iface(char *buf,
                    198:                            int size, int *offsp, int subtype);
1.1       augustss  199:
1.26      augustss  200: Static void            uaudio_mixer_add_ctl(struct uaudio_softc *sc,
                    201:                                             struct mixerctl *mp);
                    202: Static char            *uaudio_id_name(struct uaudio_softc *sc,
                    203:                                        usb_descriptor_t **dps, int id);
                    204: Static struct usb_audio_cluster uaudio_get_cluster(int id,
                    205:                                                   usb_descriptor_t **dps);
                    206: Static void            uaudio_add_input(struct uaudio_softc *sc,
                    207:                            usb_descriptor_t *v, usb_descriptor_t **dps);
                    208: Static void            uaudio_add_output(struct uaudio_softc *sc,
                    209:                            usb_descriptor_t *v, usb_descriptor_t **dps);
                    210: Static void            uaudio_add_mixer(struct uaudio_softc *sc,
                    211:                            usb_descriptor_t *v, usb_descriptor_t **dps);
                    212: Static void            uaudio_add_selector(struct uaudio_softc *sc,
                    213:                            usb_descriptor_t *v, usb_descriptor_t **dps);
                    214: Static void            uaudio_add_feature(struct uaudio_softc *sc,
                    215:                            usb_descriptor_t *v, usb_descriptor_t **dps);
                    216: Static void            uaudio_add_processing_updown(struct uaudio_softc *sc,
                    217:                                 usb_descriptor_t *v, usb_descriptor_t **dps);
                    218: Static void            uaudio_add_processing(struct uaudio_softc *sc,
                    219:                            usb_descriptor_t *v, usb_descriptor_t **dps);
                    220: Static void            uaudio_add_extension(struct uaudio_softc *sc,
                    221:                            usb_descriptor_t *v, usb_descriptor_t **dps);
                    222: Static usbd_status     uaudio_identify(struct uaudio_softc *sc,
                    223:                            usb_config_descriptor_t *cdesc);
                    224:
                    225: Static int             uaudio_signext(int type, int val);
                    226: Static int             uaudio_value2bsd(struct mixerctl *mc, int val);
                    227: Static int             uaudio_bsd2value(struct mixerctl *mc, int val);
                    228: Static int             uaudio_get(struct uaudio_softc *sc, int type,
                    229:                            int which, int wValue, int wIndex, int len);
                    230: Static int             uaudio_ctl_get(struct uaudio_softc *sc, int which,
                    231:                            struct mixerctl *mc, int chan);
                    232: Static void            uaudio_set(struct uaudio_softc *sc, int type,
                    233:                            int which, int wValue, int wIndex, int l, int v);
                    234: Static void            uaudio_ctl_set(struct uaudio_softc *sc, int which,
                    235:                            struct mixerctl *mc, int chan, int val);
                    236:
                    237: Static usbd_status     uaudio_set_speed(struct uaudio_softc *, int, u_int);
                    238:
                    239: Static usbd_status     uaudio_chan_open(struct uaudio_softc *sc,
                    240:                                         struct chan *ch);
                    241: Static void            uaudio_chan_close(struct uaudio_softc *sc,
                    242:                                          struct chan *ch);
                    243: Static usbd_status     uaudio_chan_alloc_buffers(struct uaudio_softc *,
                    244:                                                  struct chan *);
                    245: Static void            uaudio_chan_free_buffers(struct uaudio_softc *,
                    246:                                                 struct chan *);
                    247: Static void            uaudio_chan_set_param(struct chan *ch,
1.9       augustss  248:                            struct audio_params *param, u_char *start,
1.26      augustss  249:                            u_char *end, int blksize);
                    250: Static void            uaudio_chan_ptransfer(struct chan *ch);
                    251: Static void            uaudio_chan_pintr(usbd_xfer_handle xfer,
                    252:                            usbd_private_handle priv, usbd_status status);
                    253:
                    254: Static void            uaudio_chan_rtransfer(struct chan *ch);
                    255: Static void            uaudio_chan_rintr(usbd_xfer_handle xfer,
                    256:                            usbd_private_handle priv, usbd_status status);
                    257:
                    258: Static int             uaudio_open(void *, int);
                    259: Static void            uaudio_close(void *);
                    260: Static int             uaudio_drain(void *);
                    261: Static int             uaudio_query_encoding(void *, struct audio_encoding *);
                    262: Static int             uaudio_set_params(void *, int, int,
                    263:                            struct audio_params *, struct audio_params *);
                    264: Static int             uaudio_round_blocksize(void *, int);
                    265: Static int             uaudio_trigger_output(void *, void *, void *,
                    266:                                              int, void (*)(void *), void *,
                    267:                                              struct audio_params *);
                    268: Static int             uaudio_trigger_input (void *, void *, void *,
                    269:                                              int, void (*)(void *), void *,
                    270:                                              struct audio_params *);
                    271: Static int             uaudio_halt_in_dma(void *);
                    272: Static int             uaudio_halt_out_dma(void *);
                    273: Static int             uaudio_getdev(void *, struct audio_device *);
                    274: Static int             uaudio_mixer_set_port(void *, mixer_ctrl_t *);
                    275: Static int             uaudio_mixer_get_port(void *, mixer_ctrl_t *);
                    276: Static int             uaudio_query_devinfo(void *, mixer_devinfo_t *);
                    277: Static int             uaudio_get_props(void *);
1.1       augustss  278:
1.21      augustss  279: Static struct audio_hw_if uaudio_hw_if = {
1.1       augustss  280:        uaudio_open,
                    281:        uaudio_close,
                    282:        uaudio_drain,
                    283:        uaudio_query_encoding,
                    284:        uaudio_set_params,
                    285:        uaudio_round_blocksize,
                    286:        NULL,
                    287:        NULL,
                    288:        NULL,
                    289:        NULL,
                    290:        NULL,
                    291:        uaudio_halt_out_dma,
                    292:        uaudio_halt_in_dma,
                    293:        NULL,
                    294:        uaudio_getdev,
                    295:        NULL,
                    296:        uaudio_mixer_set_port,
                    297:        uaudio_mixer_get_port,
                    298:        uaudio_query_devinfo,
                    299:        NULL,
                    300:        NULL,
                    301:        NULL,
                    302:        NULL,
                    303:        uaudio_get_props,
                    304:        uaudio_trigger_output,
                    305:        uaudio_trigger_input,
                    306: };
                    307:
1.21      augustss  308: Static struct audio_device uaudio_device = {
1.1       augustss  309:        "USB audio",
                    310:        "",
                    311:        "uaudio"
                    312: };
                    313:
                    314: USB_DECLARE_DRIVER(uaudio);
                    315:
                    316: USB_MATCH(uaudio)
                    317: {
                    318:        USB_MATCH_START(uaudio, uaa);
                    319:        usb_interface_descriptor_t *id;
                    320:
1.9       augustss  321:        if (uaa->iface == NULL)
1.1       augustss  322:                return (UMATCH_NONE);
                    323:
                    324:        id = usbd_get_interface_descriptor(uaa->iface);
                    325:        /* Trigger on the control interface. */
1.9       augustss  326:        if (id == NULL ||
1.19      augustss  327:            id->bInterfaceClass != UICLASS_AUDIO ||
                    328:            id->bInterfaceSubClass != UISUBCLASS_AUDIOCONTROL ||
1.10      augustss  329:            (usbd_get_quirks(uaa->device)->uq_flags & UQ_BAD_AUDIO))
1.1       augustss  330:                return (UMATCH_NONE);
                    331:
                    332:        return (UMATCH_IFACECLASS_IFACESUBCLASS);
                    333: }
                    334:
                    335: USB_ATTACH(uaudio)
                    336: {
                    337:        USB_ATTACH_START(uaudio, sc, uaa);
                    338:        usb_interface_descriptor_t *id;
                    339:        usb_config_descriptor_t *cdesc;
                    340:        char devinfo[1024];
1.9       augustss  341:        usbd_status err;
1.37      mycroft   342:        int i, j, found;
1.1       augustss  343:
                    344:        usbd_devinfo(uaa->device, 0, devinfo);
                    345:        printf(": %s\n", devinfo);
                    346:
                    347:        sc->sc_udev = uaa->device;
                    348:
                    349:        cdesc = usbd_get_config_descriptor(sc->sc_udev);
1.13      augustss  350:        if (cdesc == NULL) {
                    351:                printf("%s: failed to get configuration descriptor\n",
                    352:                       USBDEVNAME(sc->sc_dev));
1.1       augustss  353:                USB_ATTACH_ERROR_RETURN;
1.13      augustss  354:        }
1.1       augustss  355:
1.9       augustss  356:        err = uaudio_identify(sc, cdesc);
                    357:        if (err) {
1.1       augustss  358:                printf("%s: audio descriptors make no sense, error=%d\n",
1.9       augustss  359:                       USBDEVNAME(sc->sc_dev), err);
1.1       augustss  360:                USB_ATTACH_ERROR_RETURN;
                    361:        }
                    362:
                    363:        sc->sc_ac_ifaceh = uaa->iface;
                    364:        /* Pick up the AS interface. */
                    365:        for (i = 0; i < uaa->nifaces; i++) {
1.37      mycroft   366:                if (uaa->ifaces[i] == NULL)
                    367:                        continue;
                    368:                id = usbd_get_interface_descriptor(uaa->ifaces[i]);
                    369:                if (id == NULL)
                    370:                        continue;
                    371:                found = 0;
                    372:                for (j = 0; j < sc->sc_nalts; j++) {
                    373:                        if (id->bInterfaceNumber ==
                    374:                            sc->sc_alts[j].idesc->bInterfaceNumber) {
                    375:                                sc->sc_alts[j].ifaceh = uaa->ifaces[i];
                    376:                                found = 1;
1.1       augustss  377:                        }
                    378:                }
1.37      mycroft   379:                if (found)
                    380:                        uaa->ifaces[i] = NULL;
1.1       augustss  381:        }
                    382:
1.37      mycroft   383:        for (j = 0; j < sc->sc_nalts; j++) {
                    384:                if (sc->sc_alts[j].ifaceh == NULL) {
1.40      augustss  385:                        printf("%s: alt %d missing AS interface(s)\n",
                    386:                            USBDEVNAME(sc->sc_dev), j);
1.37      mycroft   387:                        USB_ATTACH_ERROR_RETURN;
                    388:                }
1.1       augustss  389:        }
                    390:
1.40      augustss  391:        printf("%s: audio rev %d.%02x\n", USBDEVNAME(sc->sc_dev),
1.7       augustss  392:               sc->sc_audio_rev >> 8, sc->sc_audio_rev & 0xff);
                    393:
1.8       augustss  394:        sc->sc_chan.sc = sc;
                    395:
1.31      augustss  396:        if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_FRAC)
                    397:                sc->sc_chan.nofrac = 1;
                    398:
1.40      augustss  399: #ifndef UAUDIO_DEBUG
                    400:        if (bootverbose)
                    401: #endif
                    402:                printf("%s: %d mixer controls\n", USBDEVNAME(sc->sc_dev),
                    403:                    sc->sc_nctls);
                    404:
1.41      augustss  405:        usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
                    406:                           USBDEV(sc->sc_dev));
                    407:
1.1       augustss  408:        DPRINTF(("uaudio_attach: doing audio_attach_mi\n"));
1.23      augustss  409: #if defined(__OpenBSD__)
                    410:        audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
                    411: #else
1.1       augustss  412:        sc->sc_audiodev = audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
1.23      augustss  413: #endif
1.17      augustss  414:
1.1       augustss  415:        USB_ATTACH_SUCCESS_RETURN;
                    416: }
                    417:
                    418: int
1.26      augustss  419: uaudio_activate(device_ptr_t self, enum devact act)
1.1       augustss  420: {
                    421:        struct uaudio_softc *sc = (struct uaudio_softc *)self;
1.2       augustss  422:        int rv = 0;
1.1       augustss  423:
                    424:        switch (act) {
                    425:        case DVACT_ACTIVATE:
                    426:                return (EOPNOTSUPP);
                    427:                break;
                    428:
                    429:        case DVACT_DEACTIVATE:
1.40      augustss  430:                if (sc->sc_audiodev != NULL)
1.2       augustss  431:                        rv = config_deactivate(sc->sc_audiodev);
1.1       augustss  432:                sc->sc_dying = 1;
                    433:                break;
                    434:        }
1.2       augustss  435:        return (rv);
1.1       augustss  436: }
                    437:
                    438: int
1.26      augustss  439: uaudio_detach(device_ptr_t self, int flags)
1.1       augustss  440: {
                    441:        struct uaudio_softc *sc = (struct uaudio_softc *)self;
                    442:        int rv = 0;
                    443:
1.8       augustss  444:        /* Wait for outstanding requests to complete. */
                    445:        usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
                    446:
1.9       augustss  447:        if (sc->sc_audiodev != NULL)
1.1       augustss  448:                rv = config_detach(sc->sc_audiodev, flags);
1.17      augustss  449:
                    450:        usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
                    451:                           USBDEV(sc->sc_dev));
1.1       augustss  452:
                    453:        return (rv);
                    454: }
                    455:
                    456: int
1.26      augustss  457: uaudio_query_encoding(void *addr, struct audio_encoding *fp)
1.1       augustss  458: {
                    459:        struct uaudio_softc *sc = addr;
                    460:        int flags = sc->sc_altflags;
                    461:        int idx;
                    462:
                    463:        if (sc->sc_dying)
                    464:                return (EIO);
                    465:
                    466:        if (sc->sc_nalts == 0 || flags == 0)
                    467:                return (ENXIO);
                    468:
                    469:        idx = fp->index;
                    470:        switch (idx) {
                    471:        case 0:
                    472:                strcpy(fp->name, AudioEulinear);
                    473:                fp->encoding = AUDIO_ENCODING_ULINEAR;
                    474:                fp->precision = 8;
                    475:                fp->flags = flags&HAS_8U ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
                    476:                return (0);
                    477:        case 1:
                    478:                strcpy(fp->name, AudioEmulaw);
                    479:                fp->encoding = AUDIO_ENCODING_ULAW;
                    480:                fp->precision = 8;
                    481:                fp->flags = flags&HAS_MULAW ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
                    482:                return (0);
                    483:        case 2:
                    484:                strcpy(fp->name, AudioEalaw);
                    485:                fp->encoding = AUDIO_ENCODING_ALAW;
                    486:                fp->precision = 8;
                    487:                fp->flags = flags&HAS_ALAW ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
                    488:                return (0);
                    489:        case 3:
                    490:                strcpy(fp->name, AudioEslinear);
                    491:                fp->encoding = AUDIO_ENCODING_SLINEAR;
                    492:                fp->precision = 8;
                    493:                fp->flags = flags&HAS_8 ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
                    494:                return (0);
                    495:         case 4:
                    496:                strcpy(fp->name, AudioEslinear_le);
                    497:                fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
                    498:                fp->precision = 16;
                    499:                fp->flags = 0;
                    500:                return (0);
                    501:        case 5:
                    502:                strcpy(fp->name, AudioEulinear_le);
                    503:                fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
                    504:                fp->precision = 16;
                    505:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    506:                return (0);
                    507:        case 6:
                    508:                strcpy(fp->name, AudioEslinear_be);
                    509:                fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
                    510:                fp->precision = 16;
                    511:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    512:                return (0);
                    513:        case 7:
                    514:                strcpy(fp->name, AudioEulinear_be);
                    515:                fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
                    516:                fp->precision = 16;
                    517:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    518:                return (0);
                    519:        default:
                    520:                return (EINVAL);
                    521:        }
                    522: }
                    523:
                    524: usb_interface_descriptor_t *
1.26      augustss  525: uaudio_find_iface(char *buf, int size, int *offsp, int subtype)
1.1       augustss  526: {
                    527:        usb_interface_descriptor_t *d;
                    528:
                    529:        while (*offsp < size) {
                    530:                d = (void *)(buf + *offsp);
                    531:                *offsp += d->bLength;
                    532:                if (d->bDescriptorType == UDESC_INTERFACE &&
1.19      augustss  533:                    d->bInterfaceClass == UICLASS_AUDIO &&
1.1       augustss  534:                    d->bInterfaceSubClass == subtype)
                    535:                        return (d);
                    536:        }
1.40      augustss  537:        return (NULL);
1.1       augustss  538: }
                    539:
                    540: void
1.26      augustss  541: uaudio_mixer_add_ctl(struct uaudio_softc *sc, struct mixerctl *mc)
1.1       augustss  542: {
1.33      augustss  543:        int res;
1.41.2.1! nathanw   544:        size_t len = sizeof(*mc) * (sc->sc_nctls + 1);
        !           545:        struct mixerctl *nmc = sc->sc_nctls == 0 ?
        !           546:            malloc(len, M_USBDEV, M_NOWAIT) :
        !           547:            realloc(sc->sc_ctls, len, M_USBDEV, M_NOWAIT);
1.33      augustss  548:
1.41.2.1! nathanw   549:        if (nmc == NULL) {
1.1       augustss  550:                printf("uaudio_mixer_add_ctl: no memory\n");
                    551:                return;
                    552:        }
1.41.2.1! nathanw   553:        sc->sc_ctls = nmc;
1.1       augustss  554:
1.33      augustss  555:        mc->delta = 0;
1.1       augustss  556:        if (mc->type != MIX_ON_OFF) {
                    557:                /* Determine min and max values. */
                    558:                mc->minval = uaudio_signext(mc->type,
                    559:                        uaudio_get(sc, GET_MIN, UT_READ_CLASS_INTERFACE,
                    560:                                   mc->wValue[0], mc->wIndex,
                    561:                                   MIX_SIZE(mc->type)));
                    562:                mc->maxval = 1 + uaudio_signext(mc->type,
                    563:                        uaudio_get(sc, GET_MAX, UT_READ_CLASS_INTERFACE,
                    564:                                   mc->wValue[0], mc->wIndex,
                    565:                                   MIX_SIZE(mc->type)));
1.34      augustss  566:                mc->mul = mc->maxval - mc->minval;
                    567:                if (mc->mul == 0)
                    568:                        mc->mul = 1;
1.33      augustss  569:                res = uaudio_get(sc, GET_RES, UT_READ_CLASS_INTERFACE,
                    570:                                 mc->wValue[0], mc->wIndex,
                    571:                                 MIX_SIZE(mc->type));
1.34      augustss  572:                if (res > 0)
                    573:                        mc->delta = (res * 256 + mc->mul/2) / mc->mul;
1.1       augustss  574:        } else {
                    575:                mc->minval = 0;
                    576:                mc->maxval = 1;
                    577:        }
                    578:
                    579:        sc->sc_ctls[sc->sc_nctls++] = *mc;
                    580:
1.4       augustss  581: #ifdef UAUDIO_DEBUG
1.1       augustss  582:        if (uaudiodebug > 2) {
                    583:                int i;
                    584:                DPRINTF(("uaudio_mixer_add_ctl: wValue=%04x",mc->wValue[0]));
                    585:                for (i = 1; i < mc->nchan; i++)
                    586:                        DPRINTF((",%04x", mc->wValue[i]));
                    587:                DPRINTF((" wIndex=%04x type=%d name='%s' unit='%s' "
                    588:                         "min=%d max=%d\n",
                    589:                         mc->wIndex, mc->type, mc->ctlname, mc->ctlunit,
                    590:                         mc->minval, mc->maxval));
                    591:        }
                    592: #endif
                    593: }
                    594:
                    595: char *
1.26      augustss  596: uaudio_id_name(struct uaudio_softc *sc, usb_descriptor_t **dps, int id)
1.1       augustss  597: {
                    598:        static char buf[32];
                    599:        sprintf(buf, "i%d", id);
                    600:        return (buf);
                    601: }
                    602:
                    603: struct usb_audio_cluster
1.26      augustss  604: uaudio_get_cluster(int id, usb_descriptor_t **dps)
1.1       augustss  605: {
                    606:        struct usb_audio_cluster r;
                    607:        usb_descriptor_t *dp;
                    608:        int i;
                    609:
                    610:        for (i = 0; i < 25; i++) { /* avoid infinite loops */
                    611:                dp = dps[id];
                    612:                if (dp == 0)
                    613:                        goto bad;
                    614:                switch (dp->bDescriptorSubtype) {
                    615:                case UDESCSUB_AC_INPUT:
                    616: #define p ((struct usb_audio_input_terminal *)dp)
                    617:                        r.bNrChannels = p->bNrChannels;
                    618:                        USETW(r.wChannelConfig, UGETW(p->wChannelConfig));
                    619:                        r.iChannelNames = p->iChannelNames;
                    620: #undef p
                    621:                        return (r);
                    622:                case UDESCSUB_AC_OUTPUT:
                    623: #define p ((struct usb_audio_output_terminal *)dp)
                    624:                        id = p->bSourceId;
                    625: #undef p
                    626:                        break;
                    627:                case UDESCSUB_AC_MIXER:
                    628: #define p ((struct usb_audio_mixer_unit *)dp)
                    629:                        r = *(struct usb_audio_cluster *)
                    630:                                &p->baSourceId[p->bNrInPins];
                    631: #undef p
                    632:                        return (r);
                    633:                case UDESCSUB_AC_SELECTOR:
                    634:                        /* XXX This is not really right */
                    635: #define p ((struct usb_audio_selector_unit *)dp)
                    636:                        id = p->baSourceId[0];
                    637: #undef p
                    638:                        break;
                    639:                case UDESCSUB_AC_FEATURE:
                    640: #define p ((struct usb_audio_feature_unit *)dp)
                    641:                        id = p->bSourceId;
                    642: #undef p
                    643:                        break;
                    644:                case UDESCSUB_AC_PROCESSING:
                    645: #define p ((struct usb_audio_processing_unit *)dp)
                    646:                        r = *(struct usb_audio_cluster *)
                    647:                                &p->baSourceId[p->bNrInPins];
                    648: #undef p
                    649:                        return (r);
                    650:                case UDESCSUB_AC_EXTENSION:
                    651: #define p ((struct usb_audio_extension_unit *)dp)
                    652:                        r = *(struct usb_audio_cluster *)
                    653:                                &p->baSourceId[p->bNrInPins];
                    654: #undef p
                    655:                        return (r);
                    656:                default:
                    657:                        goto bad;
                    658:                }
                    659:        }
                    660:  bad:
                    661:        printf("uaudio_get_cluster: bad data\n");
                    662:        memset(&r, 0, sizeof r);
1.9       augustss  663:        return (r);
1.1       augustss  664:
                    665: }
                    666:
                    667: void
1.26      augustss  668: uaudio_add_input(struct uaudio_softc *sc, usb_descriptor_t *v,
                    669:                 usb_descriptor_t **dps)
1.1       augustss  670: {
1.4       augustss  671: #ifdef UAUDIO_DEBUG
1.1       augustss  672:        struct usb_audio_input_terminal *d =
                    673:                (struct usb_audio_input_terminal *)v;
                    674:
                    675:        DPRINTFN(2,("uaudio_add_input: bTerminalId=%d wTerminalType=0x%04x "
                    676:                    "bAssocTerminal=%d bNrChannels=%d wChannelConfig=%d "
                    677:                    "iChannelNames=%d iTerminal=%d\n",
                    678:                    d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal,
                    679:                    d->bNrChannels, UGETW(d->wChannelConfig),
                    680:                    d->iChannelNames, d->iTerminal));
                    681: #endif
                    682: }
                    683:
                    684: void
1.26      augustss  685: uaudio_add_output(struct uaudio_softc *sc, usb_descriptor_t *v,
                    686:                  usb_descriptor_t **dps)
1.1       augustss  687: {
1.4       augustss  688: #ifdef UAUDIO_DEBUG
1.1       augustss  689:        struct usb_audio_output_terminal *d =
                    690:                (struct usb_audio_output_terminal *)v;
                    691:
                    692:        DPRINTFN(2,("uaudio_add_output: bTerminalId=%d wTerminalType=0x%04x "
                    693:                    "bAssocTerminal=%d bSourceId=%d iTerminal=%d\n",
                    694:                    d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal,
                    695:                    d->bSourceId, d->iTerminal));
                    696: #endif
                    697: }
                    698:
                    699: void
1.26      augustss  700: uaudio_add_mixer(struct uaudio_softc *sc, usb_descriptor_t *v,
                    701:                 usb_descriptor_t **dps)
1.1       augustss  702: {
                    703:        struct usb_audio_mixer_unit *d = (struct usb_audio_mixer_unit *)v;
                    704:        struct usb_audio_mixer_unit_1 *d1;
                    705:        int c, chs, ichs, ochs, i, o, bno, p, mo, mc, k;
                    706:        uByte *bm;
                    707:        struct mixerctl mix;
                    708:
                    709:        DPRINTFN(2,("uaudio_add_mixer: bUnitId=%d bNrInPins=%d\n",
                    710:                    d->bUnitId, d->bNrInPins));
                    711:
                    712:        /* Compute the number of input channels */
                    713:        ichs = 0;
                    714:        for (i = 0; i < d->bNrInPins; i++)
                    715:                ichs += uaudio_get_cluster(d->baSourceId[i], dps).bNrChannels;
                    716:
                    717:        /* and the number of output channels */
                    718:        d1 = (struct usb_audio_mixer_unit_1 *)&d->baSourceId[d->bNrInPins];
                    719:        ochs = d1->bNrChannels;
                    720:        DPRINTFN(2,("uaudio_add_mixer: ichs=%d ochs=%d\n", ichs, ochs));
                    721:
                    722:        bm = d1->bmControls;
                    723:        mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
                    724:        mix.class = -1;
                    725:        mix.type = MIX_SIGNED_16;
                    726:        mix.ctlunit = AudioNvolume;
                    727: #define BIT(bno) ((bm[bno / 8] >> (7 - bno % 8)) & 1)
                    728:        for (p = i = 0; i < d->bNrInPins; i++) {
                    729:                chs = uaudio_get_cluster(d->baSourceId[i], dps).bNrChannels;
                    730:                mc = 0;
                    731:                for (c = 0; c < chs; c++) {
                    732:                        mo = 0;
                    733:                        for (o = 0; o < ochs; o++) {
                    734:                                bno = (p + c) * ochs + o;
                    735:                                if (BIT(bno))
                    736:                                        mo++;
                    737:                        }
                    738:                        if (mo == 1)
                    739:                                mc++;
                    740:                }
                    741:                if (mc == chs && chs <= MIX_MAX_CHAN) {
                    742:                        k = 0;
                    743:                        for (c = 0; c < chs; c++)
                    744:                                for (o = 0; o < ochs; o++) {
                    745:                                        bno = (p + c) * ochs + o;
                    746:                                        if (BIT(bno))
                    747:                                                mix.wValue[k++] =
                    748:                                                        MAKE(p+c+1, o+1);
                    749:                                }
                    750:                        sprintf(mix.ctlname, "mix%d-%s", d->bUnitId,
                    751:                                uaudio_id_name(sc, dps, d->baSourceId[i]));
                    752:                        mix.nchan = chs;
                    753:                        uaudio_mixer_add_ctl(sc, &mix);
                    754:                } else {
                    755:                        /* XXX */
                    756:                }
                    757: #undef BIT
                    758:                p += chs;
                    759:        }
                    760:
                    761: }
                    762:
                    763: void
1.26      augustss  764: uaudio_add_selector(struct uaudio_softc *sc, usb_descriptor_t *v,
                    765:                    usb_descriptor_t **dps)
1.1       augustss  766: {
1.4       augustss  767: #ifdef UAUDIO_DEBUG
1.1       augustss  768:        struct usb_audio_selector_unit *d =
                    769:                (struct usb_audio_selector_unit *)v;
                    770:
                    771:        DPRINTFN(2,("uaudio_add_selector: bUnitId=%d bNrInPins=%d\n",
                    772:                    d->bUnitId, d->bNrInPins));
                    773: #endif
                    774:        printf("uaudio_add_selector: NOT IMPLEMENTED\n");
                    775: }
                    776:
                    777: void
1.26      augustss  778: uaudio_add_feature(struct uaudio_softc *sc, usb_descriptor_t *v,
                    779:                   usb_descriptor_t **dps)
1.1       augustss  780: {
                    781:        struct usb_audio_feature_unit *d = (struct usb_audio_feature_unit *)v;
                    782:        uByte *ctls = d->bmaControls;
                    783:        int ctlsize = d->bControlSize;
                    784:        int nchan = (d->bLength - 7) / ctlsize;
                    785:        int srcId = d->bSourceId;
                    786:        u_int fumask, mmask, cmask;
                    787:        struct mixerctl mix;
                    788:        int chan, ctl, i, unit;
                    789:
                    790: #define GET(i) (ctls[(i)*ctlsize] | \
                    791:                (ctlsize > 1 ? ctls[(i)*ctlsize+1] << 8 : 0))
                    792:
                    793:        mmask = GET(0);
                    794:        /* Figure out what we can control */
                    795:        for (cmask = 0, chan = 1; chan < nchan; chan++) {
                    796:                DPRINTFN(9,("uaudio_add_feature: chan=%d mask=%x\n",
                    797:                            chan, GET(chan)));
                    798:                cmask |= GET(chan);
                    799:        }
                    800:
                    801:        DPRINTFN(1,("uaudio_add_feature: bUnitId=%d bSourceId=%d, "
                    802:                    "%d channels, mmask=0x%04x, cmask=0x%04x\n",
                    803:                    d->bUnitId, srcId, nchan, mmask, cmask));
                    804:
                    805:        if (nchan > MIX_MAX_CHAN)
                    806:                nchan = MIX_MAX_CHAN;
                    807:        unit = d->bUnitId;
                    808:        mix.wIndex = MAKE(unit, sc->sc_ac_iface);
                    809:        for (ctl = MUTE_CONTROL; ctl < LOUDNESS_CONTROL; ctl++) {
                    810:                fumask = FU_MASK(ctl);
                    811:                DPRINTFN(4,("uaudio_add_feature: ctl=%d fumask=0x%04x\n",
                    812:                            ctl, fumask));
                    813:                if (mmask & fumask) {
                    814:                        mix.nchan = 1;
                    815:                        mix.wValue[0] = MAKE(ctl, 0);
                    816:                } else if (cmask & fumask) {
                    817:                        mix.nchan = nchan - 1;
                    818:                        for (i = 1; i < nchan; i++) {
                    819:                                if (GET(i) & fumask)
                    820:                                        mix.wValue[i-1] = MAKE(ctl, i);
                    821:                                else
                    822:                                        mix.wValue[i-1] = -1;
                    823:                        }
                    824:                } else {
                    825:                        continue;
                    826:                }
                    827: #undef GET
                    828:                mix.class = -1; /* XXX */
                    829:                switch (ctl) {
                    830:                case MUTE_CONTROL:
                    831:                        mix.type = MIX_ON_OFF;
                    832:                        sprintf(mix.ctlname, "fea%d-%s-%s", unit,
                    833:                                uaudio_id_name(sc, dps, srcId),
                    834:                                AudioNmute);
                    835:                        mix.ctlunit = "";
                    836:                        break;
                    837:                case VOLUME_CONTROL:
                    838:                        mix.type = MIX_SIGNED_16;
                    839:                        sprintf(mix.ctlname, "fea%d-%s-%s", unit,
                    840:                                uaudio_id_name(sc, dps, srcId),
                    841:                                AudioNmaster);
                    842:                        mix.ctlunit = AudioNvolume;
                    843:                        break;
                    844:                case BASS_CONTROL:
                    845:                        mix.type = MIX_SIGNED_8;
                    846:                        sprintf(mix.ctlname, "fea%d-%s-%s", unit,
                    847:                                uaudio_id_name(sc, dps, srcId),
                    848:                                AudioNbass);
                    849:                        mix.ctlunit = AudioNbass;
                    850:                        break;
                    851:                case MID_CONTROL:
                    852:                        mix.type = MIX_SIGNED_8;
                    853:                        sprintf(mix.ctlname, "fea%d-%s-%s", unit,
                    854:                                uaudio_id_name(sc, dps, srcId),
                    855:                                AudioNmid);
                    856:                        mix.ctlunit = AudioNmid;
                    857:                        break;
                    858:                case TREBLE_CONTROL:
                    859:                        mix.type = MIX_SIGNED_8;
                    860:                        sprintf(mix.ctlname, "fea%d-%s-%s", unit,
                    861:                                uaudio_id_name(sc, dps, srcId),
                    862:                                AudioNtreble);
                    863:                        mix.ctlunit = AudioNtreble;
                    864:                        break;
                    865:                case GRAPHIC_EQUALIZER_CONTROL:
1.7       augustss  866:                        continue; /* XXX don't add anything */
1.1       augustss  867:                        break;
                    868:                case AGC_CONTROL:
                    869:                        mix.type = MIX_ON_OFF;
                    870:                        sprintf(mix.ctlname, "fea%d-%s-%s", unit,
                    871:                                uaudio_id_name(sc, dps, srcId),
                    872:                                AudioNagc);
                    873:                        mix.ctlunit = "";
                    874:                        break;
                    875:                case DELAY_CONTROL:
                    876:                        mix.type = MIX_UNSIGNED_16;
                    877:                        sprintf(mix.ctlname, "fea%d-%s-%s", unit,
                    878:                                uaudio_id_name(sc, dps, srcId),
                    879:                                AudioNdelay);
                    880:                        mix.ctlunit = "4 ms";
                    881:                        break;
                    882:                case BASS_BOOST_CONTROL:
                    883:                        mix.type = MIX_ON_OFF;
                    884:                        sprintf(mix.ctlname, "fea%d-%s-%s", unit,
                    885:                                uaudio_id_name(sc, dps, srcId),
                    886:                                AudioNbassboost);
                    887:                        mix.ctlunit = "";
                    888:                        break;
                    889:                case LOUDNESS_CONTROL:
                    890:                        mix.type = MIX_ON_OFF;
                    891:                        sprintf(mix.ctlname, "fea%d-%s-%s", unit,
                    892:                                uaudio_id_name(sc, dps, srcId),
                    893:                                AudioNloudness);
                    894:                        mix.ctlunit = "";
                    895:                        break;
                    896:                }
                    897:                uaudio_mixer_add_ctl(sc, &mix);
                    898:        }
                    899: }
                    900:
                    901: void
1.26      augustss  902: uaudio_add_processing_updown(struct uaudio_softc *sc, usb_descriptor_t *v,
                    903:                             usb_descriptor_t **dps)
1.16      augustss  904: {
                    905:        struct usb_audio_processing_unit *d =
                    906:            (struct usb_audio_processing_unit *)v;
                    907:        struct usb_audio_processing_unit_1 *d1 =
                    908:            (struct usb_audio_processing_unit_1 *)&d->baSourceId[d->bNrInPins];
                    909:        struct usb_audio_processing_unit_updown *ud =
                    910:            (struct usb_audio_processing_unit_updown *)
                    911:                &d1->bmControls[d1->bControlSize];
                    912:        struct mixerctl mix;
                    913:        int i;
                    914:
                    915:        DPRINTFN(2,("uaudio_add_processing_updown: bUnitId=%d bNrModes=%d\n",
                    916:                    d->bUnitId, ud->bNrModes));
                    917:
                    918:        if (!(d1->bmControls[0] & UA_PROC_MASK(UD_MODE_SELECT_CONTROL))) {
                    919:                DPRINTF(("uaudio_add_processing_updown: no mode select\n"));
                    920:                return;
                    921:        }
                    922:
                    923:        mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
                    924:        mix.nchan = 1;
                    925:        mix.wValue[0] = MAKE(UD_MODE_SELECT_CONTROL, 0);
                    926:        mix.class = -1;
                    927:        mix.type = MIX_ON_OFF;  /* XXX */
                    928:        mix.ctlunit = "";
                    929:        sprintf(mix.ctlname, "pro%d-mode", d->bUnitId);
                    930:
                    931:        for (i = 0; i < ud->bNrModes; i++) {
                    932:                DPRINTFN(2,("uaudio_add_processing_updown: i=%d bm=0x%x\n",
                    933:                            i, UGETW(ud->waModes[i])));
                    934:                /* XXX */
                    935:        }
                    936:        uaudio_mixer_add_ctl(sc, &mix);
                    937: }
                    938:
                    939: void
1.26      augustss  940: uaudio_add_processing(struct uaudio_softc *sc, usb_descriptor_t *v,
                    941:                      usb_descriptor_t **dps)
1.1       augustss  942: {
                    943:        struct usb_audio_processing_unit *d =
1.15      augustss  944:            (struct usb_audio_processing_unit *)v;
                    945:        struct usb_audio_processing_unit_1 *d1 =
                    946:            (struct usb_audio_processing_unit_1 *)&d->baSourceId[d->bNrInPins];
                    947:        int ptype = UGETW(d->wProcessType);
                    948:        struct mixerctl mix;
                    949:
                    950:        DPRINTFN(2,("uaudio_add_processing: wProcessType=%d bUnitId=%d "
                    951:                    "bNrInPins=%d\n", ptype, d->bUnitId, d->bNrInPins));
                    952:
                    953:        if (d1->bmControls[0] & UA_PROC_ENABLE_MASK) {
                    954:                mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
                    955:                mix.nchan = 1;
                    956:                mix.wValue[0] = MAKE(XX_ENABLE_CONTROL, 0);
                    957:                mix.class = -1;
                    958:                mix.type = MIX_ON_OFF;
                    959:                mix.ctlunit = "";
                    960:                sprintf(mix.ctlname, "pro%d.%d-enable", d->bUnitId, ptype);
                    961:                uaudio_mixer_add_ctl(sc, &mix);
                    962:        }
1.1       augustss  963:
1.15      augustss  964:        switch(ptype) {
                    965:        case UPDOWNMIX_PROCESS:
1.16      augustss  966:                uaudio_add_processing_updown(sc, v, dps);
                    967:                break;
1.15      augustss  968:        case DOLBY_PROLOGIC_PROCESS:
                    969:        case P3D_STEREO_EXTENDER_PROCESS:
                    970:        case REVERBATION_PROCESS:
                    971:        case CHORUS_PROCESS:
                    972:        case DYN_RANGE_COMP_PROCESS:
                    973:        default:
                    974: #ifdef UAUDIO_DEBUG
                    975:                printf("uaudio_add_processing: unit %d, type=%d not impl.\n",
                    976:                       d->bUnitId, ptype);
1.1       augustss  977: #endif
1.15      augustss  978:                break;
                    979:        }
1.1       augustss  980: }
                    981:
                    982: void
1.26      augustss  983: uaudio_add_extension(struct uaudio_softc *sc, usb_descriptor_t *v,
                    984:                     usb_descriptor_t **dps)
1.1       augustss  985: {
                    986:        struct usb_audio_extension_unit *d =
                    987:            (struct usb_audio_extension_unit *)v;
                    988:        struct usb_audio_extension_unit_1 *d1 =
                    989:            (struct usb_audio_extension_unit_1 *)&d->baSourceId[d->bNrInPins];
                    990:        struct mixerctl mix;
                    991:
                    992:        DPRINTFN(2,("uaudio_add_extension: bUnitId=%d bNrInPins=%d\n",
                    993:                    d->bUnitId, d->bNrInPins));
1.28      augustss  994:
1.31      augustss  995:        if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_XU)
1.28      augustss  996:                return;
1.1       augustss  997:
1.15      augustss  998:        if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) {
1.1       augustss  999:                mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
                   1000:                mix.nchan = 1;
                   1001:                mix.wValue[0] = MAKE(UA_EXT_ENABLE, 0);
                   1002:                mix.class = -1;
                   1003:                mix.type = MIX_ON_OFF;
                   1004:                mix.ctlunit = "";
                   1005:                sprintf(mix.ctlname, "ext%d-enable", d->bUnitId);
                   1006:                uaudio_mixer_add_ctl(sc, &mix);
                   1007:        }
                   1008: }
                   1009:
                   1010: usbd_status
1.26      augustss 1011: uaudio_identify(struct uaudio_softc *sc, usb_config_descriptor_t *cdesc)
1.1       augustss 1012: {
1.9       augustss 1013:        usbd_status err;
1.1       augustss 1014:
1.9       augustss 1015:        err = uaudio_identify_ac(sc, cdesc);
                   1016:        if (err)
                   1017:                return (err);
1.1       augustss 1018:        return (uaudio_identify_as(sc, cdesc));
                   1019: }
                   1020:
                   1021: void
1.26      augustss 1022: uaudio_add_alt(struct uaudio_softc *sc, struct as_info *ai)
1.1       augustss 1023: {
1.41.2.1! nathanw  1024:        size_t len = sizeof(*ai) * (sc->sc_nalts + 1);
        !          1025:        struct as_info *nai = sc->sc_nalts == 0 ?
        !          1026:            malloc(len, M_USBDEV, M_NOWAIT) :
        !          1027:            realloc(sc->sc_alts, len, M_USBDEV, M_NOWAIT);
        !          1028:
        !          1029:        if (nai == NULL) {
1.1       augustss 1030:                printf("uaudio_add_alt: no memory\n");
                   1031:                return;
                   1032:        }
1.41.2.1! nathanw  1033:
        !          1034:        sc->sc_alts = nai;
1.1       augustss 1035:        DPRINTFN(2,("uaudio_add_alt: adding alt=%d, enc=%d\n",
                   1036:                    ai->alt, ai->encoding));
                   1037:        sc->sc_alts[sc->sc_nalts++] = *ai;
                   1038: }
                   1039:
                   1040: usbd_status
1.26      augustss 1041: uaudio_process_as(struct uaudio_softc *sc, char *buf, int *offsp,
                   1042:                  int size, usb_interface_descriptor_t *id)
1.1       augustss 1043: #define offs (*offsp)
                   1044: {
                   1045:        struct usb_audio_streaming_interface_descriptor *asid;
                   1046:        struct usb_audio_streaming_type1_descriptor *asf1d;
                   1047:        usb_endpoint_descriptor_audio_t *ed;
                   1048:        struct usb_audio_streaming_endpoint_descriptor *sed;
                   1049:        int format, chan, prec, enc;
1.5       augustss 1050:        int dir, type;
1.1       augustss 1051:        struct as_info ai;
                   1052:
                   1053:        asid = (void *)(buf + offs);
                   1054:        if (asid->bDescriptorType != UDESC_CS_INTERFACE ||
                   1055:            asid->bDescriptorSubtype != AS_GENERAL)
                   1056:                return (USBD_INVAL);
                   1057:        offs += asid->bLength;
                   1058:        if (offs > size)
                   1059:                return (USBD_INVAL);
                   1060:        asf1d = (void *)(buf + offs);
                   1061:        if (asf1d->bDescriptorType != UDESC_CS_INTERFACE ||
                   1062:            asf1d->bDescriptorSubtype != FORMAT_TYPE)
                   1063:                return (USBD_INVAL);
                   1064:        offs += asf1d->bLength;
                   1065:        if (offs > size)
                   1066:                return (USBD_INVAL);
                   1067:
1.3       augustss 1068:        if (asf1d->bFormatType != FORMAT_TYPE_I) {
                   1069:                printf("%s: ignored setting with type %d format\n",
                   1070:                       USBDEVNAME(sc->sc_dev), UGETW(asid->wFormatTag));
                   1071:                return (USBD_NORMAL_COMPLETION);
                   1072:        }
                   1073:
1.1       augustss 1074:        ed = (void *)(buf + offs);
                   1075:        if (ed->bDescriptorType != UDESC_ENDPOINT)
                   1076:                return (USBD_INVAL);
1.5       augustss 1077:        DPRINTF(("uaudio_process_as: endpoint bLength=%d bDescriptorType=%d "
                   1078:                 "bEndpointAddress=%d bmAttributes=0x%x wMaxPacketSize=%d "
                   1079:                 "bInterval=%d bRefresh=%d bSynchAddress=%d\n",
                   1080:                 ed->bLength, ed->bDescriptorType, ed->bEndpointAddress,
                   1081:                 ed->bmAttributes, UGETW(ed->wMaxPacketSize),
                   1082:                 ed->bInterval, ed->bRefresh, ed->bSynchAddress));
1.1       augustss 1083:        offs += ed->bLength;
                   1084:        if (offs > size)
                   1085:                return (USBD_INVAL);
1.5       augustss 1086:        if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
1.1       augustss 1087:                return (USBD_INVAL);
1.5       augustss 1088:
                   1089:        dir = UE_GET_DIR(ed->bEndpointAddress);
                   1090:        type = UE_GET_ISO_TYPE(ed->bmAttributes);
1.31      augustss 1091:        if ((usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_INP_ASYNC) &&
                   1092:            dir == UE_DIR_IN && type == UE_ISO_ADAPT)
                   1093:                type = UE_ISO_ASYNC;
                   1094:
1.40      augustss 1095:        /* We can't handle endpoints that need a sync pipe yet. */
1.5       augustss 1096:        if (dir == UE_DIR_IN ? type == UE_ISO_ADAPT : type == UE_ISO_ASYNC) {
1.30      augustss 1097:                printf("%s: ignored %sput endpoint of type %s\n",
1.1       augustss 1098:                       USBDEVNAME(sc->sc_dev),
1.5       augustss 1099:                       dir == UE_DIR_IN ? "in" : "out",
1.32      augustss 1100:                       dir == UE_DIR_IN ? "adaptive" : "async");
1.1       augustss 1101:                return (USBD_NORMAL_COMPLETION);
                   1102:        }
                   1103:
                   1104:        sed = (void *)(buf + offs);
                   1105:        if (sed->bDescriptorType != UDESC_CS_ENDPOINT ||
                   1106:            sed->bDescriptorSubtype != AS_GENERAL)
                   1107:                return (USBD_INVAL);
                   1108:        offs += sed->bLength;
                   1109:        if (offs > size)
                   1110:                return (USBD_INVAL);
                   1111:
1.3       augustss 1112:        format = UGETW(asid->wFormatTag);
1.1       augustss 1113:        chan = asf1d->bNrChannels;
                   1114:        prec = asf1d->bBitResolution;
                   1115:        if (prec != 8 && prec != 16) {
1.35      mycroft  1116: #ifdef UAUDIO_DEBUG
1.1       augustss 1117:                printf("%s: ignored setting with precision %d\n",
                   1118:                       USBDEVNAME(sc->sc_dev), prec);
                   1119: #endif
                   1120:                return (USBD_NORMAL_COMPLETION);
                   1121:        }
                   1122:        switch (format) {
1.3       augustss 1123:        case UA_FMT_PCM:
1.1       augustss 1124:                sc->sc_altflags |= prec == 8 ? HAS_8 : HAS_16;
1.5       augustss 1125:                enc = AUDIO_ENCODING_SLINEAR_LE;
1.1       augustss 1126:                break;
1.3       augustss 1127:        case UA_FMT_PCM8:
1.5       augustss 1128:                enc = AUDIO_ENCODING_ULINEAR_LE;
1.1       augustss 1129:                sc->sc_altflags |= HAS_8U;
                   1130:                break;
1.3       augustss 1131:        case UA_FMT_ALAW:
1.5       augustss 1132:                enc = AUDIO_ENCODING_ALAW;
1.1       augustss 1133:                sc->sc_altflags |= HAS_ALAW;
                   1134:                break;
1.3       augustss 1135:        case UA_FMT_MULAW:
1.5       augustss 1136:                enc = AUDIO_ENCODING_ULAW;
1.1       augustss 1137:                sc->sc_altflags |= HAS_MULAW;
                   1138:                break;
                   1139:        default:
                   1140:                printf("%s: ignored setting with format %d\n",
                   1141:                       USBDEVNAME(sc->sc_dev), format);
                   1142:                return (USBD_NORMAL_COMPLETION);
                   1143:        }
                   1144:        DPRINTFN(1,("uaudio_identify: alt=%d enc=%d chan=%d prec=%d\n",
                   1145:                    id->bAlternateSetting, enc, chan, prec));
                   1146:        ai.alt = id->bAlternateSetting;
                   1147:        ai.encoding = enc;
                   1148:        ai.idesc = id;
                   1149:        ai.edesc = ed;
                   1150:        ai.asf1desc = asf1d;
                   1151:        uaudio_add_alt(sc, &ai);
1.5       augustss 1152:        sc->sc_chan.terminal = asid->bTerminalLink; /* XXX */
1.38      mycroft  1153:        sc->sc_chan.dir |= dir == UE_DIR_OUT ? AUMODE_PLAY : AUMODE_RECORD;
1.1       augustss 1154:        return (USBD_NORMAL_COMPLETION);
                   1155: }
                   1156: #undef offs
                   1157:
                   1158: usbd_status
1.26      augustss 1159: uaudio_identify_as(struct uaudio_softc *sc, usb_config_descriptor_t *cdesc)
1.1       augustss 1160: {
                   1161:        usb_interface_descriptor_t *id;
1.9       augustss 1162:        usbd_status err;
1.1       augustss 1163:        char *buf;
                   1164:        int size, offs;
                   1165:
                   1166:        size = UGETW(cdesc->wTotalLength);
                   1167:        buf = (char *)cdesc;
                   1168:
                   1169:        /* Locate the AudioStreaming interface descriptor. */
                   1170:        offs = 0;
1.19      augustss 1171:        id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOSTREAM);
1.9       augustss 1172:        if (id == NULL)
1.1       augustss 1173:                return (USBD_INVAL);
                   1174:
1.5       augustss 1175:        sc->sc_chan.terminal = -1;
1.35      mycroft  1176:        sc->sc_chan.dir = 0;
1.1       augustss 1177:
                   1178:        /* Loop through all the alternate settings. */
                   1179:        while (offs <= size) {
1.37      mycroft  1180:                DPRINTFN(2, ("uaudio_identify: interface %d\n",
                   1181:                    id->bInterfaceNumber));
1.1       augustss 1182:                switch (id->bNumEndpoints) {
                   1183:                case 0:
                   1184:                        DPRINTFN(2, ("uaudio_identify: AS null alt=%d\n",
                   1185:                                     id->bAlternateSetting));
                   1186:                        sc->sc_nullalt = id->bAlternateSetting;
                   1187:                        break;
                   1188:                case 1:
1.9       augustss 1189:                        err = uaudio_process_as(sc, buf, &offs, size, id);
1.1       augustss 1190:                        break;
                   1191:                default:
1.35      mycroft  1192: #ifdef UAUDIO_DEBUG
1.1       augustss 1193:                        printf("%s: ignored audio interface with %d "
                   1194:                               "endpoints\n",
                   1195:                               USBDEVNAME(sc->sc_dev), id->bNumEndpoints);
                   1196: #endif
                   1197:                        break;
                   1198:                }
1.19      augustss 1199:                id = uaudio_find_iface(buf, size, &offs,UISUBCLASS_AUDIOSTREAM);
1.9       augustss 1200:                if (id == NULL)
1.1       augustss 1201:                        break;
                   1202:        }
                   1203:        if (offs > size)
                   1204:                return (USBD_INVAL);
                   1205:        DPRINTF(("uaudio_identify_as: %d alts available\n", sc->sc_nalts));
1.5       augustss 1206:        if (sc->sc_chan.terminal < 0) {
                   1207:                printf("%s: no useable endpoint found\n",
                   1208:                       USBDEVNAME(sc->sc_dev));
                   1209:                return (USBD_INVAL);
                   1210:        }
1.36      mycroft  1211: #if 0
1.38      mycroft  1212:        if (sc->sc_chan.dir == (AUMODE_PLAY | AUMODE_RECORD))
1.35      mycroft  1213:                sc->sc_props |= AUDIO_PROP_FULLDUPLEX;
1.36      mycroft  1214: #endif
1.1       augustss 1215:        return (USBD_NORMAL_COMPLETION);
                   1216: }
                   1217:
                   1218: usbd_status
1.26      augustss 1219: uaudio_identify_ac(struct uaudio_softc *sc, usb_config_descriptor_t *cdesc)
1.1       augustss 1220: {
                   1221:        usb_interface_descriptor_t *id;
                   1222:        struct usb_audio_control_descriptor *acdp;
                   1223:        usb_descriptor_t *dp, *dps[256];
                   1224:        char *buf, *ibuf, *ibufend;
                   1225:        int size, offs, aclen, ndps, i;
                   1226:
                   1227:        size = UGETW(cdesc->wTotalLength);
                   1228:        buf = (char *)cdesc;
                   1229:
                   1230:        /* Locate the AudioControl interface descriptor. */
                   1231:        offs = 0;
1.19      augustss 1232:        id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOCONTROL);
1.14      augustss 1233:        if (id == NULL)
1.1       augustss 1234:                return (USBD_INVAL);
                   1235:        if (offs + sizeof *acdp > size)
                   1236:                return (USBD_INVAL);
                   1237:        sc->sc_ac_iface = id->bInterfaceNumber;
                   1238:        DPRINTFN(2,("uaudio_identify: AC interface is %d\n", sc->sc_ac_iface));
                   1239:
                   1240:        /* A class-specific AC interface header should follow. */
                   1241:        ibuf = buf + offs;
                   1242:        acdp = (struct usb_audio_control_descriptor *)ibuf;
                   1243:        if (acdp->bDescriptorType != UDESC_CS_INTERFACE ||
                   1244:            acdp->bDescriptorSubtype != UDESCSUB_AC_HEADER)
                   1245:                return (USBD_INVAL);
                   1246:        aclen = UGETW(acdp->wTotalLength);
                   1247:        if (offs + aclen > size)
                   1248:                return (USBD_INVAL);
1.5       augustss 1249:
1.1       augustss 1250:        if (!(usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_BAD_ADC) &&
                   1251:             UGETW(acdp->bcdADC) != UAUDIO_VERSION)
                   1252:                return (USBD_INVAL);
                   1253:
1.7       augustss 1254:        sc->sc_audio_rev = UGETW(acdp->bcdADC);
1.1       augustss 1255:        DPRINTFN(2,("uaudio_identify: found AC header, vers=%03x, len=%d\n",
1.7       augustss 1256:                 sc->sc_audio_rev, aclen));
1.1       augustss 1257:
                   1258:        sc->sc_nullalt = -1;
                   1259:
                   1260:        /* Scan through all the AC specific descriptors */
                   1261:        ibufend = ibuf + aclen;
                   1262:        dp = (usb_descriptor_t *)ibuf;
                   1263:        ndps = 0;
                   1264:        memset(dps, 0, sizeof dps);
                   1265:        for (;;) {
                   1266:                ibuf += dp->bLength;
                   1267:                if (ibuf >= ibufend)
                   1268:                        break;
                   1269:                dp = (usb_descriptor_t *)ibuf;
                   1270:                if (ibuf + dp->bLength > ibufend)
                   1271:                        return (USBD_INVAL);
                   1272:                if (dp->bDescriptorType != UDESC_CS_INTERFACE) {
                   1273:                        printf("uaudio_identify: skip desc type=0x%02x\n",
                   1274:                               dp->bDescriptorType);
                   1275:                        continue;
                   1276:                }
                   1277:                i = ((struct usb_audio_input_terminal *)dp)->bTerminalId;
                   1278:                dps[i] = dp;
                   1279:                if (i > ndps)
                   1280:                        ndps = i;
                   1281:        }
                   1282:        ndps++;
                   1283:
                   1284:        for (i = 0; i < ndps; i++) {
                   1285:                dp = dps[i];
1.14      augustss 1286:                if (dp == NULL)
1.1       augustss 1287:                        continue;
                   1288:                DPRINTF(("uaudio_identify: subtype=%d\n",
                   1289:                         dp->bDescriptorSubtype));
                   1290:                switch (dp->bDescriptorSubtype) {
                   1291:                case UDESCSUB_AC_HEADER:
                   1292:                        printf("uaudio_identify: unexpected AC header\n");
                   1293:                        break;
                   1294:                case UDESCSUB_AC_INPUT:
                   1295:                        uaudio_add_input(sc, dp, dps);
                   1296:                        break;
                   1297:                case UDESCSUB_AC_OUTPUT:
                   1298:                        uaudio_add_output(sc, dp, dps);
                   1299:                        break;
                   1300:                case UDESCSUB_AC_MIXER:
                   1301:                        uaudio_add_mixer(sc, dp, dps);
                   1302:                        break;
                   1303:                case UDESCSUB_AC_SELECTOR:
                   1304:                        uaudio_add_selector(sc, dp, dps);
                   1305:                        break;
                   1306:                case UDESCSUB_AC_FEATURE:
                   1307:                        uaudio_add_feature(sc, dp, dps);
                   1308:                        break;
                   1309:                case UDESCSUB_AC_PROCESSING:
                   1310:                        uaudio_add_processing(sc, dp, dps);
                   1311:                        break;
                   1312:                case UDESCSUB_AC_EXTENSION:
                   1313:                        uaudio_add_extension(sc, dp, dps);
                   1314:                        break;
                   1315:                default:
                   1316:                        printf("uaudio_identify: bad AC desc subtype=0x%02x\n",
                   1317:                               dp->bDescriptorSubtype);
                   1318:                        break;
                   1319:                }
                   1320:        }
                   1321:        return (USBD_NORMAL_COMPLETION);
                   1322: }
                   1323:
                   1324: int
1.26      augustss 1325: uaudio_query_devinfo(void *addr, mixer_devinfo_t *mi)
1.1       augustss 1326: {
                   1327:        struct uaudio_softc *sc = addr;
                   1328:        struct mixerctl *mc;
                   1329:        int n, nctls;
                   1330:
                   1331:        DPRINTFN(2,("uaudio_query_devinfo: index=%d\n", mi->index));
                   1332:        if (sc->sc_dying)
                   1333:                return (EIO);
                   1334:
                   1335:        n = mi->index;
                   1336:        nctls = sc->sc_nctls;
                   1337:
                   1338:        if (n < 0 || n >= nctls) {
                   1339:                switch (n - nctls) {
                   1340:                case UAC_OUTPUT:
                   1341:                        mi->type = AUDIO_MIXER_CLASS;
                   1342:                        mi->mixer_class = nctls + UAC_OUTPUT;
                   1343:                        mi->next = mi->prev = AUDIO_MIXER_LAST;
                   1344:                        strcpy(mi->label.name, AudioCoutputs);
                   1345:                        return (0);
                   1346:                case UAC_INPUT:
                   1347:                        mi->type = AUDIO_MIXER_CLASS;
                   1348:                        mi->mixer_class = nctls + UAC_INPUT;
                   1349:                        mi->next = mi->prev = AUDIO_MIXER_LAST;
                   1350:                        strcpy(mi->label.name, AudioCinputs);
                   1351:                        return (0);
                   1352:                case UAC_EQUAL:
                   1353:                        mi->type = AUDIO_MIXER_CLASS;
                   1354:                        mi->mixer_class = nctls + UAC_EQUAL;
                   1355:                        mi->next = mi->prev = AUDIO_MIXER_LAST;
                   1356:                        strcpy(mi->label.name, AudioCequalization);
                   1357:                        return (0);
                   1358:                default:
                   1359:                        return (ENXIO);
                   1360:                }
                   1361:        }
                   1362:        mc = &sc->sc_ctls[n];
                   1363:        strncpy(mi->label.name, mc->ctlname, MAX_AUDIO_DEV_LEN);
                   1364:        mi->mixer_class = mc->class;
                   1365:        mi->next = mi->prev = AUDIO_MIXER_LAST; /* XXX */
                   1366:        switch (mc->type) {
                   1367:        case MIX_ON_OFF:
                   1368:                mi->type = AUDIO_MIXER_ENUM;
                   1369:                mi->un.e.num_mem = 2;
                   1370:                strcpy(mi->un.e.member[0].label.name, AudioNoff);
                   1371:                mi->un.e.member[0].ord = 0;
                   1372:                strcpy(mi->un.e.member[1].label.name, AudioNon);
                   1373:                mi->un.e.member[1].ord = 1;
                   1374:                break;
                   1375:        default:
                   1376:                mi->type = AUDIO_MIXER_VALUE;
                   1377:                strncpy(mi->un.v.units.name, mc->ctlunit, MAX_AUDIO_DEV_LEN);
                   1378:                mi->un.v.num_channels = mc->nchan;
1.33      augustss 1379:                mi->un.v.delta = mc->delta;
1.1       augustss 1380:                break;
                   1381:        }
                   1382:        return (0);
                   1383: }
                   1384:
                   1385: int
1.26      augustss 1386: uaudio_open(void *addr, int flags)
1.1       augustss 1387: {
                   1388:        struct uaudio_softc *sc = addr;
                   1389:
                   1390:         DPRINTF(("uaudio_open: sc=%p\n", sc));
                   1391:        if (sc->sc_dying)
                   1392:                return (EIO);
                   1393:
1.5       augustss 1394:        if (sc->sc_chan.terminal < 0)
                   1395:                return (ENXIO);
                   1396:
1.38      mycroft  1397:        if ((flags & FREAD) && !(sc->sc_chan.dir & AUMODE_RECORD))
1.1       augustss 1398:                return (EACCES);
1.38      mycroft  1399:        if ((flags & FWRITE) && !(sc->sc_chan.dir & AUMODE_PLAY))
1.1       augustss 1400:                return (EACCES);
                   1401:
1.5       augustss 1402:         sc->sc_chan.intr = 0;
1.1       augustss 1403:
                   1404:         return (0);
                   1405: }
                   1406:
                   1407: /*
                   1408:  * Close function is called at splaudio().
                   1409:  */
                   1410: void
1.26      augustss 1411: uaudio_close(void *addr)
1.1       augustss 1412: {
                   1413:        struct uaudio_softc *sc = addr;
                   1414:
                   1415:        DPRINTF(("uaudio_close: sc=%p\n", sc));
                   1416:        uaudio_halt_in_dma(sc);
                   1417:        uaudio_halt_out_dma(sc);
                   1418:
1.5       augustss 1419:        sc->sc_chan.intr = 0;
1.1       augustss 1420: }
                   1421:
                   1422: int
1.26      augustss 1423: uaudio_drain(void *addr)
1.1       augustss 1424: {
                   1425:        struct uaudio_softc *sc = addr;
                   1426:
                   1427:        usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
                   1428:
                   1429:        return (0);
                   1430: }
                   1431:
                   1432: int
1.26      augustss 1433: uaudio_halt_out_dma(void *addr)
1.1       augustss 1434: {
                   1435:        struct uaudio_softc *sc = addr;
                   1436:
                   1437:        DPRINTF(("uaudio_halt_out_dma: enter\n"));
1.14      augustss 1438:        if (sc->sc_chan.pipe != NULL) {
1.5       augustss 1439:                uaudio_chan_close(sc, &sc->sc_chan);
                   1440:                sc->sc_chan.pipe = 0;
                   1441:                uaudio_chan_free_buffers(sc, &sc->sc_chan);
1.1       augustss 1442:        }
                   1443:         return (0);
                   1444: }
                   1445:
                   1446: int
1.26      augustss 1447: uaudio_halt_in_dma(void *addr)
1.1       augustss 1448: {
                   1449:        struct uaudio_softc *sc = addr;
                   1450:
                   1451:        DPRINTF(("uaudio_halt_in_dma: enter\n"));
1.14      augustss 1452:        if (sc->sc_chan.pipe != NULL) {
1.5       augustss 1453:                uaudio_chan_close(sc, &sc->sc_chan);
                   1454:                sc->sc_chan.pipe = 0;
                   1455:                uaudio_chan_free_buffers(sc, &sc->sc_chan);
                   1456:        }
1.1       augustss 1457:         return (0);
                   1458: }
                   1459:
                   1460: int
1.26      augustss 1461: uaudio_getdev(void *addr, struct audio_device *retp)
1.1       augustss 1462: {
                   1463:        struct uaudio_softc *sc = addr;
                   1464:
                   1465:        DPRINTF(("uaudio_mixer_getdev:\n"));
                   1466:        if (sc->sc_dying)
                   1467:                return (EIO);
                   1468:
                   1469:        *retp = uaudio_device;
                   1470:         return (0);
                   1471: }
                   1472:
                   1473: /*
                   1474:  * Make sure the block size is large enough to hold all outstanding transfers.
                   1475:  */
                   1476: int
1.26      augustss 1477: uaudio_round_blocksize(void *addr, int blk)
1.1       augustss 1478: {
                   1479:        struct uaudio_softc *sc = addr;
                   1480:        int bpf;
                   1481:
1.5       augustss 1482:        bpf = sc->sc_chan.bytes_per_frame + sc->sc_chan.sample_size;
1.1       augustss 1483:        /* XXX */
                   1484:        bpf *= UAUDIO_NFRAMES * UAUDIO_NCHANBUFS;
                   1485:
                   1486:        bpf = (bpf + 15) &~ 15;
                   1487:
                   1488:        if (blk < bpf)
                   1489:                blk = bpf;
                   1490:
1.5       augustss 1491: #ifdef DIAGNOSTIC
                   1492:        if (blk <= 0) {
                   1493:                printf("uaudio_round_blocksize: blk=%d\n", blk);
                   1494:                blk = 512;
                   1495:        }
                   1496: #endif
                   1497:
1.1       augustss 1498:        DPRINTFN(1,("uaudio_round_blocksize: blk=%d\n", blk));
                   1499:        return (blk);
                   1500: }
                   1501:
                   1502: int
1.26      augustss 1503: uaudio_get_props(void *addr)
1.1       augustss 1504: {
                   1505:        struct uaudio_softc *sc = addr;
                   1506:
                   1507:        return (sc->sc_props);
                   1508: }
                   1509:
                   1510: int
1.27      augustss 1511: uaudio_get(struct uaudio_softc *sc, int which, int type, int wValue,
1.26      augustss 1512:           int wIndex, int len)
1.1       augustss 1513: {
                   1514:        usb_device_request_t req;
                   1515:        u_int8_t data[4];
1.9       augustss 1516:        usbd_status err;
1.1       augustss 1517:        int val;
                   1518:
                   1519:        if (wValue == -1)
                   1520:                return (0);
                   1521:
                   1522:        req.bmRequestType = type;
                   1523:        req.bRequest = which;
                   1524:        USETW(req.wValue, wValue);
                   1525:        USETW(req.wIndex, wIndex);
                   1526:        USETW(req.wLength, len);
                   1527:        DPRINTFN(2,("uaudio_get: type=0x%02x req=0x%02x wValue=0x%04x "
                   1528:                    "wIndex=0x%04x len=%d\n",
                   1529:                    type, which, wValue, wIndex, len));
1.9       augustss 1530:        err = usbd_do_request(sc->sc_udev, &req, &data);
                   1531:        if (err) {
1.20      augustss 1532:                DPRINTF(("uaudio_get: err=%s\n", usbd_errstr(err)));
1.1       augustss 1533:                return (-1);
                   1534:        }
                   1535:        switch (len) {
                   1536:        case 1:
                   1537:                val = data[0];
                   1538:                break;
                   1539:        case 2:
                   1540:                val = data[0] | (data[1] << 8);
                   1541:                break;
                   1542:        default:
                   1543:                DPRINTF(("uaudio_get: bad length=%d\n", len));
                   1544:                return (-1);
                   1545:        }
                   1546:        DPRINTFN(2,("uaudio_get: val=%d\n", val));
                   1547:        return (val);
                   1548: }
                   1549:
                   1550: void
1.27      augustss 1551: uaudio_set(struct uaudio_softc *sc, int which, int type, int wValue,
1.26      augustss 1552:           int wIndex, int len, int val)
1.1       augustss 1553: {
                   1554:        usb_device_request_t req;
                   1555:        u_int8_t data[4];
1.9       augustss 1556:        usbd_status err;
1.1       augustss 1557:
                   1558:        if (wValue == -1)
                   1559:                return;
                   1560:
                   1561:        req.bmRequestType = type;
                   1562:        req.bRequest = which;
                   1563:        USETW(req.wValue, wValue);
                   1564:        USETW(req.wIndex, wIndex);
                   1565:        USETW(req.wLength, len);
                   1566:        switch (len) {
                   1567:        case 1:
                   1568:                data[0] = val;
                   1569:                break;
                   1570:        case 2:
                   1571:                data[0] = val;
                   1572:                data[1] = val >> 8;
                   1573:                break;
                   1574:        default:
                   1575:                return;
                   1576:        }
                   1577:        DPRINTFN(2,("uaudio_set: type=0x%02x req=0x%02x wValue=0x%04x "
                   1578:                    "wIndex=0x%04x len=%d, val=%d\n",
                   1579:                    type, which, wValue, wIndex, len, val & 0xffff));
1.9       augustss 1580:        err = usbd_do_request(sc->sc_udev, &req, &data);
1.4       augustss 1581: #ifdef UAUDIO_DEBUG
1.12      augustss 1582:        if (err)
1.9       augustss 1583:                DPRINTF(("uaudio_set: err=%d\n", err));
1.1       augustss 1584: #endif
                   1585: }
                   1586:
                   1587: int
1.26      augustss 1588: uaudio_signext(int type, int val)
1.1       augustss 1589: {
                   1590:        if (!MIX_UNSIGNED(type)) {
                   1591:                if (MIX_SIZE(type) == 2)
                   1592:                        val = (int16_t)val;
                   1593:                else
                   1594:                        val = (int8_t)val;
                   1595:        }
                   1596:        return (val);
                   1597: }
                   1598:
                   1599: int
1.26      augustss 1600: uaudio_value2bsd(struct mixerctl *mc, int val)
1.1       augustss 1601: {
                   1602:        DPRINTFN(5, ("uaudio_value2bsd: type=%03x val=%d min=%d max=%d ",
                   1603:                     mc->type, val, mc->minval, mc->maxval));
                   1604:        if (mc->type == MIX_ON_OFF)
                   1605:                val = val != 0;
                   1606:        else
1.34      augustss 1607:                val = ((uaudio_signext(mc->type, val) - mc->minval) * 256
                   1608:                        + mc->mul/2) / mc->mul;
1.1       augustss 1609:        DPRINTFN(5, ("val'=%d\n", val));
                   1610:        return (val);
                   1611: }
                   1612:
                   1613: int
1.26      augustss 1614: uaudio_bsd2value(struct mixerctl *mc, int val)
1.1       augustss 1615: {
                   1616:        DPRINTFN(5,("uaudio_bsd2value: type=%03x val=%d min=%d max=%d ",
                   1617:                    mc->type, val, mc->minval, mc->maxval));
                   1618:        if (mc->type == MIX_ON_OFF)
                   1619:                val = val != 0;
                   1620:        else
1.34      augustss 1621:                val = (val + mc->delta/2) * mc->mul / 256 + mc->minval;
1.1       augustss 1622:        DPRINTFN(5, ("val'=%d\n", val));
                   1623:        return (val);
                   1624: }
                   1625:
                   1626: int
1.26      augustss 1627: uaudio_ctl_get(struct uaudio_softc *sc, int which, struct mixerctl *mc,
                   1628:               int chan)
1.1       augustss 1629: {
                   1630:        int val;
                   1631:
                   1632:        DPRINTFN(5,("uaudio_ctl_get: which=%d chan=%d\n", which, chan));
                   1633:        val = uaudio_get(sc, which, UT_READ_CLASS_INTERFACE, mc->wValue[chan],
                   1634:                         mc->wIndex, MIX_SIZE(mc->type));
                   1635:        return (uaudio_value2bsd(mc, val));
                   1636: }
                   1637:
                   1638: void
1.26      augustss 1639: uaudio_ctl_set(struct uaudio_softc *sc, int which, struct mixerctl *mc,
                   1640:               int chan, int val)
1.1       augustss 1641: {
                   1642:        val = uaudio_bsd2value(mc, val);
                   1643:        uaudio_set(sc, which, UT_WRITE_CLASS_INTERFACE, mc->wValue[chan],
                   1644:                   mc->wIndex, MIX_SIZE(mc->type), val);
                   1645: }
                   1646:
                   1647: int
1.26      augustss 1648: uaudio_mixer_get_port(void *addr, mixer_ctrl_t *cp)
1.1       augustss 1649: {
                   1650:        struct uaudio_softc *sc = addr;
                   1651:        struct mixerctl *mc;
                   1652:        int i, n, vals[MIX_MAX_CHAN], val;
                   1653:
                   1654:        DPRINTFN(2,("uaudio_mixer_get_port: index=%d\n", cp->dev));
                   1655:
                   1656:        if (sc->sc_dying)
                   1657:                return (EIO);
                   1658:
                   1659:        n = cp->dev;
                   1660:        if (n < 0 || n >= sc->sc_nctls)
                   1661:                return (ENXIO);
                   1662:        mc = &sc->sc_ctls[n];
                   1663:
                   1664:        if (mc->type == MIX_ON_OFF) {
                   1665:                if (cp->type != AUDIO_MIXER_ENUM)
                   1666:                        return (EINVAL);
                   1667:                cp->un.ord = uaudio_ctl_get(sc, GET_CUR, mc, 0);
                   1668:        } else {
                   1669:                if (cp->type != AUDIO_MIXER_VALUE)
                   1670:                        return (EINVAL);
                   1671:                if (cp->un.value.num_channels != 1 &&
                   1672:                    cp->un.value.num_channels != mc->nchan)
                   1673:                        return (EINVAL);
                   1674:                for (i = 0; i < mc->nchan; i++)
                   1675:                        vals[i] = uaudio_ctl_get(sc, GET_CUR, mc, i);
                   1676:                if (cp->un.value.num_channels == 1 && mc->nchan != 1) {
                   1677:                        for (val = 0, i = 0; i < mc->nchan; i++)
                   1678:                                val += vals[i];
                   1679:                        vals[0] = val / mc->nchan;
                   1680:                }
                   1681:                for (i = 0; i < cp->un.value.num_channels; i++)
                   1682:                        cp->un.value.level[i] = vals[i];
                   1683:        }
                   1684:
                   1685:        return (0);
                   1686: }
                   1687:
                   1688: int
1.26      augustss 1689: uaudio_mixer_set_port(void *addr, mixer_ctrl_t *cp)
1.1       augustss 1690: {
                   1691:        struct uaudio_softc *sc = addr;
                   1692:        struct mixerctl *mc;
                   1693:        int i, n, vals[MIX_MAX_CHAN];
                   1694:
                   1695:        DPRINTFN(2,("uaudio_mixer_set_port: index = %d\n", cp->dev));
                   1696:        if (sc->sc_dying)
                   1697:                return (EIO);
                   1698:
                   1699:        n = cp->dev;
                   1700:        if (n < 0 || n >= sc->sc_nctls)
                   1701:                return (ENXIO);
                   1702:        mc = &sc->sc_ctls[n];
                   1703:
                   1704:        if (mc->type == MIX_ON_OFF) {
                   1705:                if (cp->type != AUDIO_MIXER_ENUM)
                   1706:                        return (EINVAL);
                   1707:                uaudio_ctl_set(sc, SET_CUR, mc, 0, cp->un.ord);
                   1708:        } else {
                   1709:                if (cp->type != AUDIO_MIXER_VALUE)
                   1710:                        return (EINVAL);
                   1711:                if (cp->un.value.num_channels == 1)
                   1712:                        for (i = 0; i < mc->nchan; i++)
                   1713:                                vals[i] = cp->un.value.level[0];
                   1714:                else if (cp->un.value.num_channels == mc->nchan)
                   1715:                        for (i = 0; i < mc->nchan; i++)
                   1716:                                vals[i] = cp->un.value.level[i];
                   1717:                else
                   1718:                        return (EINVAL);
                   1719:                for (i = 0; i < mc->nchan; i++)
                   1720:                        uaudio_ctl_set(sc, SET_CUR, mc, i, vals[i]);
                   1721:        }
                   1722:        return (0);
                   1723: }
                   1724:
                   1725: int
1.26      augustss 1726: uaudio_trigger_input(void *addr, void *start, void *end, int blksize,
                   1727:                     void (*intr)(void *), void *arg,
                   1728:                     struct audio_params *param)
1.1       augustss 1729: {
                   1730:        struct uaudio_softc *sc = addr;
1.5       augustss 1731:        struct chan *ch = &sc->sc_chan;
1.9       augustss 1732:        usbd_status err;
1.5       augustss 1733:        int i, s;
1.1       augustss 1734:
                   1735:        if (sc->sc_dying)
                   1736:                return (EIO);
                   1737:
1.5       augustss 1738:        DPRINTFN(3,("uaudio_trigger_input: sc=%p start=%p end=%p "
1.1       augustss 1739:                    "blksize=%d\n", sc, start, end, blksize));
                   1740:
1.5       augustss 1741:        uaudio_chan_set_param(ch, param, start, end, blksize);
                   1742:        DPRINTFN(3,("uaudio_trigger_input: sample_size=%d bytes/frame=%d "
                   1743:                    "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame,
                   1744:                    ch->fraction));
                   1745:
1.9       augustss 1746:        err = uaudio_chan_alloc_buffers(sc, ch);
                   1747:        if (err)
1.5       augustss 1748:                return (EIO);
                   1749:
1.9       augustss 1750:        err = uaudio_chan_open(sc, ch);
                   1751:        if (err) {
1.5       augustss 1752:                uaudio_chan_free_buffers(sc, ch);
                   1753:                return (EIO);
                   1754:        }
                   1755:
                   1756:        sc->sc_chan.intr = intr;
                   1757:        sc->sc_chan.arg = arg;
                   1758:
                   1759:        s = splusb();
1.22      augustss 1760:        for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX -1 shouldn't be needed */
1.5       augustss 1761:                uaudio_chan_rtransfer(ch);
                   1762:        splx(s);
                   1763:
                   1764:         return (0);
1.1       augustss 1765: }
                   1766:
                   1767: int
1.26      augustss 1768: uaudio_trigger_output(void *addr, void *start, void *end, int blksize,
                   1769:                      void (*intr)(void *), void *arg,
                   1770:                      struct audio_params *param)
1.1       augustss 1771: {
                   1772:        struct uaudio_softc *sc = addr;
1.5       augustss 1773:        struct chan *ch = &sc->sc_chan;
1.9       augustss 1774:        usbd_status err;
1.1       augustss 1775:        int i, s;
                   1776:
                   1777:        if (sc->sc_dying)
                   1778:                return (EIO);
                   1779:
                   1780:        DPRINTFN(3,("uaudio_trigger_output: sc=%p start=%p end=%p "
                   1781:                    "blksize=%d\n", sc, start, end, blksize));
                   1782:
                   1783:        uaudio_chan_set_param(ch, param, start, end, blksize);
                   1784:        DPRINTFN(3,("uaudio_trigger_output: sample_size=%d bytes/frame=%d "
                   1785:                    "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame,
                   1786:                    ch->fraction));
                   1787:
1.9       augustss 1788:        err = uaudio_chan_alloc_buffers(sc, ch);
                   1789:        if (err)
1.1       augustss 1790:                return (EIO);
                   1791:
1.9       augustss 1792:        err = uaudio_chan_open(sc, ch);
                   1793:        if (err) {
1.1       augustss 1794:                uaudio_chan_free_buffers(sc, ch);
                   1795:                return (EIO);
                   1796:        }
                   1797:
1.5       augustss 1798:        sc->sc_chan.intr = intr;
                   1799:        sc->sc_chan.arg = arg;
1.1       augustss 1800:
                   1801:        s = splusb();
1.22      augustss 1802:        for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX */
1.5       augustss 1803:                uaudio_chan_ptransfer(ch);
1.1       augustss 1804:        splx(s);
                   1805:
                   1806:         return (0);
                   1807: }
                   1808:
                   1809: /* Set up a pipe for a channel. */
                   1810: usbd_status
1.26      augustss 1811: uaudio_chan_open(struct uaudio_softc *sc, struct chan *ch)
1.1       augustss 1812: {
                   1813:        struct as_info *as = &sc->sc_alts[sc->sc_curaltidx];
                   1814:        int endpt = as->edesc->bEndpointAddress;
1.9       augustss 1815:        usbd_status err;
1.1       augustss 1816:
                   1817:        DPRINTF(("uaudio_open_chan: endpt=0x%02x, speed=%d, alt=%d\n",
                   1818:                 endpt, ch->sample_rate, as->alt));
                   1819:
                   1820:        /* Set alternate interface corresponding to the mode. */
1.37      mycroft  1821:        err = usbd_set_interface(as->ifaceh, as->alt);
1.9       augustss 1822:        if (err)
                   1823:                return (err);
1.1       augustss 1824:
                   1825:        /* Some devices do not support this request, so ignore errors. */
1.4       augustss 1826: #ifdef UAUDIO_DEBUG
1.9       augustss 1827:        err = uaudio_set_speed(sc, endpt, ch->sample_rate);
                   1828:        if (err)
                   1829:                DPRINTF(("uaudio_chan_open: set_speed failed err=%s\n",
                   1830:                         usbd_errstr(err)));
1.1       augustss 1831: #else
                   1832:        (void)uaudio_set_speed(sc, endpt, ch->sample_rate);
                   1833: #endif
                   1834:
                   1835:        DPRINTF(("uaudio_open_chan: create pipe to 0x%02x\n", endpt));
1.37      mycroft  1836:        err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->pipe);
1.9       augustss 1837:        return (err);
1.1       augustss 1838: }
                   1839:
                   1840: void
1.26      augustss 1841: uaudio_chan_close(struct uaudio_softc *sc, struct chan *ch)
1.1       augustss 1842: {
1.37      mycroft  1843:        struct as_info *as = &sc->sc_alts[sc->sc_curaltidx];
                   1844:
1.1       augustss 1845:        if (sc->sc_nullalt >= 0) {
                   1846:                DPRINTF(("uaudio_close_chan: set null alt=%d\n",
                   1847:                         sc->sc_nullalt));
1.37      mycroft  1848:                usbd_set_interface(as->ifaceh, sc->sc_nullalt);
1.1       augustss 1849:        }
                   1850:        usbd_abort_pipe(ch->pipe);
                   1851:        usbd_close_pipe(ch->pipe);
                   1852: }
                   1853:
                   1854: usbd_status
1.26      augustss 1855: uaudio_chan_alloc_buffers(struct uaudio_softc *sc, struct chan *ch)
1.1       augustss 1856: {
1.9       augustss 1857:        usbd_xfer_handle xfer;
1.1       augustss 1858:        void *buf;
                   1859:        int i, size;
                   1860:
                   1861:        size = (ch->bytes_per_frame + ch->sample_size) * UAUDIO_NFRAMES;
                   1862:        for (i = 0; i < UAUDIO_NCHANBUFS; i++) {
1.11      augustss 1863:                xfer = usbd_alloc_xfer(sc->sc_udev);
1.9       augustss 1864:                if (xfer == 0)
1.1       augustss 1865:                        goto bad;
1.9       augustss 1866:                ch->chanbufs[i].xfer = xfer;
                   1867:                buf = usbd_alloc_buffer(xfer, size);
1.1       augustss 1868:                if (buf == 0) {
                   1869:                        i++;
                   1870:                        goto bad;
                   1871:                }
                   1872:                ch->chanbufs[i].buffer = buf;
                   1873:                ch->chanbufs[i].chan = ch;
                   1874:        }
                   1875:
                   1876:        return (USBD_NORMAL_COMPLETION);
                   1877:
                   1878: bad:
                   1879:        while (--i >= 0)
                   1880:                /* implicit buffer free */
1.11      augustss 1881:                usbd_free_xfer(ch->chanbufs[i].xfer);
1.1       augustss 1882:        return (USBD_NOMEM);
                   1883: }
                   1884:
                   1885: void
1.26      augustss 1886: uaudio_chan_free_buffers(struct uaudio_softc *sc, struct chan *ch)
1.1       augustss 1887: {
                   1888:        int i;
                   1889:
                   1890:        for (i = 0; i < UAUDIO_NCHANBUFS; i++)
1.11      augustss 1891:                usbd_free_xfer(ch->chanbufs[i].xfer);
1.1       augustss 1892: }
                   1893:
                   1894: /* Called at splusb() */
                   1895: void
1.26      augustss 1896: uaudio_chan_ptransfer(struct chan *ch)
1.1       augustss 1897: {
                   1898:        struct chanbuf *cb;
                   1899:        int i, n, size, residue, total;
                   1900:
1.8       augustss 1901:        if (ch->sc->sc_dying)
                   1902:                return;
                   1903:
1.1       augustss 1904:        /* Pick the next channel buffer. */
                   1905:        cb = &ch->chanbufs[ch->curchanbuf];
                   1906:        if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
                   1907:                ch->curchanbuf = 0;
                   1908:
                   1909:        /* Compute the size of each frame in the next transfer. */
                   1910:        residue = ch->residue;
                   1911:        total = 0;
                   1912:        for (i = 0; i < UAUDIO_NFRAMES; i++) {
                   1913:                size = ch->bytes_per_frame;
                   1914:                residue += ch->fraction;
                   1915:                if (residue >= USB_FRAMES_PER_SECOND) {
1.31      augustss 1916:                        if (!ch->nofrac)
                   1917:                                size += ch->sample_size;
1.1       augustss 1918:                        residue -= USB_FRAMES_PER_SECOND;
                   1919:                }
                   1920:                cb->sizes[i] = size;
                   1921:                total += size;
                   1922:        }
                   1923:        ch->residue = residue;
                   1924:        cb->size = total;
                   1925:
                   1926:        /*
                   1927:         * Transfer data from upper layer buffer to channel buffer, taking
                   1928:         * care of wrapping the upper layer buffer.
                   1929:         */
                   1930:        n = min(total, ch->end - ch->cur);
                   1931:        memcpy(cb->buffer, ch->cur, n);
                   1932:        ch->cur += n;
                   1933:        if (ch->cur >= ch->end)
                   1934:                ch->cur = ch->start;
                   1935:        if (total > n) {
                   1936:                total -= n;
                   1937:                memcpy(cb->buffer + n, ch->cur, total);
                   1938:                ch->cur += total;
                   1939:        }
                   1940:
1.4       augustss 1941: #ifdef UAUDIO_DEBUG
1.1       augustss 1942:        if (uaudiodebug > 8) {
1.5       augustss 1943:                DPRINTF(("uaudio_chan_ptransfer: buffer=%p, residue=0.%03d\n",
1.1       augustss 1944:                         cb->buffer, ch->residue));
                   1945:                for (i = 0; i < UAUDIO_NFRAMES; i++) {
                   1946:                        DPRINTF(("   [%d] length %d\n", i, cb->sizes[i]));
                   1947:                }
                   1948:        }
                   1949: #endif
                   1950:
1.9       augustss 1951:        DPRINTFN(5,("uaudio_chan_transfer: ptransfer xfer=%p\n", cb->xfer));
1.1       augustss 1952:        /* Fill the request */
1.11      augustss 1953:        usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
                   1954:                             UAUDIO_NFRAMES, USBD_NO_COPY,
                   1955:                             uaudio_chan_pintr);
1.1       augustss 1956:
1.9       augustss 1957:        (void)usbd_transfer(cb->xfer);
1.1       augustss 1958: }
                   1959:
                   1960: void
1.26      augustss 1961: uaudio_chan_pintr(usbd_xfer_handle xfer, usbd_private_handle priv,
                   1962:                  usbd_status status)
1.1       augustss 1963: {
                   1964:        struct chanbuf *cb = priv;
                   1965:        struct chan *ch = cb->chan;
                   1966:        u_int32_t count;
                   1967:        int s;
                   1968:
                   1969:        /* Return if we are aborting. */
                   1970:        if (status == USBD_CANCELLED)
                   1971:                return;
                   1972:
1.18      augustss 1973:        usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
1.5       augustss 1974:        DPRINTFN(5,("uaudio_chan_pintr: count=%d, transferred=%d\n",
                   1975:                    count, ch->transferred));
                   1976: #ifdef DIAGNOSTIC
                   1977:        if (count != cb->size) {
                   1978:                printf("uaudio_chan_pintr: count(%d) != size(%d)\n",
                   1979:                       count, cb->size);
                   1980:        }
                   1981: #endif
                   1982:
                   1983:        ch->transferred += cb->size;
                   1984:        s = splaudio();
1.1       augustss 1985:        /* Call back to upper layer */
1.5       augustss 1986:        while (ch->transferred >= ch->blksize) {
                   1987:                ch->transferred -= ch->blksize;
                   1988:                DPRINTFN(5,("uaudio_chan_pintr: call %p(%p)\n",
                   1989:                            ch->intr, ch->arg));
                   1990:                ch->intr(ch->arg);
                   1991:        }
                   1992:        splx(s);
                   1993:
                   1994:        /* start next transfer */
                   1995:        uaudio_chan_ptransfer(ch);
                   1996: }
                   1997:
                   1998: /* Called at splusb() */
                   1999: void
1.26      augustss 2000: uaudio_chan_rtransfer(struct chan *ch)
1.5       augustss 2001: {
                   2002:        struct chanbuf *cb;
                   2003:        int i, size, residue, total;
1.8       augustss 2004:
                   2005:        if (ch->sc->sc_dying)
                   2006:                return;
1.5       augustss 2007:
                   2008:        /* Pick the next channel buffer. */
                   2009:        cb = &ch->chanbufs[ch->curchanbuf];
                   2010:        if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
                   2011:                ch->curchanbuf = 0;
                   2012:
                   2013:        /* Compute the size of each frame in the next transfer. */
                   2014:        residue = ch->residue;
                   2015:        total = 0;
                   2016:        for (i = 0; i < UAUDIO_NFRAMES; i++) {
                   2017:                size = ch->bytes_per_frame;
                   2018:                residue += ch->fraction;
                   2019:                if (residue >= USB_FRAMES_PER_SECOND) {
1.31      augustss 2020:                        if (!ch->nofrac)
                   2021:                                size += ch->sample_size;
1.5       augustss 2022:                        residue -= USB_FRAMES_PER_SECOND;
                   2023:                }
                   2024:                cb->sizes[i] = size;
                   2025:                total += size;
                   2026:        }
                   2027:        ch->residue = residue;
                   2028:        cb->size = total;
                   2029:
                   2030: #ifdef UAUDIO_DEBUG
                   2031:        if (uaudiodebug > 8) {
                   2032:                DPRINTF(("uaudio_chan_rtransfer: buffer=%p, residue=0.%03d\n",
                   2033:                         cb->buffer, ch->residue));
                   2034:                for (i = 0; i < UAUDIO_NFRAMES; i++) {
                   2035:                        DPRINTF(("   [%d] length %d\n", i, cb->sizes[i]));
                   2036:                }
                   2037:        }
                   2038: #endif
                   2039:
1.9       augustss 2040:        DPRINTFN(5,("uaudio_chan_rtransfer: transfer xfer=%p\n", cb->xfer));
1.5       augustss 2041:        /* Fill the request */
1.11      augustss 2042:        usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
                   2043:                             UAUDIO_NFRAMES, USBD_NO_COPY,
                   2044:                             uaudio_chan_rintr);
1.5       augustss 2045:
1.9       augustss 2046:        (void)usbd_transfer(cb->xfer);
1.5       augustss 2047: }
                   2048:
                   2049: void
1.26      augustss 2050: uaudio_chan_rintr(usbd_xfer_handle xfer, usbd_private_handle priv,
                   2051:                  usbd_status status)
1.5       augustss 2052: {
                   2053:        struct chanbuf *cb = priv;
                   2054:        struct chan *ch = cb->chan;
                   2055:        u_int32_t count;
                   2056:        int s, n;
                   2057:
                   2058:        /* Return if we are aborting. */
                   2059:        if (status == USBD_CANCELLED)
                   2060:                return;
                   2061:
1.18      augustss 2062:        usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
1.5       augustss 2063:        DPRINTFN(5,("uaudio_chan_rintr: count=%d, transferred=%d\n",
1.1       augustss 2064:                    count, ch->transferred));
1.31      augustss 2065:
                   2066:        if (count < cb->size) {
                   2067:                /* if the device fails to keep up, copy last byte */
                   2068:                u_char b = count ? cb->buffer[count-1] : 0;
                   2069:                while (count < cb->size)
                   2070:                        cb->buffer[count++] = b;
                   2071:        }
                   2072:
1.1       augustss 2073: #ifdef DIAGNOSTIC
                   2074:        if (count != cb->size) {
1.31      augustss 2075:                printf("uaudio_chan_rintr: count(%d) != size(%d)\n",
1.1       augustss 2076:                       count, cb->size);
                   2077:        }
                   2078: #endif
                   2079:
1.5       augustss 2080:        /*
                   2081:         * Transfer data from channel buffer to upper layer buffer, taking
                   2082:         * care of wrapping the upper layer buffer.
                   2083:         */
                   2084:        n = min(count, ch->end - ch->cur);
                   2085:        memcpy(ch->cur, cb->buffer, n);
                   2086:        ch->cur += n;
                   2087:        if (ch->cur >= ch->end)
                   2088:                ch->cur = ch->start;
                   2089:        if (count > n) {
                   2090:                memcpy(ch->cur, cb->buffer + n, count - n);
                   2091:                ch->cur += count - n;
                   2092:        }
                   2093:
                   2094:        /* Call back to upper layer */
1.1       augustss 2095:        ch->transferred += cb->size;
                   2096:        s = splaudio();
                   2097:        while (ch->transferred >= ch->blksize) {
                   2098:                ch->transferred -= ch->blksize;
1.31      augustss 2099:                DPRINTFN(5,("uaudio_chan_rintr: call %p(%p)\n",
1.1       augustss 2100:                            ch->intr, ch->arg));
                   2101:                ch->intr(ch->arg);
                   2102:        }
                   2103:        splx(s);
                   2104:
                   2105:        /* start next transfer */
1.5       augustss 2106:        uaudio_chan_rtransfer(ch);
1.1       augustss 2107: }
                   2108:
                   2109: void
1.26      augustss 2110: uaudio_chan_set_param(struct chan *ch, struct audio_params *param,
                   2111:                      u_char *start, u_char *end, int blksize)
1.1       augustss 2112: {
                   2113:        int samples_per_frame, sample_size;
                   2114:
                   2115:        sample_size = param->precision * param->channels / 8;
                   2116:        samples_per_frame = param->sample_rate / USB_FRAMES_PER_SECOND;
                   2117:        ch->fraction = param->sample_rate % USB_FRAMES_PER_SECOND;
                   2118:        ch->sample_size = sample_size;
                   2119:        ch->sample_rate = param->sample_rate;
                   2120:        ch->bytes_per_frame = samples_per_frame * sample_size;
                   2121:        ch->residue = 0;
                   2122:
                   2123:        ch->start = start;
                   2124:        ch->end = end;
                   2125:        ch->cur = start;
                   2126:        ch->blksize = blksize;
                   2127:        ch->transferred = 0;
                   2128:
                   2129:        ch->curchanbuf = 0;
                   2130: }
                   2131:
                   2132: int
1.26      augustss 2133: uaudio_set_params(void *addr, int setmode, int usemode,
1.38      mycroft  2134:                  struct audio_params *play, struct audio_params *rec)
1.1       augustss 2135: {
                   2136:        struct uaudio_softc *sc = addr;
                   2137:        int flags = sc->sc_altflags;
1.38      mycroft  2138:        int factor;
1.1       augustss 2139:        int enc, i, j;
1.38      mycroft  2140:        void (*swcode)(void *, u_char *buf, int cnt);
                   2141:        struct audio_params *p;
                   2142:        int mode;
1.1       augustss 2143:
                   2144:        if (sc->sc_dying)
                   2145:                return (EIO);
                   2146:
1.9       augustss 2147:        if (sc->sc_chan.pipe != NULL)
1.1       augustss 2148:                return (EBUSY);
                   2149:
1.38      mycroft  2150:        for (mode = AUMODE_RECORD; mode != -1;
                   2151:             mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
                   2152:                if ((setmode & mode) == 0)
                   2153:                        continue;
                   2154:                if ((sc->sc_chan.dir & mode) == 0)
                   2155:                        continue;
                   2156:
                   2157:                p = mode == AUMODE_PLAY ? play : rec;
                   2158:
                   2159:                factor = 1;
                   2160:                swcode = 0;
                   2161:                enc = p->encoding;
                   2162:                switch (enc) {
                   2163:                case AUDIO_ENCODING_SLINEAR_BE:
                   2164:                        if (p->precision == 16) {
                   2165:                                swcode = swap_bytes;
1.37      mycroft  2166:                                enc = AUDIO_ENCODING_SLINEAR_LE;
1.38      mycroft  2167:                        } else if (p->precision == 8 && !(flags & HAS_8)) {
                   2168:                                swcode = change_sign8;
1.1       augustss 2169:                                enc = AUDIO_ENCODING_ULINEAR_LE;
1.38      mycroft  2170:                        }
                   2171:                        break;
                   2172:                case AUDIO_ENCODING_SLINEAR_LE:
                   2173:                        if (p->precision == 8 && !(flags & HAS_8)) {
                   2174:                                swcode = change_sign8;
                   2175:                                enc = AUDIO_ENCODING_ULINEAR_LE;
                   2176:                        }
                   2177:                        break;
                   2178:                case AUDIO_ENCODING_ULINEAR_BE:
                   2179:                        if (p->precision == 16) {
                   2180:                                if (mode == AUMODE_PLAY)
                   2181:                                        swcode = swap_bytes_change_sign16_le;
                   2182:                                else
                   2183:                                        swcode = change_sign16_swap_bytes_le;
1.1       augustss 2184:                                enc = AUDIO_ENCODING_SLINEAR_LE;
1.38      mycroft  2185:                        } else if (p->precision == 8 && !(flags & HAS_8U)) {
                   2186:                                swcode = change_sign8;
                   2187:                                enc = AUDIO_ENCODING_SLINEAR_LE;
                   2188:                        }
                   2189:                        break;
                   2190:                case AUDIO_ENCODING_ULINEAR_LE:
                   2191:                        if (p->precision == 16) {
                   2192:                                swcode = change_sign16_le;
1.37      mycroft  2193:                                enc = AUDIO_ENCODING_SLINEAR_LE;
1.38      mycroft  2194:                        } else if (p->precision == 8 && !(flags & HAS_8U)) {
                   2195:                                swcode = change_sign8;
1.1       augustss 2196:                                enc = AUDIO_ENCODING_SLINEAR_LE;
1.38      mycroft  2197:                        }
                   2198:                        break;
                   2199:                case AUDIO_ENCODING_ULAW:
                   2200:                        if (!(flags & HAS_MULAW)) {
                   2201:                                if (mode == AUMODE_PLAY &&
                   2202:                                    (flags & HAS_16)) {
                   2203:                                        swcode = mulaw_to_slinear16_le;
                   2204:                                        factor = 2;
                   2205:                                        enc = AUDIO_ENCODING_SLINEAR_LE;
                   2206:                                } else if (flags & HAS_8U) {
                   2207:                                        if (mode == AUMODE_PLAY)
                   2208:                                                swcode = mulaw_to_ulinear8;
                   2209:                                        else
                   2210:                                                swcode = ulinear8_to_mulaw;
                   2211:                                        enc = AUDIO_ENCODING_ULINEAR_LE;
                   2212:                                } else if (flags & HAS_8) {
                   2213:                                        if (mode == AUMODE_PLAY)
                   2214:                                                swcode = mulaw_to_slinear8;
                   2215:                                        else
                   2216:                                                swcode = slinear8_to_mulaw;
                   2217:                                        enc = AUDIO_ENCODING_SLINEAR_LE;
                   2218:                                } else
                   2219:                                        return (EINVAL);
                   2220:                        }
                   2221:                        break;
                   2222:                case AUDIO_ENCODING_ALAW:
                   2223:                        if (!(flags & HAS_ALAW)) {
                   2224:                                if (mode == AUMODE_PLAY &&
                   2225:                                    (flags & HAS_16)) {
                   2226:                                        swcode = alaw_to_slinear16_le;
                   2227:                                        factor = 2;
                   2228:                                        enc = AUDIO_ENCODING_SLINEAR_LE;
                   2229:                                } else if (flags & HAS_8U) {
                   2230:                                        if (mode == AUMODE_PLAY)
                   2231:                                                swcode = alaw_to_ulinear8;
                   2232:                                        else
                   2233:                                                swcode = ulinear8_to_alaw;
                   2234:                                        enc = AUDIO_ENCODING_ULINEAR_LE;
                   2235:                                } else if (flags & HAS_8) {
                   2236:                                        if (mode == AUMODE_PLAY)
                   2237:                                                swcode = alaw_to_slinear8;
                   2238:                                        else
                   2239:                                                swcode = slinear8_to_alaw;
                   2240:                                        enc = AUDIO_ENCODING_SLINEAR_LE;
                   2241:                                } else
                   2242:                                        return (EINVAL);
                   2243:                        }
                   2244:                        break;
                   2245:                default:
                   2246:                        return (EINVAL);
1.1       augustss 2247:                }
1.38      mycroft  2248:                /* XXX do some other conversions... */
                   2249:
                   2250:                DPRINTF(("uaudio_set_params: chan=%d prec=%d enc=%d rate=%ld\n",
                   2251:                         p->channels, p->precision, enc, p->sample_rate));
                   2252:
                   2253:                for (i = 0; i < sc->sc_nalts; i++) {
                   2254:                        struct usb_audio_streaming_type1_descriptor *a1d =
                   2255:                                sc->sc_alts[i].asf1desc;
                   2256:                        if (p->channels == a1d->bNrChannels &&
                   2257:                            p->precision == a1d->bBitResolution &&
                   2258:                            enc == sc->sc_alts[i].encoding &&
                   2259:                            (mode == AUMODE_PLAY ? UE_DIR_OUT : UE_DIR_IN) ==
                   2260:                            UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress)) {
                   2261:                                if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
                   2262:                                        DPRINTFN(2,("uaudio_set_params: cont %d-%d\n",
                   2263:                                            UA_SAMP_LO(a1d), UA_SAMP_HI(a1d)));
                   2264:                                        if (UA_SAMP_LO(a1d) < p->sample_rate &&
                   2265:                                            p->sample_rate < UA_SAMP_HI(a1d))
1.1       augustss 2266:                                                goto found;
1.38      mycroft  2267:                                } else {
                   2268:                                        for (j = 0; j < a1d->bSamFreqType; j++) {
                   2269:                                                DPRINTFN(2,("uaudio_set_params: disc #"
                   2270:                                                    "%d: %d\n", j, UA_GETSAMP(a1d, j)));
                   2271:                                                /* XXX allow for some slack */
                   2272:                                                if (UA_GETSAMP(a1d, j) ==
                   2273:                                                    p->sample_rate)
                   2274:                                                        goto found;
                   2275:                                        }
1.1       augustss 2276:                                }
                   2277:                        }
                   2278:                }
1.38      mycroft  2279:                return (EINVAL);
                   2280:
                   2281:        found:
                   2282:                p->sw_code = swcode;
                   2283:                p->factor  = factor;
                   2284:                if (usemode == mode)
                   2285:                        sc->sc_curaltidx = i;
1.1       augustss 2286:        }
                   2287:
                   2288:        DPRINTF(("uaudio_set_params: use altidx=%d, altno=%d\n",
                   2289:                 sc->sc_curaltidx,
                   2290:                 sc->sc_alts[sc->sc_curaltidx].idesc->bAlternateSetting));
                   2291:
1.38      mycroft  2292:        return (0);
1.1       augustss 2293: }
                   2294:
                   2295: usbd_status
1.26      augustss 2296: uaudio_set_speed(struct uaudio_softc *sc, int endpt, u_int speed)
1.1       augustss 2297: {
                   2298:        usb_device_request_t req;
                   2299:        u_int8_t data[3];
                   2300:
                   2301:        DPRINTFN(5,("uaudio_set_speed: endpt=%d speed=%u\n", endpt, speed));
                   2302:        req.bmRequestType = UT_WRITE_CLASS_ENDPOINT;
                   2303:        req.bRequest = SET_CUR;
                   2304:        USETW2(req.wValue, SAMPLING_FREQ_CONTROL, 0);
                   2305:        USETW(req.wIndex, endpt);
                   2306:        USETW(req.wLength, 3);
                   2307:        data[0] = speed;
                   2308:        data[1] = speed >> 8;
                   2309:        data[2] = speed >> 16;
                   2310:
                   2311:        return (usbd_do_request(sc->sc_udev, &req, &data));
                   2312: }
                   2313:

CVSweb <webmaster@jp.NetBSD.org>