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