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

1.99.2.5! yamt        1: /*     $NetBSD: uaudio.c,v 1.99.2.4 2007/09/03 14:39:08 yamt 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.99.2.5! yamt       47: __KERNEL_RCSID(0, "$NetBSD: uaudio.c,v 1.99.2.4 2007/09/03 14:39:08 yamt 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/poll.h>
                     62:
                     63: #include <sys/audioio.h>
                     64: #include <dev/audio_if.h>
1.77      mycroft    65: #include <dev/audiovar.h>
1.1       augustss   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.80      kent       76: /* #define UAUDIO_DEBUG */
                     77: /* #define UAUDIO_MULTIPLE_ENDPOINTS */
1.4       augustss   78: #ifdef UAUDIO_DEBUG
1.85      kent       79: #define DPRINTF(x)     do { if (uaudiodebug) logprintf x; } while (0)
                     80: #define DPRINTFN(n,x)  do { if (uaudiodebug>(n)) logprintf x; } while (0)
1.1       augustss   81: int    uaudiodebug = 0;
                     82: #else
                     83: #define DPRINTF(x)
                     84: #define DPRINTFN(n,x)
                     85: #endif
                     86:
1.22      augustss   87: #define UAUDIO_NCHANBUFS 6     /* number of outstanding request */
1.55      kent       88: #define UAUDIO_NFRAMES   10    /* ms of sound in each request */
1.1       augustss   89:
                     90:
                     91: #define MIX_MAX_CHAN 8
                     92: struct mixerctl {
1.94      kent       93:        uint16_t        wValue[MIX_MAX_CHAN]; /* using nchan */
                     94:        uint16_t        wIndex;
                     95:        uint8_t         nchan;
                     96:        uint8_t         type;
1.1       augustss   97: #define MIX_ON_OFF     1
                     98: #define MIX_SIGNED_16  2
                     99: #define MIX_UNSIGNED_16        3
                    100: #define MIX_SIGNED_8   4
1.79      kent      101: #define MIX_SELECTOR   5
1.1       augustss  102: #define MIX_SIZE(n) ((n) == MIX_SIGNED_16 || (n) == MIX_UNSIGNED_16 ? 2 : 1)
                    103: #define MIX_UNSIGNED(n) ((n) == MIX_UNSIGNED_16)
1.34      augustss  104:        int             minval, maxval;
                    105:        u_int           delta;
                    106:        u_int           mul;
1.94      kent      107:        uint8_t         class;
1.1       augustss  108:        char            ctlname[MAX_AUDIO_DEV_LEN];
1.99      christos  109:        const char      *ctlunit;
1.1       augustss  110: };
                    111: #define MAKE(h,l) (((h) << 8) | (l))
                    112:
                    113: struct as_info {
1.94      kent      114:        uint8_t         alt;
                    115:        uint8_t         encoding;
                    116:        uint8_t         attributes; /* Copy of bmAttributes of
1.50      kent      117:                                     * usb_audio_streaming_endpoint_descriptor
                    118:                                     */
1.37      mycroft   119:        usbd_interface_handle   ifaceh;
1.78      kent      120:        const usb_interface_descriptor_t *idesc;
                    121:        const usb_endpoint_descriptor_audio_t *edesc;
1.80      kent      122:        const usb_endpoint_descriptor_audio_t *edesc1;
1.78      kent      123:        const struct usb_audio_streaming_type1_descriptor *asf1desc;
1.92      kent      124:        struct audio_format *aformat;
1.47      jdolecek  125:        int             sc_busy;        /* currently used */
1.1       augustss  126: };
                    127:
                    128: struct chan {
1.67      wiz       129:        void    (*intr)(void *);        /* DMA completion intr handler */
1.1       augustss  130:        void    *arg;           /* arg for intr() */
                    131:        usbd_pipe_handle pipe;
1.83      kent      132:        usbd_pipe_handle sync_pipe;
1.1       augustss  133:
                    134:        u_int   sample_size;
                    135:        u_int   sample_rate;
                    136:        u_int   bytes_per_frame;
                    137:        u_int   fraction;       /* fraction/1000 is the extra samples/frame */
                    138:        u_int   residue;        /* accumulates the fractional samples */
                    139:
                    140:        u_char  *start;         /* upper layer buffer start */
                    141:        u_char  *end;           /* upper layer buffer end */
                    142:        u_char  *cur;           /* current position in upper layer buffer */
                    143:        int     blksize;        /* chunk size to report up */
                    144:        int     transferred;    /* transferred bytes not reported up */
                    145:
1.47      jdolecek  146:        int     altidx;         /* currently used altidx */
1.31      augustss  147:
1.1       augustss  148:        int     curchanbuf;
                    149:        struct chanbuf {
1.56      kent      150:                struct chan     *chan;
1.9       augustss  151:                usbd_xfer_handle xfer;
1.56      kent      152:                u_char          *buffer;
1.94      kent      153:                uint16_t        sizes[UAUDIO_NFRAMES];
                    154:                uint16_t        offsets[UAUDIO_NFRAMES];
                    155:                uint16_t        size;
1.1       augustss  156:        } chanbufs[UAUDIO_NCHANBUFS];
1.8       augustss  157:
                    158:        struct uaudio_softc *sc; /* our softc */
1.1       augustss  159: };
                    160:
                    161: struct uaudio_softc {
1.86      kent      162:        USBBASEDEVICE   sc_dev;         /* base device */
1.1       augustss  163:        usbd_device_handle sc_udev;     /* USB device */
1.86      kent      164:        int             sc_ac_iface;    /* Audio Control interface */
1.1       augustss  165:        usbd_interface_handle   sc_ac_ifaceh;
1.86      kent      166:        struct chan     sc_playchan;    /* play channel */
                    167:        struct chan     sc_recchan;     /* record channel */
                    168:        int             sc_nullalt;
                    169:        int             sc_audio_rev;
                    170:        struct as_info  *sc_alts;       /* alternate settings */
                    171:        int             sc_nalts;       /* # of alternate settings */
                    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.86      kent      180:        int             sc_mode;        /* play/record capability */
                    181:        struct mixerctl *sc_ctls;       /* mixer controls */
                    182:        int             sc_nctls;       /* # of mixer controls */
                    183:        device_ptr_t    sc_audiodev;
1.92      kent      184:        struct audio_format *sc_formats;
                    185:        int             sc_nformats;
                    186:        struct audio_encoding_set *sc_encodings;
                    187:        u_int           sc_channel_config;
1.86      kent      188:        char            sc_dying;
1.1       augustss  189: };
                    190:
1.82      kent      191: struct terminal_list {
                    192:        int size;
                    193:        uint16_t terminals[1];
                    194: };
                    195: #define TERMINAL_LIST_SIZE(N)  (offsetof(struct terminal_list, terminals) \
                    196:                                + sizeof(uint16_t) * (N))
                    197:
                    198: struct io_terminal {
                    199:        union {
1.99.2.4  yamt      200:                const uaudio_cs_descriptor_t *desc;
1.82      kent      201:                const struct usb_audio_input_terminal *it;
                    202:                const struct usb_audio_output_terminal *ot;
                    203:                const struct usb_audio_mixer_unit *mu;
                    204:                const struct usb_audio_selector_unit *su;
                    205:                const struct usb_audio_feature_unit *fu;
                    206:                const struct usb_audio_processing_unit *pu;
                    207:                const struct usb_audio_extension_unit *eu;
                    208:        } d;
                    209:        int inputs_size;
                    210:        struct terminal_list **inputs; /* list of source input terminals */
                    211:        struct terminal_list *output; /* list of destination output terminals */
1.83      kent      212:        int direct;             /* directly connected to an output terminal */
1.82      kent      213: };
                    214:
                    215: #define UAC_OUTPUT     0
                    216: #define UAC_INPUT      1
                    217: #define UAC_EQUAL      2
                    218: #define UAC_RECORD     3
                    219: #define UAC_NCLASSES   4
                    220: #ifdef UAUDIO_DEBUG
                    221: Static const char *uac_names[] = {
                    222:        AudioCoutputs, AudioCinputs, AudioCequalization, AudioCrecord,
                    223: };
                    224: #endif
1.1       augustss  225:
1.86      kent      226: Static usbd_status uaudio_identify_ac
                    227:        (struct uaudio_softc *, const usb_config_descriptor_t *);
                    228: Static usbd_status uaudio_identify_as
                    229:        (struct uaudio_softc *, const usb_config_descriptor_t *);
                    230: Static usbd_status uaudio_process_as
                    231:        (struct uaudio_softc *, const char *, int *, int,
                    232:         const usb_interface_descriptor_t *);
1.78      kent      233:
                    234: Static void    uaudio_add_alt(struct uaudio_softc *, const struct as_info *);
                    235:
                    236: Static const usb_interface_descriptor_t *uaudio_find_iface
                    237:        (const char *, int, int *, int);
                    238:
                    239: Static void    uaudio_mixer_add_ctl(struct uaudio_softc *, struct mixerctl *);
1.86      kent      240: Static char    *uaudio_id_name
                    241:        (struct uaudio_softc *, const struct io_terminal *, int);
1.91      kent      242: #ifdef UAUDIO_DEBUG
                    243: Static void    uaudio_dump_cluster(const struct usb_audio_cluster *);
                    244: #endif
1.86      kent      245: Static struct usb_audio_cluster uaudio_get_cluster
                    246:        (int, const struct io_terminal *);
                    247: Static void    uaudio_add_input
                    248:        (struct uaudio_softc *, const struct io_terminal *, int);
                    249: Static void    uaudio_add_output
                    250:        (struct uaudio_softc *, const struct io_terminal *, int);
                    251: Static void    uaudio_add_mixer
                    252:        (struct uaudio_softc *, const struct io_terminal *, int);
                    253: Static void    uaudio_add_selector
                    254:        (struct uaudio_softc *, const struct io_terminal *, int);
1.82      kent      255: #ifdef UAUDIO_DEBUG
                    256: Static const char *uaudio_get_terminal_name(int);
                    257: #endif
1.86      kent      258: Static int     uaudio_determine_class
                    259:        (const struct io_terminal *, struct mixerctl *);
                    260: Static const char *uaudio_feature_name
                    261:        (const struct io_terminal *, struct mixerctl *);
                    262: Static void    uaudio_add_feature
                    263:        (struct uaudio_softc *, const struct io_terminal *, int);
                    264: Static void    uaudio_add_processing_updown
                    265:        (struct uaudio_softc *, const struct io_terminal *, int);
                    266: Static void    uaudio_add_processing
                    267:        (struct uaudio_softc *, const struct io_terminal *, int);
                    268: Static void    uaudio_add_extension
                    269:        (struct uaudio_softc *, const struct io_terminal *, int);
                    270: Static struct terminal_list *uaudio_merge_terminal_list
                    271:        (const struct io_terminal *);
                    272: Static struct terminal_list *uaudio_io_terminaltype
                    273:        (int, struct io_terminal *, int);
                    274: Static usbd_status uaudio_identify
                    275:        (struct uaudio_softc *, const usb_config_descriptor_t *);
1.78      kent      276:
                    277: Static int     uaudio_signext(int, int);
                    278: Static int     uaudio_value2bsd(struct mixerctl *, int);
                    279: Static int     uaudio_bsd2value(struct mixerctl *, int);
                    280: Static int     uaudio_get(struct uaudio_softc *, int, int, int, int, int);
1.86      kent      281: Static int     uaudio_ctl_get
                    282:        (struct uaudio_softc *, int, struct mixerctl *, int);
                    283: Static void    uaudio_set
                    284:        (struct uaudio_softc *, int, int, int, int, int, int);
                    285: Static void    uaudio_ctl_set
                    286:        (struct uaudio_softc *, int, struct mixerctl *, int, int);
1.78      kent      287:
                    288: Static usbd_status uaudio_set_speed(struct uaudio_softc *, int, u_int);
                    289:
                    290: Static usbd_status uaudio_chan_open(struct uaudio_softc *, struct chan *);
                    291: Static void    uaudio_chan_close(struct uaudio_softc *, struct chan *);
1.86      kent      292: Static usbd_status uaudio_chan_alloc_buffers
                    293:        (struct uaudio_softc *, struct chan *);
1.78      kent      294: Static void    uaudio_chan_free_buffers(struct uaudio_softc *, struct chan *);
1.86      kent      295: Static void    uaudio_chan_init
                    296:        (struct chan *, int, const struct audio_params *, int);
1.78      kent      297: Static void    uaudio_chan_set_param(struct chan *, u_char *, u_char *, int);
                    298: Static void    uaudio_chan_ptransfer(struct chan *);
1.86      kent      299: Static void    uaudio_chan_pintr
                    300:        (usbd_xfer_handle, usbd_private_handle, usbd_status);
1.78      kent      301:
                    302: Static void    uaudio_chan_rtransfer(struct chan *);
1.86      kent      303: Static void    uaudio_chan_rintr
                    304:        (usbd_xfer_handle, usbd_private_handle, usbd_status);
1.78      kent      305:
                    306: Static int     uaudio_open(void *, int);
                    307: Static void    uaudio_close(void *);
                    308: Static int     uaudio_drain(void *);
                    309: Static int     uaudio_query_encoding(void *, struct audio_encoding *);
1.86      kent      310: Static int     uaudio_set_params
1.93      kent      311:        (void *, int, int, struct audio_params *, struct audio_params *,
                    312:         stream_filter_list_t *, stream_filter_list_t *);
                    313: Static int     uaudio_round_blocksize(void *, int, int, const audio_params_t *);
1.86      kent      314: Static int     uaudio_trigger_output
                    315:        (void *, void *, void *, int, void (*)(void *), void *,
1.93      kent      316:         const audio_params_t *);
1.86      kent      317: Static int     uaudio_trigger_input
                    318:        (void *, void *, void *, int, void (*)(void *), void *,
1.93      kent      319:         const audio_params_t *);
1.78      kent      320: Static int     uaudio_halt_in_dma(void *);
                    321: Static int     uaudio_halt_out_dma(void *);
                    322: Static int     uaudio_getdev(void *, struct audio_device *);
                    323: Static int     uaudio_mixer_set_port(void *, mixer_ctrl_t *);
                    324: Static int     uaudio_mixer_get_port(void *, mixer_ctrl_t *);
                    325: Static int     uaudio_query_devinfo(void *, mixer_devinfo_t *);
                    326: Static int     uaudio_get_props(void *);
1.1       augustss  327:
1.88      yamt      328: Static const struct audio_hw_if uaudio_hw_if = {
1.1       augustss  329:        uaudio_open,
                    330:        uaudio_close,
                    331:        uaudio_drain,
                    332:        uaudio_query_encoding,
                    333:        uaudio_set_params,
                    334:        uaudio_round_blocksize,
                    335:        NULL,
                    336:        NULL,
                    337:        NULL,
                    338:        NULL,
                    339:        NULL,
                    340:        uaudio_halt_out_dma,
                    341:        uaudio_halt_in_dma,
                    342:        NULL,
                    343:        uaudio_getdev,
                    344:        NULL,
                    345:        uaudio_mixer_set_port,
                    346:        uaudio_mixer_get_port,
                    347:        uaudio_query_devinfo,
                    348:        NULL,
                    349:        NULL,
                    350:        NULL,
                    351:        NULL,
                    352:        uaudio_get_props,
                    353:        uaudio_trigger_output,
                    354:        uaudio_trigger_input,
1.43      augustss  355:        NULL,
1.99.2.2  yamt      356:        NULL,
1.1       augustss  357: };
                    358:
1.21      augustss  359: Static struct audio_device uaudio_device = {
1.1       augustss  360:        "USB audio",
                    361:        "",
                    362:        "uaudio"
                    363: };
                    364:
1.99.2.5! yamt      365: int uaudio_match(device_t, struct cfdata *, void *);
        !           366: void uaudio_attach(device_t, device_t, void *);
        !           367: int uaudio_detach(device_t, int);
        !           368: void uaudio_childdet(device_t, device_t);
        !           369: int uaudio_activate(device_t, enum devact);
        !           370:
        !           371: extern struct cfdriver uaudio_cd;
        !           372:
        !           373: CFATTACH_DECL2(uaudio, sizeof(struct uaudio_softc),
        !           374:     uaudio_match, uaudio_attach, uaudio_detach, uaudio_activate, NULL,
        !           375:     uaudio_childdet);
1.1       augustss  376:
                    377: USB_MATCH(uaudio)
                    378: {
1.99.2.4  yamt      379:        USB_IFMATCH_START(uaudio, uaa);
1.1       augustss  380:
                    381:        /* Trigger on the control interface. */
1.99.2.4  yamt      382:        if (uaa->class != UICLASS_AUDIO ||
                    383:            uaa->subclass != UISUBCLASS_AUDIOCONTROL ||
1.10      augustss  384:            (usbd_get_quirks(uaa->device)->uq_flags & UQ_BAD_AUDIO))
1.94      kent      385:                return UMATCH_NONE;
1.1       augustss  386:
1.94      kent      387:        return UMATCH_IFACECLASS_IFACESUBCLASS;
1.1       augustss  388: }
                    389:
                    390: USB_ATTACH(uaudio)
                    391: {
1.99.2.4  yamt      392:        USB_IFATTACH_START(uaudio, sc, uaa);
1.1       augustss  393:        usb_interface_descriptor_t *id;
                    394:        usb_config_descriptor_t *cdesc;
1.98      augustss  395:        char *devinfop;
1.9       augustss  396:        usbd_status err;
1.37      mycroft   397:        int i, j, found;
1.1       augustss  398:
1.98      augustss  399:        devinfop = usbd_devinfo_alloc(uaa->device, 0);
                    400:        printf(": %s\n", devinfop);
                    401:        usbd_devinfo_free(devinfop);
1.1       augustss  402:
                    403:        sc->sc_udev = uaa->device;
                    404:
                    405:        cdesc = usbd_get_config_descriptor(sc->sc_udev);
1.13      augustss  406:        if (cdesc == NULL) {
                    407:                printf("%s: failed to get configuration descriptor\n",
                    408:                       USBDEVNAME(sc->sc_dev));
1.1       augustss  409:                USB_ATTACH_ERROR_RETURN;
1.13      augustss  410:        }
1.1       augustss  411:
1.9       augustss  412:        err = uaudio_identify(sc, cdesc);
                    413:        if (err) {
1.1       augustss  414:                printf("%s: audio descriptors make no sense, error=%d\n",
1.9       augustss  415:                       USBDEVNAME(sc->sc_dev), err);
1.1       augustss  416:                USB_ATTACH_ERROR_RETURN;
                    417:        }
                    418:
                    419:        sc->sc_ac_ifaceh = uaa->iface;
                    420:        /* Pick up the AS interface. */
                    421:        for (i = 0; i < uaa->nifaces; i++) {
1.37      mycroft   422:                if (uaa->ifaces[i] == NULL)
                    423:                        continue;
                    424:                id = usbd_get_interface_descriptor(uaa->ifaces[i]);
                    425:                if (id == NULL)
                    426:                        continue;
                    427:                found = 0;
                    428:                for (j = 0; j < sc->sc_nalts; j++) {
                    429:                        if (id->bInterfaceNumber ==
                    430:                            sc->sc_alts[j].idesc->bInterfaceNumber) {
                    431:                                sc->sc_alts[j].ifaceh = uaa->ifaces[i];
                    432:                                found = 1;
1.1       augustss  433:                        }
                    434:                }
1.37      mycroft   435:                if (found)
                    436:                        uaa->ifaces[i] = NULL;
1.1       augustss  437:        }
                    438:
1.37      mycroft   439:        for (j = 0; j < sc->sc_nalts; j++) {
                    440:                if (sc->sc_alts[j].ifaceh == NULL) {
1.40      augustss  441:                        printf("%s: alt %d missing AS interface(s)\n",
                    442:                            USBDEVNAME(sc->sc_dev), j);
1.37      mycroft   443:                        USB_ATTACH_ERROR_RETURN;
                    444:                }
1.1       augustss  445:        }
                    446:
1.40      augustss  447:        printf("%s: audio rev %d.%02x\n", USBDEVNAME(sc->sc_dev),
1.7       augustss  448:               sc->sc_audio_rev >> 8, sc->sc_audio_rev & 0xff);
                    449:
1.47      jdolecek  450:        sc->sc_playchan.sc = sc->sc_recchan.sc = sc;
1.60      kent      451:        sc->sc_playchan.altidx = -1;
                    452:        sc->sc_recchan.altidx = -1;
1.8       augustss  453:
1.31      augustss  454:        if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_FRAC)
1.47      jdolecek  455:                sc->sc_altflags |= UA_NOFRAC;
1.31      augustss  456:
1.40      augustss  457: #ifndef UAUDIO_DEBUG
                    458:        if (bootverbose)
                    459: #endif
                    460:                printf("%s: %d mixer controls\n", USBDEVNAME(sc->sc_dev),
                    461:                    sc->sc_nctls);
                    462:
