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