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