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