1.41      augustss  463:        usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
                    464:                           USBDEV(sc->sc_dev));
                    465:
1.1       augustss  466:        DPRINTF(("uaudio_attach: doing audio_attach_mi\n"));
1.23      augustss  467: #if defined(__OpenBSD__)
                    468:        audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
                    469: #else
1.1       augustss  470:        sc->sc_audiodev = audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
1.23      augustss  471: #endif
1.17      augustss  472:
1.1       augustss  473:        USB_ATTACH_SUCCESS_RETURN;
                    474: }
                    475:
                    476: int
1.26      augustss  477: uaudio_activate(device_ptr_t self, enum devact act)
1.1       augustss  478: {
1.94      kent      479:        struct uaudio_softc *sc;
                    480:        int rv;
1.1       augustss  481:
1.94      kent      482:        sc = (struct uaudio_softc *)self;
                    483:        rv = 0;
1.1       augustss  484:        switch (act) {
                    485:        case DVACT_ACTIVATE:
1.94      kent      486:                return EOPNOTSUPP;
1.1       augustss  487:
                    488:        case DVACT_DEACTIVATE:
1.40      augustss  489:                if (sc->sc_audiodev != NULL)
1.2       augustss  490:                        rv = config_deactivate(sc->sc_audiodev);
1.1       augustss  491:                sc->sc_dying = 1;
                    492:                break;
                    493:        }
1.94      kent      494:        return rv;
1.1       augustss  495: }
                    496:
1.99.2.5! yamt      497: void
        !           498: uaudio_childdet(device_t self, device_t child)
        !           499: {
        !           500:        struct uaudio_softc *sc = device_private(self);
        !           501:
        !           502:        KASSERT(sc->sc_audiodev == child);
        !           503:        sc->sc_audiodev = NULL;
        !           504: }
        !           505:
1.1       augustss  506: int
1.99.2.5! yamt      507: uaudio_detach(device_t self, int flags)
1.1       augustss  508: {
1.99.2.5! yamt      509:        struct uaudio_softc *sc = device_private(self);
1.94      kent      510:        int rv;
1.1       augustss  511:
1.94      kent      512:        rv = 0;
1.8       augustss  513:        /* Wait for outstanding requests to complete. */
                    514:        usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
                    515:
1.9       augustss  516:        if (sc->sc_audiodev != NULL)
1.1       augustss  517:                rv = config_detach(sc->sc_audiodev, flags);
1.17      augustss  518:
                    519:        usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
                    520:                           USBDEV(sc->sc_dev));
1.1       augustss  521:
1.92      kent      522:        if (sc->sc_formats != NULL)
                    523:                free(sc->sc_formats, M_USBDEV);
                    524:        auconv_delete_encodings(sc->sc_encodings);
1.94      kent      525:        return rv;
1.1       augustss  526: }
                    527:
1.86      kent      528: Static int
1.26      augustss  529: uaudio_query_encoding(void *addr, struct audio_encoding *fp)
1.1       augustss  530: {
1.94      kent      531:        struct uaudio_softc *sc;
                    532:        int flags;
1.1       augustss  533:
1.94      kent      534:        sc = addr;
                    535:        flags = sc->sc_altflags;
1.1       augustss  536:        if (sc->sc_dying)
1.94      kent      537:                return EIO;
1.56      kent      538:
1.1       augustss  539:        if (sc->sc_nalts == 0 || flags == 0)
1.94      kent      540:                return ENXIO;
1.1       augustss  541:
1.92      kent      542:        return auconv_query_encoding(sc->sc_encodings, fp);
1.1       augustss  543: }
                    544:
1.86      kent      545: Static const usb_interface_descriptor_t *
1.99      christos  546: uaudio_find_iface(const char *tbuf, int size, int *offsp, int subtype)
1.1       augustss  547: {
1.78      kent      548:        const usb_interface_descriptor_t *d;
1.1       augustss  549:
                    550:        while (*offsp < size) {
1.99      christos  551:                d = (const void *)(tbuf + *offsp);
1.1       augustss  552:                *offsp += d->bLength;
                    553:                if (d->bDescriptorType == UDESC_INTERFACE &&
1.19      augustss  554:                    d->bInterfaceClass == UICLASS_AUDIO &&
1.1       augustss  555:                    d->bInterfaceSubClass == subtype)
1.94      kent      556:                        return d;
1.1       augustss  557:        }
1.94      kent      558:        return NULL;
1.1       augustss  559: }
                    560:
1.86      kent      561: Static void
1.26      augustss  562: uaudio_mixer_add_ctl(struct uaudio_softc *sc, struct mixerctl *mc)
1.1       augustss  563: {
1.33      augustss  564:        int res;
1.84      kent      565:        size_t len;
                    566:        struct mixerctl *nmc;
1.33      augustss  567:
1.82      kent      568:        if (mc->class < UAC_NCLASSES) {
                    569:                DPRINTF(("%s: adding %s.%s\n",
                    570:                         __func__, uac_names[mc->class], mc->ctlname));
                    571:        } else {
                    572:                DPRINTF(("%s: adding %s\n", __func__, mc->ctlname));
                    573:        }
1.84      kent      574:        len = sizeof(*mc) * (sc->sc_nctls + 1);
                    575:        nmc = malloc(len, M_USBDEV, M_NOWAIT);
1.42      christos  576:        if (nmc == NULL) {
1.1       augustss  577:                printf("uaudio_mixer_add_ctl: no memory\n");
                    578:                return;
                    579:        }
1.84      kent      580:        /* Copy old data, if there was any */
                    581:        if (sc->sc_nctls != 0) {
                    582:                memcpy(nmc, sc->sc_ctls, sizeof(*mc) * (sc->sc_nctls));
                    583:                free(sc->sc_ctls, M_USBDEV);
                    584:        }
1.42      christos  585:        sc->sc_ctls = nmc;
1.1       augustss  586:
1.33      augustss  587:        mc->delta = 0;
1.79      kent      588:        if (mc->type == MIX_ON_OFF) {
                    589:                mc->minval = 0;
                    590:                mc->maxval = 1;
                    591:        } else if (mc->type == MIX_SELECTOR) {
                    592:                ;
                    593:        } else {
1.1       augustss  594:                /* Determine min and max values. */
1.56      kent      595:                mc->minval = uaudio_signext(mc->type,
                    596:                        uaudio_get(sc, GET_MIN, UT_READ_CLASS_INTERFACE,
                    597:                                   mc->wValue[0], mc->wIndex,
1.1       augustss  598:                                   MIX_SIZE(mc->type)));
1.56      kent      599:                mc->maxval = 1 + uaudio_signext(mc->type,
1.1       augustss  600:                        uaudio_get(sc, GET_MAX, UT_READ_CLASS_INTERFACE,
                    601:                                   mc->wValue[0], mc->wIndex,
                    602:                                   MIX_SIZE(mc->type)));
1.34      augustss  603:                mc->mul = mc->maxval - mc->minval;
                    604:                if (mc->mul == 0)
                    605:                        mc->mul = 1;
1.33      augustss  606:                res = uaudio_get(sc, GET_RES, UT_READ_CLASS_INTERFACE,
                    607:                                 mc->wValue[0], mc->wIndex,
                    608:                                 MIX_SIZE(mc->type));
1.34      augustss  609:                if (res > 0)
1.69      wiz       610:                        mc->delta = (res * 255 + mc->mul/2) / mc->mul;
1.1       augustss  611:        }
                    612:
                    613:        sc->sc_ctls[sc->sc_nctls++] = *mc;
                    614:
1.4       augustss  615: #ifdef UAUDIO_DEBUG
1.1       augustss  616:        if (uaudiodebug > 2) {
                    617:                int i;
                    618:                DPRINTF(("uaudio_mixer_add_ctl: wValue=%04x",mc->wValue[0]));
                    619:                for (i = 1; i < mc->nchan; i++)
                    620:                        DPRINTF((",%04x", mc->wValue[i]));
                    621:                DPRINTF((" wIndex=%04x type=%d name='%s' unit='%s' "
                    622:                         "min=%d max=%d\n",
                    623:                         mc->wIndex, mc->type, mc->ctlname, mc->ctlunit,
                    624:                         mc->minval, mc->maxval));
                    625:        }
                    626: #endif
                    627: }
                    628:
1.86      kent      629: Static char *
1.99.2.2  yamt      630: uaudio_id_name(struct uaudio_softc *sc,
                    631:     const struct io_terminal *iot, int id)
1.1       augustss  632: {
1.99      christos  633:        static char tbuf[32];
1.94      kent      634:
1.99      christos  635:        snprintf(tbuf, sizeof(tbuf), "i%d", id);
                    636:        return tbuf;
1.1       augustss  637: }
                    638:
1.91      kent      639: #ifdef UAUDIO_DEBUG
                    640: Static void
                    641: uaudio_dump_cluster(const struct usb_audio_cluster *cl)
                    642: {
                    643:        static const char *channel_names[16] = {
                    644:                "LEFT", "RIGHT", "CENTER", "LFE",
                    645:                "LEFT_SURROUND", "RIGHT_SURROUND", "LEFT_CENTER", "RIGHT_CENTER",
                    646:                "SURROUND", "LEFT_SIDE", "RIGHT_SIDE", "TOP",
                    647:                "RESERVED12", "RESERVED13", "RESERVED14", "RESERVED15",
                    648:        };
                    649:        int cc, i, first;
                    650:
                    651:        cc = UGETW(cl->wChannelConfig);
                    652:        logprintf("cluster: bNrChannels=%u wChannelConfig=0x%.4x",
                    653:                  cl->bNrChannels, cc);
                    654:        first = TRUE;
                    655:        for (i = 0; cc != 0; i++) {
                    656:                if (cc & 1) {
                    657:                        logprintf("%c%s", first ? '<' : ',', channel_names[i]);
                    658:                        first = FALSE;
                    659:                }
                    660:                cc = cc >> 1;
                    661:        }
                    662:        logprintf("> iChannelNames=%u", cl->iChannelNames);
                    663: }
                    664: #endif
                    665:
1.86      kent      666: Static struct usb_audio_cluster
1.82      kent      667: uaudio_get_cluster(int id, const struct io_terminal *iot)
1.1       augustss  668: {
                    669:        struct usb_audio_cluster r;
1.99.2.4  yamt      670:        const uaudio_cs_descriptor_t *dp;
1.1       augustss  671:        int i;
                    672:
                    673:        for (i = 0; i < 25; i++) { /* avoid infinite loops */
1.82      kent      674:                dp = iot[id].d.desc;
1.1       augustss  675:                if (dp == 0)
                    676:                        goto bad;
                    677:                switch (dp->bDescriptorSubtype) {
                    678:                case UDESCSUB_AC_INPUT:
1.82      kent      679:                        r.bNrChannels = iot[id].d.it->bNrChannels;
                    680:                        USETW(r.wChannelConfig, UGETW(iot[id].d.it->wChannelConfig));
                    681:                        r.iChannelNames = iot[id].d.it->iChannelNames;
1.94      kent      682:                        return r;
1.1       augustss  683:                case UDESCSUB_AC_OUTPUT:
1.82      kent      684:                        id = iot[id].d.ot->bSourceId;
1.1       augustss  685:                        break;
                    686:                case UDESCSUB_AC_MIXER:
1.99      christos  687:                        r = *(const struct usb_audio_cluster *)
1.82      kent      688:                                &iot[id].d.mu->baSourceId[iot[id].d.mu->bNrInPins];
1.94      kent      689:                        return r;
1.1       augustss  690:                case UDESCSUB_AC_SELECTOR:
                    691:                        /* XXX This is not really right */
1.82      kent      692:                        id = iot[id].d.su->baSourceId[0];
1.1       augustss  693:                        break;
                    694:                case UDESCSUB_AC_FEATURE:
1.82      kent      695:                        id = iot[id].d.fu->bSourceId;
1.1       augustss  696:                        break;
                    697:                case UDESCSUB_AC_PROCESSING:
1.99      christos  698:                        r = *(const struct usb_audio_cluster *)
1.82      kent      699:                                &iot[id].d.pu->baSourceId[iot[id].d.pu->bNrInPins];
1.94      kent      700:                        return r;
1.1       augustss  701:                case UDESCSUB_AC_EXTENSION:
1.99      christos  702:                        r = *(const struct usb_audio_cluster *)
1.82      kent      703:                                &iot[id].d.eu->baSourceId[iot[id].d.eu->bNrInPins];
1.94      kent      704:                        return r;
1.1       augustss  705:                default:
                    706:                        goto bad;
                    707:                }
                    708:        }
                    709:  bad:
                    710:        printf("uaudio_get_cluster: bad data\n");
                    711:        memset(&r, 0, sizeof r);
1.94      kent      712:        return r;
1.1       augustss  713:
                    714: }
                    715:
