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