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

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

CVSweb <webmaster@jp.NetBSD.org>