1.86      kent      716: Static void
1.82      kent      717: uaudio_add_input(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
1.1       augustss  718: {
1.94      kent      719:        const struct usb_audio_input_terminal *d;
1.1       augustss  720:
1.94      kent      721:        d = iot[id].d.it;
1.92      kent      722: #ifdef UAUDIO_DEBUG
1.1       augustss  723:        DPRINTFN(2,("uaudio_add_input: bTerminalId=%d wTerminalType=0x%04x "
                    724:                    "bAssocTerminal=%d bNrChannels=%d wChannelConfig=%d "
                    725:                    "iChannelNames=%d iTerminal=%d\n",
                    726:                    d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal,
                    727:                    d->bNrChannels, UGETW(d->wChannelConfig),
                    728:                    d->iChannelNames, d->iTerminal));
                    729: #endif
1.92      kent      730:        /* If USB input terminal, record wChannelConfig */
                    731:        if ((UGETW(d->wTerminalType) & 0xff00) != 0x0100)
                    732:                return;
                    733:        sc->sc_channel_config = UGETW(d->wChannelConfig);
1.1       augustss  734: }
                    735:
1.86      kent      736: Static void
1.99.2.2  yamt      737: uaudio_add_output(struct uaudio_softc *sc,
                    738:     const struct io_terminal *iot, int id)
1.1       augustss  739: {
1.4       augustss  740: #ifdef UAUDIO_DEBUG
1.94      kent      741:        const struct usb_audio_output_terminal *d;
1.1       augustss  742:
1.94      kent      743:        d = iot[id].d.ot;
1.1       augustss  744:        DPRINTFN(2,("uaudio_add_output: bTerminalId=%d wTerminalType=0x%04x "
                    745:                    "bAssocTerminal=%d bSourceId=%d iTerminal=%d\n",
                    746:                    d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal,
                    747:                    d->bSourceId, d->iTerminal));
                    748: #endif
                    749: }
                    750:
1.86      kent      751: Static void
1.82      kent      752: uaudio_add_mixer(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
1.1       augustss  753: {
1.94      kent      754:        const struct usb_audio_mixer_unit *d;
1.99      christos  755:        const struct usb_audio_mixer_unit_1 *d1;
1.1       augustss  756:        int c, chs, ichs, ochs, i, o, bno, p, mo, mc, k;
1.99      christos  757:        const uByte *bm;
1.1       augustss  758:        struct mixerctl mix;
                    759:
1.94      kent      760:        d = iot[id].d.mu;
1.1       augustss  761:        DPRINTFN(2,("uaudio_add_mixer: bUnitId=%d bNrInPins=%d\n",
                    762:                    d->bUnitId, d->bNrInPins));
1.56      kent      763:
1.1       augustss  764:        /* Compute the number of input channels */
                    765:        ichs = 0;
                    766:        for (i = 0; i < d->bNrInPins; i++)
1.82      kent      767:                ichs += uaudio_get_cluster(d->baSourceId[i], iot).bNrChannels;
1.1       augustss  768:
                    769:        /* and the number of output channels */
1.99      christos  770:        d1 = (const struct usb_audio_mixer_unit_1 *)&d->baSourceId[d->bNrInPins];
1.1       augustss  771:        ochs = d1->bNrChannels;
                    772:        DPRINTFN(2,("uaudio_add_mixer: ichs=%d ochs=%d\n", ichs, ochs));
                    773:
                    774:        bm = d1->bmControls;
                    775:        mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
1.82      kent      776:        uaudio_determine_class(&iot[id], &mix);
1.1       augustss  777:        mix.type = MIX_SIGNED_16;
                    778:        mix.ctlunit = AudioNvolume;
1.99.2.1  yamt      779: #define _BIT(bno) ((bm[bno / 8] >> (7 - bno % 8)) & 1)
1.1       augustss  780:        for (p = i = 0; i < d->bNrInPins; i++) {
1.82      kent      781:                chs = uaudio_get_cluster(d->baSourceId[i], iot).bNrChannels;
1.1       augustss  782:                mc = 0;
                    783:                for (c = 0; c < chs; c++) {
                    784:                        mo = 0;
                    785:                        for (o = 0; o < ochs; o++) {
                    786:                                bno = (p + c) * ochs + o;
1.99.2.1  yamt      787:                                if (_BIT(bno))
1.1       augustss  788:                                        mo++;
                    789:                        }
                    790:                        if (mo == 1)
                    791:                                mc++;
                    792:                }
                    793:                if (mc == chs && chs <= MIX_MAX_CHAN) {
                    794:                        k = 0;
                    795:                        for (c = 0; c < chs; c++)
                    796:                                for (o = 0; o < ochs; o++) {
                    797:                                        bno = (p + c) * ochs + o;
1.99.2.1  yamt      798:                                        if (_BIT(bno))
1.56      kent      799:                                                mix.wValue[k++] =
1.1       augustss  800:                                                        MAKE(p+c+1, o+1);
                    801:                                }
1.70      itojun    802:                        snprintf(mix.ctlname, sizeof(mix.ctlname), "mix%d-%s",
1.82      kent      803:                            d->bUnitId, uaudio_id_name(sc, iot,
1.70      itojun    804:                            d->baSourceId[i]));
1.1       augustss  805:                        mix.nchan = chs;
                    806:                        uaudio_mixer_add_ctl(sc, &mix);
                    807:                } else {
                    808:                        /* XXX */
                    809:                }
1.99.2.1  yamt      810: #undef _BIT
1.1       augustss  811:                p += chs;
                    812:        }
                    813:
                    814: }
                    815:
1.86      kent      816: Static void
1.82      kent      817: uaudio_add_selector(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
1.1       augustss  818: {
1.94      kent      819:        const struct usb_audio_selector_unit *d;
1.79      kent      820:        struct mixerctl mix;
                    821:        int i, wp;
1.1       augustss  822:
1.94      kent      823:        d = iot[id].d.su;
1.1       augustss  824:        DPRINTFN(2,("uaudio_add_selector: bUnitId=%d bNrInPins=%d\n",
                    825:                    d->bUnitId, d->bNrInPins));
1.79      kent      826:        mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
                    827:        mix.wValue[0] = MAKE(0, 0);
1.82      kent      828:        uaudio_determine_class(&iot[id], &mix);
1.79      kent      829:        mix.nchan = 1;
                    830:        mix.type = MIX_SELECTOR;
                    831:        mix.ctlunit = "";
                    832:        mix.minval = 1;
                    833:        mix.maxval = d->bNrInPins;
                    834:        mix.mul = mix.maxval - mix.minval;
1.81      kent      835:        wp = snprintf(mix.ctlname, MAX_AUDIO_DEV_LEN, "sel%d-", d->bUnitId);
1.79      kent      836:        for (i = 1; i <= d->bNrInPins; i++) {
                    837:                wp += snprintf(mix.ctlname + wp, MAX_AUDIO_DEV_LEN - wp,
                    838:                               "i%d", d->baSourceId[i - 1]);
                    839:                if (wp > MAX_AUDIO_DEV_LEN - 1)
                    840:                        break;
                    841:        }
                    842:        uaudio_mixer_add_ctl(sc, &mix);
1.1       augustss  843: }
                    844:
1.82      kent      845: #ifdef UAUDIO_DEBUG
1.86      kent      846: Static const char *
1.82      kent      847: uaudio_get_terminal_name(int terminal_type)
                    848: {
1.99      christos  849:        static char tbuf[100];
1.82      kent      850:
                    851:        switch (terminal_type) {
1.87      kent      852:        /* USB terminal types */
                    853:        case UAT_UNDEFINED:     return "UAT_UNDEFINED";
1.82      kent      854:        case UAT_STREAM:        return "UAT_STREAM";
1.87      kent      855:        case UAT_VENDOR:        return "UAT_VENDOR";
                    856:        /* input terminal types */
                    857:        case UATI_UNDEFINED:    return "UATI_UNDEFINED";
1.82      kent      858:        case UATI_MICROPHONE:   return "UATI_MICROPHONE";
                    859:        case UATI_DESKMICROPHONE:       return "UATI_DESKMICROPHONE";
                    860:        case UATI_PERSONALMICROPHONE:   return "UATI_PERSONALMICROPHONE";
                    861:        case UATI_OMNIMICROPHONE:       return "UATI_OMNIMICROPHONE";
                    862:        case UATI_MICROPHONEARRAY:      return "UATI_MICROPHONEARRAY";
                    863:        case UATI_PROCMICROPHONEARR:    return "UATI_PROCMICROPHONEARR";
1.87      kent      864:        /* output terminal types */
                    865:        case UATO_UNDEFINED:    return "UATO_UNDEFINED";
1.82      kent      866:        case UATO_SPEAKER:      return "UATO_SPEAKER";
1.87      kent      867:        case UATO_HEADPHONES:   return "UATO_HEADPHONES";
                    868:        case UATO_DISPLAYAUDIO: return "UATO_DISPLAYAUDIO";
1.82      kent      869:        case UATO_DESKTOPSPEAKER:       return "UATO_DESKTOPSPEAKER";
                    870:        case UATO_ROOMSPEAKER:  return "UATO_ROOMSPEAKER";
                    871:        case UATO_COMMSPEAKER:  return "UATO_COMMSPEAKER";
                    872:        case UATO_SUBWOOFER:    return "UATO_SUBWOOFER";
1.87      kent      873:        /* bidir terminal types */
1.82      kent      874:        case UATB_UNDEFINED:    return "UATB_UNDEFINED";
                    875:        case UATB_HANDSET:      return "UATB_HANDSET";
                    876:        case UATB_HEADSET:      return "UATB_HEADSET";
                    877:        case UATB_SPEAKERPHONE: return "UATB_SPEAKERPHONE";
                    878:        case UATB_SPEAKERPHONEESUP:     return "UATB_SPEAKERPHONEESUP";
                    879:        case UATB_SPEAKERPHONEECANC:    return "UATB_SPEAKERPHONEECANC";
1.87      kent      880:        /* telephony terminal types */
1.82      kent      881:        case UATT_UNDEFINED:    return "UATT_UNDEFINED";
                    882:        case UATT_PHONELINE:    return "UATT_PHONELINE";
                    883:        case UATT_TELEPHONE:    return "UATT_TELEPHONE";
                    884:        case UATT_DOWNLINEPHONE:        return "UATT_DOWNLINEPHONE";
1.87      kent      885:        /* external terminal types */
1.82      kent      886:        case UATE_UNDEFINED:    return "UATE_UNDEFINED";
1.87      kent      887:        case UATE_ANALOGCONN:   return "UATE_ANALOGCONN";
                    888:        case UATE_LINECONN:     return "UATE_LINECONN";
                    889:        case UATE_LEGACYCONN:   return "UATE_LEGACYCONN";
                    890:        case UATE_DIGITALAUIFC: return "UATE_DIGITALAUIFC";
                    891:        case UATE_SPDIF:        return "UATE_SPDIF";
                    892:        case UATE_1394DA:       return "UATE_1394DA";
                    893:        case UATE_1394DV:       return "UATE_1394DV";
                    894:        /* embedded function terminal types */
1.82      kent      895:        case UATF_UNDEFINED:    return "UATF_UNDEFINED";
                    896:        case UATF_CALIBNOISE:   return "UATF_CALIBNOISE";
                    897:        case UATF_EQUNOISE:     return "UATF_EQUNOISE";
1.87      kent      898:        case UATF_CDPLAYER:     return "UATF_CDPLAYER";
1.82      kent      899:        case UATF_DAT:  return "UATF_DAT";
                    900:        case UATF_DCC:  return "UATF_DCC";
                    901:        case UATF_MINIDISK:     return "UATF_MINIDISK";
                    902:        case UATF_ANALOGTAPE:   return "UATF_ANALOGTAPE";
                    903:        case UATF_PHONOGRAPH:   return "UATF_PHONOGRAPH";
                    904:        case UATF_VCRAUDIO:     return "UATF_VCRAUDIO";
1.87      kent      905:        case UATF_VIDEODISCAUDIO:       return "UATF_VIDEODISCAUDIO";
                    906:        case UATF_DVDAUDIO:     return "UATF_DVDAUDIO";
                    907:        case UATF_TVTUNERAUDIO: return "UATF_TVTUNERAUDIO";
1.82      kent      908:        case UATF_SATELLITE:    return "UATF_SATELLITE";
                    909:        case UATF_CABLETUNER:   return "UATF_CABLETUNER";
                    910:        case UATF_DSS:  return "UATF_DSS";
                    911:        case UATF_RADIORECV:    return "UATF_RADIORECV";
                    912:        case UATF_RADIOXMIT:    return "UATF_RADIOXMIT";
                    913:        case UATF_MULTITRACK:   return "UATF_MULTITRACK";
1.87      kent      914:        case UATF_SYNTHESIZER:  return "UATF_SYNTHESIZER";
1.82      kent      915:        default:
1.99      christos  916:                snprintf(tbuf, sizeof(tbuf), "unknown type (0x%.4x)", terminal_type);
                    917:                return tbuf;
1.82      kent      918:        }
                    919: }
                    920: #endif
                    921:
1.86      kent      922: Static int
1.82      kent      923: uaudio_determine_class(const struct io_terminal *iot, struct mixerctl *mix)
                    924: {
                    925:        int terminal_type;
                    926:
                    927:        if (iot == NULL || iot->output == NULL) {
                    928:                mix->class = UAC_OUTPUT;
                    929:                return 0;
                    930:        }
                    931:        terminal_type = 0;
                    932:        if (iot->output->size == 1)
                    933:                terminal_type = iot->output->terminals[0];
                    934:        /*
                    935:         * If the only output terminal is USB,
                    936:         * the class is UAC_RECORD.
                    937:         */
                    938:        if ((terminal_type & 0xff00) == (UAT_UNDEFINED & 0xff00)) {
                    939:                mix->class = UAC_RECORD;
                    940:                if (iot->inputs_size == 1
                    941:                    && iot->inputs[0] != NULL
                    942:                    && iot->inputs[0]->size == 1)
                    943:                        return iot->inputs[0]->terminals[0];
                    944:                else
                    945:                        return 0;
                    946:        }
                    947:        /*
1.83      kent      948:         * If the ultimate destination of the unit is just one output
1.82      kent      949:         * terminal and the unit is connected to the output terminal
                    950:         * directly, the class is UAC_OUTPUT.
                    951:         */
                    952:        if (terminal_type != 0 && iot->direct) {
                    953:                mix->class = UAC_OUTPUT;
                    954:                return terminal_type;
                    955:        }
                    956:        /*
                    957:         * If the unit is connected to just one input terminal,
                    958:         * the class is UAC_INPUT.
                    959:         */
                    960:        if (iot->inputs_size == 1 && iot->inputs[0] != NULL
                    961:            && iot->inputs[0]->size == 1) {
                    962:                mix->class = UAC_INPUT;
                    963:                return iot->inputs[0]->terminals[0];
                    964:        }
                    965:        /*
                    966:         * Otherwise, the class is UAC_OUTPUT.
                    967:         */
                    968:        mix->class = UAC_OUTPUT;
                    969:        return terminal_type;
                    970: }
                    971:
1.86      kent      972: Static const char *
1.82      kent      973: uaudio_feature_name(const struct io_terminal *iot, struct mixerctl *mix)
                    974: {
                    975:        int terminal_type;
                    976:
                    977:        terminal_type = uaudio_determine_class(iot, mix);
                    978:        if (mix->class == UAC_RECORD && terminal_type == 0)
                    979:                return AudioNmixerout;
                    980:        DPRINTF(("%s: terminal_type=%s\n", __func__,
                    981:                 uaudio_get_terminal_name(terminal_type)));
                    982:        switch (terminal_type) {
                    983:        case UAT_STREAM:
                    984:                return AudioNdac;
                    985:
                    986:        case UATI_MICROPHONE:
                    987:        case UATI_DESKMICROPHONE:
                    988:        case UATI_PERSONALMICROPHONE:
                    989:        case UATI_OMNIMICROPHONE:
                    990:        case UATI_MICROPHONEARRAY:
                    991:        case UATI_PROCMICROPHONEARR:
                    992:                return AudioNmicrophone;
                    993:
                    994:        case UATO_SPEAKER:
                    995:        case UATO_DESKTOPSPEAKER:
                    996:        case UATO_ROOMSPEAKER:
                    997:        case UATO_COMMSPEAKER:
                    998:                return AudioNspeaker;
                    999:
                   1000:        case UATO_HEADPHONES:
                   1001:                return AudioNheadphone;
                   1002:
1.87      kent     1003:        case UATO_SUBWOOFER:
                   1004:                return AudioNlfe;
                   1005:
                   1006:        /* telephony terminal types */
                   1007:        case UATT_UNDEFINED:
                   1008:        case UATT_PHONELINE:
                   1009:        case UATT_TELEPHONE:
                   1010:        case UATT_DOWNLINEPHONE:
                   1011:                return "phone";
                   1012:
1.82      kent     1013:        case UATE_ANALOGCONN:
                   1014:        case UATE_LINECONN:
                   1015:        case UATE_LEGACYCONN:
                   1016:                return AudioNline;
                   1017:
                   1018:        case UATE_DIGITALAUIFC:
                   1019:        case UATE_SPDIF:
                   1020:        case UATE_1394DA:
                   1021:        case UATE_1394DV:
                   1022:                return AudioNaux;
                   1023:
                   1024:        case UATF_CDPLAYER:
                   1025:                return AudioNcd;
                   1026:
                   1027:        case UATF_SYNTHESIZER:
                   1028:                return AudioNfmsynth;
                   1029:
                   1030:        case UATF_VIDEODISCAUDIO:
                   1031:        case UATF_DVDAUDIO:
                   1032:        case UATF_TVTUNERAUDIO:
                   1033:                return AudioNvideo;
                   1034:
                   1035:        case UAT_UNDEFINED:
                   1036:        case UAT_VENDOR:
                   1037:        case UATI_UNDEFINED:
                   1038: /* output terminal types */
                   1039:        case UATO_UNDEFINED:
                   1040:        case UATO_DISPLAYAUDIO:
                   1041: /* bidir terminal types */
                   1042:        case UATB_UNDEFINED:
                   1043:        case UATB_HANDSET:
                   1044:        case UATB_HEADSET:
                   1045:        case UATB_SPEAKERPHONE:
                   1046:        case UATB_SPEAKERPHONEESUP:
                   1047:        case UATB_SPEAKERPHONEECANC:
                   1048: /* external terminal types */
                   1049:        case UATE_UNDEFINED:
                   1050: /* embedded function terminal types */
                   1051:        case UATF_UNDEFINED:
                   1052:        case UATF_CALIBNOISE:
                   1053:        case UATF_EQUNOISE:
                   1054:        case UATF_DAT:
                   1055:        case UATF_DCC:
                   1056:        case UATF_MINIDISK:
                   1057:        case UATF_ANALOGTAPE:
                   1058:        case UATF_PHONOGRAPH:
                   1059:        case UATF_VCRAUDIO:
                   1060:        case UATF_SATELLITE:
                   1061:        case UATF_CABLETUNER:
                   1062:        case UATF_DSS:
                   1063:        case UATF_RADIORECV:
                   1064:        case UATF_RADIOXMIT:
                   1065:        case UATF_MULTITRACK:
                   1066:        case 0xffff:
                   1067:        default:
                   1068:                DPRINTF(("%s: 'master' for 0x%.4x\n", __func__, terminal_type));
                   1069:                return AudioNmaster;
                   1070:        }
                   1071:        return AudioNmaster;
                   1072: }
                   1073:
1.86      kent     1074: Static void
1.82      kent     1075: uaudio_add_feature(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
1.1       augustss 1076: {
1.94      kent     1077:        const struct usb_audio_feature_unit *d;
                   1078:        const uByte *ctls;
                   1079:        int ctlsize;
                   1080:        int nchan;
1.1       augustss 1081:        u_int fumask, mmask, cmask;
                   1082:        struct mixerctl mix;
                   1083:        int chan, ctl, i, unit;
1.82      kent     1084:        const char *mixername;
1.1       augustss 1085:
                   1086: #define GET(i) (ctls[(i)*ctlsize] | \
                   1087:                (ctlsize > 1 ? ctls[(i)*ctlsize+1] << 8 : 0))
1.94      kent     1088:        d = iot[id].d.fu;
                   1089:        ctls = d->bmaControls;
                   1090:        ctlsize = d->bControlSize;
                   1091:        nchan = (d->bLength - 7) / ctlsize;
1.1       augustss 1092:        mmask = GET(0);
                   1093:        /* Figure out what we can control */
                   1094:        for (cmask = 0, chan = 1; chan < nchan; chan++) {
                   1095:                DPRINTFN(9,("uaudio_add_feature: chan=%d mask=%x\n",
                   1096:                            chan, GET(chan)));
                   1097:                cmask |= GET(chan);
                   1098:        }
                   1099:
1.82      kent     1100:        DPRINTFN(1,("uaudio_add_feature: bUnitId=%d, "
1.56      kent     1101:                    "%d channels, mmask=0x%04x, cmask=0x%04x\n",
1.82      kent     1102:                    d->bUnitId, nchan, mmask, cmask));
1.1       augustss 1103:
                   1104:        if (nchan > MIX_MAX_CHAN)
                   1105:                nchan = MIX_MAX_CHAN;
                   1106:        unit = d->bUnitId;
                   1107:        mix.wIndex = MAKE(unit, sc->sc_ac_iface);
                   1108:        for (ctl = MUTE_CONTROL; ctl < LOUDNESS_CONTROL; ctl++) {
                   1109:                fumask = FU_MASK(ctl);
                   1110:                DPRINTFN(4,("uaudio_add_feature: ctl=%d fumask=0x%04x\n",
                   1111:                            ctl, fumask));
                   1112:                if (mmask & fumask) {
                   1113:                        mix.nchan = 1;
                   1114:                        mix.wValue[0] = MAKE(ctl, 0);
                   1115:                } else if (cmask & fumask) {
                   1116:                        mix.nchan = nchan - 1;
                   1117:                        for (i = 1; i < nchan; i++) {
                   1118:                                if (GET(i) & fumask)
                   1119:                                        mix.wValue[i-1] = MAKE(ctl, i);
                   1120:                                else
                   1121:                                        mix.wValue[i-1] = -1;
                   1122:                        }
                   1123:                } else {
                   1124:                        continue;
                   1125:                }
                   1126: #undef GET
1.82      kent     1127:                mixername = uaudio_feature_name(&iot[id], &mix);
1.1       augustss 1128:                switch (ctl) {
                   1129:                case MUTE_CONTROL:
                   1130:                        mix.type = MIX_ON_OFF;
1.63      augustss 1131:                        mix.ctlunit = "";
1.70      itojun   1132:                        snprintf(mix.ctlname, sizeof(mix.ctlname),
1.82      kent     1133:                                 "%s.%s", mixername, AudioNmute);
1.1       augustss 1134:                        break;
                   1135:                case VOLUME_CONTROL:
                   1136:                        mix.type = MIX_SIGNED_16;
1.63      augustss 1137:                        mix.ctlunit = AudioNvolume;
1.82      kent     1138:                        strlcpy(mix.ctlname, mixername, sizeof(mix.ctlname));
1.1       augustss 1139:                        break;
                   1140:                case BASS_CONTROL:
                   1141:                        mix.type = MIX_SIGNED_8;
1.63      augustss 1142:                        mix.ctlunit = AudioNbass;
1.70      itojun   1143:                        snprintf(mix.ctlname, sizeof(mix.ctlname),
1.82      kent     1144:                                 "%s.%s", mixername, AudioNbass);
1.1       augustss 1145:                        break;
                   1146:                case MID_CONTROL:
                   1147:                        mix.type = MIX_SIGNED_8;
1.63      augustss 1148:                        mix.ctlunit = AudioNmid;
1.70      itojun   1149:                        snprintf(mix.ctlname, sizeof(mix.ctlname),
1.82      kent     1150:                                 "%s.%s", mixername, AudioNmid);
1.1       augustss 1151:                        break;
                   1152:                case TREBLE_CONTROL:
                   1153:                        mix.type = MIX_SIGNED_8;
1.63      augustss 1154:                        mix.ctlunit = AudioNtreble;
1.70      itojun   1155:                        snprintf(mix.ctlname, sizeof(mix.ctlname),
1.82      kent     1156:                                 "%s.%s", mixername, AudioNtreble);
1.1       augustss 1157:                        break;
                   1158:                case GRAPHIC_EQUALIZER_CONTROL:
1.7       augustss 1159:                        continue; /* XXX don't add anything */
1.1       augustss 1160:                        break;
                   1161:                case AGC_CONTROL:
                   1162:                        mix.type = MIX_ON_OFF;
                   1163:                        mix.ctlunit = "";
1.82      kent     1164:                        snprintf(mix.ctlname, sizeof(mix.ctlname), "%s.%s",
                   1165:                                 mixername, AudioNagc);
1.1       augustss 1166:                        break;
                   1167:                case DELAY_CONTROL:
                   1168:                        mix.type = MIX_UNSIGNED_16;
1.82      kent     1169:                        mix.ctlunit = "4 ms";
1.70      itojun   1170:                        snprintf(mix.ctlname, sizeof(mix.ctlname),
1.82      kent     1171:                                 "%s.%s", mixername, AudioNdelay);
1.1       augustss 1172:                        break;
                   1173:                case BASS_BOOST_CONTROL:
                   1174:                        mix.type = MIX_ON_OFF;
1.82      kent     1175:                        mix.ctlunit = "";
1.70      itojun   1176:                        snprintf(mix.ctlname, sizeof(mix.ctlname),
1.82      kent     1177:                                 "%s.%s", mixername, AudioNbassboost);
1.1       augustss 1178:                        break;
                   1179:                case LOUDNESS_CONTROL:
                   1180:                        mix.type = MIX_ON_OFF;
1.82      kent     1181:                        mix.ctlunit = "";
1.70      itojun   1182:                        snprintf(mix.ctlname, sizeof(mix.ctlname),
1.82      kent     1183:                                 "%s.%s", mixername, AudioNloudness);
1.1       augustss 1184:                        break;
                   1185:                }
                   1186:                uaudio_mixer_add_ctl(sc, &mix);
                   1187:        }
                   1188: }
                   1189:
1.86      kent     1190: Static void
1.78      kent     1191: uaudio_add_processing_updown(struct uaudio_softc *sc,
1.82      kent     1192:                             const struct io_terminal *iot, int id)
1.78      kent     1193: {
1.94      kent     1194:        const struct usb_audio_processing_unit *d;
                   1195:        const struct usb_audio_processing_unit_1 *d1;
                   1196:        const struct usb_audio_processing_unit_updown *ud;
1.16      augustss 1197:        struct mixerctl mix;
                   1198:        int i;
                   1199:
1.94      kent     1200:        d = iot[id].d.pu;
                   1201:        d1 = (const struct usb_audio_processing_unit_1 *)
                   1202:            &d->baSourceId[d->bNrInPins];
                   1203:        ud = (const struct usb_audio_processing_unit_updown *)
                   1204:            &d1->bmControls[d1->bControlSize];
1.16      augustss 1205:        DPRINTFN(2,("uaudio_add_processing_updown: bUnitId=%d bNrModes=%d\n",
                   1206:                    d->bUnitId, ud->bNrModes));
                   1207:
                   1208:        if (!(d1->bmControls[0] & UA_PROC_MASK(UD_MODE_SELECT_CONTROL))) {
                   1209:                DPRINTF(("uaudio_add_processing_updown: no mode select\n"));
                   1210:                return;
                   1211:        }
                   1212:
                   1213:        mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
                   1214:        mix.nchan = 1;
                   1215:        mix.wValue[0] = MAKE(UD_MODE_SELECT_CONTROL, 0);
1.82      kent     1216:        uaudio_determine_class(&iot[id], &mix);
1.16      augustss 1217:        mix.type = MIX_ON_OFF;  /* XXX */
                   1218:        mix.ctlunit = "";
1.70      itojun   1219:        snprintf(mix.ctlname, sizeof(mix.ctlname), "pro%d-mode", d->bUnitId);
1.16      augustss 1220:
                   1221:        for (i = 0; i < ud->bNrModes; i++) {
                   1222:                DPRINTFN(2,("uaudio_add_processing_updown: i=%d bm=0x%x\n",
                   1223:                            i, UGETW(ud->waModes[i])));
                   1224:                /* XXX */
                   1225:        }
                   1226:        uaudio_mixer_add_ctl(sc, &mix);
                   1227: }
                   1228:
1.86      kent     1229: Static void
1.82      kent     1230: uaudio_add_processing(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
1.1       augustss 1231: {
1.94      kent     1232:        const struct usb_audio_processing_unit *d;
                   1233:        const struct usb_audio_processing_unit_1 *d1;
                   1234:        int ptype;
1.15      augustss 1235:        struct mixerctl mix;
                   1236:
1.94      kent     1237:        d = iot[id].d.pu;
                   1238:        d1 = (const struct usb_audio_processing_unit_1 *)
                   1239:            &d->baSourceId[d->bNrInPins];
                   1240:        ptype = UGETW(d->wProcessType);
1.15      augustss 1241:        DPRINTFN(2,("uaudio_add_processing: wProcessType=%d bUnitId=%d "
                   1242:                    "bNrInPins=%d\n", ptype, d->bUnitId, d->bNrInPins));
                   1243:
                   1244:        if (d1->bmControls[0] & UA_PROC_ENABLE_MASK) {
                   1245:                mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
                   1246:                mix.nchan = 1;
                   1247:                mix.wValue[0] = MAKE(XX_ENABLE_CONTROL, 0);
1.82      kent     1248:                uaudio_determine_class(&iot[id], &mix);
1.15      augustss 1249:                mix.type = MIX_ON_OFF;
                   1250:                mix.ctlunit = "";
1.70      itojun   1251:                snprintf(mix.ctlname, sizeof(mix.ctlname), "pro%d.%d-enable",
                   1252:                    d->bUnitId, ptype);
1.15      augustss 1253:                uaudio_mixer_add_ctl(sc, &mix);
                   1254:        }
1.1       augustss 1255:
1.15      augustss 1256:        switch(ptype) {
                   1257:        case UPDOWNMIX_PROCESS:
1.82      kent     1258:                uaudio_add_processing_updown(sc, iot, id);
1.16      augustss 1259:                break;
1.15      augustss 1260:        case DOLBY_PROLOGIC_PROCESS:
                   1261:        case P3D_STEREO_EXTENDER_PROCESS:
                   1262:        case REVERBATION_PROCESS:
                   1263:        case CHORUS_PROCESS:
                   1264:        case DYN_RANGE_COMP_PROCESS:
                   1265:        default:
                   1266: #ifdef UAUDIO_DEBUG
                   1267:                printf("uaudio_add_processing: unit %d, type=%d not impl.\n",
                   1268:                       d->bUnitId, ptype);
1.1       augustss 1269: #endif
1.15      augustss 1270:                break;
                   1271:        }
1.1       augustss 1272: }
                   1273:
1.86      kent     1274: Static void
1.82      kent     1275: uaudio_add_extension(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
1.1       augustss 1276: {
1.94      kent     1277:        const struct usb_audio_extension_unit *d;
                   1278:        const struct usb_audio_extension_unit_1 *d1;
1.1       augustss 1279:        struct mixerctl mix;
                   1280:
1.94      kent     1281:        d = iot[id].d.eu;
                   1282:        d1 = (const struct usb_audio_extension_unit_1 *)
                   1283:            &d->baSourceId[d->bNrInPins];
1.1       augustss 1284:        DPRINTFN(2,("uaudio_add_extension: bUnitId=%d bNrInPins=%d\n",
                   1285:                    d->bUnitId, d->bNrInPins));
1.28      augustss 1286:
1.31      augustss 1287:        if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_XU)
1.28      augustss 1288:                return;
1.1       augustss 1289:
1.15      augustss 1290:        if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) {
1.1       augustss 1291:                mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
                   1292:                mix.nchan = 1;
                   1293:                mix.wValue[0] = MAKE(UA_EXT_ENABLE, 0);
1.82      kent     1294:                uaudio_determine_class(&iot[id], &mix);
1.1       augustss 1295:                mix.type = MIX_ON_OFF;
                   1296:                mix.ctlunit = "";
1.70      itojun   1297:                snprintf(mix.ctlname, sizeof(mix.ctlname), "ext%d-enable",
                   1298:                    d->bUnitId);
1.1       augustss 1299:                uaudio_mixer_add_ctl(sc, &mix);
                   1300:        }
                   1301: }
                   1302:
1.86      kent     1303: Static struct terminal_list*
1.82      kent     1304: uaudio_merge_terminal_list(const struct io_terminal *iot)
                   1305: {
                   1306:        struct terminal_list *tml;
                   1307:        uint16_t *ptm;
                   1308:        int i, len;
                   1309:
                   1310:        len = 0;
                   1311:        if (iot->inputs == NULL)
                   1312:                return NULL;
                   1313:        for (i = 0; i < iot->inputs_size; i++) {
                   1314:                if (iot->inputs[i] != NULL)
                   1315:                        len += iot->inputs[i]->size;
                   1316:        }
                   1317:        tml = malloc(TERMINAL_LIST_SIZE(len), M_TEMP, M_NOWAIT);
                   1318:        if (tml == NULL) {
                   1319:                printf("uaudio_merge_terminal_list: no memory\n");
                   1320:                return NULL;
                   1321:        }
                   1322:        tml->size = 0;
                   1323:        ptm = tml->terminals;
                   1324:        for (i = 0; i < iot->inputs_size; i++) {
                   1325:                if (iot->inputs[i] == NULL)
                   1326:                        continue;
                   1327:                if (iot->inputs[i]->size > len)
                   1328:                        break;
                   1329:                memcpy(ptm, iot->inputs[i]->terminals,
                   1330:                       iot->inputs[i]->size * sizeof(uint16_t));
                   1331:                tml->size += iot->inputs[i]->size;
                   1332:                ptm += iot->inputs[i]->size;
                   1333:                len -= iot->inputs[i]->size;
                   1334:        }
                   1335:        return tml;
                   1336: }
                   1337:
1.86      kent     1338: Static struct terminal_list *
1.82      kent     1339: uaudio_io_terminaltype(int outtype, struct io_terminal *iot, int id)
                   1340: {
                   1341:        struct terminal_list *tml;
                   1342:        struct io_terminal *it;
                   1343:        int src_id, i;
                   1344:
                   1345:        it = &iot[id];
                   1346:        if (it->output != NULL) {
                   1347:                /* already has outtype? */
                   1348:                for (i = 0; i < it->output->size; i++)
                   1349:                        if (it->output->terminals[i] == outtype)
                   1350:                                return uaudio_merge_terminal_list(it);
                   1351:                tml = malloc(TERMINAL_LIST_SIZE(it->output->size + 1),
                   1352:                             M_TEMP, M_NOWAIT);
                   1353:                if (tml == NULL) {
                   1354:                        printf("uaudio_io_terminaltype: no memory\n");
                   1355:                        return uaudio_merge_terminal_list(it);
                   1356:                }
                   1357:                memcpy(tml, it->output, TERMINAL_LIST_SIZE(it->output->size));
                   1358:                tml->terminals[it->output->size] = outtype;
                   1359:                tml->size++;
                   1360:                free(it->output, M_TEMP);
                   1361:                it->output = tml;
                   1362:                if (it->inputs != NULL) {
                   1363:                        for (i = 0; i < it->inputs_size; i++)
                   1364:                                if (it->inputs[i] != NULL)
                   1365:                                        free(it->inputs[i], M_TEMP);
                   1366:                        free(it->inputs, M_TEMP);
                   1367:                }
                   1368:                it->inputs_size = 0;
                   1369:                it->inputs = NULL;
                   1370:        } else {                /* end `iot[id] != NULL' */
                   1371:                it->inputs_size = 0;
                   1372:                it->inputs = NULL;
                   1373:                it->output = malloc(TERMINAL_LIST_SIZE(1), M_TEMP, M_NOWAIT);
                   1374:                if (it->output == NULL) {
                   1375:                        printf("uaudio_io_terminaltype: no memory\n");
                   1376:                        return NULL;
                   1377:                }
                   1378:                it->output->terminals[0] = outtype;
                   1379:                it->output->size = 1;
                   1380:                it->direct = FALSE;
                   1381:        }
                   1382:
                   1383:        switch (it->d.desc->bDescriptorSubtype) {
                   1384:        case UDESCSUB_AC_INPUT:
                   1385:                it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
                   1386:                if (it->inputs == NULL) {
                   1387:                        printf("uaudio_io_terminaltype: no memory\n");
                   1388:                        return NULL;
                   1389:                }
                   1390:                tml = malloc(TERMINAL_LIST_SIZE(1), M_TEMP, M_NOWAIT);
                   1391:                if (tml == NULL) {
                   1392:                        printf("uaudio_io_terminaltype: no memory\n");
                   1393:                        free(it->inputs, M_TEMP);
                   1394:                        it->inputs = NULL;
                   1395:                        return NULL;
                   1396:                }
                   1397:                it->inputs[0] = tml;
                   1398:                tml->terminals[0] = UGETW(it->d.it->wTerminalType);
                   1399:                tml->size = 1;
                   1400:                it->inputs_size = 1;
                   1401:                return uaudio_merge_terminal_list(it);
                   1402:        case UDESCSUB_AC_FEATURE:
                   1403:                src_id = it->d.fu->bSourceId;
                   1404:                it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
                   1405:                if (it->inputs == NULL) {
                   1406:                        printf("uaudio_io_terminaltype: no memory\n");
                   1407:                        return uaudio_io_terminaltype(outtype, iot, src_id);
                   1408:                }
                   1409:                it->inputs[0] = uaudio_io_terminaltype(outtype, iot, src_id);
                   1410:                it->inputs_size = 1;
                   1411:                return uaudio_merge_terminal_list(it);
                   1412:        case UDESCSUB_AC_OUTPUT:
                   1413:                it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
                   1414:                if (it->inputs == NULL) {
                   1415:                        printf("uaudio_io_terminaltype: no memory\n");
                   1416:                        return NULL;
                   1417:                }
                   1418:                src_id = it->d.ot->bSourceId;
                   1419:                it->inputs[0] = uaudio_io_terminaltype(outtype, iot, src_id);
                   1420:                it->inputs_size = 1;
                   1421:                iot[src_id].direct = TRUE;
                   1422:                return NULL;
                   1423:        case UDESCSUB_AC_MIXER:
                   1424:                it->inputs_size = 0;
                   1425:                it->inputs = malloc(sizeof(struct terminal_list *)
                   1426:                                    * it->d.mu->bNrInPins, M_TEMP, M_NOWAIT);
                   1427:                if (it->inputs == NULL) {
                   1428:                        printf("uaudio_io_terminaltype: no memory\n");
                   1429:                        return NULL;
                   1430:                }
                   1431:                for (i = 0; i < it->d.mu->bNrInPins; i++) {
                   1432:                        src_id = it->d.mu->baSourceId[i];
                   1433:                        it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
                   1434:                                                               src_id);
                   1435:                        it->inputs_size++;
                   1436:                }
                   1437:                return uaudio_merge_terminal_list(it);
                   1438:        case UDESCSUB_AC_SELECTOR:
                   1439:                it->inputs_size = 0;
                   1440:                it->inputs = malloc(sizeof(struct terminal_list *)
                   1441:                                    * it->d.su->bNrInPins, M_TEMP, M_NOWAIT);
                   1442:                if (it->inputs == NULL) {
                   1443:                        printf("uaudio_io_terminaltype: no memory\n");
                   1444:                        return NULL;
                   1445:                }
                   1446:                for (i = 0; i < it->d.su->bNrInPins; i++) {
                   1447:                        src_id = it->d.su->baSourceId[i];
                   1448:                        it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
                   1449:                                                               src_id);
                   1450:                        it->inputs_size++;
                   1451:                }
                   1452:                return uaudio_merge_terminal_list(it);
                   1453:        case UDESCSUB_AC_PROCESSING:
                   1454:                it->inputs_size = 0;
                   1455:                it->inputs = malloc(sizeof(struct terminal_list *)
                   1456:                                    * it->d.pu->bNrInPins, M_TEMP, M_NOWAIT);
                   1457:                if (it->inputs == NULL) {
                   1458:                        printf("uaudio_io_terminaltype: no memory\n");
                   1459:                        return NULL;
                   1460:                }
                   1461:                for (i = 0; i < it->d.pu->bNrInPins; i++) {
                   1462:                        src_id = it->d.pu->baSourceId[i];
                   1463:                        it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
                   1464:                                                               src_id);
                   1465:                        it->inputs_size++;
                   1466:                }
                   1467:                return uaudio_merge_terminal_list(it);
                   1468:        case UDESCSUB_AC_EXTENSION:
                   1469:                it->inputs_size = 0;
                   1470:                it->inputs = malloc(sizeof(struct terminal_list *)
                   1471:                                    * it->d.eu->bNrInPins, M_TEMP, M_NOWAIT);
                   1472:                if (it->inputs == NULL) {
                   1473:                        printf("uaudio_io_terminaltype: no memory\n");
                   1474:                        return NULL;
                   1475:                }
                   1476:                for (i = 0; i < it->d.eu->bNrInPins; i++) {
                   1477:                        src_id = it->d.eu->baSourceId[i];
                   1478:                        it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
                   1479:                                                               src_id);
                   1480:                        it->inputs_size++;
                   1481:                }
                   1482:                return uaudio_merge_terminal_list(it);
                   1483:        case UDESCSUB_AC_HEADER:
                   1484:        default:
                   1485:                return NULL;
                   1486:        }
                   1487: }
                   1488:
