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