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