1.86      kent     1489: Static usbd_status
1.78      kent     1490: uaudio_identify(struct uaudio_softc *sc, const usb_config_descriptor_t *cdesc)
1.1       augustss 1491: {
1.9       augustss 1492:        usbd_status err;
1.1       augustss 1493:
1.9       augustss 1494:        err = uaudio_identify_ac(sc, cdesc);
                   1495:        if (err)
1.94      kent     1496:                return err;
                   1497:        return uaudio_identify_as(sc, cdesc);
1.1       augustss 1498: }
                   1499:
1.86      kent     1500: Static void
1.78      kent     1501: uaudio_add_alt(struct uaudio_softc *sc, const struct as_info *ai)
1.1       augustss 1502: {
1.84      kent     1503:        size_t len;
                   1504:        struct as_info *nai;
1.42      christos 1505:
1.84      kent     1506:        len = sizeof(*ai) * (sc->sc_nalts + 1);
                   1507:        nai = malloc(len, M_USBDEV, M_NOWAIT);
1.42      christos 1508:        if (nai == NULL) {
1.1       augustss 1509:                printf("uaudio_add_alt: no memory\n");
                   1510:                return;
                   1511:        }
1.84      kent     1512:        /* Copy old data, if there was any */
                   1513:        if (sc->sc_nalts != 0) {
                   1514:                memcpy(nai, sc->sc_alts, sizeof(*ai) * (sc->sc_nalts));
                   1515:                free(sc->sc_alts, M_USBDEV);
                   1516:        }
1.42      christos 1517:        sc->sc_alts = nai;
1.1       augustss 1518:        DPRINTFN(2,("uaudio_add_alt: adding alt=%d, enc=%d\n",
                   1519:                    ai->alt, ai->encoding));
                   1520:        sc->sc_alts[sc->sc_nalts++] = *ai;
                   1521: }
                   1522:
