[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.22

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

CVSweb <webmaster@jp.NetBSD.org>