1.86      kent     1523: Static usbd_status
1.99      christos 1524: uaudio_process_as(struct uaudio_softc *sc, const char *tbuf, int *offsp,
1.78      kent     1525:                  int size, const usb_interface_descriptor_t *id)
1.1       augustss 1526: #define offs (*offsp)
                   1527: {
1.78      kent     1528:        const struct usb_audio_streaming_interface_descriptor *asid;
                   1529:        const struct usb_audio_streaming_type1_descriptor *asf1d;
                   1530:        const usb_endpoint_descriptor_audio_t *ed;
1.80      kent     1531:        const usb_endpoint_descriptor_audio_t *epdesc1;
1.78      kent     1532:        const struct usb_audio_streaming_endpoint_descriptor *sed;
1.1       augustss 1533:        int format, chan, prec, enc;
1.80      kent     1534:        int dir, type, sync;
1.1       augustss 1535:        struct as_info ai;
1.78      kent     1536:        const char *format_str;
1.1       augustss 1537:
1.99      christos 1538:        asid = (const void *)(tbuf + offs);
1.1       augustss 1539:        if (asid->bDescriptorType != UDESC_CS_INTERFACE ||
                   1540:            asid->bDescriptorSubtype != AS_GENERAL)
1.94      kent     1541:                return USBD_INVAL;
1.78      kent     1542:        DPRINTF(("uaudio_process_as: asid: bTerminakLink=%d wFormatTag=%d\n",
                   1543:                 asid->bTerminalLink, UGETW(asid->wFormatTag)));
1.1       augustss 1544:        offs += asid->bLength;
                   1545:        if (offs > size)
1.94      kent     1546:                return USBD_INVAL;
1.78      kent     1547:
1.99      christos 1548:        asf1d = (const void *)(tbuf + offs);
1.1       augustss 1549:        if (asf1d->bDescriptorType != UDESC_CS_INTERFACE ||
                   1550:            asf1d->bDescriptorSubtype != FORMAT_TYPE)
1.94      kent     1551:                return USBD_INVAL;
1.1       augustss 1552:        offs += asf1d->bLength;
                   1553:        if (offs > size)
1.94      kent     1554:                return USBD_INVAL;
1.1       augustss 1555:
1.3       augustss 1556:        if (asf1d->bFormatType != FORMAT_TYPE_I) {
                   1557:                printf("%s: ignored setting with type %d format\n",
                   1558:                       USBDEVNAME(sc->sc_dev), UGETW(asid->wFormatTag));
1.94      kent     1559:                return USBD_NORMAL_COMPLETION;
1.3       augustss 1560:        }
                   1561:
1.99      christos 1562:        ed = (const void *)(tbuf + offs);
1.1       augustss 1563:        if (ed->bDescriptorType != UDESC_ENDPOINT)
1.94      kent     1564:                return USBD_INVAL;
1.80      kent     1565:        DPRINTF(("uaudio_process_as: endpoint[0] bLength=%d bDescriptorType=%d "
1.5       augustss 1566:                 "bEndpointAddress=%d bmAttributes=0x%x wMaxPacketSize=%d "
                   1567:                 "bInterval=%d bRefresh=%d bSynchAddress=%d\n",
                   1568:                 ed->bLength, ed->bDescriptorType, ed->bEndpointAddress,
                   1569:                 ed->bmAttributes, UGETW(ed->wMaxPacketSize),
                   1570:                 ed->bInterval, ed->bRefresh, ed->bSynchAddress));
1.1       augustss 1571:        offs += ed->bLength;
                   1572:        if (offs > size)
1.94      kent     1573:                return USBD_INVAL;
1.5       augustss 1574:        if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
1.94      kent     1575:                return USBD_INVAL;
1.5       augustss 1576:
                   1577:        dir = UE_GET_DIR(ed->bEndpointAddress);
                   1578:        type = UE_GET_ISO_TYPE(ed->bmAttributes);
1.31      augustss 1579:        if ((usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_INP_ASYNC) &&
                   1580:            dir == UE_DIR_IN && type == UE_ISO_ADAPT)
                   1581:                type = UE_ISO_ASYNC;
                   1582:
1.40      augustss 1583:        /* We can't handle endpoints that need a sync pipe yet. */
1.80      kent     1584:        sync = FALSE;
1.78      kent     1585:        if (dir == UE_DIR_IN && type == UE_ISO_ADAPT) {
1.80      kent     1586:                sync = TRUE;
                   1587: #ifndef UAUDIO_MULTIPLE_ENDPOINTS
1.78      kent     1588:                printf("%s: ignored input endpoint of type adaptive\n",
                   1589:                       USBDEVNAME(sc->sc_dev));
1.94      kent     1590:                return USBD_NORMAL_COMPLETION;
1.80      kent     1591: #endif
1.78      kent     1592:        }
                   1593:        if (dir != UE_DIR_IN && type == UE_ISO_ASYNC) {
1.80      kent     1594:                sync = TRUE;
                   1595: #ifndef UAUDIO_MULTIPLE_ENDPOINTS
1.78      kent     1596:                printf("%s: ignored output endpoint of type async\n",
                   1597:                       USBDEVNAME(sc->sc_dev));
1.94      kent     1598:                return USBD_NORMAL_COMPLETION;
1.80      kent     1599: #endif
1.1       augustss 1600:        }
1.56      kent     1601:
1.99      christos 1602:        sed = (const void *)(tbuf + offs);
1.1       augustss 1603:        if (sed->bDescriptorType != UDESC_CS_ENDPOINT ||
                   1604:            sed->bDescriptorSubtype != AS_GENERAL)
1.94      kent     1605:                return USBD_INVAL;
1.80      kent     1606:        DPRINTF((" streadming_endpoint: offset=%d bLength=%d\n", offs, sed->bLength));
1.1       augustss 1607:        offs += sed->bLength;
                   1608:        if (offs > size)
1.94      kent     1609:                return USBD_INVAL;
1.56      kent     1610:
1.99.2.1  yamt     1611: #ifdef UAUDIO_MULTIPLE_ENDPOINTS
1.80      kent     1612:        if (sync && id->bNumEndpoints <= 1) {
                   1613:                printf("%s: a sync-pipe endpoint but no other endpoint\n",
                   1614:                       USBDEVNAME(sc->sc_dev));
                   1615:                return USBD_INVAL;
                   1616:        }
1.99.2.1  yamt     1617: #endif
1.80      kent     1618:        if (!sync && id->bNumEndpoints > 1) {
                   1619:                printf("%s: non sync-pipe endpoint but multiple endpoints\n",
                   1620:                       USBDEVNAME(sc->sc_dev));
                   1621:                return USBD_INVAL;
                   1622:        }
                   1623:        epdesc1 = NULL;
                   1624:        if (id->bNumEndpoints > 1) {
1.99      christos 1625:                epdesc1 = (const void*)(tbuf + offs);
1.80      kent     1626:                if (epdesc1->bDescriptorType != UDESC_ENDPOINT)
                   1627:                        return USBD_INVAL;
                   1628:                DPRINTF(("uaudio_process_as: endpoint[1] bLength=%d "
                   1629:                         "bDescriptorType=%d bEndpointAddress=%d "
                   1630:                         "bmAttributes=0x%x wMaxPacketSize=%d bInterval=%d "
                   1631:                         "bRefresh=%d bSynchAddress=%d\n",
                   1632:                         epdesc1->bLength, epdesc1->bDescriptorType,
                   1633:                         epdesc1->bEndpointAddress, epdesc1->bmAttributes,
                   1634:                         UGETW(epdesc1->wMaxPacketSize), epdesc1->bInterval,
                   1635:                         epdesc1->bRefresh, epdesc1->bSynchAddress));
                   1636:                offs += epdesc1->bLength;
                   1637:                if (offs > size)
                   1638:                        return USBD_INVAL;
                   1639:                if (epdesc1->bSynchAddress != 0) {
                   1640:                        printf("%s: invalid endpoint: bSynchAddress=0\n",
                   1641:                               USBDEVNAME(sc->sc_dev));
                   1642:                        return USBD_INVAL;
                   1643:                }
                   1644:                if (UE_GET_XFERTYPE(epdesc1->bmAttributes) != UE_ISOCHRONOUS) {
                   1645:                        printf("%s: invalid endpoint: bmAttributes=0x%x\n",
                   1646:                               USBDEVNAME(sc->sc_dev), epdesc1->bmAttributes);
                   1647:                        return USBD_INVAL;
                   1648:                }
                   1649:                if (epdesc1->bEndpointAddress != ed->bSynchAddress) {
                   1650:                        printf("%s: invalid endpoint addresses: "
                   1651:                               "ep[0]->bSynchAddress=0x%x "
                   1652:                               "ep[1]->bEndpointAddress=0x%x\n",
                   1653:                               USBDEVNAME(sc->sc_dev), ed->bSynchAddress,
                   1654:                               epdesc1->bEndpointAddress);
                   1655:                        return USBD_INVAL;
                   1656:                }
                   1657:                /* UE_GET_ADDR(epdesc1->bEndpointAddress), and epdesc1->bRefresh */
                   1658:        }
                   1659:
1.3       augustss 1660:        format = UGETW(asid->wFormatTag);
1.1       augustss 1661:        chan = asf1d->bNrChannels;
                   1662:        prec = asf1d->bBitResolution;
1.51      kent     1663:        if (prec != 8 && prec != 16 && prec != 24) {
1.1       augustss 1664:                printf("%s: ignored setting with precision %d\n",
                   1665:                       USBDEVNAME(sc->sc_dev), prec);
1.94      kent     1666:                return USBD_NORMAL_COMPLETION;
1.1       augustss 1667:        }
                   1668:        switch (format) {
1.3       augustss 1669:        case UA_FMT_PCM:
1.51      kent     1670:                if (prec == 8) {
                   1671:                        sc->sc_altflags |= HAS_8;
                   1672:                } else if (prec == 16) {
                   1673:                        sc->sc_altflags |= HAS_16;
                   1674:                } else if (prec == 24) {
                   1675:                        sc->sc_altflags |= HAS_24;
                   1676:                }
1.5       augustss 1677:                enc = AUDIO_ENCODING_SLINEAR_LE;
1.78      kent     1678:                format_str = "pcm";
1.1       augustss 1679:                break;
1.3       augustss 1680:        case UA_FMT_PCM8:
1.5       augustss 1681:                enc = AUDIO_ENCODING_ULINEAR_LE;
1.1       augustss 1682:                sc->sc_altflags |= HAS_8U;
1.78      kent     1683:                format_str = "pcm8";
1.1       augustss 1684:                break;
1.3       augustss 1685:        case UA_FMT_ALAW:
1.5       augustss 1686:                enc = AUDIO_ENCODING_ALAW;
1.1       augustss 1687:                sc->sc_altflags |= HAS_ALAW;
1.78      kent     1688:                format_str = "alaw";
1.1       augustss 1689:                break;
1.3       augustss 1690:        case UA_FMT_MULAW:
1.5       augustss 1691:                enc = AUDIO_ENCODING_ULAW;
1.1       augustss 1692:                sc->sc_altflags |= HAS_MULAW;
1.78      kent     1693:                format_str = "mulaw";
1.1       augustss 1694:                break;
1.80      kent     1695:        case UA_FMT_IEEE_FLOAT:
1.1       augustss 1696:        default:
                   1697:                printf("%s: ignored setting with format %d\n",
                   1698:                       USBDEVNAME(sc->sc_dev), format);
1.94      kent     1699:                return USBD_NORMAL_COMPLETION;
1.1       augustss 1700:        }
1.78      kent     1701: #ifdef UAUDIO_DEBUG
                   1702:        printf("%s: %s: %dch, %d/%dbit, %s,", USBDEVNAME(sc->sc_dev),
                   1703:               dir == UE_DIR_IN ? "recording" : "playback",
                   1704:               chan, prec, asf1d->bSubFrameSize * 8, format_str);
                   1705:        if (asf1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
                   1706:                printf(" %d-%dHz\n", UA_SAMP_LO(asf1d), UA_SAMP_HI(asf1d));
                   1707:        } else {
                   1708:                int r;
                   1709:                printf(" %d", UA_GETSAMP(asf1d, 0));
                   1710:                for (r = 1; r < asf1d->bSamFreqType; r++)
                   1711:                        printf(",%d", UA_GETSAMP(asf1d, r));
                   1712:                printf("Hz\n");
                   1713:        }
                   1714: #endif
1.1       augustss 1715:        ai.alt = id->bAlternateSetting;
                   1716:        ai.encoding = enc;
1.50      kent     1717:        ai.attributes = sed->bmAttributes;
1.1       augustss 1718:        ai.idesc = id;
                   1719:        ai.edesc = ed;
1.80      kent     1720:        ai.edesc1 = epdesc1;
1.1       augustss 1721:        ai.asf1desc = asf1d;
1.50      kent     1722:        ai.sc_busy = 0;
1.99.2.1  yamt     1723:        ai.aformat = NULL;
                   1724:        ai.ifaceh = NULL;
1.1       augustss 1725:        uaudio_add_alt(sc, &ai);
1.50      kent     1726: #ifdef UAUDIO_DEBUG
1.78      kent     1727:        if (ai.attributes & UA_SED_FREQ_CONTROL)
                   1728:                DPRINTFN(1, ("uaudio_process_as:  FREQ_CONTROL\n"));
                   1729:        if (ai.attributes & UA_SED_PITCH_CONTROL)
                   1730:                DPRINTFN(1, ("uaudio_process_as:  PITCH_CONTROL\n"));
1.50      kent     1731: #endif
1.47      jdolecek 1732:        sc->sc_mode |= (dir == UE_DIR_OUT) ? AUMODE_PLAY : AUMODE_RECORD;
                   1733:
1.94      kent     1734:        return USBD_NORMAL_COMPLETION;
1.1       augustss 1735: }
                   1736: #undef offs
1.56      kent     1737:
1.86      kent     1738: Static usbd_status
1.78      kent     1739: uaudio_identify_as(struct uaudio_softc *sc,
                   1740:                   const usb_config_descriptor_t *cdesc)
1.1       augustss 1741: {
1.78      kent     1742:        const usb_interface_descriptor_t *id;
1.99      christos 1743:        const char *tbuf;
1.92      kent     1744:        struct audio_format *auf;
                   1745:        const struct usb_audio_streaming_type1_descriptor *t1desc;
1.1       augustss 1746:        int size, offs;
1.92      kent     1747:        int i, j;
1.1       augustss 1748:
                   1749:        size = UGETW(cdesc->wTotalLength);
1.99      christos 1750:        tbuf = (const char *)cdesc;
1.1       augustss 1751:
                   1752:        /* Locate the AudioStreaming interface descriptor. */
                   1753:        offs = 0;
1.99      christos 1754:        id = uaudio_find_iface(tbuf, size, &offs, UISUBCLASS_AUDIOSTREAM);
1.9       augustss 1755:        if (id == NULL)
1.94      kent     1756:                return USBD_INVAL;
1.1       augustss 1757:
                   1758:        /* Loop through all the alternate settings. */
                   1759:        while (offs <= size) {
1.80      kent     1760:                DPRINTFN(2, ("uaudio_identify: interface=%d offset=%d\n",
                   1761:                    id->bInterfaceNumber, offs));
1.1       augustss 1762:                switch (id->bNumEndpoints) {
                   1763:                case 0:
                   1764:                        DPRINTFN(2, ("uaudio_identify: AS null alt=%d\n",
                   1765:                                     id->bAlternateSetting));
                   1766:                        sc->sc_nullalt = id->bAlternateSetting;
                   1767:                        break;
                   1768:                case 1:
1.80      kent     1769: #ifdef UAUDIO_MULTIPLE_ENDPOINTS
                   1770:                case 2:
                   1771: #endif
1.99      christos 1772:                        uaudio_process_as(sc, tbuf, &offs, size, id);
1.1       augustss 1773:                        break;
                   1774:                default:
                   1775:                        printf("%s: ignored audio interface with %d "
                   1776:                               "endpoints\n",
                   1777:                               USBDEVNAME(sc->sc_dev), id->bNumEndpoints);
                   1778:                        break;
                   1779:                }
1.99      christos 1780:                id = uaudio_find_iface(tbuf, size, &offs,UISUBCLASS_AUDIOSTREAM);
1.9       augustss 1781:                if (id == NULL)
1.1       augustss 1782:                        break;
                   1783:        }
                   1784:        if (offs > size)
1.94      kent     1785:                return USBD_INVAL;
1.1       augustss 1786:        DPRINTF(("uaudio_identify_as: %d alts available\n", sc->sc_nalts));
1.47      jdolecek 1787:
1.74      mycroft  1788:        if (sc->sc_mode == 0) {
1.56      kent     1789:                printf("%s: no usable endpoint found\n",
1.5       augustss 1790:                       USBDEVNAME(sc->sc_dev));
1.94      kent     1791:                return USBD_INVAL;
1.5       augustss 1792:        }
1.47      jdolecek 1793:
1.92      kent     1794:        /* build audio_format array */
                   1795:        sc->sc_formats = malloc(sizeof(struct audio_format) * sc->sc_nalts,
                   1796:                                M_USBDEV, M_NOWAIT);
                   1797:        if (sc->sc_formats == NULL)
                   1798:                return USBD_NOMEM;
                   1799:        sc->sc_nformats = sc->sc_nalts;
                   1800:        for (i = 0; i < sc->sc_nalts; i++) {
                   1801:                auf = &sc->sc_formats[i];
                   1802:                t1desc = sc->sc_alts[i].asf1desc;
                   1803:                auf->driver_data = NULL;
                   1804:                if (UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress) == UE_DIR_OUT)
                   1805:                        auf->mode = AUMODE_PLAY;
                   1806:                else
                   1807:                        auf->mode = AUMODE_RECORD;
                   1808:                auf->encoding = sc->sc_alts[i].encoding;
1.93      kent     1809:                auf->validbits = t1desc->bBitResolution;
                   1810:                auf->precision = t1desc->bSubFrameSize * 8;
1.92      kent     1811:                auf->channels = t1desc->bNrChannels;
                   1812:                auf->channel_mask = sc->sc_channel_config;
                   1813:                auf->frequency_type = t1desc->bSamFreqType;
                   1814:                if (t1desc->bSamFreqType == UA_SAMP_CONTNUOUS) {
                   1815:                        auf->frequency[0] = UA_SAMP_LO(t1desc);
                   1816:                        auf->frequency[1] = UA_SAMP_HI(t1desc);
                   1817:                } else {
                   1818:                        for (j = 0; j  < t1desc->bSamFreqType; j++) {
                   1819:                                if (j >= AUFMT_MAX_FREQUENCIES) {
                   1820:                                        printf("%s: please increase "
                   1821:                                               "AUFMT_MAX_FREQUENCIES to %d\n",
                   1822:                                               __func__, t1desc->bSamFreqType);
                   1823:                                        break;
                   1824:                                }
                   1825:                                auf->frequency[j] = UA_GETSAMP(t1desc, j);
                   1826:                        }
                   1827:                }
                   1828:                sc->sc_alts[i].aformat = auf;
                   1829:        }
                   1830:
                   1831:        if (0 != auconv_create_encodings(sc->sc_formats, sc->sc_nformats,
                   1832:                                         &sc->sc_encodings)) {
                   1833:                free(sc->sc_formats, M_DEVBUF);
                   1834:                sc->sc_formats = NULL;
                   1835:                return ENOMEM;
                   1836:        }
                   1837:
1.94      kent     1838:        return USBD_NORMAL_COMPLETION;
1.1       augustss 1839: }
                   1840:
1.86      kent     1841: Static usbd_status
1.78      kent     1842: uaudio_identify_ac(struct uaudio_softc *sc, const usb_config_descriptor_t *cdesc)
1.1       augustss 1843: {
1.82      kent     1844:        struct io_terminal* iot;
1.78      kent     1845:        const usb_interface_descriptor_t *id;
                   1846:        const struct usb_audio_control_descriptor *acdp;
1.99.2.4  yamt     1847:        const uaudio_cs_descriptor_t *dp;
1.82      kent     1848:        const struct usb_audio_output_terminal *pot;
                   1849:        struct terminal_list *tml;
1.99      christos 1850:        const char *tbuf, *ibuf, *ibufend;
1.82      kent     1851:        int size, offs, aclen, ndps, i, j;
1.1       augustss 1852:
                   1853:        size = UGETW(cdesc->wTotalLength);
1.99      christos 1854:        tbuf = (const char *)cdesc;
1.1       augustss 1855:
                   1856:        /* Locate the AudioControl interface descriptor. */
                   1857:        offs = 0;
1.99      christos 1858:        id = uaudio_find_iface(tbuf, size, &offs, UISUBCLASS_AUDIOCONTROL);
1.14      augustss 1859:        if (id == NULL)
1.94      kent     1860:                return USBD_INVAL;
1.1       augustss 1861:        if (offs + sizeof *acdp > size)
1.94      kent     1862:                return USBD_INVAL;
1.1       augustss 1863:        sc->sc_ac_iface = id->bInterfaceNumber;
1.82      kent     1864:        DPRINTFN(2,("uaudio_identify_ac: AC interface is %d\n", sc->sc_ac_iface));
1.1       augustss 1865:
                   1866:        /* A class-specific AC interface header should follow. */
1.99      christos 1867:        ibuf = tbuf + offs;
1.78      kent     1868:        acdp = (const struct usb_audio_control_descriptor *)ibuf;
1.1       augustss 1869:        if (acdp->bDescriptorType != UDESC_CS_INTERFACE ||
                   1870:            acdp->bDescriptorSubtype != UDESCSUB_AC_HEADER)
1.94      kent     1871:                return USBD_INVAL;
1.1       augustss 1872:        aclen = UGETW(acdp->wTotalLength);
                   1873:        if (offs + aclen > size)
1.94      kent     1874:                return USBD_INVAL;
1.5       augustss 1875:
1.1       augustss 1876:        if (!(usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_BAD_ADC) &&
                   1877:             UGETW(acdp->bcdADC) != UAUDIO_VERSION)
1.94      kent     1878:                return USBD_INVAL;
1.1       augustss 1879:
1.7       augustss 1880:        sc->sc_audio_rev = UGETW(acdp->bcdADC);
1.82      kent     1881:        DPRINTFN(2,("uaudio_identify_ac: found AC header, vers=%03x, len=%d\n",
1.7       augustss 1882:                 sc->sc_audio_rev, aclen));
1.1       augustss 1883:
                   1884:        sc->sc_nullalt = -1;
                   1885:
                   1886:        /* Scan through all the AC specific descriptors */
                   1887:        ibufend = ibuf + aclen;
1.99.2.4  yamt     1888:        dp = (const uaudio_cs_descriptor_t *)ibuf;
1.1       augustss 1889:        ndps = 0;
1.82      kent     1890:        iot = malloc(sizeof(struct io_terminal) * 256, M_TEMP, M_NOWAIT | M_ZERO);
                   1891:        if (iot == NULL) {
                   1892:                printf("%s: no memory\n", __func__);
                   1893:                return USBD_NOMEM;
                   1894:        }
1.1       augustss 1895:        for (;;) {
                   1896:                ibuf += dp->bLength;
                   1897:                if (ibuf >= ibufend)
                   1898:                        break;
1.99.2.4  yamt     1899:                dp = (const uaudio_cs_descriptor_t *)ibuf;
1.97      martin   1900:                if (ibuf + dp->bLength > ibufend) {
                   1901:                        free(iot, M_TEMP);
1.94      kent     1902:                        return USBD_INVAL;
1.97      martin   1903:                }
1.1       augustss 1904:                if (dp->bDescriptorType != UDESC_CS_INTERFACE) {
1.82      kent     1905:                        printf("uaudio_identify_ac: skip desc type=0x%02x\n",
1.1       augustss 1906:                               dp->bDescriptorType);
                   1907:                        continue;
                   1908:                }
1.82      kent     1909:                i = ((const struct usb_audio_input_terminal *)dp)->bTerminalId;
                   1910:                iot[i].d.desc = dp;
1.1       augustss 1911:                if (i > ndps)
                   1912:                        ndps = i;
                   1913:        }
                   1914:        ndps++;
                   1915:
1.82      kent     1916:        /* construct io_terminal */
                   1917:        for (i = 0; i < ndps; i++) {
                   1918:                dp = iot[i].d.desc;
                   1919:                if (dp == NULL)
                   1920:                        continue;
                   1921:                if (dp->bDescriptorSubtype != UDESCSUB_AC_OUTPUT)
                   1922:                        continue;
                   1923:                pot = iot[i].d.ot;
                   1924:                tml = uaudio_io_terminaltype(UGETW(pot->wTerminalType), iot, i);
                   1925:                if (tml != NULL)
                   1926:                        free(tml, M_TEMP);
                   1927:        }
                   1928:
                   1929: #ifdef UAUDIO_DEBUG
                   1930:        for (i = 0; i < 256; i++) {
1.91      kent     1931:                struct usb_audio_cluster cluster;
                   1932:
1.82      kent     1933:                if (iot[i].d.desc == NULL)
                   1934:                        continue;
1.89      kent     1935:                logprintf("id %d:\t", i);
1.82      kent     1936:                switch (iot[i].d.desc->bDescriptorSubtype) {
                   1937:                case UDESCSUB_AC_INPUT:
1.89      kent     1938:                        logprintf("AC_INPUT type=%s\n", uaudio_get_terminal_name
                   1939:                                  (UGETW(iot[i].d.it->wTerminalType)));
1.91      kent     1940:                        logprintf("\t");
                   1941:                        cluster = uaudio_get_cluster(i, iot);
                   1942:                        uaudio_dump_cluster(&cluster);
                   1943:                        logprintf("\n");
1.82      kent     1944:                        break;
                   1945:                case UDESCSUB_AC_OUTPUT:
1.89      kent     1946:                        logprintf("AC_OUTPUT type=%s ", uaudio_get_terminal_name
                   1947:                                  (UGETW(iot[i].d.ot->wTerminalType)));
                   1948:                        logprintf("src=%d\n", iot[i].d.ot->bSourceId);
1.82      kent     1949:                        break;
                   1950:                case UDESCSUB_AC_MIXER:
1.89      kent     1951:                        logprintf("AC_MIXER src=");
1.82      kent     1952:                        for (j = 0; j < iot[i].d.mu->bNrInPins; j++)
1.89      kent     1953:                                logprintf("%d ", iot[i].d.mu->baSourceId[j]);
1.91      kent     1954:                        logprintf("\n\t");
                   1955:                        cluster = uaudio_get_cluster(i, iot);
                   1956:                        uaudio_dump_cluster(&cluster);
1.89      kent     1957:                        logprintf("\n");
1.82      kent     1958:                        break;
                   1959:                case UDESCSUB_AC_SELECTOR:
1.89      kent     1960:                        logprintf("AC_SELECTOR src=");
1.82      kent     1961:                        for (j = 0; j < iot[i].d.su->bNrInPins; j++)
1.89      kent     1962:                                logprintf("%d ", iot[i].d.su->baSourceId[j]);
                   1963:                        logprintf("\n");
1.82      kent     1964:                        break;
                   1965:                case UDESCSUB_AC_FEATURE:
1.89      kent     1966:                        logprintf("AC_FEATURE src=%d\n", iot[i].d.fu->bSourceId);
1.82      kent     1967:                        break;
                   1968:                case UDESCSUB_AC_PROCESSING:
1.89      kent     1969:                        logprintf("AC_PROCESSING src=");
1.82      kent     1970:                        for (j = 0; j < iot[i].d.pu->bNrInPins; j++)
1.89      kent     1971:                                logprintf("%d ", iot[i].d.pu->baSourceId[j]);
1.91      kent     1972:                        logprintf("\n\t");
                   1973:                        cluster = uaudio_get_cluster(i, iot);
                   1974:                        uaudio_dump_cluster(&cluster);
1.89      kent     1975:                        logprintf("\n");
1.82      kent     1976:                        break;
                   1977:                case UDESCSUB_AC_EXTENSION:
1.89      kent     1978:                        logprintf("AC_EXTENSION src=");
1.82      kent     1979:                        for (j = 0; j < iot[i].d.eu->bNrInPins; j++)
1.89      kent     1980:                                logprintf("%d ", iot[i].d.eu->baSourceId[j]);
1.91      kent     1981:                        logprintf("\n\t");
                   1982:                        cluster = uaudio_get_cluster(i, iot);
                   1983:                        uaudio_dump_cluster(&cluster);
1.89      kent     1984:                        logprintf("\n");
1.82      kent     1985:                        break;
                   1986:                default:
1.89      kent     1987:                        logprintf("unknown audio control (subtype=%d)\n",
                   1988:                                  iot[i].d.desc->bDescriptorSubtype);
1.82      kent     1989:                }
                   1990:                for (j = 0; j < iot[i].inputs_size; j++) {
                   1991:                        int k;
1.89      kent     1992:                        logprintf("\tinput%d: ", j);
1.82      kent     1993:                        tml = iot[i].inputs[j];
                   1994:                        if (tml == NULL) {
1.89      kent     1995:                                logprintf("NULL\n");
1.82      kent     1996:                                continue;
                   1997:                        }
                   1998:                        for (k = 0; k < tml->size; k++)
1.89      kent     1999:                                logprintf("%s ", uaudio_get_terminal_name
                   2000:                                          (tml->terminals[k]));
                   2001:                        logprintf("\n");
1.82      kent     2002:                }
1.89      kent     2003:                logprintf("\toutput: ");
1.82      kent     2004:                tml = iot[i].output;
                   2005:                for (j = 0; j < tml->size; j++)
1.89      kent     2006:                        logprintf("%s ", uaudio_get_terminal_name(tml->terminals[j]));
                   2007:                logprintf("\n");
1.82      kent     2008:        }
                   2009: #endif
                   2010:
1.1       augustss 2011:        for (i = 0; i < ndps; i++) {
1.82      kent     2012:                dp = iot[i].d.desc;
1.14      augustss 2013:                if (dp == NULL)
1.1       augustss 2014:                        continue;
1.82      kent     2015:                DPRINTF(("uaudio_identify_ac: id=%d subtype=%d\n",
                   2016:                         i, dp->bDescriptorSubtype));
1.1       augustss 2017:                switch (dp->bDescriptorSubtype) {
                   2018:                case UDESCSUB_AC_HEADER:
1.82      kent     2019:                        printf("uaudio_identify_ac: unexpected AC header\n");
1.1       augustss 2020:                        break;
                   2021:                case UDESCSUB_AC_INPUT:
1.82      kent     2022:                        uaudio_add_input(sc, iot, i);
1.1       augustss 2023:                        break;
                   2024:                case UDESCSUB_AC_OUTPUT:
1.82      kent     2025:                        uaudio_add_output(sc, iot, i);
1.1       augustss 2026:                        break;
                   2027:                case UDESCSUB_AC_MIXER:
1.82      kent     2028:                        uaudio_add_mixer(sc, iot, i);
1.1       augustss 2029:                        break;
                   2030:                case UDESCSUB_AC_SELECTOR:
1.82      kent     2031:                        uaudio_add_selector(sc, iot, i);
1.1       augustss 2032:                        break;
                   2033:                case UDESCSUB_AC_FEATURE:
1.82      kent     2034:                        uaudio_add_feature(sc, iot, i);
1.1       augustss 2035:                        break;
                   2036:                case UDESCSUB_AC_PROCESSING:
1.82      kent     2037:                        uaudio_add_processing(sc, iot, i);
1.1       augustss 2038:                        break;
                   2039:                case UDESCSUB_AC_EXTENSION:
1.82      kent     2040:                        uaudio_add_extension(sc, iot, i);
1.1       augustss 2041:                        break;
                   2042:                default:
1.82      kent     2043:                        printf("uaudio_identify_ac: bad AC desc subtype=0x%02x\n",
1.1       augustss 2044:                               dp->bDescriptorSubtype);
                   2045:                        break;
                   2046:                }
                   2047:        }
1.82      kent     2048:
                   2049:        /* delete io_terminal */
                   2050:        for (i = 0; i < 256; i++) {
                   2051:                if (iot[i].d.desc == NULL)
                   2052:                        continue;
                   2053:                if (iot[i].inputs != NULL) {
                   2054:                        for (j = 0; j < iot[i].inputs_size; j++) {
                   2055:                                if (iot[i].inputs[j] != NULL)
                   2056:                                        free(iot[i].inputs[j], M_TEMP);
                   2057:                        }
                   2058:                        free(iot[i].inputs, M_TEMP);
                   2059:                }
                   2060:                if (iot[i].output != NULL)
                   2061:                        free(iot[i].output, M_TEMP);
                   2062:                iot[i].d.desc = NULL;
                   2063:        }
                   2064:        free(iot, M_TEMP);
                   2065:
1.94      kent     2066:        return USBD_NORMAL_COMPLETION;
1.1       augustss 2067: }
                   2068:
1.86      kent     2069: Static int
1.26      augustss 2070: uaudio_query_devinfo(void *addr, mixer_devinfo_t *mi)
1.1       augustss 2071: {
1.94      kent     2072:        struct uaudio_softc *sc;
1.1       augustss 2073:        struct mixerctl *mc;
1.79      kent     2074:        int n, nctls, i;
1.1       augustss 2075:
                   2076:        DPRINTFN(2,("uaudio_query_devinfo: index=%d\n", mi->index));
1.94      kent     2077:        sc = addr;
1.1       augustss 2078:        if (sc->sc_dying)
1.94      kent     2079:                return EIO;
1.56      kent     2080:
1.1       augustss 2081:        n = mi->index;
                   2082:        nctls = sc->sc_nctls;
                   2083:
1.63      augustss 2084:        switch (n) {
                   2085:        case UAC_OUTPUT:
                   2086:                mi->type = AUDIO_MIXER_CLASS;
                   2087:                mi->mixer_class = UAC_OUTPUT;
                   2088:                mi->next = mi->prev = AUDIO_MIXER_LAST;
1.71      itojun   2089:                strlcpy(mi->label.name, AudioCoutputs, sizeof(mi->label.name));
1.94      kent     2090:                return 0;
1.63      augustss 2091:        case UAC_INPUT:
                   2092:                mi->type = AUDIO_MIXER_CLASS;
                   2093:                mi->mixer_class = UAC_INPUT;
                   2094:                mi->next = mi->prev = AUDIO_MIXER_LAST;
1.71      itojun   2095:                strlcpy(mi->label.name, AudioCinputs, sizeof(mi->label.name));
1.94      kent     2096:                return 0;
1.63      augustss 2097:        case UAC_EQUAL:
                   2098:                mi->type = AUDIO_MIXER_CLASS;
                   2099:                mi->mixer_class = UAC_EQUAL;
                   2100:                mi->next = mi->prev = AUDIO_MIXER_LAST;
1.71      itojun   2101:                strlcpy(mi->label.name, AudioCequalization,
                   2102:                    sizeof(mi->label.name));
1.94      kent     2103:                return 0;
1.82      kent     2104:        case UAC_RECORD:
                   2105:                mi->type = AUDIO_MIXER_CLASS;
                   2106:                mi->mixer_class = UAC_RECORD;
                   2107:                mi->next = mi->prev = AUDIO_MIXER_LAST;
                   2108:                strlcpy(mi->label.name, AudioCrecord, sizeof(mi->label.name));
                   2109:                return 0;
1.63      augustss 2110:        default:
                   2111:                break;
1.1       augustss 2112:        }
1.63      augustss 2113:
                   2114:        n -= UAC_NCLASSES;
                   2115:        if (n < 0 || n >= nctls)
1.94      kent     2116:                return ENXIO;
1.63      augustss 2117:
1.1       augustss 2118:        mc = &sc->sc_ctls[n];
1.71      itojun   2119:        strlcpy(mi->label.name, mc->ctlname, sizeof(mi->label.name));
1.1       augustss 2120:        mi->mixer_class = mc->class;
                   2121:        mi->next = mi->prev = AUDIO_MIXER_LAST; /* XXX */
                   2122:        switch (mc->type) {
                   2123:        case MIX_ON_OFF:
                   2124:                mi->type = AUDIO_MIXER_ENUM;
                   2125:                mi->un.e.num_mem = 2;
1.71      itojun   2126:                strlcpy(mi->un.e.member[0].label.name, AudioNoff,
                   2127:                    sizeof(mi->un.e.member[0].label.name));
1.1       augustss 2128:                mi->un.e.member[0].ord = 0;
1.71      itojun   2129:                strlcpy(mi->un.e.member[1].label.name, AudioNon,
                   2130:                    sizeof(mi->un.e.member[1].label.name));
1.1       augustss 2131:                mi->un.e.member[1].ord = 1;
                   2132:                break;
1.79      kent     2133:        case MIX_SELECTOR:
                   2134:                mi->type = AUDIO_MIXER_ENUM;
                   2135:                mi->un.e.num_mem = mc->maxval - mc->minval + 1;
                   2136:                for (i = 0; i <= mc->maxval - mc->minval; i++) {
                   2137:                        snprintf(mi->un.e.member[i].label.name,
                   2138:                                 sizeof(mi->un.e.member[i].label.name),
                   2139:                                 "%d", i + mc->minval);
                   2140:                        mi->un.e.member[i].ord = i + mc->minval;
                   2141:                }
                   2142:                break;
1.1       augustss 2143:        default:
                   2144:                mi->type = AUDIO_MIXER_VALUE;
                   2145:                strncpy(mi->un.v.units.name, mc->ctlunit, MAX_AUDIO_DEV_LEN);
                   2146:                mi->un.v.num_channels = mc->nchan;
1.33      augustss 2147:                mi->un.v.delta = mc->delta;
1.1       augustss 2148:                break;
                   2149:        }
1.94      kent     2150:        return 0;
1.1       augustss 2151: }
                   2152:
1.86      kent     2153: Static int
1.26      augustss 2154: uaudio_open(void *addr, int flags)
1.1       augustss 2155: {
1.94      kent     2156:        struct uaudio_softc *sc;
1.1       augustss 2157:
1.95      dsainty  2158:        sc = addr;
1.56      kent     2159:        DPRINTF(("uaudio_open: sc=%p\n", sc));
1.1       augustss 2160:        if (sc->sc_dying)
1.94      kent     2161:                return EIO;
1.1       augustss 2162:
1.77      mycroft  2163:        if ((flags & FWRITE) && !(sc->sc_mode & AUMODE_PLAY))
1.94      kent     2164:                return EACCES;
1.77      mycroft  2165:        if ((flags & FREAD) && !(sc->sc_mode & AUMODE_RECORD))
1.94      kent     2166:                return EACCES;
1.1       augustss 2167:
1.94      kent     2168:        return 0;
1.1       augustss 2169: }
                   2170:
                   2171: /*
                   2172:  * Close function is called at splaudio().
                   2173:  */
1.86      kent     2174: Static void
1.26      augustss 2175: uaudio_close(void *addr)
1.1       augustss 2176: {
                   2177: }
                   2178:
1.86      kent     2179: Static int
1.26      augustss 2180: uaudio_drain(void *addr)
1.1       augustss 2181: {
1.94      kent     2182:        struct uaudio_softc *sc;
1.1       augustss 2183:
1.94      kent     2184:        sc = addr;
1.1       augustss 2185:        usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
                   2186:
1.94      kent     2187:        return 0;
1.1       augustss 2188: }
                   2189:
1.86      kent     2190: Static int
1.26      augustss 2191: uaudio_halt_out_dma(void *addr)
1.1       augustss 2192: {
1.94      kent     2193:        struct uaudio_softc *sc;
1.1       augustss 2194:
                   2195:        DPRINTF(("uaudio_halt_out_dma: enter\n"));
1.94      kent     2196:        sc = addr;
1.47      jdolecek 2197:        if (sc->sc_playchan.pipe != NULL) {
                   2198:                uaudio_chan_close(sc, &sc->sc_playchan);
                   2199:                sc->sc_playchan.pipe = NULL;
                   2200:                uaudio_chan_free_buffers(sc, &sc->sc_playchan);
1.74      mycroft  2201:                sc->sc_playchan.intr = NULL;
1.1       augustss 2202:        }
1.94      kent     2203:        return 0;
1.1       augustss 2204: }
                   2205:
1.86      kent     2206: Static int
1.26      augustss 2207: uaudio_halt_in_dma(void *addr)
1.1       augustss 2208: {
1.94      kent     2209:        struct uaudio_softc *sc;
1.1       augustss 2210:
                   2211:        DPRINTF(("uaudio_halt_in_dma: enter\n"));
1.94      kent     2212:        sc = addr;
1.47      jdolecek 2213:        if (sc->sc_recchan.pipe != NULL) {
                   2214:                uaudio_chan_close(sc, &sc->sc_recchan);
                   2215:                sc->sc_recchan.pipe = NULL;
                   2216:                uaudio_chan_free_buffers(sc, &sc->sc_recchan);
1.74      mycroft  2217:                sc->sc_recchan.intr = NULL;
1.5       augustss 2218:        }
1.94      kent     2219:        return 0;
1.1       augustss 2220: }
                   2221:
1.86      kent     2222: Static int
1.26      augustss 2223: uaudio_getdev(void *addr, struct audio_device *retp)
1.1       augustss 2224: {
1.94      kent     2225:        struct uaudio_softc *sc;
1.1       augustss 2226:
                   2227:        DPRINTF(("uaudio_mixer_getdev:\n"));
1.94      kent     2228:        sc = addr;
1.1       augustss 2229:        if (sc->sc_dying)
1.94      kent     2230:                return EIO;
1.56      kent     2231:
1.1       augustss 2232:        *retp = uaudio_device;
1.94      kent     2233:        return 0;
1.1       augustss 2234: }
                   2235:
                   2236: /*
                   2237:  * Make sure the block size is large enough to hold all outstanding transfers.
                   2238:  */
1.86      kent     2239: Static int
1.93      kent     2240: uaudio_round_blocksize(void *addr, int blk,
                   2241:                       int mode, const audio_params_t *param)
1.1       augustss 2242: {
1.94      kent     2243:        struct uaudio_softc *sc;
1.96      kent     2244:        int b;
1.1       augustss 2245:
1.94      kent     2246:        sc = addr;
1.96      kent     2247:        DPRINTF(("uaudio_round_blocksize: blk=%d mode=%s\n", blk,
                   2248:            mode == AUMODE_PLAY ? "AUMODE_PLAY" : "AUMODE_RECORD"));
                   2249:
                   2250:        /* chan.bytes_per_frame can be 0. */
                   2251:        if (mode == AUMODE_PLAY || sc->sc_recchan.bytes_per_frame <= 0) {
                   2252:                b = param->sample_rate * UAUDIO_NFRAMES * UAUDIO_NCHANBUFS;
                   2253:
                   2254:                /*
                   2255:                 * This does not make accurate value in the case
                   2256:                 * of b % USB_FRAMES_PER_SECOND != 0
                   2257:                 */
                   2258:                b /= USB_FRAMES_PER_SECOND;
                   2259:
                   2260:                b *= param->precision / 8 * param->channels;
1.47      jdolecek 2261:        } else {
1.96      kent     2262:                /*
                   2263:                 * use wMaxPacketSize in bytes_per_frame.
                   2264:                 * See uaudio_set_params() and uaudio_chan_init()
                   2265:                 */
                   2266:                b = sc->sc_recchan.bytes_per_frame
                   2267:                    * UAUDIO_NFRAMES * UAUDIO_NCHANBUFS;
1.47      jdolecek 2268:        }
1.1       augustss 2269:
1.96      kent     2270:        if (b <= 0)
                   2271:                b = 1;
                   2272:        blk = blk <= b ? b : blk / b * b;
1.1       augustss 2273:
1.5       augustss 2274: #ifdef DIAGNOSTIC
                   2275:        if (blk <= 0) {
                   2276:                printf("uaudio_round_blocksize: blk=%d\n", blk);
                   2277:                blk = 512;
                   2278:        }
                   2279: #endif
                   2280:
1.96      kent     2281:        DPRINTF(("uaudio_round_blocksize: resultant blk=%d\n", blk));
1.94      kent     2282:        return blk;
1.1       augustss 2283: }
                   2284:
1.86      kent     2285: Static int
1.26      augustss 2286: uaudio_get_props(void *addr)
1.1       augustss 2287: {
1.94      kent     2288:        return AUDIO_PROP_FULLDUPLEX | AUDIO_PROP_INDEPENDENT;
1.1       augustss 2289:
                   2290: }
                   2291:
1.86      kent     2292: Static int
1.27      augustss 2293: uaudio_get(struct uaudio_softc *sc, int which, int type, int wValue,
1.26      augustss 2294:           int wIndex, int len)
1.1       augustss 2295: {
                   2296:        usb_device_request_t req;
                   2297:        u_int8_t data[4];
1.9       augustss 2298:        usbd_status err;
1.1       augustss 2299:        int val;
                   2300:
                   2301:        if (wValue == -1)
1.94      kent     2302:                return 0;
1.1       augustss 2303:
                   2304:        req.bmRequestType = type;
                   2305:        req.bRequest = which;
                   2306:        USETW(req.wValue, wValue);
                   2307:        USETW(req.wIndex, wIndex);
                   2308:        USETW(req.wLength, len);
                   2309:        DPRINTFN(2,("uaudio_get: type=0x%02x req=0x%02x wValue=0x%04x "
1.56      kent     2310:                    "wIndex=0x%04x len=%d\n",
1.1       augustss 2311:                    type, which, wValue, wIndex, len));
1.47      jdolecek 2312:        err = usbd_do_request(sc->sc_udev, &req, data);
1.9       augustss 2313:        if (err) {
1.20      augustss 2314:                DPRINTF(("uaudio_get: err=%s\n", usbd_errstr(err)));
1.94      kent     2315:                return -1;
1.1       augustss 2316:        }
                   2317:        switch (len) {
                   2318:        case 1:
                   2319:                val = data[0];
                   2320:                break;
                   2321:        case 2:
                   2322:                val = data[0] | (data[1] << 8);
                   2323:                break;
                   2324:        default:
                   2325:                DPRINTF(("uaudio_get: bad length=%d\n", len));
1.94      kent     2326:                return -1;
1.1       augustss 2327:        }
                   2328:        DPRINTFN(2,("uaudio_get: val=%d\n", val));
1.94      kent     2329:        return val;
1.1       augustss 2330: }
                   2331:
1.86      kent     2332: Static void
1.27      augustss 2333: uaudio_set(struct uaudio_softc *sc, int which, int type, int wValue,
1.26      augustss 2334:           int wIndex, int len, int val)
1.1       augustss 2335: {
                   2336:        usb_device_request_t req;
                   2337:        u_int8_t data[4];
1.9       augustss 2338:        usbd_status err;
1.1       augustss 2339:
                   2340:        if (wValue == -1)
                   2341:                return;
                   2342:
                   2343:        req.bmRequestType = type;
                   2344:        req.bRequest = which;
                   2345:        USETW(req.wValue, wValue);
                   2346:        USETW(req.wIndex, wIndex);
                   2347:        USETW(req.wLength, len);
                   2348:        switch (len) {
                   2349:        case 1:
                   2350:                data[0] = val;
                   2351:                break;
                   2352:        case 2:
                   2353:                data[0] = val;
                   2354:                data[1] = val >> 8;
                   2355:                break;
                   2356:        default:
                   2357:                return;
                   2358:        }
                   2359:        DPRINTFN(2,("uaudio_set: type=0x%02x req=0x%02x wValue=0x%04x "
1.56      kent     2360:                    "wIndex=0x%04x len=%d, val=%d\n",
1.1       augustss 2361:                    type, which, wValue, wIndex, len, val & 0xffff));
1.47      jdolecek 2362:        err = usbd_do_request(sc->sc_udev, &req, data);
1.4       augustss 2363: #ifdef UAUDIO_DEBUG
1.12      augustss 2364:        if (err)
1.9       augustss 2365:                DPRINTF(("uaudio_set: err=%d\n", err));
1.1       augustss 2366: #endif
                   2367: }
                   2368:
1.86      kent     2369: Static int
1.26      augustss 2370: uaudio_signext(int type, int val)
1.1       augustss 2371: {
                   2372:        if (!MIX_UNSIGNED(type)) {
                   2373:                if (MIX_SIZE(type) == 2)
                   2374:                        val = (int16_t)val;
                   2375:                else
                   2376:                        val = (int8_t)val;
                   2377:        }
1.94      kent     2378:        return val;
1.1       augustss 2379: }
                   2380:
1.86      kent     2381: Static int
1.26      augustss 2382: uaudio_value2bsd(struct mixerctl *mc, int val)
1.1       augustss 2383: {
                   2384:        DPRINTFN(5, ("uaudio_value2bsd: type=%03x val=%d min=%d max=%d ",
                   2385:                     mc->type, val, mc->minval, mc->maxval));
1.79      kent     2386:        if (mc->type == MIX_ON_OFF) {
1.47      jdolecek 2387:                val = (val != 0);
1.79      kent     2388:        } else if (mc->type == MIX_SELECTOR) {
                   2389:                if (val < mc->minval || val > mc->maxval)
                   2390:                        val = mc->minval;
                   2391:        } else
1.69      wiz      2392:                val = ((uaudio_signext(mc->type, val) - mc->minval) * 255
1.34      augustss 2393:                        + mc->mul/2) / mc->mul;
1.1       augustss 2394:        DPRINTFN(5, ("val'=%d\n", val));
1.94      kent     2395:        return val;
1.1       augustss 2396: }
                   2397:
                   2398: int
1.26      augustss 2399: uaudio_bsd2value(struct mixerctl *mc, int val)
1.1       augustss 2400: {
                   2401:        DPRINTFN(5,("uaudio_bsd2value: type=%03x val=%d min=%d max=%d ",
                   2402:                    mc->type, val, mc->minval, mc->maxval));
1.79      kent     2403:        if (mc->type == MIX_ON_OFF) {
1.47      jdolecek 2404:                val = (val != 0);
1.79      kent     2405:        } else if (mc->type == MIX_SELECTOR) {
                   2406:                if (val < mc->minval || val > mc->maxval)
                   2407:                        val = mc->minval;
                   2408:        } else
1.69      wiz      2409:                val = (val + mc->delta/2) * mc->mul / 255 + mc->minval;
1.1       augustss 2410:        DPRINTFN(5, ("val'=%d\n", val));
1.94      kent     2411:        return val;
1.1       augustss 2412: }
                   2413:
1.86      kent     2414: Static int
1.56      kent     2415: uaudio_ctl_get(struct uaudio_softc *sc, int which, struct mixerctl *mc,
1.26      augustss 2416:               int chan)
1.1       augustss 2417: {
                   2418:        int val;
                   2419:
                   2420:        DPRINTFN(5,("uaudio_ctl_get: which=%d chan=%d\n", which, chan));
                   2421:        val = uaudio_get(sc, which, UT_READ_CLASS_INTERFACE, mc->wValue[chan],
                   2422:                         mc->wIndex, MIX_SIZE(mc->type));
1.94      kent     2423:        return uaudio_value2bsd(mc, val);
1.1       augustss 2424: }
                   2425:
1.86      kent     2426: Static void
1.26      augustss 2427: uaudio_ctl_set(struct uaudio_softc *sc, int which, struct mixerctl *mc,
                   2428:               int chan, int val)
1.1       augustss 2429: {
                   2430:        val = uaudio_bsd2value(mc, val);
                   2431:        uaudio_set(sc, which, UT_WRITE_CLASS_INTERFACE, mc->wValue[chan],
                   2432:                   mc->wIndex, MIX_SIZE(mc->type), val);
                   2433: }
                   2434:
1.86      kent     2435: Static int
1.26      augustss 2436: uaudio_mixer_get_port(void *addr, mixer_ctrl_t *cp)
1.1       augustss 2437: {
1.94      kent     2438:        struct uaudio_softc *sc;
1.1       augustss 2439:        struct mixerctl *mc;
                   2440:        int i, n, vals[MIX_MAX_CHAN], val;
                   2441:
                   2442:        DPRINTFN(2,("uaudio_mixer_get_port: index=%d\n", cp->dev));
1.94      kent     2443:        sc = addr;
1.1       augustss 2444:        if (sc->sc_dying)
1.94      kent     2445:                return EIO;
1.56      kent     2446:
1.63      augustss 2447:        n = cp->dev - UAC_NCLASSES;
1.1       augustss 2448:        if (n < 0 || n >= sc->sc_nctls)
1.94      kent     2449:                return ENXIO;
1.1       augustss 2450:        mc = &sc->sc_ctls[n];
                   2451:
                   2452:        if (mc->type == MIX_ON_OFF) {
                   2453:                if (cp->type != AUDIO_MIXER_ENUM)
1.94      kent     2454:                        return EINVAL;
1.1       augustss 2455:                cp->un.ord = uaudio_ctl_get(sc, GET_CUR, mc, 0);
1.79      kent     2456:        } else if (mc->type == MIX_SELECTOR) {
                   2457:                if (cp->type != AUDIO_MIXER_ENUM)
1.94      kent     2458:                        return EINVAL;
1.79      kent     2459:                cp->un.ord = uaudio_ctl_get(sc, GET_CUR, mc, 0);
1.1       augustss 2460:        } else {
                   2461:                if (cp->type != AUDIO_MIXER_VALUE)
1.94      kent     2462:                        return EINVAL;
1.1       augustss 2463:                if (cp->un.value.num_channels != 1 &&
                   2464:                    cp->un.value.num_channels != mc->nchan)
1.94      kent     2465:                        return EINVAL;
1.1       augustss 2466:                for (i = 0; i < mc->nchan; i++)
                   2467:                        vals[i] = uaudio_ctl_get(sc, GET_CUR, mc, i);
                   2468:                if (cp->un.value.num_channels == 1 && mc->nchan != 1) {
                   2469:                        for (val = 0, i = 0; i < mc->nchan; i++)
                   2470:                                val += vals[i];
                   2471:                        vals[0] = val / mc->nchan;
                   2472:                }
                   2473:                for (i = 0; i < cp->un.value.num_channels; i++)
                   2474:                        cp->un.value.level[i] = vals[i];
                   2475:        }
                   2476:
1.94      kent     2477:        return 0;
1.1       augustss 2478: }
1.56      kent     2479:
1.86      kent     2480: Static int
1.26      augustss 2481: uaudio_mixer_set_port(void *addr, mixer_ctrl_t *cp)
1.1       augustss 2482: {
1.94      kent     2483:        struct uaudio_softc *sc;
1.1       augustss 2484:        struct mixerctl *mc;
                   2485:        int i, n, vals[MIX_MAX_CHAN];
                   2486:
                   2487:        DPRINTFN(2,("uaudio_mixer_set_port: index = %d\n", cp->dev));
1.94      kent     2488:        sc = addr;
1.1       augustss 2489:        if (sc->sc_dying)
1.94      kent     2490:                return EIO;
1.56      kent     2491:
1.63      augustss 2492:        n = cp->dev - UAC_NCLASSES;
1.1       augustss 2493:        if (n < 0 || n >= sc->sc_nctls)
1.94      kent     2494:                return ENXIO;
1.1       augustss 2495:        mc = &sc->sc_ctls[n];
                   2496:
                   2497:        if (mc->type == MIX_ON_OFF) {
                   2498:                if (cp->type != AUDIO_MIXER_ENUM)
1.94      kent     2499:                        return EINVAL;
1.1       augustss 2500:                uaudio_ctl_set(sc, SET_CUR, mc, 0, cp->un.ord);
1.79      kent     2501:        } else if (mc->type == MIX_SELECTOR) {
                   2502:                if (cp->type != AUDIO_MIXER_ENUM)
1.94      kent     2503:                        return EINVAL;
1.79      kent     2504:                uaudio_ctl_set(sc, SET_CUR, mc, 0, cp->un.ord);
1.1       augustss 2505:        } else {
                   2506:                if (cp->type != AUDIO_MIXER_VALUE)
1.94      kent     2507:                        return EINVAL;
1.1       augustss 2508:                if (cp->un.value.num_channels == 1)
                   2509:                        for (i = 0; i < mc->nchan; i++)
                   2510:                                vals[i] = cp->un.value.level[0];
                   2511:                else if (cp->un.value.num_channels == mc->nchan)
                   2512:                        for (i = 0; i < mc->nchan; i++)
                   2513:                                vals[i] = cp->un.value.level[i];
                   2514:                else
1.94      kent     2515:                        return EINVAL;
1.1       augustss 2516:                for (i = 0; i < mc->nchan; i++)
                   2517:                        uaudio_ctl_set(sc, SET_CUR, mc, i, vals[i]);
                   2518:        }
1.94      kent     2519:        return 0;
1.1       augustss 2520: }
                   2521:
1.86      kent     2522: Static int
1.26      augustss 2523: uaudio_trigger_input(void *addr, void *start, void *end, int blksize,
                   2524:                     void (*intr)(void *), void *arg,
1.93      kent     2525:                     const audio_params_t *param)
1.1       augustss 2526: {
1.94      kent     2527:        struct uaudio_softc *sc;
                   2528:        struct chan *ch;
1.9       augustss 2529:        usbd_status err;
1.5       augustss 2530:        int i, s;
1.1       augustss 2531:
1.94      kent     2532:        sc = addr;
1.1       augustss 2533:        if (sc->sc_dying)
1.94      kent     2534:                return EIO;
1.1       augustss 2535:
1.5       augustss 2536:        DPRINTFN(3,("uaudio_trigger_input: sc=%p start=%p end=%p "
1.1       augustss 2537:                    "blksize=%d\n", sc, start, end, blksize));
1.94      kent     2538:        ch = &sc->sc_recchan;
1.54      kent     2539:        uaudio_chan_set_param(ch, start, end, blksize);
1.5       augustss 2540:        DPRINTFN(3,("uaudio_trigger_input: sample_size=%d bytes/frame=%d "
                   2541:                    "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame,
                   2542:                    ch->fraction));
                   2543:
1.9       augustss 2544:        err = uaudio_chan_alloc_buffers(sc, ch);
                   2545:        if (err)
1.94      kent     2546:                return EIO;
1.5       augustss 2547:
1.9       augustss 2548:        err = uaudio_chan_open(sc, ch);
                   2549:        if (err) {
1.5       augustss 2550:                uaudio_chan_free_buffers(sc, ch);
1.94      kent     2551:                return EIO;
1.5       augustss 2552:        }
                   2553:
1.47      jdolecek 2554:        ch->intr = intr;
                   2555:        ch->arg = arg;
1.5       augustss 2556:
                   2557:        s = splusb();
1.22      augustss 2558:        for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX -1 shouldn't be needed */
1.5       augustss 2559:                uaudio_chan_rtransfer(ch);
                   2560:        splx(s);
                   2561:
1.94      kent     2562:        return 0;
1.1       augustss 2563: }
1.56      kent     2564:
1.86      kent     2565: Static int
1.26      augustss 2566: uaudio_trigger_output(void *addr, void *start, void *end, int blksize,
                   2567:                      void (*intr)(void *), void *arg,
1.93      kent     2568:                      const audio_params_t *param)
1.1       augustss 2569: {
1.94      kent     2570:        struct uaudio_softc *sc;
                   2571:        struct chan *ch;
1.9       augustss 2572:        usbd_status err;
1.1       augustss 2573:        int i, s;
                   2574:
1.94      kent     2575:        sc = addr;
1.1       augustss 2576:        if (sc->sc_dying)
1.94      kent     2577:                return EIO;
1.1       augustss 2578:
                   2579:        DPRINTFN(3,("uaudio_trigger_output: sc=%p start=%p end=%p "
                   2580:                    "blksize=%d\n", sc, start, end, blksize));
1.94      kent     2581:        ch = &sc->sc_playchan;
1.54      kent     2582:        uaudio_chan_set_param(ch, start, end, blksize);
1.1       augustss 2583:        DPRINTFN(3,("uaudio_trigger_output: sample_size=%d bytes/frame=%d "
                   2584:                    "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame,
                   2585:                    ch->fraction));
                   2586:
1.9       augustss 2587:        err = uaudio_chan_alloc_buffers(sc, ch);
                   2588:        if (err)
1.94      kent     2589:                return EIO;
1.1       augustss 2590:
1.9       augustss 2591:        err = uaudio_chan_open(sc, ch);
                   2592:        if (err) {
1.1       augustss 2593:                uaudio_chan_free_buffers(sc, ch);
1.94      kent     2594:                return EIO;
1.1       augustss 2595:        }
                   2596:
1.47      jdolecek 2597:        ch->intr = intr;
                   2598:        ch->arg = arg;
1.1       augustss 2599:
                   2600:        s = splusb();
1.22      augustss 2601:        for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX */
1.5       augustss 2602:                uaudio_chan_ptransfer(ch);
1.1       augustss 2603:        splx(s);
                   2604:
1.94      kent     2605:        return 0;
1.1       augustss 2606: }
                   2607:
                   2608: /* Set up a pipe for a channel. */
1.86      kent     2609: Static usbd_status
1.26      augustss 2610: uaudio_chan_open(struct uaudio_softc *sc, struct chan *ch)
1.1       augustss 2611: {
1.94      kent     2612:        struct as_info *as;
                   2613:        int endpt;
1.9       augustss 2614:        usbd_status err;
1.1       augustss 2615:
1.94      kent     2616:        as = &sc->sc_alts[ch->altidx];
                   2617:        endpt = as->edesc->bEndpointAddress;
1.56      kent     2618:        DPRINTF(("uaudio_chan_open: endpt=0x%02x, speed=%d, alt=%d\n",
1.1       augustss 2619:                 endpt, ch->sample_rate, as->alt));
                   2620:
                   2621:        /* Set alternate interface corresponding to the mode. */
1.37      mycroft  2622:        err = usbd_set_interface(as->ifaceh, as->alt);
1.9       augustss 2623:        if (err)
1.94      kent     2624:                return err;
1.1       augustss 2625:
1.90      kent     2626:        /*
                   2627:         * If just one sampling rate is supported,
                   2628:         * no need to call uaudio_set_speed().
                   2629:         * Roland SD-90 freezes by a SAMPLING_FREQ_CONTROL request.
                   2630:         */
                   2631:        if (as->asf1desc->bSamFreqType != 1) {
                   2632:                err = uaudio_set_speed(sc, endpt, ch->sample_rate);
1.99.2.2  yamt     2633:                if (err) {
1.90      kent     2634:                        DPRINTF(("uaudio_chan_open: set_speed failed err=%s\n",
                   2635:                                 usbd_errstr(err)));
1.99.2.2  yamt     2636:                }
1.90      kent     2637:        }
1.1       augustss 2638:
1.83      kent     2639:        ch->pipe = 0;
                   2640:        ch->sync_pipe = 0;
1.47      jdolecek 2641:        DPRINTF(("uaudio_chan_open: create pipe to 0x%02x\n", endpt));
1.37      mycroft  2642:        err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->pipe);
1.83      kent     2643:        if (err)
                   2644:                return err;
                   2645:        if (as->edesc1 != NULL) {
                   2646:                endpt = as->edesc1->bEndpointAddress;
                   2647:                DPRINTF(("uaudio_chan_open: create sync-pipe to 0x%02x\n", endpt));
                   2648:                err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->sync_pipe);
                   2649:        }
                   2650:        return err;
1.1       augustss 2651: }
                   2652:
1.86      kent     2653: Static void
1.26      augustss 2654: uaudio_chan_close(struct uaudio_softc *sc, struct chan *ch)
1.1       augustss 2655: {
1.94      kent     2656:        struct as_info *as;
1.37      mycroft  2657:
1.94      kent     2658:        as = &sc->sc_alts[ch->altidx];
1.58      kent     2659:        as->sc_busy = 0;
1.92      kent     2660:        AUFMT_VALIDATE(as->aformat);
1.1       augustss 2661:        if (sc->sc_nullalt >= 0) {
1.47      jdolecek 2662:                DPRINTF(("uaudio_chan_close: set null alt=%d\n",
1.1       augustss 2663:                         sc->sc_nullalt));
1.37      mycroft  2664:                usbd_set_interface(as->ifaceh, sc->sc_nullalt);
1.1       augustss 2665:        }
1.83      kent     2666:        if (ch->pipe) {
                   2667:                usbd_abort_pipe(ch->pipe);
                   2668:                usbd_close_pipe(ch->pipe);
                   2669:        }
                   2670:        if (ch->sync_pipe) {
                   2671:                usbd_abort_pipe(ch->sync_pipe);
                   2672:                usbd_close_pipe(ch->sync_pipe);
                   2673:        }
1.1       augustss 2674: }
                   2675:
1.86      kent     2676: Static usbd_status
1.26      augustss 2677: uaudio_chan_alloc_buffers(struct uaudio_softc *sc, struct chan *ch)
1.1       augustss 2678: {
1.9       augustss 2679:        usbd_xfer_handle xfer;
1.99      christos 2680:        void *tbuf;
1.1       augustss 2681:        int i, size;
                   2682:
                   2683:        size = (ch->bytes_per_frame + ch->sample_size) * UAUDIO_NFRAMES;
                   2684:        for (i = 0; i < UAUDIO_NCHANBUFS; i++) {
1.11      augustss 2685:                xfer = usbd_alloc_xfer(sc->sc_udev);
1.9       augustss 2686:                if (xfer == 0)
1.1       augustss 2687:                        goto bad;
1.9       augustss 2688:                ch->chanbufs[i].xfer = xfer;
1.99      christos 2689:                tbuf = usbd_alloc_buffer(xfer, size);
                   2690:                if (tbuf == 0) {
1.1       augustss 2691:                        i++;
                   2692:                        goto bad;
                   2693:                }
1.99      christos 2694:                ch->chanbufs[i].buffer = tbuf;
1.1       augustss 2695:                ch->chanbufs[i].chan = ch;
                   2696:        }
                   2697:
1.94      kent     2698:        return USBD_NORMAL_COMPLETION;
1.1       augustss 2699:
                   2700: bad:
                   2701:        while (--i >= 0)
                   2702:                /* implicit buffer free */
1.11      augustss 2703:                usbd_free_xfer(ch->chanbufs[i].xfer);
1.94      kent     2704:        return USBD_NOMEM;
1.1       augustss 2705: }
                   2706:
1.86      kent     2707: Static void
1.26      augustss 2708: uaudio_chan_free_buffers(struct uaudio_softc *sc, struct chan *ch)
1.1       augustss 2709: {
                   2710:        int i;
                   2711:
                   2712:        for (i = 0; i < UAUDIO_NCHANBUFS; i++)
1.11      augustss 2713:                usbd_free_xfer(ch->chanbufs[i].xfer);
1.1       augustss 2714: }
                   2715:
                   2716: /* Called at splusb() */
1.86      kent     2717: Static void
1.26      augustss 2718: uaudio_chan_ptransfer(struct chan *ch)
1.1       augustss 2719: {
                   2720:        struct chanbuf *cb;
                   2721:        int i, n, size, residue, total;
                   2722:
1.8       augustss 2723:        if (ch->sc->sc_dying)
                   2724:                return;
                   2725:
1.1       augustss 2726:        /* Pick the next channel buffer. */
                   2727:        cb = &ch->chanbufs[ch->curchanbuf];
                   2728:        if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
                   2729:                ch->curchanbuf = 0;
                   2730:
                   2731:        /* Compute the size of each frame in the next transfer. */
                   2732:        residue = ch->residue;
                   2733:        total = 0;
                   2734:        for (i = 0; i < UAUDIO_NFRAMES; i++) {
                   2735:                size = ch->bytes_per_frame;
                   2736:                residue += ch->fraction;
                   2737:                if (residue >= USB_FRAMES_PER_SECOND) {
1.47      jdolecek 2738:                        if ((ch->sc->sc_altflags & UA_NOFRAC) == 0)
1.31      augustss 2739:                                size += ch->sample_size;
1.1       augustss 2740:                        residue -= USB_FRAMES_PER_SECOND;
                   2741:                }
                   2742:                cb->sizes[i] = size;
                   2743:                total += size;
                   2744:        }
                   2745:        ch->residue = residue;
                   2746:        cb->size = total;
                   2747:
1.56      kent     2748:        /*
1.1       augustss 2749:         * Transfer data from upper layer buffer to channel buffer, taking
                   2750:         * care of wrapping the upper layer buffer.
                   2751:         */
                   2752:        n = min(total, ch->end - ch->cur);
                   2753:        memcpy(cb->buffer, ch->cur, n);
                   2754:        ch->cur += n;
                   2755:        if (ch->cur >= ch->end)
                   2756:                ch->cur = ch->start;
                   2757:        if (total > n) {
                   2758:                total -= n;
                   2759:                memcpy(cb->buffer + n, ch->cur, total);
                   2760:                ch->cur += total;
                   2761:        }
                   2762:
1.4       augustss 2763: #ifdef UAUDIO_DEBUG
1.1       augustss 2764:        if (uaudiodebug > 8) {
1.5       augustss 2765:                DPRINTF(("uaudio_chan_ptransfer: buffer=%p, residue=0.%03d\n",
1.1       augustss 2766:                         cb->buffer, ch->residue));
                   2767:                for (i = 0; i < UAUDIO_NFRAMES; i++) {
                   2768:                        DPRINTF(("   [%d] length %d\n", i, cb->sizes[i]));
                   2769:                }
                   2770:        }
                   2771: #endif
                   2772:
1.9       augustss 2773:        DPRINTFN(5,("uaudio_chan_transfer: ptransfer xfer=%p\n", cb->xfer));
1.1       augustss 2774:        /* Fill the request */
1.56      kent     2775:        usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
                   2776:                             UAUDIO_NFRAMES, USBD_NO_COPY,
1.11      augustss 2777:                             uaudio_chan_pintr);
1.1       augustss 2778:
1.9       augustss 2779:        (void)usbd_transfer(cb->xfer);
1.1       augustss 2780: }
                   2781:
1.86      kent     2782: Static void
1.26      augustss 2783: uaudio_chan_pintr(usbd_xfer_handle xfer, usbd_private_handle priv,
                   2784:                  usbd_status status)
1.1       augustss 2785: {
1.94      kent     2786:        struct chanbuf *cb;
                   2787:        struct chan *ch;
                   2788:        uint32_t count;
1.1       augustss 2789:        int s;
                   2790:
1.94      kent     2791:        cb = priv;
                   2792:        ch = cb->chan;
1.1       augustss 2793:        /* Return if we are aborting. */
                   2794:        if (status == USBD_CANCELLED)
                   2795:                return;
                   2796:
1.18      augustss 2797:        usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
1.5       augustss 2798:        DPRINTFN(5,("uaudio_chan_pintr: count=%d, transferred=%d\n",
                   2799:                    count, ch->transferred));
                   2800: #ifdef DIAGNOSTIC
                   2801:        if (count != cb->size) {
                   2802:                printf("uaudio_chan_pintr: count(%d) != size(%d)\n",
                   2803:                       count, cb->size);
                   2804:        }
                   2805: #endif
                   2806:
                   2807:        ch->transferred += cb->size;
                   2808:        s = splaudio();
1.1       augustss 2809:        /* Call back to upper layer */
1.5       augustss 2810:        while (ch->transferred >= ch->blksize) {
                   2811:                ch->transferred -= ch->blksize;
1.56      kent     2812:                DPRINTFN(5,("uaudio_chan_pintr: call %p(%p)\n",
1.5       augustss 2813:                            ch->intr, ch->arg));
                   2814:                ch->intr(ch->arg);
                   2815:        }
                   2816:        splx(s);
                   2817:
                   2818:        /* start next transfer */
                   2819:        uaudio_chan_ptransfer(ch);
                   2820: }
                   2821:
                   2822: /* Called at splusb() */
1.86      kent     2823: Static void
1.26      augustss 2824: uaudio_chan_rtransfer(struct chan *ch)
1.5       augustss 2825: {
                   2826:        struct chanbuf *cb;
                   2827:        int i, size, residue, total;
1.8       augustss 2828:
                   2829:        if (ch->sc->sc_dying)
                   2830:                return;
1.5       augustss 2831:
                   2832:        /* Pick the next channel buffer. */
                   2833:        cb = &ch->chanbufs[ch->curchanbuf];
                   2834:        if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
                   2835:                ch->curchanbuf = 0;
                   2836:
                   2837:        /* Compute the size of each frame in the next transfer. */
                   2838:        residue = ch->residue;
                   2839:        total = 0;
                   2840:        for (i = 0; i < UAUDIO_NFRAMES; i++) {
                   2841:                size = ch->bytes_per_frame;
                   2842:                cb->sizes[i] = size;
1.62      toshii   2843:                cb->offsets[i] = total;
1.5       augustss 2844:                total += size;
                   2845:        }
                   2846:        ch->residue = residue;
                   2847:        cb->size = total;
                   2848:
                   2849: #ifdef UAUDIO_DEBUG
                   2850:        if (uaudiodebug > 8) {
                   2851:                DPRINTF(("uaudio_chan_rtransfer: buffer=%p, residue=0.%03d\n",
                   2852:                         cb->buffer, ch->residue));
                   2853:                for (i = 0; i < UAUDIO_NFRAMES; i++) {
                   2854:                        DPRINTF(("   [%d] length %d\n", i, cb->sizes[i]));
                   2855:                }
                   2856:        }
                   2857: #endif
                   2858:
1.9       augustss 2859:        DPRINTFN(5,("uaudio_chan_rtransfer: transfer xfer=%p\n", cb->xfer));
1.5       augustss 2860:        /* Fill the request */
1.56      kent     2861:        usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
                   2862:                             UAUDIO_NFRAMES, USBD_NO_COPY,
1.11      augustss 2863:                             uaudio_chan_rintr);
1.5       augustss 2864:
1.9       augustss 2865:        (void)usbd_transfer(cb->xfer);
1.5       augustss 2866: }
                   2867:
1.86      kent     2868: Static void
1.26      augustss 2869: uaudio_chan_rintr(usbd_xfer_handle xfer, usbd_private_handle priv,
                   2870:                  usbd_status status)
1.5       augustss 2871: {
1.94      kent     2872:        struct chanbuf *cb;
                   2873:        struct chan *ch;
                   2874:        uint32_t count;
1.62      toshii   2875:        int s, i, n, frsize;
1.5       augustss 2876:
1.94      kent     2877:        cb = priv;
                   2878:        ch = cb->chan;
1.5       augustss 2879:        /* Return if we are aborting. */
                   2880:        if (status == USBD_CANCELLED)
                   2881:                return;
                   2882:
1.18      augustss 2883:        usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
1.5       augustss 2884:        DPRINTFN(5,("uaudio_chan_rintr: count=%d, transferred=%d\n",
1.1       augustss 2885:                    count, ch->transferred));
1.31      augustss 2886:
1.62      toshii   2887:        /* count < cb->size is normal for asynchronous source */
1.1       augustss 2888: #ifdef DIAGNOSTIC
1.62      toshii   2889:        if (count > cb->size) {
                   2890:                printf("uaudio_chan_rintr: count(%d) > size(%d)\n",
1.1       augustss 2891:                       count, cb->size);
                   2892:        }
                   2893: #endif
                   2894:
1.56      kent     2895:        /*
1.5       augustss 2896:         * Transfer data from channel buffer to upper layer buffer, taking
                   2897:         * care of wrapping the upper layer buffer.
                   2898:         */
1.62      toshii   2899:        for(i = 0; i < UAUDIO_NFRAMES; i++) {
                   2900:                frsize = cb->sizes[i];
                   2901:                n = min(frsize, ch->end - ch->cur);
                   2902:                memcpy(ch->cur, cb->buffer + cb->offsets[i], n);
                   2903:                ch->cur += n;
                   2904:                if (ch->cur >= ch->end)
                   2905:                        ch->cur = ch->start;
                   2906:                if (frsize > n) {
                   2907:                        memcpy(ch->cur, cb->buffer + cb->offsets[i] + n,
                   2908:                            frsize - n);
                   2909:                        ch->cur += frsize - n;
                   2910:                }
1.5       augustss 2911:        }
                   2912:
                   2913:        /* Call back to upper layer */
1.62      toshii   2914:        ch->transferred += count;
1.1       augustss 2915:        s = splaudio();
                   2916:        while (ch->transferred >= ch->blksize) {
                   2917:                ch->transferred -= ch->blksize;
1.56      kent     2918:                DPRINTFN(5,("uaudio_chan_rintr: call %p(%p)\n",
1.1       augustss 2919:                            ch->intr, ch->arg));
                   2920:                ch->intr(ch->arg);
                   2921:        }
                   2922:        splx(s);
                   2923:
                   2924:        /* start next transfer */
1.5       augustss 2925:        uaudio_chan_rtransfer(ch);
1.1       augustss 2926: }
                   2927:
1.86      kent     2928: Static void
1.65      toshii   2929: uaudio_chan_init(struct chan *ch, int altidx, const struct audio_params *param,
                   2930:     int maxpktsize)
1.1       augustss 2931: {
                   2932:        int samples_per_frame, sample_size;
                   2933:
1.54      kent     2934:        ch->altidx = altidx;
1.93      kent     2935:        sample_size = param->precision * param->channels / 8;
                   2936:        samples_per_frame = param->sample_rate / USB_FRAMES_PER_SECOND;
1.1       augustss 2937:        ch->sample_size = sample_size;
1.93      kent     2938:        ch->sample_rate = param->sample_rate;
1.65      toshii   2939:        if (maxpktsize == 0) {
1.93      kent     2940:                ch->fraction = param->sample_rate % USB_FRAMES_PER_SECOND;
1.65      toshii   2941:                ch->bytes_per_frame = samples_per_frame * sample_size;
                   2942:        } else {
                   2943:                ch->fraction = 0;
                   2944:                ch->bytes_per_frame = maxpktsize;
                   2945:        }
1.1       augustss 2946:        ch->residue = 0;
1.54      kent     2947: }
1.1       augustss 2948:
1.86      kent     2949: Static void
1.54      kent     2950: uaudio_chan_set_param(struct chan *ch, u_char *start, u_char *end, int blksize)
                   2951: {
1.94      kent     2952:
1.1       augustss 2953:        ch->start = start;
                   2954:        ch->end = end;
                   2955:        ch->cur = start;
                   2956:        ch->blksize = blksize;
                   2957:        ch->transferred = 0;
                   2958:        ch->curchanbuf = 0;
                   2959: }
                   2960:
1.86      kent     2961: Static int
1.26      augustss 2962: uaudio_set_params(void *addr, int setmode, int usemode,
1.93      kent     2963:                  struct audio_params *play, struct audio_params *rec,
                   2964:                  stream_filter_list_t *pfil, stream_filter_list_t *rfil)
1.1       augustss 2965: {
1.94      kent     2966:        struct uaudio_softc *sc;
                   2967:        int paltidx, raltidx;
1.38      mycroft  2968:        struct audio_params *p;
1.93      kent     2969:        stream_filter_list_t *fil;
1.92      kent     2970:        int mode, i;
1.1       augustss 2971:
1.94      kent     2972:        sc = addr;
                   2973:        paltidx = -1;
                   2974:        raltidx = -1;
1.1       augustss 2975:        if (sc->sc_dying)
1.94      kent     2976:                return EIO;
1.1       augustss 2977:
1.73      mycroft  2978:        if (((usemode & AUMODE_PLAY) && sc->sc_playchan.pipe != NULL) ||
                   2979:            ((usemode & AUMODE_RECORD) && sc->sc_recchan.pipe != NULL))
1.94      kent     2980:                return EBUSY;
1.1       augustss 2981:
1.92      kent     2982:        if ((usemode & AUMODE_PLAY) && sc->sc_playchan.altidx != -1) {
1.47      jdolecek 2983:                sc->sc_alts[sc->sc_playchan.altidx].sc_busy = 0;
1.92      kent     2984:                AUFMT_VALIDATE(sc->sc_alts[sc->sc_playchan.altidx].aformat);
                   2985:        }
                   2986:        if ((usemode & AUMODE_RECORD) && sc->sc_recchan.altidx != -1) {
1.47      jdolecek 2987:                sc->sc_alts[sc->sc_recchan.altidx].sc_busy = 0;
1.92      kent     2988:                AUFMT_VALIDATE(sc->sc_alts[sc->sc_recchan.altidx].aformat);
                   2989:        }
1.47      jdolecek 2990:
1.76      mycroft  2991:        /* Some uaudio devices are unidirectional.  Don't try to find a
                   2992:           matching mode for the unsupported direction. */
                   2993:        setmode &= sc->sc_mode;
                   2994:
1.38      mycroft  2995:        for (mode = AUMODE_RECORD; mode != -1;
                   2996:             mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
1.76      mycroft  2997:                if ((setmode & mode) == 0)
1.38      mycroft  2998:                        continue;
1.56      kent     2999:
1.93      kent     3000:                if (mode == AUMODE_PLAY) {
                   3001:                        p = play;
                   3002:                        fil = pfil;
                   3003:                } else {
                   3004:                        p = rec;
                   3005:                        fil = rfil;
                   3006:                }
1.92      kent     3007:                i = auconv_set_converter(sc->sc_formats, sc->sc_nformats,
1.93      kent     3008:                                         mode, p, TRUE, fil);
1.50      kent     3009:                if (i < 0)
1.92      kent     3010:                        return EINVAL;
1.73      mycroft  3011:
                   3012:                if (mode == AUMODE_PLAY)
                   3013:                        paltidx = i;
                   3014:                else
                   3015:                        raltidx = i;
1.1       augustss 3016:        }
                   3017:
1.73      mycroft  3018:        if ((setmode & AUMODE_PLAY)) {
1.93      kent     3019:                p = pfil->req_size > 0 ? &pfil->filters[0].param : play;
1.47      jdolecek 3020:                /* XXX abort transfer if currently happening? */
1.93      kent     3021:                uaudio_chan_init(&sc->sc_playchan, paltidx, p, 0);
1.47      jdolecek 3022:        }
1.73      mycroft  3023:        if ((setmode & AUMODE_RECORD)) {
1.93      kent     3024:                p = rfil->req_size > 0 ? &pfil->filters[0].param : rec;
1.47      jdolecek 3025:                /* XXX abort transfer if currently happening? */
1.93      kent     3026:                uaudio_chan_init(&sc->sc_recchan, raltidx, p,
1.65      toshii   3027:                    UGETW(sc->sc_alts[raltidx].edesc->wMaxPacketSize));
1.47      jdolecek 3028:        }
                   3029:
1.92      kent     3030:        if ((usemode & AUMODE_PLAY) && sc->sc_playchan.altidx != -1) {
1.73      mycroft  3031:                sc->sc_alts[sc->sc_playchan.altidx].sc_busy = 1;
1.92      kent     3032:                AUFMT_INVALIDATE(sc->sc_alts[sc->sc_playchan.altidx].aformat);
                   3033:        }
                   3034:        if ((usemode & AUMODE_RECORD) && sc->sc_recchan.altidx != -1) {
1.73      mycroft  3035:                sc->sc_alts[sc->sc_recchan.altidx].sc_busy = 1;
1.92      kent     3036:                AUFMT_INVALIDATE(sc->sc_alts[sc->sc_recchan.altidx].aformat);
                   3037:        }
1.73      mycroft  3038:
1.56      kent     3039:        DPRINTF(("uaudio_set_params: use altidx=p%d/r%d, altno=p%d/r%d\n",
                   3040:                 sc->sc_playchan.altidx, sc->sc_recchan.altidx,
1.47      jdolecek 3041:                 (sc->sc_playchan.altidx >= 0)
                   3042:                   ?sc->sc_alts[sc->sc_playchan.altidx].idesc->bAlternateSetting
                   3043:                   : -1,
                   3044:                 (sc->sc_recchan.altidx >= 0)
                   3045:                   ? sc->sc_alts[sc->sc_recchan.altidx].idesc->bAlternateSetting
                   3046:                   : -1));
1.56      kent     3047:
1.94      kent     3048:        return 0;
1.1       augustss 3049: }
                   3050:
1.86      kent     3051: Static usbd_status
1.26      augustss 3052: uaudio_set_speed(struct uaudio_softc *sc, int endpt, u_int speed)
1.1       augustss 3053: {
                   3054:        usb_device_request_t req;
1.94      kent     3055:        uint8_t data[3];
1.1       augustss 3056:
                   3057:        DPRINTFN(5,("uaudio_set_speed: endpt=%d speed=%u\n", endpt, speed));
                   3058:        req.bmRequestType = UT_WRITE_CLASS_ENDPOINT;
                   3059:        req.bRequest = SET_CUR;
                   3060:        USETW2(req.wValue, SAMPLING_FREQ_CONTROL, 0);
                   3061:        USETW(req.wIndex, endpt);
                   3062:        USETW(req.wLength, 3);
                   3063:        data[0] = speed;
                   3064:        data[1] = speed >> 8;
                   3065:        data[2] = speed >> 16;
                   3066:
1.94      kent     3067:        return usbd_do_request(sc->sc_udev, &req, data);
1.1       augustss 3068: }

CVSweb <webmaster@jp.NetBSD.org>