1 /* $NetBSD: uaudio.c,v 1.91 2004/11/05 17:46:14 kent Exp $ */
2 /* $FreeBSD: src/sys/dev/sound/usb/uaudio.c,v 1.14.2.2 2006/04/04 17:34:10 ariff Exp $ */
3 /* $DragonFly: src/sys/dev/sound/usb/uaudio.c,v 1.14 2007/06/28 13:55:12 hasso Exp $: */
6 * Copyright (c) 1999 The NetBSD Foundation, Inc.
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Lennart Augustsson (lennart@augustsson.net) at
11 * Carlstedt Research & Technology.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 * must display the following acknowledgement:
23 * This product includes software developed by the NetBSD
24 * Foundation, Inc. and its contributors.
25 * 4. Neither the name of The NetBSD Foundation nor the names of its
26 * contributors may be used to endorse or promote products derived
27 * from this software without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
30 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
31 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
33 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 * POSSIBILITY OF SUCH DAMAGE.
43 * USB audio specs: http://www.usb.org/developers/devclass_docs/audio10.pdf
44 * http://www.usb.org/developers/devclass_docs/frmts10.pdf
45 * http://www.usb.org/developers/devclass_docs/termt10.pdf
48 #include <sys/cdefs.h>
49 #if defined(__NetBSD__) || defined(__OpenBSD__)
50 __KERNEL_RCSID(0, "$NetBSD: uaudio.c,v 1.91 2004/11/05 17:46:14 kent Exp $");
55 * $NetBSD: uaudio.c,v 1.94 2005/01/15 15:19:53 kent Exp $
56 * $NetBSD: uaudio.c,v 1.95 2005/01/16 06:02:19 dsainty Exp $
57 * $NetBSD: uaudio.c,v 1.96 2005/01/16 12:46:00 kent Exp $
58 * $NetBSD: uaudio.c,v 1.97 2005/02/24 08:19:38 martin Exp $
61 #include <sys/param.h>
62 #include <sys/systm.h>
63 #include <sys/kernel.h>
64 #include <sys/malloc.h>
65 #if defined(__NetBSD__) || defined(__OpenBSD__)
66 #include <sys/device.h>
67 #include <sys/ioctl.h>
71 #include <sys/reboot.h> /* for bootverbose */
72 #include <sys/select.h>
74 #if defined(__NetBSD__) || defined(__OpenBSD__)
75 #include <sys/device.h>
76 #elif defined(__FreeBSD__) || defined(__DragonFly__)
77 #include <sys/module.h>
82 #if defined(__FreeBSD__)
83 #include <sys/sysctl.h>
85 #elif defined(__DragonFly__)
86 #include <sys/sysctl.h>
87 #include <sys/thread2.h>
90 #if defined(__NetBSD__) || defined(__OpenBSD__)
91 #include <sys/audioio.h>
92 #include <dev/audio_if.h>
93 #include <dev/audiovar.h>
94 #include <dev/mulaw.h>
95 #include <dev/auconv.h>
96 #elif defined(__FreeBSD__) || defined(__DragonFly__)
97 #include <dev/sound/pcm/sound.h> /* XXXXX */
98 #include <dev/sound/chip.h>
99 #include "feeder_if.h"
102 #include <bus/usb/usb.h>
103 #include <bus/usb/usbdi.h>
104 #include <bus/usb/usbdi_util.h>
105 #include <bus/usb/usb_quirks.h>
107 #if defined(__NetBSD__) || defined(__OpenBSD__)
108 #include <dev/usb/uaudioreg.h>
109 #elif defined(__FreeBSD__) || defined(__DragonFly__)
110 #include <dev/sound/usb/uaudioreg.h>
111 #include <dev/sound/usb/uaudio.h>
114 #if defined(__NetBSD__) || defined(__OpenBSD__)
115 /* #define UAUDIO_DEBUG */
117 /* #define USB_DEBUG */
119 /* #define UAUDIO_MULTIPLE_ENDPOINTS */
121 #define DPRINTF(x) do { if (uaudiodebug) kprintf x; } while (0)
122 #define DPRINTFN(n,x) do { if (uaudiodebug>(n)) kprintf x; } while (0)
124 #if defined(__FreeBSD__) || defined(__DragonFly__)
125 SYSCTL_NODE(_hw_usb
, OID_AUTO
, uaudio
, CTLFLAG_RW
, 0, "USB uaudio");
126 SYSCTL_INT(_hw_usb_uaudio
, OID_AUTO
, debug
, CTLFLAG_RW
,
127 &uaudiodebug
, 0, "uaudio debug level");
131 #define DPRINTFN(n,x)
134 #define UAUDIO_NCHANBUFS 6 /* number of outstanding request */
135 #if defined(__NetBSD__) || defined(__OpenBSD__)
136 #define UAUDIO_NFRAMES 10 /* ms of sound in each request */
137 #elif defined(__FreeBSD__) || defined(__DragonFly__)
138 #define UAUDIO_NFRAMES 20 /* ms of sound in each request */
142 #define MIX_MAX_CHAN 8
144 uint16_t wValue
[MIX_MAX_CHAN
]; /* using nchan */
149 #define MIX_SIGNED_16 2
150 #define MIX_UNSIGNED_16 3
151 #define MIX_SIGNED_8 4
152 #define MIX_SELECTOR 5
153 #define MIX_SIZE(n) ((n) == MIX_SIGNED_16 || (n) == MIX_UNSIGNED_16 ? 2 : 1)
154 #define MIX_UNSIGNED(n) ((n) == MIX_UNSIGNED_16)
158 #if defined(__FreeBSD__) || defined(__DragonFly__) /* XXXXX */
160 #define MAX_SELECTOR_INPUT_PIN 256
161 uint8_t slctrtype
[MAX_SELECTOR_INPUT_PIN
];
164 #if !defined(__FreeBSD__) && !defined(__DragonFly__)
165 char ctlname
[MAX_AUDIO_DEV_LEN
];
169 #define MAKE(h,l) (((h) << 8) | (l))
174 uint8_t attributes
; /* Copy of bmAttributes of
175 * usb_audio_streaming_endpoint_descriptor
177 usbd_interface_handle ifaceh
;
178 const usb_interface_descriptor_t
*idesc
;
179 const usb_endpoint_descriptor_audio_t
*edesc
;
180 const usb_endpoint_descriptor_audio_t
*edesc1
;
181 const struct usb_audio_streaming_type1_descriptor
*asf1desc
;
182 int sc_busy
; /* currently used */
186 #if defined(__NetBSD__) || defined(__OpenBSD__)
187 void (*intr
)(void *); /* DMA completion intr handler */
188 void *arg
; /* arg for intr() */
190 struct pcm_channel
*pcm_ch
;
192 usbd_pipe_handle pipe
;
193 usbd_pipe_handle sync_pipe
;
197 u_int bytes_per_frame
;
198 u_int fraction
; /* fraction/1000 is the extra samples/frame */
199 u_int residue
; /* accumulates the fractional samples */
201 u_char
*start
; /* upper layer buffer start */
202 u_char
*end
; /* upper layer buffer end */
203 u_char
*cur
; /* current position in upper layer buffer */
204 int blksize
; /* chunk size to report up */
205 int transferred
; /* transferred bytes not reported up */
207 int altidx
; /* currently used altidx */
212 usbd_xfer_handle xfer
;
214 u_int16_t sizes
[UAUDIO_NFRAMES
];
215 u_int16_t offsets
[UAUDIO_NFRAMES
];
217 } chanbufs
[UAUDIO_NCHANBUFS
];
219 struct uaudio_softc
*sc
; /* our softc */
220 #if defined(__FreeBSD__) || defined(__DragonFly__)
227 struct uaudio_softc
{
228 device_t sc_dev
; /* base device */
229 usbd_device_handle sc_udev
; /* USB device */
230 int sc_ac_iface
; /* Audio Control interface */
231 usbd_interface_handle sc_ac_ifaceh
;
232 struct chan sc_playchan
; /* play channel */
233 struct chan sc_recchan
; /* record channel */
236 struct as_info
*sc_alts
; /* alternate settings */
237 int sc_nalts
; /* # of alternate settings */
242 #define HAS_ALAW 0x08
243 #define HAS_MULAW 0x10
244 #define UA_NOFRAC 0x20 /* don't do sample rate adjustment */
247 int sc_mode
; /* play/record capability */
248 struct mixerctl
*sc_ctls
; /* mixer controls */
249 int sc_nctls
; /* # of mixer controls */
250 device_t sc_audiodev
;
252 #if defined(__FreeBSD__) || defined(__DragonFly__)
253 struct sbuf uaudio_sndstat
;
254 int uaudio_sndstat_flag
;
258 struct terminal_list
{
260 uint16_t terminals
[1];
262 #define TERMINAL_LIST_SIZE(N) (offsetof(struct terminal_list, terminals) \
263 + sizeof(uint16_t) * (N))
267 const usb_descriptor_t
*desc
;
268 const struct usb_audio_input_terminal
*it
;
269 const struct usb_audio_output_terminal
*ot
;
270 const struct usb_audio_mixer_unit
*mu
;
271 const struct usb_audio_selector_unit
*su
;
272 const struct usb_audio_feature_unit
*fu
;
273 const struct usb_audio_processing_unit
*pu
;
274 const struct usb_audio_extension_unit
*eu
;
277 struct terminal_list
**inputs
; /* list of source input terminals */
278 struct terminal_list
*output
; /* list of destination output terminals */
279 int direct
; /* directly connected to an output terminal */
286 #define UAC_NCLASSES 4
288 #if defined(__FreeBSD__) || defined(__DragonFly__)
289 #define AudioCinputs "inputs"
290 #define AudioCoutputs "outputs"
291 #define AudioCrecord "record"
292 #define AudioCequalization "equalization"
294 static const char *uac_names
[] = {
295 AudioCoutputs
, AudioCinputs
, AudioCequalization
, AudioCrecord
,
299 static usbd_status uaudio_identify_ac
300 (struct uaudio_softc
*, const usb_config_descriptor_t
*);
301 static usbd_status uaudio_identify_as
302 (struct uaudio_softc
*, const usb_config_descriptor_t
*);
303 static usbd_status uaudio_process_as
304 (struct uaudio_softc
*, const char *, int *, int,
305 const usb_interface_descriptor_t
*);
307 static void uaudio_add_alt(struct uaudio_softc
*, const struct as_info
*);
309 static const usb_interface_descriptor_t
*uaudio_find_iface
310 (const char *, int, int *, int);
312 static void uaudio_mixer_add_ctl(struct uaudio_softc
*, struct mixerctl
*);
314 #if defined(__NetBSD__) || defined(__OpenBSD__)
315 static char *uaudio_id_name
316 (struct uaudio_softc
*, const struct io_terminal
*, int);
320 static void uaudio_dump_cluster(const struct usb_audio_cluster
*);
322 static struct usb_audio_cluster uaudio_get_cluster
323 (int, const struct io_terminal
*);
324 static void uaudio_add_input
325 (struct uaudio_softc
*, const struct io_terminal
*, int);
326 static void uaudio_add_output
327 (struct uaudio_softc
*, const struct io_terminal
*, int);
328 static void uaudio_add_mixer
329 (struct uaudio_softc
*, const struct io_terminal
*, int);
330 static void uaudio_add_selector
331 (struct uaudio_softc
*, const struct io_terminal
*, int);
333 static const char *uaudio_get_terminal_name(int);
335 static int uaudio_determine_class
336 (const struct io_terminal
*, struct mixerctl
*);
337 #if defined(__FreeBSD__) || defined(__DragonFly__)
338 static const int uaudio_feature_name(const struct io_terminal
*,
341 static const char *uaudio_feature_name
342 (const struct io_terminal
*, struct mixerctl
*);
344 static void uaudio_add_feature
345 (struct uaudio_softc
*, const struct io_terminal
*, int);
346 static void uaudio_add_processing_updown
347 (struct uaudio_softc
*, const struct io_terminal
*, int);
348 static void uaudio_add_processing
349 (struct uaudio_softc
*, const struct io_terminal
*, int);
350 static void uaudio_add_extension
351 (struct uaudio_softc
*, const struct io_terminal
*, int);
352 static struct terminal_list
*uaudio_merge_terminal_list
353 (const struct io_terminal
*);
354 static struct terminal_list
*uaudio_io_terminaltype
355 (int, struct io_terminal
*, int);
356 static usbd_status uaudio_identify
357 (struct uaudio_softc
*, const usb_config_descriptor_t
*);
359 static int uaudio_signext(int, int);
360 #if defined(__NetBSD__) || defined(__OpenBSD__)
361 static int uaudio_value2bsd(struct mixerctl
*, int);
363 static int uaudio_bsd2value(struct mixerctl
*, int);
364 static int uaudio_get(struct uaudio_softc
*, int, int, int, int, int);
365 #if defined(__NetBSD__) || defined(__OpenBSD__)
366 static int uaudio_ctl_get
367 (struct uaudio_softc
*, int, struct mixerctl
*, int);
369 static void uaudio_set
370 (struct uaudio_softc
*, int, int, int, int, int, int);
371 static void uaudio_ctl_set
372 (struct uaudio_softc
*, int, struct mixerctl
*, int, int);
374 static usbd_status
uaudio_set_speed(struct uaudio_softc
*, int, u_int
);
376 static usbd_status
uaudio_chan_open(struct uaudio_softc
*, struct chan
*);
377 static void uaudio_chan_close(struct uaudio_softc
*, struct chan
*);
378 static usbd_status uaudio_chan_alloc_buffers
379 (struct uaudio_softc
*, struct chan
*);
380 static void uaudio_chan_free_buffers(struct uaudio_softc
*, struct chan
*);
382 #if defined(__NetBSD__) || defined(__OpenBSD__)
383 static void uaudio_chan_init
384 (struct chan
*, int, const struct audio_params
*, int);
385 static void uaudio_chan_set_param(struct chan
*, u_char
*, u_char
*, int);
388 static void uaudio_chan_ptransfer(struct chan
*);
389 static void uaudio_chan_pintr
390 (usbd_xfer_handle
, usbd_private_handle
, usbd_status
);
392 static void uaudio_chan_rtransfer(struct chan
*);
393 static void uaudio_chan_rintr
394 (usbd_xfer_handle
, usbd_private_handle
, usbd_status
);
396 #if defined(__NetBSD__) || defined(__OpenBSD__)
397 static int uaudio_open(void *, int);
398 static void uaudio_close(void *);
399 static int uaudio_drain(void *);
400 static int uaudio_query_encoding(void *, struct audio_encoding
*);
401 static void uaudio_get_minmax_rates
402 (int, const struct as_info
*, const struct audio_params
*,
403 int, u_long
*, u_long
*);
404 static int uaudio_match_alt_sub
405 (int, const struct as_info
*, const struct audio_params
*, int, u_long
);
406 static int uaudio_match_alt_chan
407 (int, const struct as_info
*, struct audio_params
*, int);
408 static int uaudio_match_alt
409 (int, const struct as_info
*, struct audio_params
*, int);
410 static int uaudio_set_params
411 (void *, int, int, struct audio_params
*, struct audio_params
*);
412 static int uaudio_round_blocksize(void *, int);
413 static int uaudio_trigger_output
414 (void *, void *, void *, int, void (*)(void *), void *,
415 struct audio_params
*);
416 static int uaudio_trigger_input
417 (void *, void *, void *, int, void (*)(void *), void *,
418 struct audio_params
*);
419 static int uaudio_halt_in_dma(void *);
420 static int uaudio_halt_out_dma(void *);
421 static int uaudio_getdev(void *, struct audio_device
*);
422 static int uaudio_mixer_set_port(void *, mixer_ctrl_t
*);
423 static int uaudio_mixer_get_port(void *, mixer_ctrl_t
*);
424 static int uaudio_query_devinfo(void *, mixer_devinfo_t
*);
425 static int uaudio_get_props(void *);
427 static const struct audio_hw_if uaudio_hw_if
= {
431 uaudio_query_encoding
,
433 uaudio_round_blocksize
,
444 uaudio_mixer_set_port
,
445 uaudio_mixer_get_port
,
446 uaudio_query_devinfo
,
452 uaudio_trigger_output
,
453 uaudio_trigger_input
,
457 static struct audio_device uaudio_device
= {
463 #elif defined(__FreeBSD__) || defined(__DragonFly__)
464 static int audio_attach_mi(device_t
);
465 static int uaudio_init_params(struct uaudio_softc
* sc
, struct chan
*ch
, int mode
);
466 static int uaudio_sndstat_prepare_pcm(struct sbuf
*s
, device_t dev
, int verbose
);
468 /* for NetBSD compatibirity */
469 #define AUMODE_PLAY 0x01
470 #define AUMODE_RECORD 0x02
472 #define AUDIO_PROP_FULLDUPLEX 0x01
474 #define AUDIO_ENCODING_ULAW 1
475 #define AUDIO_ENCODING_ALAW 2
476 #define AUDIO_ENCODING_SLINEAR_LE 6
477 #define AUDIO_ENCODING_SLINEAR_BE 7
478 #define AUDIO_ENCODING_ULINEAR_LE 8
479 #define AUDIO_ENCODING_ULINEAR_BE 9
481 #endif /* FreeBSD || DragonFly */
484 #if defined(__NetBSD__) || defined(__OpenBSD__)
486 USB_DECLARE_DRIVER(uaudio
);
488 #elif defined(__FreeBSD__) || defined(__DragonFly__)
490 USB_DECLARE_DRIVER_INIT(uaudio
,
491 DEVMETHOD(device_suspend
, bus_generic_suspend
),
492 DEVMETHOD(device_resume
, bus_generic_resume
),
493 DEVMETHOD(device_shutdown
, bus_generic_shutdown
),
494 DEVMETHOD(bus_print_child
, bus_generic_print_child
)
501 USB_MATCH_START(uaudio
, uaa
);
502 usb_interface_descriptor_t
*id
;
504 if (uaa
->iface
== NULL
)
507 id
= usbd_get_interface_descriptor(uaa
->iface
);
508 /* Trigger on the control interface. */
510 id
->bInterfaceClass
!= UICLASS_AUDIO
||
511 id
->bInterfaceSubClass
!= UISUBCLASS_AUDIOCONTROL
||
512 (usbd_get_quirks(uaa
->device
)->uq_flags
& UQ_BAD_AUDIO
))
515 return UMATCH_IFACECLASS_IFACESUBCLASS
;
520 USB_ATTACH_START(uaudio
, sc
, uaa
);
521 usb_interface_descriptor_t
*id
;
522 usb_config_descriptor_t
*cdesc
;
527 #if defined(__FreeBSD__) || defined(__DragonFly__)
528 usbd_devinfo(uaa
->device
, 0, devinfo
);
531 usbd_devinfo(uaa
->device
, 0, devinfo
, sizeof(devinfo
));
532 kprintf(": %s\n", devinfo
);
535 sc
->sc_udev
= uaa
->device
;
537 cdesc
= usbd_get_config_descriptor(sc
->sc_udev
);
539 kprintf("%s: failed to get configuration descriptor\n",
540 device_get_nameunit(sc
->sc_dev
));
541 USB_ATTACH_ERROR_RETURN
;
544 err
= uaudio_identify(sc
, cdesc
);
546 kprintf("%s: audio descriptors make no sense, error=%d\n",
547 device_get_nameunit(sc
->sc_dev
), err
);
548 USB_ATTACH_ERROR_RETURN
;
551 sc
->sc_ac_ifaceh
= uaa
->iface
;
552 /* Pick up the AS interface. */
553 for (i
= 0; i
< uaa
->nifaces
; i
++) {
554 if (uaa
->ifaces
[i
] == NULL
)
556 id
= usbd_get_interface_descriptor(uaa
->ifaces
[i
]);
560 for (j
= 0; j
< sc
->sc_nalts
; j
++) {
561 if (id
->bInterfaceNumber
==
562 sc
->sc_alts
[j
].idesc
->bInterfaceNumber
) {
563 sc
->sc_alts
[j
].ifaceh
= uaa
->ifaces
[i
];
568 uaa
->ifaces
[i
] = NULL
;
571 for (j
= 0; j
< sc
->sc_nalts
; j
++) {
572 if (sc
->sc_alts
[j
].ifaceh
== NULL
) {
573 kprintf("%s: alt %d missing AS interface(s)\n",
574 device_get_nameunit(sc
->sc_dev
), j
);
575 USB_ATTACH_ERROR_RETURN
;
579 kprintf("%s: audio rev %d.%02x\n", device_get_nameunit(sc
->sc_dev
),
580 sc
->sc_audio_rev
>> 8, sc
->sc_audio_rev
& 0xff);
582 sc
->sc_playchan
.sc
= sc
->sc_recchan
.sc
= sc
;
583 sc
->sc_playchan
.altidx
= -1;
584 sc
->sc_recchan
.altidx
= -1;
586 if (usbd_get_quirks(sc
->sc_udev
)->uq_flags
& UQ_AU_NO_FRAC
)
587 sc
->sc_altflags
|= UA_NOFRAC
;
592 kprintf("%s: %d mixer controls\n", device_get_nameunit(sc
->sc_dev
),
595 #if !defined(__FreeBSD__) && !defined(__DragonFly__)
596 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH
, sc
->sc_udev
,
600 DPRINTF(("uaudio_attach: doing audio_attach_mi\n"));
601 #if defined(__OpenBSD__)
602 audio_attach_mi(&uaudio_hw_if
, sc
, &sc
->sc_dev
);
603 #elif defined(__NetBSD__)
604 sc
->sc_audiodev
= audio_attach_mi(&uaudio_hw_if
, sc
, &sc
->sc_dev
);
605 #elif defined(__FreeBSD__) || defined(__DragonFly__)
607 if (audio_attach_mi(sc
->sc_dev
)) {
608 kprintf("audio_attach_mi failed\n");
609 USB_ATTACH_ERROR_RETURN
;
613 USB_ATTACH_SUCCESS_RETURN
;
616 #if defined(__NetBSD__) || defined(__OpenBSD__)
618 uaudio_activate(device_t self
, enum devact act
)
620 struct uaudio_softc
*sc
;
623 sc
= (struct uaudio_softc
*)self
;
629 case DVACT_DEACTIVATE
:
630 if (sc
->sc_audiodev
!= NULL
)
631 rv
= config_deactivate(sc
->sc_audiodev
);
639 #if defined(__NetBSD__) || defined(__OpenBSD__)
641 uaudio_detach(device_t self
, int flags
)
643 struct uaudio_softc
*sc
;
646 sc
= (struct uaudio_softc
*)self
;
648 /* Wait for outstanding requests to complete. */
649 usbd_delay_ms(sc
->sc_udev
, UAUDIO_NCHANBUFS
* UAUDIO_NFRAMES
);
651 if (sc
->sc_audiodev
!= NULL
)
652 rv
= config_detach(sc
->sc_audiodev
, flags
);
654 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH
, sc
->sc_udev
,
659 #elif defined(__FreeBSD__) || defined(__DragonFly__)
663 USB_DETACH_START(uaudio
, sc
);
665 sbuf_delete(&(sc
->uaudio_sndstat
));
666 sc
->uaudio_sndstat_flag
= 0;
671 /* Wait for outstanding requests to complete. */
672 usbd_delay_ms(sc
->sc_udev
, UAUDIO_NCHANBUFS
* UAUDIO_NFRAMES
);
676 return bus_generic_detach(sc
->sc_dev
);
680 #if defined(__NetBSD__) || defined(__OpenBSD__)
682 uaudio_query_encoding(void *addr
, struct audio_encoding
*fp
)
684 struct uaudio_softc
*sc
;
689 flags
= sc
->sc_altflags
;
693 if (sc
->sc_nalts
== 0 || flags
== 0)
699 strlcpy(fp
->name
, AudioEulinear
, sizeof(fp
->name
));
700 fp
->encoding
= AUDIO_ENCODING_ULINEAR
;
702 fp
->flags
= flags
&HAS_8U
? 0 : AUDIO_ENCODINGFLAG_EMULATED
;
705 strlcpy(fp
->name
, AudioEmulaw
, sizeof(fp
->name
));
706 fp
->encoding
= AUDIO_ENCODING_ULAW
;
708 fp
->flags
= flags
&HAS_MULAW
? 0 : AUDIO_ENCODINGFLAG_EMULATED
;
711 strlcpy(fp
->name
, AudioEalaw
, sizeof(fp
->name
));
712 fp
->encoding
= AUDIO_ENCODING_ALAW
;
714 fp
->flags
= flags
&HAS_ALAW
? 0 : AUDIO_ENCODINGFLAG_EMULATED
;
717 strlcpy(fp
->name
, AudioEslinear
, sizeof(fp
->name
));
718 fp
->encoding
= AUDIO_ENCODING_SLINEAR
;
720 fp
->flags
= flags
&HAS_8
? 0 : AUDIO_ENCODINGFLAG_EMULATED
;
723 strlcpy(fp
->name
, AudioEslinear_le
, sizeof(fp
->name
));
724 fp
->encoding
= AUDIO_ENCODING_SLINEAR_LE
;
729 strlcpy(fp
->name
, AudioEulinear_le
, sizeof(fp
->name
));
730 fp
->encoding
= AUDIO_ENCODING_ULINEAR_LE
;
732 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
735 strlcpy(fp
->name
, AudioEslinear_be
, sizeof(fp
->name
));
736 fp
->encoding
= AUDIO_ENCODING_SLINEAR_BE
;
738 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
741 strlcpy(fp
->name
, AudioEulinear_be
, sizeof(fp
->name
));
742 fp
->encoding
= AUDIO_ENCODING_ULINEAR_BE
;
744 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
752 static const usb_interface_descriptor_t
*
753 uaudio_find_iface(const char *buf
, int size
, int *offsp
, int subtype
)
755 const usb_interface_descriptor_t
*d
;
757 while (*offsp
< size
) {
758 d
= (const void *)(buf
+ *offsp
);
759 *offsp
+= d
->bLength
;
760 if (d
->bDescriptorType
== UDESC_INTERFACE
&&
761 d
->bInterfaceClass
== UICLASS_AUDIO
&&
762 d
->bInterfaceSubClass
== subtype
)
769 uaudio_mixer_add_ctl(struct uaudio_softc
*sc
, struct mixerctl
*mc
)
773 struct mixerctl
*nmc
;
775 #if defined(__FreeBSD__) || defined(__DragonFly__)
776 if (mc
->class < UAC_NCLASSES
) {
777 DPRINTF(("%s: adding %s.%d\n",
778 __func__
, uac_names
[mc
->class], mc
->ctl
));
780 DPRINTF(("%s: adding %d\n", __func__
, mc
->ctl
));
783 if (mc
->class < UAC_NCLASSES
) {
784 DPRINTF(("%s: adding %s.%s\n",
785 __func__
, uac_names
[mc
->class], mc
->ctlname
));
787 DPRINTF(("%s: adding %s\n", __func__
, mc
->ctlname
));
790 len
= sizeof(*mc
) * (sc
->sc_nctls
+ 1);
791 nmc
= kmalloc(len
, M_USBDEV
, M_NOWAIT
);
793 kprintf("uaudio_mixer_add_ctl: no memory\n");
796 /* Copy old data, if there was any */
797 if (sc
->sc_nctls
!= 0) {
798 memcpy(nmc
, sc
->sc_ctls
, sizeof(*mc
) * (sc
->sc_nctls
));
799 kfree(sc
->sc_ctls
, M_USBDEV
);
804 if (mc
->type
== MIX_ON_OFF
) {
807 } else if (mc
->type
== MIX_SELECTOR
) {
810 /* Determine min and max values. */
811 mc
->minval
= uaudio_signext(mc
->type
,
812 uaudio_get(sc
, GET_MIN
, UT_READ_CLASS_INTERFACE
,
813 mc
->wValue
[0], mc
->wIndex
,
814 MIX_SIZE(mc
->type
)));
815 mc
->maxval
= 1 + uaudio_signext(mc
->type
,
816 uaudio_get(sc
, GET_MAX
, UT_READ_CLASS_INTERFACE
,
817 mc
->wValue
[0], mc
->wIndex
,
818 MIX_SIZE(mc
->type
)));
819 mc
->mul
= mc
->maxval
- mc
->minval
;
822 res
= uaudio_get(sc
, GET_RES
, UT_READ_CLASS_INTERFACE
,
823 mc
->wValue
[0], mc
->wIndex
,
826 mc
->delta
= (res
* 255 + mc
->mul
/2) / mc
->mul
;
829 sc
->sc_ctls
[sc
->sc_nctls
++] = *mc
;
832 if (uaudiodebug
> 2) {
834 DPRINTF(("uaudio_mixer_add_ctl: wValue=%04x",mc
->wValue
[0]));
835 for (i
= 1; i
< mc
->nchan
; i
++)
836 DPRINTF((",%04x", mc
->wValue
[i
]));
837 #if defined(__FreeBSD__) || defined(__DragonFly__)
838 DPRINTF((" wIndex=%04x type=%d ctl='%d' "
840 mc
->wIndex
, mc
->type
, mc
->ctl
,
841 mc
->minval
, mc
->maxval
));
843 DPRINTF((" wIndex=%04x type=%d name='%s' unit='%s' "
845 mc
->wIndex
, mc
->type
, mc
->ctlname
, mc
->ctlunit
,
846 mc
->minval
, mc
->maxval
));
852 #if defined(__NetBSD__) || defined(__OpenBSD__)
854 uaudio_id_name(struct uaudio_softc
*sc
, const struct io_terminal
*iot
, int id
)
858 ksnprintf(buf
, sizeof(buf
), "i%d", id
);
865 uaudio_dump_cluster(const struct usb_audio_cluster
*cl
)
867 static const char *channel_names
[16] = {
868 "LEFT", "RIGHT", "CENTER", "LFE",
869 "LEFT_SURROUND", "RIGHT_SURROUND", "LEFT_CENTER", "RIGHT_CENTER",
870 "SURROUND", "LEFT_SIDE", "RIGHT_SIDE", "TOP",
871 "RESERVED12", "RESERVED13", "RESERVED14", "RESERVED15",
875 cc
= UGETW(cl
->wChannelConfig
);
876 kprintf("cluster: bNrChannels=%u wChannelConfig=0x%.4x",
877 cl
->bNrChannels
, cc
);
879 for (i
= 0; cc
!= 0; i
++) {
881 kprintf("%c%s", first
? '<' : ',', channel_names
[i
]);
886 kprintf("> iChannelNames=%u", cl
->iChannelNames
);
890 static struct usb_audio_cluster
891 uaudio_get_cluster(int id
, const struct io_terminal
*iot
)
893 struct usb_audio_cluster r
;
894 const usb_descriptor_t
*dp
;
897 for (i
= 0; i
< 25; i
++) { /* avoid infinite loops */
901 switch (dp
->bDescriptorSubtype
) {
902 case UDESCSUB_AC_INPUT
:
903 r
.bNrChannels
= iot
[id
].d
.it
->bNrChannels
;
904 USETW(r
.wChannelConfig
, UGETW(iot
[id
].d
.it
->wChannelConfig
));
905 r
.iChannelNames
= iot
[id
].d
.it
->iChannelNames
;
907 case UDESCSUB_AC_OUTPUT
:
908 id
= iot
[id
].d
.ot
->bSourceId
;
910 case UDESCSUB_AC_MIXER
:
911 r
= *(const struct usb_audio_cluster
*)
912 &iot
[id
].d
.mu
->baSourceId
[iot
[id
].d
.mu
->bNrInPins
];
914 case UDESCSUB_AC_SELECTOR
:
915 /* XXX This is not really right */
916 id
= iot
[id
].d
.su
->baSourceId
[0];
918 case UDESCSUB_AC_FEATURE
:
919 id
= iot
[id
].d
.fu
->bSourceId
;
921 case UDESCSUB_AC_PROCESSING
:
922 r
= *(const struct usb_audio_cluster
*)
923 &iot
[id
].d
.pu
->baSourceId
[iot
[id
].d
.pu
->bNrInPins
];
925 case UDESCSUB_AC_EXTENSION
:
926 r
= *(const struct usb_audio_cluster
*)
927 &iot
[id
].d
.eu
->baSourceId
[iot
[id
].d
.eu
->bNrInPins
];
934 kprintf("uaudio_get_cluster: bad data\n");
935 memset(&r
, 0, sizeof r
);
941 uaudio_add_input(struct uaudio_softc
*sc
, const struct io_terminal
*iot
, int id
)
944 const struct usb_audio_input_terminal
*d
= iot
[id
].d
.it
;
946 DPRINTFN(2,("uaudio_add_input: bTerminalId=%d wTerminalType=0x%04x "
947 "bAssocTerminal=%d bNrChannels=%d wChannelConfig=%d "
948 "iChannelNames=%d iTerminal=%d\n",
949 d
->bTerminalId
, UGETW(d
->wTerminalType
), d
->bAssocTerminal
,
950 d
->bNrChannels
, UGETW(d
->wChannelConfig
),
951 d
->iChannelNames
, d
->iTerminal
));
956 uaudio_add_output(struct uaudio_softc
*sc
, const struct io_terminal
*iot
, int id
)
959 const struct usb_audio_output_terminal
*d
;
962 DPRINTFN(2,("uaudio_add_output: bTerminalId=%d wTerminalType=0x%04x "
963 "bAssocTerminal=%d bSourceId=%d iTerminal=%d\n",
964 d
->bTerminalId
, UGETW(d
->wTerminalType
), d
->bAssocTerminal
,
965 d
->bSourceId
, d
->iTerminal
));
970 uaudio_add_mixer(struct uaudio_softc
*sc
, const struct io_terminal
*iot
, int id
)
972 const struct usb_audio_mixer_unit
*d
= iot
[id
].d
.mu
;
973 const struct usb_audio_mixer_unit_1
*d1
;
974 int c
, chs
, ichs
, ochs
, i
, o
, bno
, p
, mo
, mc
, k
;
978 DPRINTFN(2,("uaudio_add_mixer: bUnitId=%d bNrInPins=%d\n",
979 d
->bUnitId
, d
->bNrInPins
));
981 /* Compute the number of input channels */
983 for (i
= 0; i
< d
->bNrInPins
; i
++)
984 ichs
+= uaudio_get_cluster(d
->baSourceId
[i
], iot
).bNrChannels
;
986 /* and the number of output channels */
987 d1
= (const struct usb_audio_mixer_unit_1
*)&d
->baSourceId
[d
->bNrInPins
];
988 ochs
= d1
->bNrChannels
;
989 DPRINTFN(2,("uaudio_add_mixer: ichs=%d ochs=%d\n", ichs
, ochs
));
992 mix
.wIndex
= MAKE(d
->bUnitId
, sc
->sc_ac_iface
);
993 uaudio_determine_class(&iot
[id
], &mix
);
994 mix
.type
= MIX_SIGNED_16
;
995 #if !defined(__FreeBSD__) && !defined(__DragonFly__) /* XXXXX */
996 mix
.ctlunit
= AudioNvolume
;
999 #define BIT(bno) ((bm[bno / 8] >> (7 - bno % 8)) & 1)
1000 for (p
= i
= 0; i
< d
->bNrInPins
; i
++) {
1001 chs
= uaudio_get_cluster(d
->baSourceId
[i
], iot
).bNrChannels
;
1003 for (c
= 0; c
< chs
; c
++) {
1005 for (o
= 0; o
< ochs
; o
++) {
1006 bno
= (p
+ c
) * ochs
+ o
;
1013 if (mc
== chs
&& chs
<= MIX_MAX_CHAN
) {
1015 for (c
= 0; c
< chs
; c
++)
1016 for (o
= 0; o
< ochs
; o
++) {
1017 bno
= (p
+ c
) * ochs
+ o
;
1022 #if !defined(__FreeBSD__) && !defined(__DragonFly__)
1023 ksnprintf(mix
.ctlname
, sizeof(mix
.ctlname
), "mix%d-%s",
1024 d
->bUnitId
, uaudio_id_name(sc
, iot
,
1028 uaudio_mixer_add_ctl(sc
, &mix
);
1039 uaudio_add_selector(struct uaudio_softc
*sc
, const struct io_terminal
*iot
, int id
)
1041 const struct usb_audio_selector_unit
*d
;
1042 struct mixerctl mix
;
1043 #if !defined(__FreeBSD__) && !defined(__DragonFly__)
1047 struct mixerctl dummy
;
1051 DPRINTFN(2,("uaudio_add_selector: bUnitId=%d bNrInPins=%d\n",
1052 d
->bUnitId
, d
->bNrInPins
));
1053 mix
.wIndex
= MAKE(d
->bUnitId
, sc
->sc_ac_iface
);
1054 mix
.wValue
[0] = MAKE(0, 0);
1055 uaudio_determine_class(&iot
[id
], &mix
);
1057 mix
.type
= MIX_SELECTOR
;
1058 #if defined(__FreeBSD__) || defined(__DragonFly__)
1059 mix
.ctl
= SOUND_MIXER_NRDEVICES
; /* XXXXX */
1061 mix
.maxval
= d
->bNrInPins
;
1062 mix
.mul
= mix
.maxval
- mix
.minval
;
1063 for (i
= 0; i
< MAX_SELECTOR_INPUT_PIN
; i
++) {
1064 mix
.slctrtype
[i
] = SOUND_MIXER_NRDEVICES
;
1066 for (i
= mix
.minval
; i
<= mix
.maxval
; i
++) {
1067 mix
.slctrtype
[i
- 1] = uaudio_feature_name(&iot
[d
->baSourceId
[i
- 1]], &dummy
);
1072 mix
.maxval
= d
->bNrInPins
;
1073 mix
.mul
= mix
.maxval
- mix
.minval
;
1074 wp
= ksnprintf(mix
.ctlname
, MAX_AUDIO_DEV_LEN
, "sel%d-", d
->bUnitId
);
1075 for (i
= 1; i
<= d
->bNrInPins
; i
++) {
1076 wp
+= ksnprintf(mix
.ctlname
+ wp
, MAX_AUDIO_DEV_LEN
- wp
,
1077 "i%d", d
->baSourceId
[i
- 1]);
1078 if (wp
> MAX_AUDIO_DEV_LEN
- 1)
1082 uaudio_mixer_add_ctl(sc
, &mix
);
1087 uaudio_get_terminal_name(int terminal_type
)
1089 static char buf
[100];
1091 switch (terminal_type
) {
1092 /* USB terminal types */
1093 case UAT_UNDEFINED
: return "UAT_UNDEFINED";
1094 case UAT_STREAM
: return "UAT_STREAM";
1095 case UAT_VENDOR
: return "UAT_VENDOR";
1096 /* input terminal types */
1097 case UATI_UNDEFINED
: return "UATI_UNDEFINED";
1098 case UATI_MICROPHONE
: return "UATI_MICROPHONE";
1099 case UATI_DESKMICROPHONE
: return "UATI_DESKMICROPHONE";
1100 case UATI_PERSONALMICROPHONE
: return "UATI_PERSONALMICROPHONE";
1101 case UATI_OMNIMICROPHONE
: return "UATI_OMNIMICROPHONE";
1102 case UATI_MICROPHONEARRAY
: return "UATI_MICROPHONEARRAY";
1103 case UATI_PROCMICROPHONEARR
: return "UATI_PROCMICROPHONEARR";
1104 /* output terminal types */
1105 case UATO_UNDEFINED
: return "UATO_UNDEFINED";
1106 case UATO_SPEAKER
: return "UATO_SPEAKER";
1107 case UATO_HEADPHONES
: return "UATO_HEADPHONES";
1108 case UATO_DISPLAYAUDIO
: return "UATO_DISPLAYAUDIO";
1109 case UATO_DESKTOPSPEAKER
: return "UATO_DESKTOPSPEAKER";
1110 case UATO_ROOMSPEAKER
: return "UATO_ROOMSPEAKER";
1111 case UATO_COMMSPEAKER
: return "UATO_COMMSPEAKER";
1112 case UATO_SUBWOOFER
: return "UATO_SUBWOOFER";
1113 /* bidir terminal types */
1114 case UATB_UNDEFINED
: return "UATB_UNDEFINED";
1115 case UATB_HANDSET
: return "UATB_HANDSET";
1116 case UATB_HEADSET
: return "UATB_HEADSET";
1117 case UATB_SPEAKERPHONE
: return "UATB_SPEAKERPHONE";
1118 case UATB_SPEAKERPHONEESUP
: return "UATB_SPEAKERPHONEESUP";
1119 case UATB_SPEAKERPHONEECANC
: return "UATB_SPEAKERPHONEECANC";
1120 /* telephony terminal types */
1121 case UATT_UNDEFINED
: return "UATT_UNDEFINED";
1122 case UATT_PHONELINE
: return "UATT_PHONELINE";
1123 case UATT_TELEPHONE
: return "UATT_TELEPHONE";
1124 case UATT_DOWNLINEPHONE
: return "UATT_DOWNLINEPHONE";
1125 /* external terminal types */
1126 case UATE_UNDEFINED
: return "UATE_UNDEFINED";
1127 case UATE_ANALOGCONN
: return "UATE_ANALOGCONN";
1128 case UATE_LINECONN
: return "UATE_LINECONN";
1129 case UATE_LEGACYCONN
: return "UATE_LEGACYCONN";
1130 case UATE_DIGITALAUIFC
: return "UATE_DIGITALAUIFC";
1131 case UATE_SPDIF
: return "UATE_SPDIF";
1132 case UATE_1394DA
: return "UATE_1394DA";
1133 case UATE_1394DV
: return "UATE_1394DV";
1134 /* embedded function terminal types */
1135 case UATF_UNDEFINED
: return "UATF_UNDEFINED";
1136 case UATF_CALIBNOISE
: return "UATF_CALIBNOISE";
1137 case UATF_EQUNOISE
: return "UATF_EQUNOISE";
1138 case UATF_CDPLAYER
: return "UATF_CDPLAYER";
1139 case UATF_DAT
: return "UATF_DAT";
1140 case UATF_DCC
: return "UATF_DCC";
1141 case UATF_MINIDISK
: return "UATF_MINIDISK";
1142 case UATF_ANALOGTAPE
: return "UATF_ANALOGTAPE";
1143 case UATF_PHONOGRAPH
: return "UATF_PHONOGRAPH";
1144 case UATF_VCRAUDIO
: return "UATF_VCRAUDIO";
1145 case UATF_VIDEODISCAUDIO
: return "UATF_VIDEODISCAUDIO";
1146 case UATF_DVDAUDIO
: return "UATF_DVDAUDIO";
1147 case UATF_TVTUNERAUDIO
: return "UATF_TVTUNERAUDIO";
1148 case UATF_SATELLITE
: return "UATF_SATELLITE";
1149 case UATF_CABLETUNER
: return "UATF_CABLETUNER";
1150 case UATF_DSS
: return "UATF_DSS";
1151 case UATF_RADIORECV
: return "UATF_RADIORECV";
1152 case UATF_RADIOXMIT
: return "UATF_RADIOXMIT";
1153 case UATF_MULTITRACK
: return "UATF_MULTITRACK";
1154 case UATF_SYNTHESIZER
: return "UATF_SYNTHESIZER";
1156 ksnprintf(buf
, sizeof(buf
), "unknown type (0x%.4x)", terminal_type
);
1163 uaudio_determine_class(const struct io_terminal
*iot
, struct mixerctl
*mix
)
1167 if (iot
== NULL
|| iot
->output
== NULL
) {
1168 mix
->class = UAC_OUTPUT
;
1172 if (iot
->output
->size
== 1)
1173 terminal_type
= iot
->output
->terminals
[0];
1175 * If the only output terminal is USB,
1176 * the class is UAC_RECORD.
1178 if ((terminal_type
& 0xff00) == (UAT_UNDEFINED
& 0xff00)) {
1179 mix
->class = UAC_RECORD
;
1180 if (iot
->inputs_size
== 1
1181 && iot
->inputs
[0] != NULL
1182 && iot
->inputs
[0]->size
== 1)
1183 return iot
->inputs
[0]->terminals
[0];
1188 * If the ultimate destination of the unit is just one output
1189 * terminal and the unit is connected to the output terminal
1190 * directly, the class is UAC_OUTPUT.
1192 if (terminal_type
!= 0 && iot
->direct
) {
1193 mix
->class = UAC_OUTPUT
;
1194 return terminal_type
;
1197 * If the unit is connected to just one input terminal,
1198 * the class is UAC_INPUT.
1200 if (iot
->inputs_size
== 1 && iot
->inputs
[0] != NULL
1201 && iot
->inputs
[0]->size
== 1) {
1202 mix
->class = UAC_INPUT
;
1203 return iot
->inputs
[0]->terminals
[0];
1206 * Otherwise, the class is UAC_OUTPUT.
1208 mix
->class = UAC_OUTPUT
;
1209 return terminal_type
;
1212 #if defined(__FreeBSD__) || defined(__DragonFly__)
1214 uaudio_feature_name(const struct io_terminal
*iot
, struct mixerctl
*mix
)
1218 terminal_type
= uaudio_determine_class(iot
, mix
);
1219 if (mix
->class == UAC_RECORD
&& terminal_type
== 0)
1220 return SOUND_MIXER_IMIX
;
1221 DPRINTF(("%s: terminal_type=%s\n", __func__
,
1222 uaudio_get_terminal_name(terminal_type
)));
1223 switch (terminal_type
) {
1225 return SOUND_MIXER_PCM
;
1227 case UATI_MICROPHONE
:
1228 case UATI_DESKMICROPHONE
:
1229 case UATI_PERSONALMICROPHONE
:
1230 case UATI_OMNIMICROPHONE
:
1231 case UATI_MICROPHONEARRAY
:
1232 case UATI_PROCMICROPHONEARR
:
1233 return SOUND_MIXER_MIC
;
1236 case UATO_DESKTOPSPEAKER
:
1237 case UATO_ROOMSPEAKER
:
1238 case UATO_COMMSPEAKER
:
1239 return SOUND_MIXER_SPEAKER
;
1241 case UATE_ANALOGCONN
:
1243 case UATE_LEGACYCONN
:
1244 return SOUND_MIXER_LINE
;
1246 case UATE_DIGITALAUIFC
:
1250 return SOUND_MIXER_ALTPCM
;
1253 return SOUND_MIXER_CD
;
1255 case UATF_SYNTHESIZER
:
1256 return SOUND_MIXER_SYNTH
;
1258 case UATF_VIDEODISCAUDIO
:
1260 case UATF_TVTUNERAUDIO
:
1261 return SOUND_MIXER_VIDEO
;
1263 /* telephony terminal types */
1264 case UATT_UNDEFINED
:
1265 case UATT_PHONELINE
:
1266 case UATT_TELEPHONE
:
1267 case UATT_DOWNLINEPHONE
:
1268 return SOUND_MIXER_PHONEIN
;
1269 /* return SOUND_MIXER_PHONEOUT;*/
1271 case UATF_RADIORECV
:
1272 case UATF_RADIOXMIT
:
1273 return SOUND_MIXER_RADIO
;
1277 case UATI_UNDEFINED
:
1278 /* output terminal types */
1279 case UATO_UNDEFINED
:
1280 case UATO_DISPLAYAUDIO
:
1281 case UATO_SUBWOOFER
:
1282 case UATO_HEADPHONES
:
1283 /* bidir terminal types */
1284 case UATB_UNDEFINED
:
1287 case UATB_SPEAKERPHONE
:
1288 case UATB_SPEAKERPHONEESUP
:
1289 case UATB_SPEAKERPHONEECANC
:
1290 /* external terminal types */
1291 case UATE_UNDEFINED
:
1292 /* embedded function terminal types */
1293 case UATF_UNDEFINED
:
1294 case UATF_CALIBNOISE
:
1299 case UATF_ANALOGTAPE
:
1300 case UATF_PHONOGRAPH
:
1302 case UATF_SATELLITE
:
1303 case UATF_CABLETUNER
:
1305 case UATF_MULTITRACK
:
1308 DPRINTF(("%s: 'master' for 0x%.4x\n", __func__
, terminal_type
));
1309 return SOUND_MIXER_VOLUME
;
1311 return SOUND_MIXER_VOLUME
;
1315 uaudio_feature_name(const struct io_terminal
*iot
, struct mixerctl
*mix
)
1319 terminal_type
= uaudio_determine_class(iot
, mix
);
1320 if (mix
->class == UAC_RECORD
&& terminal_type
== 0)
1321 return AudioNmixerout
;
1322 DPRINTF(("%s: terminal_type=%s\n", __func__
,
1323 uaudio_get_terminal_name(terminal_type
)));
1324 switch (terminal_type
) {
1328 case UATI_MICROPHONE
:
1329 case UATI_DESKMICROPHONE
:
1330 case UATI_PERSONALMICROPHONE
:
1331 case UATI_OMNIMICROPHONE
:
1332 case UATI_MICROPHONEARRAY
:
1333 case UATI_PROCMICROPHONEARR
:
1334 return AudioNmicrophone
;
1337 case UATO_DESKTOPSPEAKER
:
1338 case UATO_ROOMSPEAKER
:
1339 case UATO_COMMSPEAKER
:
1340 return AudioNspeaker
;
1342 case UATO_HEADPHONES
:
1343 return AudioNheadphone
;
1345 case UATO_SUBWOOFER
:
1348 /* telephony terminal types */
1349 case UATT_UNDEFINED
:
1350 case UATT_PHONELINE
:
1351 case UATT_TELEPHONE
:
1352 case UATT_DOWNLINEPHONE
:
1355 case UATE_ANALOGCONN
:
1357 case UATE_LEGACYCONN
:
1360 case UATE_DIGITALAUIFC
:
1369 case UATF_SYNTHESIZER
:
1370 return AudioNfmsynth
;
1372 case UATF_VIDEODISCAUDIO
:
1374 case UATF_TVTUNERAUDIO
:
1379 case UATI_UNDEFINED
:
1380 /* output terminal types */
1381 case UATO_UNDEFINED
:
1382 case UATO_DISPLAYAUDIO
:
1383 /* bidir terminal types */
1384 case UATB_UNDEFINED
:
1387 case UATB_SPEAKERPHONE
:
1388 case UATB_SPEAKERPHONEESUP
:
1389 case UATB_SPEAKERPHONEECANC
:
1390 /* external terminal types */
1391 case UATE_UNDEFINED
:
1392 /* embedded function terminal types */
1393 case UATF_UNDEFINED
:
1394 case UATF_CALIBNOISE
:
1399 case UATF_ANALOGTAPE
:
1400 case UATF_PHONOGRAPH
:
1402 case UATF_SATELLITE
:
1403 case UATF_CABLETUNER
:
1405 case UATF_RADIORECV
:
1406 case UATF_RADIOXMIT
:
1407 case UATF_MULTITRACK
:
1410 DPRINTF(("%s: 'master' for 0x%.4x\n", __func__
, terminal_type
));
1411 return AudioNmaster
;
1413 return AudioNmaster
;
1418 uaudio_add_feature(struct uaudio_softc
*sc
, const struct io_terminal
*iot
, int id
)
1420 const struct usb_audio_feature_unit
*d
;
1424 u_int fumask
, mmask
, cmask
;
1425 struct mixerctl mix
;
1426 int chan
, ctl
, i
, unit
;
1427 #if defined(__FreeBSD__) || defined(__DragonFly__)
1430 const char *mixername
;
1433 #define GET(i) (ctls[(i)*ctlsize] | \
1434 (ctlsize > 1 ? ctls[(i)*ctlsize+1] << 8 : 0))
1436 ctls
= d
->bmaControls
;
1437 ctlsize
= d
->bControlSize
;
1438 nchan
= (d
->bLength
- 7) / ctlsize
;
1440 /* Figure out what we can control */
1441 for (cmask
= 0, chan
= 1; chan
< nchan
; chan
++) {
1442 DPRINTFN(9,("uaudio_add_feature: chan=%d mask=%x\n",
1447 #if !defined(__FreeBSD__) && !defined(__DragonFly__)
1448 DPRINTFN(1,("uaudio_add_feature: bUnitId=%d, "
1449 "%d channels, mmask=0x%04x, cmask=0x%04x\n",
1450 d
->bUnitId
, nchan
, mmask
, cmask
));
1453 if (nchan
> MIX_MAX_CHAN
)
1454 nchan
= MIX_MAX_CHAN
;
1456 mix
.wIndex
= MAKE(unit
, sc
->sc_ac_iface
);
1457 for (ctl
= MUTE_CONTROL
; ctl
< LOUDNESS_CONTROL
; ctl
++) {
1458 fumask
= FU_MASK(ctl
);
1459 DPRINTFN(4,("uaudio_add_feature: ctl=%d fumask=0x%04x\n",
1461 if (mmask
& fumask
) {
1463 mix
.wValue
[0] = MAKE(ctl
, 0);
1464 } else if (cmask
& fumask
) {
1465 mix
.nchan
= nchan
- 1;
1466 for (i
= 1; i
< nchan
; i
++) {
1467 if (GET(i
) & fumask
)
1468 mix
.wValue
[i
-1] = MAKE(ctl
, i
);
1470 mix
.wValue
[i
-1] = -1;
1477 #if defined(__FreeBSD__) || defined(__DragonFly__)
1478 mixernumber
= uaudio_feature_name(&iot
[id
], &mix
);
1480 mixername
= uaudio_feature_name(&iot
[id
], &mix
);
1484 mix
.type
= MIX_ON_OFF
;
1485 #if defined(__FreeBSD__) || defined(__DragonFly__)
1486 mix
.ctl
= SOUND_MIXER_NRDEVICES
;
1489 ksnprintf(mix
.ctlname
, sizeof(mix
.ctlname
),
1490 "%s.%s", mixername
, AudioNmute
);
1493 case VOLUME_CONTROL
:
1494 mix
.type
= MIX_SIGNED_16
;
1495 #if defined(__FreeBSD__) || defined(__DragonFly__)
1496 mix
.ctl
= mixernumber
;
1498 mix
.ctlunit
= AudioNvolume
;
1499 strlcpy(mix
.ctlname
, mixername
, sizeof(mix
.ctlname
));
1503 mix
.type
= MIX_SIGNED_8
;
1504 #if defined(__FreeBSD__) || defined(__DragonFly__)
1505 mix
.ctl
= SOUND_MIXER_BASS
;
1507 mix
.ctlunit
= AudioNbass
;
1508 ksnprintf(mix
.ctlname
, sizeof(mix
.ctlname
),
1509 "%s.%s", mixername
, AudioNbass
);
1513 mix
.type
= MIX_SIGNED_8
;
1514 #if defined(__FreeBSD__) || defined(__DragonFly__)
1515 mix
.ctl
= SOUND_MIXER_NRDEVICES
; /* XXXXX */
1517 mix
.ctlunit
= AudioNmid
;
1518 ksnprintf(mix
.ctlname
, sizeof(mix
.ctlname
),
1519 "%s.%s", mixername
, AudioNmid
);
1522 case TREBLE_CONTROL
:
1523 mix
.type
= MIX_SIGNED_8
;
1524 #if defined(__FreeBSD__) || defined(__DragonFly__)
1525 mix
.ctl
= SOUND_MIXER_TREBLE
;
1527 mix
.ctlunit
= AudioNtreble
;
1528 ksnprintf(mix
.ctlname
, sizeof(mix
.ctlname
),
1529 "%s.%s", mixername
, AudioNtreble
);
1532 case GRAPHIC_EQUALIZER_CONTROL
:
1533 continue; /* XXX don't add anything */
1536 mix
.type
= MIX_ON_OFF
;
1537 #if defined(__FreeBSD__) || defined(__DragonFly__)
1538 mix
.ctl
= SOUND_MIXER_NRDEVICES
; /* XXXXX */
1541 ksnprintf(mix
.ctlname
, sizeof(mix
.ctlname
), "%s.%s",
1542 mixername
, AudioNagc
);
1546 mix
.type
= MIX_UNSIGNED_16
;
1547 #if defined(__FreeBSD__) || defined(__DragonFly__)
1548 mix
.ctl
= SOUND_MIXER_NRDEVICES
; /* XXXXX */
1550 mix
.ctlunit
= "4 ms";
1551 ksnprintf(mix
.ctlname
, sizeof(mix
.ctlname
),
1552 "%s.%s", mixername
, AudioNdelay
);
1555 case BASS_BOOST_CONTROL
:
1556 mix
.type
= MIX_ON_OFF
;
1557 #if defined(__FreeBSD__) || defined(__DragonFly__)
1558 mix
.ctl
= SOUND_MIXER_NRDEVICES
; /* XXXXX */
1561 ksnprintf(mix
.ctlname
, sizeof(mix
.ctlname
),
1562 "%s.%s", mixername
, AudioNbassboost
);
1565 case LOUDNESS_CONTROL
:
1566 mix
.type
= MIX_ON_OFF
;
1567 #if defined(__FreeBSD__) || defined(__DragonFly__)
1568 mix
.ctl
= SOUND_MIXER_LOUD
; /* Is this correct ? */
1571 ksnprintf(mix
.ctlname
, sizeof(mix
.ctlname
),
1572 "%s.%s", mixername
, AudioNloudness
);
1576 uaudio_mixer_add_ctl(sc
, &mix
);
1581 uaudio_add_processing_updown(struct uaudio_softc
*sc
,
1582 const struct io_terminal
*iot
, int id
)
1584 const struct usb_audio_processing_unit
*d
;
1585 const struct usb_audio_processing_unit_1
*d1
;
1586 const struct usb_audio_processing_unit_updown
*ud
;
1587 struct mixerctl mix
;
1591 d1
= (const struct usb_audio_processing_unit_1
*)
1592 &d
->baSourceId
[d
->bNrInPins
];
1593 ud
= (const struct usb_audio_processing_unit_updown
*)
1594 &d1
->bmControls
[d1
->bControlSize
];
1595 DPRINTFN(2,("uaudio_add_processing_updown: bUnitId=%d bNrModes=%d\n",
1596 d
->bUnitId
, ud
->bNrModes
));
1598 if (!(d1
->bmControls
[0] & UA_PROC_MASK(UD_MODE_SELECT_CONTROL
))) {
1599 DPRINTF(("uaudio_add_processing_updown: no mode select\n"));
1603 mix
.wIndex
= MAKE(d
->bUnitId
, sc
->sc_ac_iface
);
1605 mix
.wValue
[0] = MAKE(UD_MODE_SELECT_CONTROL
, 0);
1606 uaudio_determine_class(&iot
[id
], &mix
);
1607 mix
.type
= MIX_ON_OFF
; /* XXX */
1608 #if !defined(__FreeBSD__) && !defined(__DragonFly__)
1610 ksnprintf(mix
.ctlname
, sizeof(mix
.ctlname
), "pro%d-mode", d
->bUnitId
);
1613 for (i
= 0; i
< ud
->bNrModes
; i
++) {
1614 DPRINTFN(2,("uaudio_add_processing_updown: i=%d bm=0x%x\n",
1615 i
, UGETW(ud
->waModes
[i
])));
1618 uaudio_mixer_add_ctl(sc
, &mix
);
1622 uaudio_add_processing(struct uaudio_softc
*sc
, const struct io_terminal
*iot
, int id
)
1624 const struct usb_audio_processing_unit
*d
;
1625 const struct usb_audio_processing_unit_1
*d1
;
1627 struct mixerctl mix
;
1630 d1
= (const struct usb_audio_processing_unit_1
*)
1631 &d
->baSourceId
[d
->bNrInPins
];
1632 ptype
= UGETW(d
->wProcessType
);
1633 DPRINTFN(2,("uaudio_add_processing: wProcessType=%d bUnitId=%d "
1634 "bNrInPins=%d\n", ptype
, d
->bUnitId
, d
->bNrInPins
));
1636 if (d1
->bmControls
[0] & UA_PROC_ENABLE_MASK
) {
1637 mix
.wIndex
= MAKE(d
->bUnitId
, sc
->sc_ac_iface
);
1639 mix
.wValue
[0] = MAKE(XX_ENABLE_CONTROL
, 0);
1640 uaudio_determine_class(&iot
[id
], &mix
);
1641 mix
.type
= MIX_ON_OFF
;
1642 #if !defined(__FreeBSD__) && !defined(__DragonFly__)
1644 ksnprintf(mix
.ctlname
, sizeof(mix
.ctlname
), "pro%d.%d-enable",
1647 uaudio_mixer_add_ctl(sc
, &mix
);
1651 case UPDOWNMIX_PROCESS
:
1652 uaudio_add_processing_updown(sc
, iot
, id
);
1654 case DOLBY_PROLOGIC_PROCESS
:
1655 case P3D_STEREO_EXTENDER_PROCESS
:
1656 case REVERBATION_PROCESS
:
1657 case CHORUS_PROCESS
:
1658 case DYN_RANGE_COMP_PROCESS
:
1661 kprintf("uaudio_add_processing: unit %d, type=%d not impl.\n",
1669 uaudio_add_extension(struct uaudio_softc
*sc
, const struct io_terminal
*iot
, int id
)
1671 const struct usb_audio_extension_unit
*d
;
1672 const struct usb_audio_extension_unit_1
*d1
;
1673 struct mixerctl mix
;
1676 d1
= (const struct usb_audio_extension_unit_1
*)
1677 &d
->baSourceId
[d
->bNrInPins
];
1678 DPRINTFN(2,("uaudio_add_extension: bUnitId=%d bNrInPins=%d\n",
1679 d
->bUnitId
, d
->bNrInPins
));
1681 if (usbd_get_quirks(sc
->sc_udev
)->uq_flags
& UQ_AU_NO_XU
)
1684 if (d1
->bmControls
[0] & UA_EXT_ENABLE_MASK
) {
1685 mix
.wIndex
= MAKE(d
->bUnitId
, sc
->sc_ac_iface
);
1687 mix
.wValue
[0] = MAKE(UA_EXT_ENABLE
, 0);
1688 uaudio_determine_class(&iot
[id
], &mix
);
1689 mix
.type
= MIX_ON_OFF
;
1690 #if !defined(__FreeBSD__) && !defined(__DragonFly__)
1692 ksnprintf(mix
.ctlname
, sizeof(mix
.ctlname
), "ext%d-enable",
1695 uaudio_mixer_add_ctl(sc
, &mix
);
1699 static struct terminal_list
*
1700 uaudio_merge_terminal_list(const struct io_terminal
*iot
)
1702 struct terminal_list
*tml
;
1707 if (iot
->inputs
== NULL
)
1709 for (i
= 0; i
< iot
->inputs_size
; i
++) {
1710 if (iot
->inputs
[i
] != NULL
)
1711 len
+= iot
->inputs
[i
]->size
;
1713 tml
= kmalloc(TERMINAL_LIST_SIZE(len
), M_TEMP
, M_NOWAIT
);
1715 kprintf("uaudio_merge_terminal_list: no memory\n");
1719 ptm
= tml
->terminals
;
1720 for (i
= 0; i
< iot
->inputs_size
; i
++) {
1721 if (iot
->inputs
[i
] == NULL
)
1723 if (iot
->inputs
[i
]->size
> len
)
1725 memcpy(ptm
, iot
->inputs
[i
]->terminals
,
1726 iot
->inputs
[i
]->size
* sizeof(uint16_t));
1727 tml
->size
+= iot
->inputs
[i
]->size
;
1728 ptm
+= iot
->inputs
[i
]->size
;
1729 len
-= iot
->inputs
[i
]->size
;
1734 static struct terminal_list
*
1735 uaudio_io_terminaltype(int outtype
, struct io_terminal
*iot
, int id
)
1737 struct terminal_list
*tml
;
1738 struct io_terminal
*it
;
1742 if (it
->output
!= NULL
) {
1743 /* already has outtype? */
1744 for (i
= 0; i
< it
->output
->size
; i
++)
1745 if (it
->output
->terminals
[i
] == outtype
)
1746 return uaudio_merge_terminal_list(it
);
1747 tml
= kmalloc(TERMINAL_LIST_SIZE(it
->output
->size
+ 1),
1750 kprintf("uaudio_io_terminaltype: no memory\n");
1751 return uaudio_merge_terminal_list(it
);
1753 memcpy(tml
, it
->output
, TERMINAL_LIST_SIZE(it
->output
->size
));
1754 tml
->terminals
[it
->output
->size
] = outtype
;
1756 kfree(it
->output
, M_TEMP
);
1758 if (it
->inputs
!= NULL
) {
1759 for (i
= 0; i
< it
->inputs_size
; i
++)
1760 if (it
->inputs
[i
] != NULL
)
1761 kfree(it
->inputs
[i
], M_TEMP
);
1762 kfree(it
->inputs
, M_TEMP
);
1764 it
->inputs_size
= 0;
1766 } else { /* end `iot[id] != NULL' */
1767 it
->inputs_size
= 0;
1769 it
->output
= kmalloc(TERMINAL_LIST_SIZE(1), M_TEMP
, M_NOWAIT
);
1770 if (it
->output
== NULL
) {
1771 kprintf("uaudio_io_terminaltype: no memory\n");
1774 it
->output
->terminals
[0] = outtype
;
1775 it
->output
->size
= 1;
1779 switch (it
->d
.desc
->bDescriptorSubtype
) {
1780 case UDESCSUB_AC_INPUT
:
1781 it
->inputs
= kmalloc(sizeof(struct terminal_list
*), M_TEMP
, M_NOWAIT
);
1782 if (it
->inputs
== NULL
) {
1783 kprintf("uaudio_io_terminaltype: no memory\n");
1786 tml
= kmalloc(TERMINAL_LIST_SIZE(1), M_TEMP
, M_NOWAIT
);
1788 kprintf("uaudio_io_terminaltype: no memory\n");
1789 kfree(it
->inputs
, M_TEMP
);
1793 it
->inputs
[0] = tml
;
1794 tml
->terminals
[0] = UGETW(it
->d
.it
->wTerminalType
);
1796 it
->inputs_size
= 1;
1797 return uaudio_merge_terminal_list(it
);
1798 case UDESCSUB_AC_FEATURE
:
1799 src_id
= it
->d
.fu
->bSourceId
;
1800 it
->inputs
= kmalloc(sizeof(struct terminal_list
*), M_TEMP
, M_NOWAIT
);
1801 if (it
->inputs
== NULL
) {
1802 kprintf("uaudio_io_terminaltype: no memory\n");
1803 return uaudio_io_terminaltype(outtype
, iot
, src_id
);
1805 it
->inputs
[0] = uaudio_io_terminaltype(outtype
, iot
, src_id
);
1806 it
->inputs_size
= 1;
1807 return uaudio_merge_terminal_list(it
);
1808 case UDESCSUB_AC_OUTPUT
:
1809 it
->inputs
= kmalloc(sizeof(struct terminal_list
*), M_TEMP
, M_NOWAIT
);
1810 if (it
->inputs
== NULL
) {
1811 kprintf("uaudio_io_terminaltype: no memory\n");
1814 src_id
= it
->d
.ot
->bSourceId
;
1815 it
->inputs
[0] = uaudio_io_terminaltype(outtype
, iot
, src_id
);
1816 it
->inputs_size
= 1;
1817 iot
[src_id
].direct
= TRUE
;
1819 case UDESCSUB_AC_MIXER
:
1820 it
->inputs_size
= 0;
1821 it
->inputs
= kmalloc(sizeof(struct terminal_list
*)
1822 * it
->d
.mu
->bNrInPins
, M_TEMP
, M_NOWAIT
);
1823 if (it
->inputs
== NULL
) {
1824 kprintf("uaudio_io_terminaltype: no memory\n");
1827 for (i
= 0; i
< it
->d
.mu
->bNrInPins
; i
++) {
1828 src_id
= it
->d
.mu
->baSourceId
[i
];
1829 it
->inputs
[i
] = uaudio_io_terminaltype(outtype
, iot
,
1833 return uaudio_merge_terminal_list(it
);
1834 case UDESCSUB_AC_SELECTOR
:
1835 it
->inputs_size
= 0;
1836 it
->inputs
= kmalloc(sizeof(struct terminal_list
*)
1837 * it
->d
.su
->bNrInPins
, M_TEMP
, M_NOWAIT
);
1838 if (it
->inputs
== NULL
) {
1839 kprintf("uaudio_io_terminaltype: no memory\n");
1842 for (i
= 0; i
< it
->d
.su
->bNrInPins
; i
++) {
1843 src_id
= it
->d
.su
->baSourceId
[i
];
1844 it
->inputs
[i
] = uaudio_io_terminaltype(outtype
, iot
,
1848 return uaudio_merge_terminal_list(it
);
1849 case UDESCSUB_AC_PROCESSING
:
1850 it
->inputs_size
= 0;
1851 it
->inputs
= kmalloc(sizeof(struct terminal_list
*)
1852 * it
->d
.pu
->bNrInPins
, M_TEMP
, M_NOWAIT
);
1853 if (it
->inputs
== NULL
) {
1854 kprintf("uaudio_io_terminaltype: no memory\n");
1857 for (i
= 0; i
< it
->d
.pu
->bNrInPins
; i
++) {
1858 src_id
= it
->d
.pu
->baSourceId
[i
];
1859 it
->inputs
[i
] = uaudio_io_terminaltype(outtype
, iot
,
1863 return uaudio_merge_terminal_list(it
);
1864 case UDESCSUB_AC_EXTENSION
:
1865 it
->inputs_size
= 0;
1866 it
->inputs
= kmalloc(sizeof(struct terminal_list
*)
1867 * it
->d
.eu
->bNrInPins
, M_TEMP
, M_NOWAIT
);
1868 if (it
->inputs
== NULL
) {
1869 kprintf("uaudio_io_terminaltype: no memory\n");
1872 for (i
= 0; i
< it
->d
.eu
->bNrInPins
; i
++) {
1873 src_id
= it
->d
.eu
->baSourceId
[i
];
1874 it
->inputs
[i
] = uaudio_io_terminaltype(outtype
, iot
,
1878 return uaudio_merge_terminal_list(it
);
1879 case UDESCSUB_AC_HEADER
:
1886 uaudio_identify(struct uaudio_softc
*sc
, const usb_config_descriptor_t
*cdesc
)
1890 err
= uaudio_identify_ac(sc
, cdesc
);
1893 return uaudio_identify_as(sc
, cdesc
);
1897 uaudio_add_alt(struct uaudio_softc
*sc
, const struct as_info
*ai
)
1900 struct as_info
*nai
;
1902 len
= sizeof(*ai
) * (sc
->sc_nalts
+ 1);
1903 nai
= kmalloc(len
, M_USBDEV
, M_NOWAIT
);
1905 kprintf("uaudio_add_alt: no memory\n");
1908 /* Copy old data, if there was any */
1909 if (sc
->sc_nalts
!= 0) {
1910 memcpy(nai
, sc
->sc_alts
, sizeof(*ai
) * (sc
->sc_nalts
));
1911 kfree(sc
->sc_alts
, M_USBDEV
);
1914 DPRINTFN(2,("uaudio_add_alt: adding alt=%d, enc=%d\n",
1915 ai
->alt
, ai
->encoding
));
1916 sc
->sc_alts
[sc
->sc_nalts
++] = *ai
;
1920 uaudio_process_as(struct uaudio_softc
*sc
, const char *buf
, int *offsp
,
1921 int size
, const usb_interface_descriptor_t
*id
)
1922 #define offs (*offsp)
1924 const struct usb_audio_streaming_interface_descriptor
*asid
;
1925 const struct usb_audio_streaming_type1_descriptor
*asf1d
;
1926 const usb_endpoint_descriptor_audio_t
*ed
;
1927 const usb_endpoint_descriptor_audio_t
*epdesc1
;
1928 const struct usb_audio_streaming_endpoint_descriptor
*sed
;
1929 int format
, chan
, prec
, enc
;
1930 int dir
, type
, sync
;
1932 const char *format_str
;
1934 asid
= (const void *)(buf
+ offs
);
1936 if (asid
->bDescriptorType
!= UDESC_CS_INTERFACE
||
1937 asid
->bDescriptorSubtype
!= AS_GENERAL
)
1939 DPRINTF(("uaudio_process_as: asid: bTerminakLink=%d wFormatTag=%d\n",
1940 asid
->bTerminalLink
, UGETW(asid
->wFormatTag
)));
1941 offs
+= asid
->bLength
;
1945 asf1d
= (const void *)(buf
+ offs
);
1946 if (asf1d
->bDescriptorType
!= UDESC_CS_INTERFACE
||
1947 asf1d
->bDescriptorSubtype
!= FORMAT_TYPE
)
1949 offs
+= asf1d
->bLength
;
1953 if (asf1d
->bFormatType
!= FORMAT_TYPE_I
) {
1954 kprintf("%s: ignored setting with type %d format\n",
1955 device_get_nameunit(sc
->sc_dev
), UGETW(asid
->wFormatTag
));
1956 return USBD_NORMAL_COMPLETION
;
1959 ed
= (const void *)(buf
+ offs
);
1960 if (ed
->bDescriptorType
!= UDESC_ENDPOINT
)
1962 DPRINTF(("uaudio_process_as: endpoint[0] bLength=%d bDescriptorType=%d "
1963 "bEndpointAddress=%d bmAttributes=0x%x wMaxPacketSize=%d "
1964 "bInterval=%d bRefresh=%d bSynchAddress=%d\n",
1965 ed
->bLength
, ed
->bDescriptorType
, ed
->bEndpointAddress
,
1966 ed
->bmAttributes
, UGETW(ed
->wMaxPacketSize
),
1967 ed
->bInterval
, ed
->bRefresh
, ed
->bSynchAddress
));
1968 offs
+= ed
->bLength
;
1971 if (UE_GET_XFERTYPE(ed
->bmAttributes
) != UE_ISOCHRONOUS
)
1974 dir
= UE_GET_DIR(ed
->bEndpointAddress
);
1975 type
= UE_GET_ISO_TYPE(ed
->bmAttributes
);
1976 if ((usbd_get_quirks(sc
->sc_udev
)->uq_flags
& UQ_AU_INP_ASYNC
) &&
1977 dir
== UE_DIR_IN
&& type
== UE_ISO_ADAPT
)
1978 type
= UE_ISO_ASYNC
;
1980 /* We can't handle endpoints that need a sync pipe yet. */
1982 if (dir
== UE_DIR_IN
&& type
== UE_ISO_ADAPT
) {
1984 #ifndef UAUDIO_MULTIPLE_ENDPOINTS
1985 kprintf("%s: ignored input endpoint of type adaptive\n",
1986 device_get_nameunit(sc
->sc_dev
));
1987 return USBD_NORMAL_COMPLETION
;
1990 if (dir
!= UE_DIR_IN
&& type
== UE_ISO_ASYNC
) {
1992 #ifndef UAUDIO_MULTIPLE_ENDPOINTS
1993 kprintf("%s: ignored output endpoint of type async\n",
1994 device_get_nameunit(sc
->sc_dev
));
1995 return USBD_NORMAL_COMPLETION
;
1999 sed
= (const void *)(buf
+ offs
);
2000 if (sed
->bDescriptorType
!= UDESC_CS_ENDPOINT
||
2001 sed
->bDescriptorSubtype
!= AS_GENERAL
)
2003 DPRINTF((" streadming_endpoint: offset=%d bLength=%d\n", offs
, sed
->bLength
));
2004 offs
+= sed
->bLength
;
2008 if (sync
&& id
->bNumEndpoints
<= 1) {
2009 kprintf("%s: a sync-pipe endpoint but no other endpoint\n",
2010 device_get_nameunit(sc
->sc_dev
));
2013 if (!sync
&& id
->bNumEndpoints
> 1) {
2014 kprintf("%s: non sync-pipe endpoint but multiple endpoints\n",
2015 device_get_nameunit(sc
->sc_dev
));
2019 if (id
->bNumEndpoints
> 1) {
2020 epdesc1
= (const void*)(buf
+ offs
);
2021 if (epdesc1
->bDescriptorType
!= UDESC_ENDPOINT
)
2023 DPRINTF(("uaudio_process_as: endpoint[1] bLength=%d "
2024 "bDescriptorType=%d bEndpointAddress=%d "
2025 "bmAttributes=0x%x wMaxPacketSize=%d bInterval=%d "
2026 "bRefresh=%d bSynchAddress=%d\n",
2027 epdesc1
->bLength
, epdesc1
->bDescriptorType
,
2028 epdesc1
->bEndpointAddress
, epdesc1
->bmAttributes
,
2029 UGETW(epdesc1
->wMaxPacketSize
), epdesc1
->bInterval
,
2030 epdesc1
->bRefresh
, epdesc1
->bSynchAddress
));
2031 offs
+= epdesc1
->bLength
;
2034 if (epdesc1
->bSynchAddress
!= 0) {
2035 kprintf("%s: invalid endpoint: bSynchAddress=0\n",
2036 device_get_nameunit(sc
->sc_dev
));
2039 if (UE_GET_XFERTYPE(epdesc1
->bmAttributes
) != UE_ISOCHRONOUS
) {
2040 kprintf("%s: invalid endpoint: bmAttributes=0x%x\n",
2041 device_get_nameunit(sc
->sc_dev
), epdesc1
->bmAttributes
);
2044 if (epdesc1
->bEndpointAddress
!= ed
->bSynchAddress
) {
2045 kprintf("%s: invalid endpoint addresses: "
2046 "ep[0]->bSynchAddress=0x%x "
2047 "ep[1]->bEndpointAddress=0x%x\n",
2048 device_get_nameunit(sc
->sc_dev
), ed
->bSynchAddress
,
2049 epdesc1
->bEndpointAddress
);
2052 /* UE_GET_ADDR(epdesc1->bEndpointAddress), and epdesc1->bRefresh */
2055 format
= UGETW(asid
->wFormatTag
);
2056 chan
= asf1d
->bNrChannels
;
2057 prec
= asf1d
->bBitResolution
;
2058 if (prec
!= 8 && prec
!= 16 && prec
!= 24 && prec
!= 32) {
2059 kprintf("%s: ignored setting with precision %d\n",
2060 device_get_nameunit(sc
->sc_dev
), prec
);
2061 return USBD_NORMAL_COMPLETION
;
2066 sc
->sc_altflags
|= HAS_8
;
2067 } else if (prec
== 16) {
2068 sc
->sc_altflags
|= HAS_16
;
2069 } else if (prec
== 24) {
2070 sc
->sc_altflags
|= HAS_24
;
2071 } else if (prec
== 32) {
2072 sc
->sc_altflags
|= HAS_32
;
2074 enc
= AUDIO_ENCODING_SLINEAR_LE
;
2078 enc
= AUDIO_ENCODING_ULINEAR_LE
;
2079 sc
->sc_altflags
|= HAS_8U
;
2080 format_str
= "pcm8";
2083 enc
= AUDIO_ENCODING_ALAW
;
2084 sc
->sc_altflags
|= HAS_ALAW
;
2085 format_str
= "alaw";
2088 enc
= AUDIO_ENCODING_ULAW
;
2089 sc
->sc_altflags
|= HAS_MULAW
;
2090 format_str
= "mulaw";
2092 case UA_FMT_IEEE_FLOAT
:
2094 kprintf("%s: ignored setting with format %d\n",
2095 device_get_nameunit(sc
->sc_dev
), format
);
2096 return USBD_NORMAL_COMPLETION
;
2099 kprintf("%s: %s: %dch, %d/%dbit, %s,", device_get_nameunit(sc
->sc_dev
),
2100 dir
== UE_DIR_IN
? "recording" : "playback",
2101 chan
, prec
, asf1d
->bSubFrameSize
* 8, format_str
);
2102 if (asf1d
->bSamFreqType
== UA_SAMP_CONTNUOUS
) {
2103 kprintf(" %d-%dHz\n", UA_SAMP_LO(asf1d
), UA_SAMP_HI(asf1d
));
2106 kprintf(" %d", UA_GETSAMP(asf1d
, 0));
2107 for (r
= 1; r
< asf1d
->bSamFreqType
; r
++)
2108 kprintf(",%d", UA_GETSAMP(asf1d
, r
));
2112 #if defined(__FreeBSD__) || defined(__DragonFly__)
2113 if (sc
->uaudio_sndstat_flag
!= 0) {
2114 sbuf_printf(&(sc
->uaudio_sndstat
), "\n\t");
2115 sbuf_printf(&(sc
->uaudio_sndstat
),
2116 "mode %d:(%s) %dch, %d/%dbit, %s,",
2117 id
->bAlternateSetting
,
2118 dir
== UE_DIR_IN
? "input" : "output",
2119 chan
, prec
, asf1d
->bSubFrameSize
* 8, format_str
);
2120 if (asf1d
->bSamFreqType
== UA_SAMP_CONTNUOUS
) {
2121 sbuf_printf(&(sc
->uaudio_sndstat
), " %d-%dHz",
2122 UA_SAMP_LO(asf1d
), UA_SAMP_HI(asf1d
));
2125 sbuf_printf(&(sc
->uaudio_sndstat
),
2126 " %d", UA_GETSAMP(asf1d
, 0));
2127 for (r
= 1; r
< asf1d
->bSamFreqType
; r
++)
2128 sbuf_printf(&(sc
->uaudio_sndstat
),
2129 ",%d", UA_GETSAMP(asf1d
, r
));
2130 sbuf_printf(&(sc
->uaudio_sndstat
), "Hz");
2134 ai
.alt
= id
->bAlternateSetting
;
2136 ai
.attributes
= sed
->bmAttributes
;
2139 ai
.edesc1
= epdesc1
;
2140 ai
.asf1desc
= asf1d
;
2142 uaudio_add_alt(sc
, &ai
);
2144 if (ai
.attributes
& UA_SED_FREQ_CONTROL
)
2145 DPRINTFN(1, ("uaudio_process_as: FREQ_CONTROL\n"));
2146 if (ai
.attributes
& UA_SED_PITCH_CONTROL
)
2147 DPRINTFN(1, ("uaudio_process_as: PITCH_CONTROL\n"));
2149 sc
->sc_mode
|= (dir
== UE_DIR_OUT
) ? AUMODE_PLAY
: AUMODE_RECORD
;
2151 return USBD_NORMAL_COMPLETION
;
2156 uaudio_identify_as(struct uaudio_softc
*sc
,
2157 const usb_config_descriptor_t
*cdesc
)
2159 const usb_interface_descriptor_t
*id
;
2163 size
= UGETW(cdesc
->wTotalLength
);
2164 buf
= (const char *)cdesc
;
2166 /* Locate the AudioStreaming interface descriptor. */
2168 id
= uaudio_find_iface(buf
, size
, &offs
, UISUBCLASS_AUDIOSTREAM
);
2172 #if defined(__FreeBSD__) || defined(__DragonFly__)
2173 sc
->uaudio_sndstat_flag
= 0;
2174 if (sbuf_new(&(sc
->uaudio_sndstat
), NULL
, 4096, SBUF_AUTOEXTEND
) != NULL
)
2175 sc
->uaudio_sndstat_flag
= 1;
2177 /* Loop through all the alternate settings. */
2178 while (offs
<= size
) {
2179 DPRINTFN(2, ("uaudio_identify: interface=%d offset=%d\n",
2180 id
->bInterfaceNumber
, offs
));
2181 switch (id
->bNumEndpoints
) {
2183 DPRINTFN(2, ("uaudio_identify: AS null alt=%d\n",
2184 id
->bAlternateSetting
));
2185 sc
->sc_nullalt
= id
->bAlternateSetting
;
2188 #ifdef UAUDIO_MULTIPLE_ENDPOINTS
2191 uaudio_process_as(sc
, buf
, &offs
, size
, id
);
2194 kprintf("%s: ignored audio interface with %d "
2196 device_get_nameunit(sc
->sc_dev
), id
->bNumEndpoints
);
2199 id
= uaudio_find_iface(buf
, size
, &offs
,UISUBCLASS_AUDIOSTREAM
);
2203 #if defined(__FreeBSD__) || defined(__DragonFly__)
2204 sbuf_finish(&(sc
->uaudio_sndstat
));
2208 DPRINTF(("uaudio_identify_as: %d alts available\n", sc
->sc_nalts
));
2210 if (sc
->sc_mode
== 0) {
2211 kprintf("%s: no usable endpoint found\n",
2212 device_get_nameunit(sc
->sc_dev
));
2216 return USBD_NORMAL_COMPLETION
;
2220 uaudio_identify_ac(struct uaudio_softc
*sc
, const usb_config_descriptor_t
*cdesc
)
2222 struct io_terminal
* iot
;
2223 const usb_interface_descriptor_t
*id
;
2224 const struct usb_audio_control_descriptor
*acdp
;
2225 const usb_descriptor_t
*dp
;
2226 const struct usb_audio_output_terminal
*pot
;
2227 struct terminal_list
*tml
;
2228 const char *buf
, *ibuf
, *ibufend
;
2229 int size
, offs
, aclen
, ndps
, i
, j
;
2231 size
= UGETW(cdesc
->wTotalLength
);
2232 buf
= (const char *)cdesc
;
2234 /* Locate the AudioControl interface descriptor. */
2236 id
= uaudio_find_iface(buf
, size
, &offs
, UISUBCLASS_AUDIOCONTROL
);
2239 if (offs
+ sizeof *acdp
> size
)
2241 sc
->sc_ac_iface
= id
->bInterfaceNumber
;
2242 DPRINTFN(2,("uaudio_identify_ac: AC interface is %d\n", sc
->sc_ac_iface
));
2244 /* A class-specific AC interface header should follow. */
2246 acdp
= (const struct usb_audio_control_descriptor
*)ibuf
;
2247 if (acdp
->bDescriptorType
!= UDESC_CS_INTERFACE
||
2248 acdp
->bDescriptorSubtype
!= UDESCSUB_AC_HEADER
)
2250 aclen
= UGETW(acdp
->wTotalLength
);
2251 if (offs
+ aclen
> size
)
2254 if (!(usbd_get_quirks(sc
->sc_udev
)->uq_flags
& UQ_BAD_ADC
) &&
2255 UGETW(acdp
->bcdADC
) != UAUDIO_VERSION
)
2258 sc
->sc_audio_rev
= UGETW(acdp
->bcdADC
);
2259 DPRINTFN(2,("uaudio_identify_ac: found AC header, vers=%03x, len=%d\n",
2260 sc
->sc_audio_rev
, aclen
));
2262 sc
->sc_nullalt
= -1;
2264 /* Scan through all the AC specific descriptors */
2265 ibufend
= ibuf
+ aclen
;
2266 dp
= (const usb_descriptor_t
*)ibuf
;
2268 iot
= kmalloc(sizeof(struct io_terminal
) * 256, M_TEMP
, M_NOWAIT
| M_ZERO
);
2270 kprintf("%s: no memory\n", __func__
);
2274 ibuf
+= dp
->bLength
;
2275 if (ibuf
>= ibufend
)
2277 dp
= (const usb_descriptor_t
*)ibuf
;
2278 if (ibuf
+ dp
->bLength
> ibufend
) {
2282 if (dp
->bDescriptorType
!= UDESC_CS_INTERFACE
) {
2283 kprintf("uaudio_identify_ac: skip desc type=0x%02x\n",
2284 dp
->bDescriptorType
);
2287 i
= ((const struct usb_audio_input_terminal
*)dp
)->bTerminalId
;
2294 /* construct io_terminal */
2295 for (i
= 0; i
< ndps
; i
++) {
2299 if (dp
->bDescriptorSubtype
!= UDESCSUB_AC_OUTPUT
)
2302 tml
= uaudio_io_terminaltype(UGETW(pot
->wTerminalType
), iot
, i
);
2308 for (i
= 0; i
< 256; i
++) {
2309 struct usb_audio_cluster cluster
;
2311 if (iot
[i
].d
.desc
== NULL
)
2313 kprintf("id %d:\t", i
);
2314 switch (iot
[i
].d
.desc
->bDescriptorSubtype
) {
2315 case UDESCSUB_AC_INPUT
:
2316 kprintf("AC_INPUT type=%s\n", uaudio_get_terminal_name
2317 (UGETW(iot
[i
].d
.it
->wTerminalType
)));
2319 cluster
= uaudio_get_cluster(i
, iot
);
2320 uaudio_dump_cluster(&cluster
);
2323 case UDESCSUB_AC_OUTPUT
:
2324 kprintf("AC_OUTPUT type=%s ", uaudio_get_terminal_name
2325 (UGETW(iot
[i
].d
.ot
->wTerminalType
)));
2326 kprintf("src=%d\n", iot
[i
].d
.ot
->bSourceId
);
2328 case UDESCSUB_AC_MIXER
:
2329 kprintf("AC_MIXER src=");
2330 for (j
= 0; j
< iot
[i
].d
.mu
->bNrInPins
; j
++)
2331 kprintf("%d ", iot
[i
].d
.mu
->baSourceId
[j
]);
2333 cluster
= uaudio_get_cluster(i
, iot
);
2334 uaudio_dump_cluster(&cluster
);
2337 case UDESCSUB_AC_SELECTOR
:
2338 kprintf("AC_SELECTOR src=");
2339 for (j
= 0; j
< iot
[i
].d
.su
->bNrInPins
; j
++)
2340 kprintf("%d ", iot
[i
].d
.su
->baSourceId
[j
]);
2343 case UDESCSUB_AC_FEATURE
:
2344 kprintf("AC_FEATURE src=%d\n", iot
[i
].d
.fu
->bSourceId
);
2346 case UDESCSUB_AC_PROCESSING
:
2347 kprintf("AC_PROCESSING src=");
2348 for (j
= 0; j
< iot
[i
].d
.pu
->bNrInPins
; j
++)
2349 kprintf("%d ", iot
[i
].d
.pu
->baSourceId
[j
]);
2351 cluster
= uaudio_get_cluster(i
, iot
);
2352 uaudio_dump_cluster(&cluster
);
2355 case UDESCSUB_AC_EXTENSION
:
2356 kprintf("AC_EXTENSION src=");
2357 for (j
= 0; j
< iot
[i
].d
.eu
->bNrInPins
; j
++)
2358 kprintf("%d ", iot
[i
].d
.eu
->baSourceId
[j
]);
2360 cluster
= uaudio_get_cluster(i
, iot
);
2361 uaudio_dump_cluster(&cluster
);
2365 kprintf("unknown audio control (subtype=%d)\n",
2366 iot
[i
].d
.desc
->bDescriptorSubtype
);
2368 for (j
= 0; j
< iot
[i
].inputs_size
; j
++) {
2370 kprintf("\tinput%d: ", j
);
2371 tml
= iot
[i
].inputs
[j
];
2376 for (k
= 0; k
< tml
->size
; k
++)
2377 kprintf("%s ", uaudio_get_terminal_name
2378 (tml
->terminals
[k
]));
2381 kprintf("\toutput: ");
2382 tml
= iot
[i
].output
;
2383 for (j
= 0; j
< tml
->size
; j
++)
2384 kprintf("%s ", uaudio_get_terminal_name(tml
->terminals
[j
]));
2389 for (i
= 0; i
< ndps
; i
++) {
2393 DPRINTF(("uaudio_identify_ac: id=%d subtype=%d\n",
2394 i
, dp
->bDescriptorSubtype
));
2395 switch (dp
->bDescriptorSubtype
) {
2396 case UDESCSUB_AC_HEADER
:
2397 kprintf("uaudio_identify_ac: unexpected AC header\n");
2399 case UDESCSUB_AC_INPUT
:
2400 uaudio_add_input(sc
, iot
, i
);
2402 case UDESCSUB_AC_OUTPUT
:
2403 uaudio_add_output(sc
, iot
, i
);
2405 case UDESCSUB_AC_MIXER
:
2406 uaudio_add_mixer(sc
, iot
, i
);
2408 case UDESCSUB_AC_SELECTOR
:
2409 uaudio_add_selector(sc
, iot
, i
);
2411 case UDESCSUB_AC_FEATURE
:
2412 uaudio_add_feature(sc
, iot
, i
);
2414 case UDESCSUB_AC_PROCESSING
:
2415 uaudio_add_processing(sc
, iot
, i
);
2417 case UDESCSUB_AC_EXTENSION
:
2418 uaudio_add_extension(sc
, iot
, i
);
2421 kprintf("uaudio_identify_ac: bad AC desc subtype=0x%02x\n",
2422 dp
->bDescriptorSubtype
);
2427 /* delete io_terminal */
2428 for (i
= 0; i
< 256; i
++) {
2429 if (iot
[i
].d
.desc
== NULL
)
2431 if (iot
[i
].inputs
!= NULL
) {
2432 for (j
= 0; j
< iot
[i
].inputs_size
; j
++) {
2433 if (iot
[i
].inputs
[j
] != NULL
)
2434 kfree(iot
[i
].inputs
[j
], M_TEMP
);
2436 kfree(iot
[i
].inputs
, M_TEMP
);
2438 if (iot
[i
].output
!= NULL
)
2439 kfree(iot
[i
].output
, M_TEMP
);
2440 iot
[i
].d
.desc
= NULL
;
2444 return USBD_NORMAL_COMPLETION
;
2447 #if defined(__NetBSD__) || defined(__OpenBSD__)
2449 uaudio_query_devinfo(void *addr
, mixer_devinfo_t
*mi
)
2451 struct uaudio_softc
*sc
;
2452 struct mixerctl
*mc
;
2456 DPRINTFN(2,("uaudio_query_devinfo: index=%d\n", mi
->index
));
2461 nctls
= sc
->sc_nctls
;
2465 mi
->type
= AUDIO_MIXER_CLASS
;
2466 mi
->mixer_class
= UAC_OUTPUT
;
2467 mi
->next
= mi
->prev
= AUDIO_MIXER_LAST
;
2468 strlcpy(mi
->label
.name
, AudioCoutputs
, sizeof(mi
->label
.name
));
2471 mi
->type
= AUDIO_MIXER_CLASS
;
2472 mi
->mixer_class
= UAC_INPUT
;
2473 mi
->next
= mi
->prev
= AUDIO_MIXER_LAST
;
2474 strlcpy(mi
->label
.name
, AudioCinputs
, sizeof(mi
->label
.name
));
2477 mi
->type
= AUDIO_MIXER_CLASS
;
2478 mi
->mixer_class
= UAC_EQUAL
;
2479 mi
->next
= mi
->prev
= AUDIO_MIXER_LAST
;
2480 strlcpy(mi
->label
.name
, AudioCequalization
,
2481 sizeof(mi
->label
.name
));
2484 mi
->type
= AUDIO_MIXER_CLASS
;
2485 mi
->mixer_class
= UAC_RECORD
;
2486 mi
->next
= mi
->prev
= AUDIO_MIXER_LAST
;
2487 strlcpy(mi
->label
.name
, AudioCrecord
, sizeof(mi
->label
.name
));
2494 if (n
< 0 || n
>= nctls
)
2497 mc
= &sc
->sc_ctls
[n
];
2498 strlcpy(mi
->label
.name
, mc
->ctlname
, sizeof(mi
->label
.name
));
2499 mi
->mixer_class
= mc
->class;
2500 mi
->next
= mi
->prev
= AUDIO_MIXER_LAST
; /* XXX */
2503 mi
->type
= AUDIO_MIXER_ENUM
;
2504 mi
->un
.e
.num_mem
= 2;
2505 strlcpy(mi
->un
.e
.member
[0].label
.name
, AudioNoff
,
2506 sizeof(mi
->un
.e
.member
[0].label
.name
));
2507 mi
->un
.e
.member
[0].ord
= 0;
2508 strlcpy(mi
->un
.e
.member
[1].label
.name
, AudioNon
,
2509 sizeof(mi
->un
.e
.member
[1].label
.name
));
2510 mi
->un
.e
.member
[1].ord
= 1;
2513 mi
->type
= AUDIO_MIXER_ENUM
;
2514 mi
->un
.e
.num_mem
= mc
->maxval
- mc
->minval
+ 1;
2515 for (i
= 0; i
<= mc
->maxval
- mc
->minval
; i
++) {
2516 ksnprintf(mi
->un
.e
.member
[i
].label
.name
,
2517 sizeof(mi
->un
.e
.member
[i
].label
.name
),
2518 "%d", i
+ mc
->minval
);
2519 mi
->un
.e
.member
[i
].ord
= i
+ mc
->minval
;
2523 mi
->type
= AUDIO_MIXER_VALUE
;
2524 strncpy(mi
->un
.v
.units
.name
, mc
->ctlunit
, MAX_AUDIO_DEV_LEN
);
2525 mi
->un
.v
.num_channels
= mc
->nchan
;
2526 mi
->un
.v
.delta
= mc
->delta
;
2533 uaudio_open(void *addr
, int flags
)
2535 struct uaudio_softc
*sc
;
2538 DPRINTF(("uaudio_open: sc=%p\n", sc
));
2542 if ((flags
& FWRITE
) && !(sc
->sc_mode
& AUMODE_PLAY
))
2544 if ((flags
& FREAD
) && !(sc
->sc_mode
& AUMODE_RECORD
))
2551 * Close function is called at splaudio().
2554 uaudio_close(void *addr
)
2559 uaudio_drain(void *addr
)
2561 struct uaudio_softc
*sc
;
2564 usbd_delay_ms(sc
->sc_udev
, UAUDIO_NCHANBUFS
* UAUDIO_NFRAMES
);
2570 uaudio_halt_out_dma(void *addr
)
2572 struct uaudio_softc
*sc
;
2578 DPRINTF(("uaudio_halt_out_dma: enter\n"));
2579 if (sc
->sc_playchan
.pipe
!= NULL
) {
2580 uaudio_chan_close(sc
, &sc
->sc_playchan
);
2581 sc
->sc_playchan
.pipe
= NULL
;
2582 uaudio_chan_free_buffers(sc
, &sc
->sc_playchan
);
2583 sc
->sc_playchan
.intr
= NULL
;
2589 uaudio_halt_in_dma(void *addr
)
2591 struct uaudio_softc
*sc
;
2593 DPRINTF(("uaudio_halt_in_dma: enter\n"));
2595 if (sc
->sc_recchan
.pipe
!= NULL
) {
2596 uaudio_chan_close(sc
, &sc
->sc_recchan
);
2597 sc
->sc_recchan
.pipe
= NULL
;
2598 uaudio_chan_free_buffers(sc
, &sc
->sc_recchan
);
2599 sc
->sc_recchan
.intr
= NULL
;
2605 uaudio_getdev(void *addr
, struct audio_device
*retp
)
2607 struct uaudio_softc
*sc
;
2609 DPRINTF(("uaudio_mixer_getdev:\n"));
2614 *retp
= uaudio_device
;
2619 * Make sure the block size is large enough to hold all outstanding transfers.
2622 uaudio_round_blocksize(void *addr
, int blk
)
2624 struct uaudio_softc
*sc
;
2628 DPRINTF(("uaudio_round_blocksize: blk=%d mode=%s\n", blk
,
2629 mode
== AUMODE_PLAY
? "AUMODE_PLAY" : "AUMODE_RECORD"));
2631 /* chan.bytes_per_frame can be 0. */
2632 if (mode
== AUMODE_PLAY
|| sc
->sc_recchan
.bytes_per_frame
<= 0) {
2633 b
= param
->sample_rate
* UAUDIO_NFRAMES
* UAUDIO_NCHANBUFS
;
2636 * This does not make accurate value in the case
2637 * of b % USB_FRAMES_PER_SECOND != 0
2639 b
/= USB_FRAMES_PER_SECOND
;
2641 b
*= param
->precision
/ 8 * param
->channels
;
2644 * use wMaxPacketSize in bytes_per_frame.
2645 * See uaudio_set_params() and uaudio_chan_init()
2647 b
= sc
->sc_recchan
.bytes_per_frame
2648 * UAUDIO_NFRAMES
* UAUDIO_NCHANBUFS
;
2653 blk
= blk
<= b
? b
: blk
/ b
* b
;
2657 kprintf("uaudio_round_blocksize: blk=%d\n", blk
);
2662 DPRINTF(("uaudio_round_blocksize: resultant blk=%d\n", blk
));
2667 uaudio_get_props(void *addr
)
2669 return AUDIO_PROP_FULLDUPLEX
| AUDIO_PROP_INDEPENDENT
;
2672 #endif /* NetBSD or OpenBSD */
2675 uaudio_get(struct uaudio_softc
*sc
, int which
, int type
, int wValue
,
2676 int wIndex
, int len
)
2678 usb_device_request_t req
;
2683 #if defined(__FreeBSD__) || defined(__DragonFly__)
2691 req
.bmRequestType
= type
;
2692 req
.bRequest
= which
;
2693 USETW(req
.wValue
, wValue
);
2694 USETW(req
.wIndex
, wIndex
);
2695 USETW(req
.wLength
, len
);
2696 DPRINTFN(2,("uaudio_get: type=0x%02x req=0x%02x wValue=0x%04x "
2697 "wIndex=0x%04x len=%d\n",
2698 type
, which
, wValue
, wIndex
, len
));
2699 err
= usbd_do_request(sc
->sc_udev
, &req
, data
);
2701 DPRINTF(("uaudio_get: err=%s\n", usbd_errstr(err
)));
2709 val
= data
[0] | (data
[1] << 8);
2712 DPRINTF(("uaudio_get: bad length=%d\n", len
));
2715 DPRINTFN(2,("uaudio_get: val=%d\n", val
));
2720 uaudio_set(struct uaudio_softc
*sc
, int which
, int type
, int wValue
,
2721 int wIndex
, int len
, int val
)
2723 usb_device_request_t req
;
2727 #if defined(__FreeBSD__) || defined(__DragonFly__)
2735 req
.bmRequestType
= type
;
2736 req
.bRequest
= which
;
2737 USETW(req
.wValue
, wValue
);
2738 USETW(req
.wIndex
, wIndex
);
2739 USETW(req
.wLength
, len
);
2751 DPRINTFN(2,("uaudio_set: type=0x%02x req=0x%02x wValue=0x%04x "
2752 "wIndex=0x%04x len=%d, val=%d\n",
2753 type
, which
, wValue
, wIndex
, len
, val
& 0xffff));
2754 err
= usbd_do_request(sc
->sc_udev
, &req
, data
);
2757 DPRINTF(("uaudio_set: err=%d\n", err
));
2762 uaudio_signext(int type
, int val
)
2764 if (!MIX_UNSIGNED(type
)) {
2765 if (MIX_SIZE(type
) == 2)
2773 #if defined(__NetBSD__) || defined(__OpenBSD__)
2775 uaudio_value2bsd(struct mixerctl
*mc
, int val
)
2777 DPRINTFN(5, ("uaudio_value2bsd: type=%03x val=%d min=%d max=%d ",
2778 mc
->type
, val
, mc
->minval
, mc
->maxval
));
2779 if (mc
->type
== MIX_ON_OFF
) {
2781 } else if (mc
->type
== MIX_SELECTOR
) {
2782 if (val
< mc
->minval
|| val
> mc
->maxval
)
2785 val
= ((uaudio_signext(mc
->type
, val
) - mc
->minval
) * 255
2786 + mc
->mul
/2) / mc
->mul
;
2787 DPRINTFN(5, ("val'=%d\n", val
));
2793 uaudio_bsd2value(struct mixerctl
*mc
, int val
)
2795 DPRINTFN(5,("uaudio_bsd2value: type=%03x val=%d min=%d max=%d ",
2796 mc
->type
, val
, mc
->minval
, mc
->maxval
));
2797 if (mc
->type
== MIX_ON_OFF
) {
2799 } else if (mc
->type
== MIX_SELECTOR
) {
2800 if (val
< mc
->minval
|| val
> mc
->maxval
)
2803 val
= (val
+ mc
->delta
/2) * mc
->mul
/ 255 + mc
->minval
;
2804 DPRINTFN(5, ("val'=%d\n", val
));
2808 #if defined(__NetBSD__) || defined(__OpenBSD__)
2810 uaudio_ctl_get(struct uaudio_softc
*sc
, int which
, struct mixerctl
*mc
,
2815 DPRINTFN(5,("uaudio_ctl_get: which=%d chan=%d\n", which
, chan
));
2816 val
= uaudio_get(sc
, which
, UT_READ_CLASS_INTERFACE
, mc
->wValue
[chan
],
2817 mc
->wIndex
, MIX_SIZE(mc
->type
));
2818 return uaudio_value2bsd(mc
, val
);
2823 uaudio_ctl_set(struct uaudio_softc
*sc
, int which
, struct mixerctl
*mc
,
2826 val
= uaudio_bsd2value(mc
, val
);
2827 uaudio_set(sc
, which
, UT_WRITE_CLASS_INTERFACE
, mc
->wValue
[chan
],
2828 mc
->wIndex
, MIX_SIZE(mc
->type
), val
);
2831 #if defined(__NetBSD__) || defined(__OpenBSD__)
2833 uaudio_mixer_get_port(void *addr
, mixer_ctrl_t
*cp
)
2835 struct uaudio_softc
*sc
;
2836 struct mixerctl
*mc
;
2837 int i
, n
, vals
[MIX_MAX_CHAN
], val
;
2839 DPRINTFN(2,("uaudio_mixer_get_port: index=%d\n", cp
->dev
));
2844 n
= cp
->dev
- UAC_NCLASSES
;
2845 if (n
< 0 || n
>= sc
->sc_nctls
)
2847 mc
= &sc
->sc_ctls
[n
];
2849 if (mc
->type
== MIX_ON_OFF
) {
2850 if (cp
->type
!= AUDIO_MIXER_ENUM
)
2852 cp
->un
.ord
= uaudio_ctl_get(sc
, GET_CUR
, mc
, 0);
2853 } else if (mc
->type
== MIX_SELECTOR
) {
2854 if (cp
->type
!= AUDIO_MIXER_ENUM
)
2856 cp
->un
.ord
= uaudio_ctl_get(sc
, GET_CUR
, mc
, 0);
2858 if (cp
->type
!= AUDIO_MIXER_VALUE
)
2860 if (cp
->un
.value
.num_channels
!= 1 &&
2861 cp
->un
.value
.num_channels
!= mc
->nchan
)
2863 for (i
= 0; i
< mc
->nchan
; i
++)
2864 vals
[i
] = uaudio_ctl_get(sc
, GET_CUR
, mc
, i
);
2865 if (cp
->un
.value
.num_channels
== 1 && mc
->nchan
!= 1) {
2866 for (val
= 0, i
= 0; i
< mc
->nchan
; i
++)
2868 vals
[0] = val
/ mc
->nchan
;
2870 for (i
= 0; i
< cp
->un
.value
.num_channels
; i
++)
2871 cp
->un
.value
.level
[i
] = vals
[i
];
2878 uaudio_mixer_set_port(void *addr
, mixer_ctrl_t
*cp
)
2880 struct uaudio_softc
*sc
;
2881 struct mixerctl
*mc
;
2882 int i
, n
, vals
[MIX_MAX_CHAN
];
2884 DPRINTFN(2,("uaudio_mixer_set_port: index = %d\n", cp
->dev
));
2889 n
= cp
->dev
- UAC_NCLASSES
;
2890 if (n
< 0 || n
>= sc
->sc_nctls
)
2892 mc
= &sc
->sc_ctls
[n
];
2894 if (mc
->type
== MIX_ON_OFF
) {
2895 if (cp
->type
!= AUDIO_MIXER_ENUM
)
2897 uaudio_ctl_set(sc
, SET_CUR
, mc
, 0, cp
->un
.ord
);
2898 } else if (mc
->type
== MIX_SELECTOR
) {
2899 if (cp
->type
!= AUDIO_MIXER_ENUM
)
2901 uaudio_ctl_set(sc
, SET_CUR
, mc
, 0, cp
->un
.ord
);
2903 if (cp
->type
!= AUDIO_MIXER_VALUE
)
2905 if (cp
->un
.value
.num_channels
== 1)
2906 for (i
= 0; i
< mc
->nchan
; i
++)
2907 vals
[i
] = cp
->un
.value
.level
[0];
2908 else if (cp
->un
.value
.num_channels
== mc
->nchan
)
2909 for (i
= 0; i
< mc
->nchan
; i
++)
2910 vals
[i
] = cp
->un
.value
.level
[i
];
2913 for (i
= 0; i
< mc
->nchan
; i
++)
2914 uaudio_ctl_set(sc
, SET_CUR
, mc
, i
, vals
[i
]);
2920 uaudio_trigger_input(void *addr
, void *start
, void *end
, int blksize
,
2921 void (*intr
)(void *), void *arg
,
2922 struct audio_params
*param
)
2924 struct uaudio_softc
*sc
;
2933 DPRINTFN(3,("uaudio_trigger_input: sc=%p start=%p end=%p "
2934 "blksize=%d\n", sc
, start
, end
, blksize
));
2935 ch
= &sc
->sc_recchan
;
2936 uaudio_chan_set_param(ch
, start
, end
, blksize
);
2937 DPRINTFN(3,("uaudio_trigger_input: sample_size=%d bytes/frame=%d "
2938 "fraction=0.%03d\n", ch
->sample_size
, ch
->bytes_per_frame
,
2941 err
= uaudio_chan_alloc_buffers(sc
, ch
);
2945 err
= uaudio_chan_open(sc
, ch
);
2947 uaudio_chan_free_buffers(sc
, ch
);
2955 for (i
= 0; i
< UAUDIO_NCHANBUFS
-1; i
++) /* XXX -1 shouldn't be needed */
2956 uaudio_chan_rtransfer(ch
);
2963 uaudio_trigger_output(void *addr
, void *start
, void *end
, int blksize
,
2964 void (*intr
)(void *), void *arg
,
2965 struct audio_params
*param
)
2967 struct uaudio_softc
*sc
;
2976 DPRINTFN(3,("uaudio_trigger_output: sc=%p start=%p end=%p "
2977 "blksize=%d\n", sc
, start
, end
, blksize
));
2978 ch
= &sc
->sc_playchan
;
2979 uaudio_chan_set_param(ch
, start
, end
, blksize
);
2980 DPRINTFN(3,("uaudio_trigger_output: sample_size=%d bytes/frame=%d "
2981 "fraction=0.%03d\n", ch
->sample_size
, ch
->bytes_per_frame
,
2984 err
= uaudio_chan_alloc_buffers(sc
, ch
);
2988 err
= uaudio_chan_open(sc
, ch
);
2990 uaudio_chan_free_buffers(sc
, ch
);
2998 for (i
= 0; i
< UAUDIO_NCHANBUFS
-1; i
++) /* XXX */
2999 uaudio_chan_ptransfer(ch
);
3004 #endif /* NetBSD or OpenBSD */
3006 /* Set up a pipe for a channel. */
3008 uaudio_chan_open(struct uaudio_softc
*sc
, struct chan
*ch
)
3014 #if defined(__FreeBSD__) || defined(__DragonFly__)
3019 as
= &sc
->sc_alts
[ch
->altidx
];
3020 endpt
= as
->edesc
->bEndpointAddress
;
3021 DPRINTF(("uaudio_chan_open: endpt=0x%02x, speed=%d, alt=%d\n",
3022 endpt
, ch
->sample_rate
, as
->alt
));
3024 /* Set alternate interface corresponding to the mode. */
3025 err
= usbd_set_interface(as
->ifaceh
, as
->alt
);
3030 * If just one sampling rate is supported,
3031 * no need to call uaudio_set_speed().
3032 * Roland SD-90 freezes by a SAMPLING_FREQ_CONTROL request.
3034 if (as
->asf1desc
->bSamFreqType
!= 1) {
3035 err
= uaudio_set_speed(sc
, endpt
, ch
->sample_rate
);
3037 DPRINTF(("uaudio_chan_open: set_speed failed err=%s\n",
3043 DPRINTF(("uaudio_chan_open: create pipe to 0x%02x\n", endpt
));
3044 err
= usbd_open_pipe(as
->ifaceh
, endpt
, 0, &ch
->pipe
);
3047 if (as
->edesc1
!= NULL
) {
3048 endpt
= as
->edesc1
->bEndpointAddress
;
3049 DPRINTF(("uaudio_chan_open: create sync-pipe to 0x%02x\n", endpt
));
3050 err
= usbd_open_pipe(as
->ifaceh
, endpt
, 0, &ch
->sync_pipe
);
3056 uaudio_chan_close(struct uaudio_softc
*sc
, struct chan
*ch
)
3060 #if defined(__FreeBSD__) || defined(__DragonFly__)
3065 as
= &sc
->sc_alts
[ch
->altidx
];
3067 if (sc
->sc_nullalt
>= 0) {
3068 DPRINTF(("uaudio_chan_close: set null alt=%d\n",
3070 usbd_set_interface(as
->ifaceh
, sc
->sc_nullalt
);
3073 usbd_abort_pipe(ch
->pipe
);
3074 usbd_close_pipe(ch
->pipe
);
3076 if (ch
->sync_pipe
) {
3077 usbd_abort_pipe(ch
->sync_pipe
);
3078 usbd_close_pipe(ch
->sync_pipe
);
3083 uaudio_chan_alloc_buffers(struct uaudio_softc
*sc
, struct chan
*ch
)
3085 usbd_xfer_handle xfer
;
3089 size
= (ch
->bytes_per_frame
+ ch
->sample_size
) * UAUDIO_NFRAMES
;
3090 for (i
= 0; i
< UAUDIO_NCHANBUFS
; i
++) {
3091 xfer
= usbd_alloc_xfer(sc
->sc_udev
);
3094 ch
->chanbufs
[i
].xfer
= xfer
;
3095 buf
= usbd_alloc_buffer(xfer
, size
);
3100 ch
->chanbufs
[i
].buffer
= buf
;
3101 ch
->chanbufs
[i
].chan
= ch
;
3104 return USBD_NORMAL_COMPLETION
;
3108 /* implicit buffer kfree */
3109 usbd_free_xfer(ch
->chanbufs
[i
].xfer
);
3114 uaudio_chan_free_buffers(struct uaudio_softc
*sc
, struct chan
*ch
)
3118 for (i
= 0; i
< UAUDIO_NCHANBUFS
; i
++)
3119 usbd_free_xfer(ch
->chanbufs
[i
].xfer
);
3122 /* Called at splusb() */
3124 uaudio_chan_ptransfer(struct chan
*ch
)
3127 int i
, n
, size
, residue
, total
;
3129 if (ch
->sc
->sc_dying
)
3132 /* Pick the next channel buffer. */
3133 cb
= &ch
->chanbufs
[ch
->curchanbuf
];
3134 if (++ch
->curchanbuf
>= UAUDIO_NCHANBUFS
)
3137 /* Compute the size of each frame in the next transfer. */
3138 residue
= ch
->residue
;
3140 for (i
= 0; i
< UAUDIO_NFRAMES
; i
++) {
3141 size
= ch
->bytes_per_frame
;
3142 residue
+= ch
->fraction
;
3143 if (residue
>= USB_FRAMES_PER_SECOND
) {
3144 if ((ch
->sc
->sc_altflags
& UA_NOFRAC
) == 0)
3145 size
+= ch
->sample_size
;
3146 residue
-= USB_FRAMES_PER_SECOND
;
3148 cb
->sizes
[i
] = size
;
3151 ch
->residue
= residue
;
3155 * Transfer data from upper layer buffer to channel buffer, taking
3156 * care of wrapping the upper layer buffer.
3158 n
= min(total
, ch
->end
- ch
->cur
);
3159 memcpy(cb
->buffer
, ch
->cur
, n
);
3161 if (ch
->cur
>= ch
->end
)
3162 ch
->cur
= ch
->start
;
3165 memcpy(cb
->buffer
+ n
, ch
->cur
, total
);
3170 if (uaudiodebug
> 8) {
3171 DPRINTF(("uaudio_chan_ptransfer: buffer=%p, residue=0.%03d\n",
3172 cb
->buffer
, ch
->residue
));
3173 for (i
= 0; i
< UAUDIO_NFRAMES
; i
++) {
3174 DPRINTF((" [%d] length %d\n", i
, cb
->sizes
[i
]));
3179 DPRINTFN(5,("uaudio_chan_transfer: ptransfer xfer=%p\n", cb
->xfer
));
3180 /* Fill the request */
3181 usbd_setup_isoc_xfer(cb
->xfer
, ch
->pipe
, cb
, cb
->sizes
,
3182 UAUDIO_NFRAMES
, USBD_NO_COPY
,
3185 (void)usbd_transfer(cb
->xfer
);
3189 uaudio_chan_pintr(usbd_xfer_handle xfer
, usbd_private_handle priv
,
3195 #if !defined(__DragonFly__)
3201 /* Return if we are aborting. */
3202 if (status
== USBD_CANCELLED
)
3205 usbd_get_xfer_status(xfer
, NULL
, NULL
, &count
, NULL
);
3206 DPRINTFN(5,("uaudio_chan_pintr: count=%d, transferred=%d\n",
3207 count
, ch
->transferred
));
3209 if (count
!= cb
->size
) {
3210 kprintf("uaudio_chan_pintr: count(%d) != size(%d)\n",
3215 ch
->transferred
+= cb
->size
;
3216 #if defined(__FreeBSD__)
3219 chn_intr(ch
->pcm_ch
);
3221 #elif defined(__DragonFly__)
3223 chn_intr(ch
->pcm_ch
);
3227 /* Call back to upper layer */
3228 while (ch
->transferred
>= ch
->blksize
) {
3229 ch
->transferred
-= ch
->blksize
;
3230 DPRINTFN(5,("uaudio_chan_pintr: call %p(%p)\n",
3231 ch
->intr
, ch
->arg
));
3237 /* start next transfer */
3238 uaudio_chan_ptransfer(ch
);
3241 /* Called at splusb() */
3243 uaudio_chan_rtransfer(struct chan
*ch
)
3246 int i
, size
, residue
, total
;
3248 if (ch
->sc
->sc_dying
)
3251 /* Pick the next channel buffer. */
3252 cb
= &ch
->chanbufs
[ch
->curchanbuf
];
3253 if (++ch
->curchanbuf
>= UAUDIO_NCHANBUFS
)
3256 /* Compute the size of each frame in the next transfer. */
3257 residue
= ch
->residue
;
3259 for (i
= 0; i
< UAUDIO_NFRAMES
; i
++) {
3260 size
= ch
->bytes_per_frame
;
3261 cb
->sizes
[i
] = size
;
3262 cb
->offsets
[i
] = total
;
3265 ch
->residue
= residue
;
3269 if (uaudiodebug
> 8) {
3270 DPRINTF(("uaudio_chan_rtransfer: buffer=%p, residue=0.%03d\n",
3271 cb
->buffer
, ch
->residue
));
3272 for (i
= 0; i
< UAUDIO_NFRAMES
; i
++) {
3273 DPRINTF((" [%d] length %d\n", i
, cb
->sizes
[i
]));
3278 DPRINTFN(5,("uaudio_chan_rtransfer: transfer xfer=%p\n", cb
->xfer
));
3279 /* Fill the request */
3280 usbd_setup_isoc_xfer(cb
->xfer
, ch
->pipe
, cb
, cb
->sizes
,
3281 UAUDIO_NFRAMES
, USBD_NO_COPY
,
3284 (void)usbd_transfer(cb
->xfer
);
3288 uaudio_chan_rintr(usbd_xfer_handle xfer
, usbd_private_handle priv
,
3291 struct chanbuf
*cb
= priv
;
3292 struct chan
*ch
= cb
->chan
;
3294 #if !defined(__DragonFly__)
3299 /* Return if we are aborting. */
3300 if (status
== USBD_CANCELLED
)
3303 usbd_get_xfer_status(xfer
, NULL
, NULL
, &count
, NULL
);
3304 DPRINTFN(5,("uaudio_chan_rintr: count=%d, transferred=%d\n",
3305 count
, ch
->transferred
));
3307 /* count < cb->size is normal for asynchronous source */
3309 if (count
> cb
->size
) {
3310 kprintf("uaudio_chan_rintr: count(%d) > size(%d)\n",
3316 * Transfer data from channel buffer to upper layer buffer, taking
3317 * care of wrapping the upper layer buffer.
3319 for(i
= 0; i
< UAUDIO_NFRAMES
; i
++) {
3320 frsize
= cb
->sizes
[i
];
3321 n
= min(frsize
, ch
->end
- ch
->cur
);
3322 memcpy(ch
->cur
, cb
->buffer
+ cb
->offsets
[i
], n
);
3324 if (ch
->cur
>= ch
->end
)
3325 ch
->cur
= ch
->start
;
3327 memcpy(ch
->cur
, cb
->buffer
+ cb
->offsets
[i
] + n
,
3329 ch
->cur
+= frsize
- n
;
3333 /* Call back to upper layer */
3334 ch
->transferred
+= count
;
3335 #if defined(__FreeBSD__)
3337 chn_intr(ch
->pcm_ch
);
3339 #elif defined(__DragonFly__)
3341 chn_intr(ch
->pcm_ch
);
3345 while (ch
->transferred
>= ch
->blksize
) {
3346 ch
->transferred
-= ch
->blksize
;
3347 DPRINTFN(5,("uaudio_chan_rintr: call %p(%p)\n",
3348 ch
->intr
, ch
->arg
));
3354 /* start next transfer */
3355 uaudio_chan_rtransfer(ch
);
3358 #if defined(__NetBSD__) || defined(__OpenBSD__)
3360 uaudio_chan_init(struct chan
*ch
, int altidx
, const struct audio_params
*param
,
3363 int samples_per_frame
, sample_size
;
3365 ch
->altidx
= altidx
;
3366 sample_size
= param
->precision
* param
->factor
* param
->hw_channels
/ 8;
3367 samples_per_frame
= param
->hw_sample_rate
/ USB_FRAMES_PER_SECOND
;
3368 ch
->sample_size
= sample_size
;
3369 ch
->sample_rate
= param
->hw_sample_rate
;
3370 if (maxpktsize
== 0) {
3371 ch
->fraction
= param
->hw_sample_rate
% USB_FRAMES_PER_SECOND
;
3372 ch
->bytes_per_frame
= samples_per_frame
* sample_size
;
3375 ch
->bytes_per_frame
= maxpktsize
;
3381 uaudio_chan_set_param(struct chan
*ch
, u_char
*start
, u_char
*end
, int blksize
)
3386 ch
->blksize
= blksize
;
3387 ch
->transferred
= 0;
3392 uaudio_get_minmax_rates(int nalts
, const struct as_info
*alts
,
3393 const struct audio_params
*p
, int mode
,
3394 u_long
*min
, u_long
*max
)
3396 const struct usb_audio_streaming_type1_descriptor
*a1d
;
3401 for (i
= 0; i
< nalts
; i
++) {
3402 a1d
= alts
[i
].asf1desc
;
3403 if (alts
[i
].sc_busy
)
3405 if (p
->hw_channels
!= a1d
->bNrChannels
)
3407 if (p
->hw_precision
!= a1d
->bBitResolution
)
3409 if (p
->hw_encoding
!= alts
[i
].encoding
)
3411 if (mode
!= UE_GET_DIR(alts
[i
].edesc
->bEndpointAddress
))
3413 if (a1d
->bSamFreqType
== UA_SAMP_CONTNUOUS
) {
3414 DPRINTFN(2,("uaudio_get_minmax_rates: cont %d-%d\n",
3415 UA_SAMP_LO(a1d
), UA_SAMP_HI(a1d
)));
3416 if (UA_SAMP_LO(a1d
) < *min
)
3417 *min
= UA_SAMP_LO(a1d
);
3418 if (UA_SAMP_HI(a1d
) > *max
)
3419 *max
= UA_SAMP_HI(a1d
);
3421 for (j
= 0; j
< a1d
->bSamFreqType
; j
++) {
3422 DPRINTFN(2,("uaudio_get_minmax_rates: disc #%d: %d\n",
3423 j
, UA_GETSAMP(a1d
, j
)));
3424 if (UA_GETSAMP(a1d
, j
) < *min
)
3425 *min
= UA_GETSAMP(a1d
, j
);
3426 if (UA_GETSAMP(a1d
, j
) > *max
)
3427 *max
= UA_GETSAMP(a1d
, j
);
3434 uaudio_match_alt_sub(int nalts
, const struct as_info
*alts
,
3435 const struct audio_params
*p
, int mode
, u_long rate
)
3437 const struct usb_audio_streaming_type1_descriptor
*a1d
;
3440 DPRINTF(("uaudio_match_alt_sub: search for %luHz %dch\n",
3441 rate
, p
->hw_channels
));
3442 for (i
= 0; i
< nalts
; i
++) {
3443 a1d
= alts
[i
].asf1desc
;
3444 if (alts
[i
].sc_busy
)
3446 if (p
->hw_channels
!= a1d
->bNrChannels
)
3448 if (p
->hw_precision
!= a1d
->bBitResolution
)
3450 if (p
->hw_encoding
!= alts
[i
].encoding
)
3452 if (mode
!= UE_GET_DIR(alts
[i
].edesc
->bEndpointAddress
))
3454 if (a1d
->bSamFreqType
== UA_SAMP_CONTNUOUS
) {
3455 DPRINTFN(3,("uaudio_match_alt_sub: cont %d-%d\n",
3456 UA_SAMP_LO(a1d
), UA_SAMP_HI(a1d
)));
3457 if (UA_SAMP_LO(a1d
) <= rate
&& rate
<= UA_SAMP_HI(a1d
))
3460 for (j
= 0; j
< a1d
->bSamFreqType
; j
++) {
3461 DPRINTFN(3,("uaudio_match_alt_sub: disc #%d: %d\n",
3462 j
, UA_GETSAMP(a1d
, j
)));
3463 /* XXX allow for some slack */
3464 if (UA_GETSAMP(a1d
, j
) == rate
)
3473 uaudio_match_alt_chan(int nalts
, const struct as_info
*alts
,
3474 struct audio_params
*p
, int mode
)
3481 DPRINTF(("uaudio_match_alt_chan: examine %ldHz %dch %dbit.\n",
3482 p
->sample_rate
, p
->hw_channels
, p
->hw_precision
));
3483 i
= uaudio_match_alt_sub(nalts
, alts
, p
, mode
, p
->sample_rate
);
3487 uaudio_get_minmax_rates(nalts
, alts
, p
, mode
, &min
, &max
);
3488 DPRINTF(("uaudio_match_alt_chan: min=%lu max=%lu\n", min
, max
));
3491 /* Search for biggers */
3493 while ((rate
= p
->sample_rate
* n
++) <= max
) {
3494 i
= uaudio_match_alt_sub(nalts
, alts
, p
, mode
, rate
);
3496 p
->hw_sample_rate
= rate
;
3500 if (p
->sample_rate
>= min
) {
3501 i
= uaudio_match_alt_sub(nalts
, alts
, p
, mode
, max
);
3503 p
->hw_sample_rate
= max
;
3507 i
= uaudio_match_alt_sub(nalts
, alts
, p
, mode
, min
);
3509 p
->hw_sample_rate
= min
;
3517 uaudio_match_alt(int nalts
, const struct as_info
*alts
,
3518 struct audio_params
*p
, int mode
)
3522 mode
= mode
== AUMODE_PLAY
? UE_DIR_OUT
: UE_DIR_IN
;
3523 i
= uaudio_match_alt_chan(nalts
, alts
, p
, mode
);
3527 for (n
= p
->channels
+ 1; n
<= AUDIO_MAX_CHANNELS
; n
++) {
3529 i
= uaudio_match_alt_chan(nalts
, alts
, p
, mode
);
3534 if (p
->channels
!= 2)
3537 return uaudio_match_alt_chan(nalts
, alts
, p
, mode
);
3541 uaudio_set_params(void *addr
, int setmode
, int usemode
,
3542 struct audio_params
*play
, struct audio_params
*rec
)
3544 struct uaudio_softc
*sc
;
3548 int paltidx
, raltidx
;
3549 void (*swcode
)(void *, u_char
*buf
, int cnt
);
3550 struct audio_params
*p
;
3554 flags
= sc
->sc_altflags
;
3560 if (((usemode
& AUMODE_PLAY
) && sc
->sc_playchan
.pipe
!= NULL
) ||
3561 ((usemode
& AUMODE_RECORD
) && sc
->sc_recchan
.pipe
!= NULL
))
3564 if ((usemode
& AUMODE_PLAY
) && sc
->sc_playchan
.altidx
!= -1)
3565 sc
->sc_alts
[sc
->sc_playchan
.altidx
].sc_busy
= 0;
3566 if ((usemode
& AUMODE_RECORD
) && sc
->sc_recchan
.altidx
!= -1)
3567 sc
->sc_alts
[sc
->sc_recchan
.altidx
].sc_busy
= 0;
3569 /* Some uaudio devices are unidirectional. Don't try to find a
3570 matching mode for the unsupported direction. */
3571 setmode
&= sc
->sc_mode
;
3573 for (mode
= AUMODE_RECORD
; mode
!= -1;
3574 mode
= mode
== AUMODE_RECORD
? AUMODE_PLAY
: -1) {
3575 if ((setmode
& mode
) == 0)
3578 p
= (mode
== AUMODE_PLAY
) ? play
: rec
;
3584 case AUDIO_ENCODING_SLINEAR_BE
:
3586 case AUDIO_ENCODING_SLINEAR_LE
:
3587 if (enc
== AUDIO_ENCODING_SLINEAR_BE
3588 && p
->precision
== 16 && (flags
& HAS_16
)) {
3589 swcode
= swap_bytes
;
3590 enc
= AUDIO_ENCODING_SLINEAR_LE
;
3591 } else if (p
->precision
== 8) {
3592 if (flags
& HAS_8
) {
3594 } else if (flags
& HAS_8U
) {
3595 swcode
= change_sign8
;
3596 enc
= AUDIO_ENCODING_ULINEAR_LE
;
3597 } else if (flags
& HAS_16
) {
3599 p
->hw_precision
= 16;
3600 if (mode
== AUMODE_PLAY
)
3601 swcode
= linear8_to_linear16_le
;
3603 swcode
= linear16_to_linear8_le
;
3607 case AUDIO_ENCODING_ULINEAR_BE
:
3609 case AUDIO_ENCODING_ULINEAR_LE
:
3610 if (p
->precision
== 16) {
3611 if (enc
== AUDIO_ENCODING_ULINEAR_LE
)
3612 swcode
= change_sign16_le
;
3613 else if (mode
== AUMODE_PLAY
)
3614 swcode
= swap_bytes_change_sign16_le
;
3616 swcode
= change_sign16_swap_bytes_le
;
3617 enc
= AUDIO_ENCODING_SLINEAR_LE
;
3618 } else if (p
->precision
== 8) {
3619 if (flags
& HAS_8U
) {
3621 } else if (flags
& HAS_8
) {
3622 swcode
= change_sign8
;
3623 enc
= AUDIO_ENCODING_SLINEAR_LE
;
3624 } else if (flags
& HAS_16
) {
3626 p
->hw_precision
= 16;
3627 enc
= AUDIO_ENCODING_SLINEAR_LE
;
3628 if (mode
== AUMODE_PLAY
)
3629 swcode
= ulinear8_to_slinear16_le
;
3631 swcode
= slinear16_to_ulinear8_le
;
3635 case AUDIO_ENCODING_ULAW
:
3636 if (flags
& HAS_MULAW
)
3638 if (flags
& HAS_16
) {
3639 if (mode
== AUMODE_PLAY
)
3640 swcode
= mulaw_to_slinear16_le
;
3642 swcode
= slinear16_to_mulaw_le
;
3644 enc
= AUDIO_ENCODING_SLINEAR_LE
;
3645 p
->hw_precision
= 16;
3646 } else if (flags
& HAS_8U
) {
3647 if (mode
== AUMODE_PLAY
)
3648 swcode
= mulaw_to_ulinear8
;
3650 swcode
= ulinear8_to_mulaw
;
3651 enc
= AUDIO_ENCODING_ULINEAR_LE
;
3652 } else if (flags
& HAS_8
) {
3653 if (mode
== AUMODE_PLAY
)
3654 swcode
= mulaw_to_slinear8
;
3656 swcode
= slinear8_to_mulaw
;
3657 enc
= AUDIO_ENCODING_SLINEAR_LE
;
3661 case AUDIO_ENCODING_ALAW
:
3662 if (flags
& HAS_ALAW
)
3664 if (mode
== AUMODE_PLAY
&& (flags
& HAS_16
)) {
3665 swcode
= alaw_to_slinear16_le
;
3667 enc
= AUDIO_ENCODING_SLINEAR_LE
;
3668 p
->hw_precision
= 16;
3669 } else if (flags
& HAS_8U
) {
3670 if (mode
== AUMODE_PLAY
)
3671 swcode
= alaw_to_ulinear8
;
3673 swcode
= ulinear8_to_alaw
;
3674 enc
= AUDIO_ENCODING_ULINEAR_LE
;
3675 } else if (flags
& HAS_8
) {
3676 if (mode
== AUMODE_PLAY
)
3677 swcode
= alaw_to_slinear8
;
3679 swcode
= slinear8_to_alaw
;
3680 enc
= AUDIO_ENCODING_SLINEAR_LE
;
3687 /* XXX do some other conversions... */
3689 DPRINTF(("uaudio_set_params: chan=%d prec=%d enc=%d rate=%ld\n",
3690 p
->channels
, p
->hw_precision
, enc
, p
->sample_rate
));
3692 p
->hw_encoding
= enc
;
3693 i
= uaudio_match_alt(sc
->sc_nalts
, sc
->sc_alts
, p
, mode
);
3697 p
->sw_code
= swcode
;
3700 if (mode
== AUMODE_PLAY
)
3706 if ((setmode
& AUMODE_PLAY
)) {
3707 /* XXX abort transfer if currently happening? */
3708 uaudio_chan_init(&sc
->sc_playchan
, paltidx
, play
, 0);
3710 if ((setmode
& AUMODE_RECORD
)) {
3711 /* XXX abort transfer if currently happening? */
3712 uaudio_chan_init(&sc
->sc_recchan
, raltidx
, rec
,
3713 UGETW(sc
->sc_alts
[raltidx
].edesc
->wMaxPacketSize
));
3716 if ((usemode
& AUMODE_PLAY
) && sc
->sc_playchan
.altidx
!= -1)
3717 sc
->sc_alts
[sc
->sc_playchan
.altidx
].sc_busy
= 1;
3718 if ((usemode
& AUMODE_RECORD
) && sc
->sc_recchan
.altidx
!= -1)
3719 sc
->sc_alts
[sc
->sc_recchan
.altidx
].sc_busy
= 1;
3721 DPRINTF(("uaudio_set_params: use altidx=p%d/r%d, altno=p%d/r%d\n",
3722 sc
->sc_playchan
.altidx
, sc
->sc_recchan
.altidx
,
3723 (sc
->sc_playchan
.altidx
>= 0)
3724 ?sc
->sc_alts
[sc
->sc_playchan
.altidx
].idesc
->bAlternateSetting
3726 (sc
->sc_recchan
.altidx
>= 0)
3727 ? sc
->sc_alts
[sc
->sc_recchan
.altidx
].idesc
->bAlternateSetting
3732 #endif /* NetBSD or OpenBSD */
3735 uaudio_set_speed(struct uaudio_softc
*sc
, int endpt
, u_int speed
)
3737 usb_device_request_t req
;
3740 DPRINTFN(5,("uaudio_set_speed: endpt=%d speed=%u\n", endpt
, speed
));
3741 req
.bmRequestType
= UT_WRITE_CLASS_ENDPOINT
;
3742 req
.bRequest
= SET_CUR
;
3743 USETW2(req
.wValue
, SAMPLING_FREQ_CONTROL
, 0);
3744 USETW(req
.wIndex
, endpt
);
3745 USETW(req
.wLength
, 3);
3747 data
[1] = speed
>> 8;
3748 data
[2] = speed
>> 16;
3750 return usbd_do_request(sc
->sc_udev
, &req
, data
);
3754 #if defined(__FreeBSD__) || defined(__DragonFly__)
3755 /************************************************************/
3757 uaudio_init_params(struct uaudio_softc
*sc
, struct chan
*ch
, int mode
)
3760 int samples_per_frame
, sample_size
;
3762 if ((sc
->sc_playchan
.pipe
!= NULL
) || (sc
->sc_recchan
.pipe
!= NULL
))
3765 switch(ch
->format
& 0x000FFFFF) {
3767 enc
= AUDIO_ENCODING_ULINEAR_LE
;
3771 enc
= AUDIO_ENCODING_SLINEAR_LE
;
3774 case AFMT_A_LAW
: /* ? */
3775 enc
= AUDIO_ENCODING_ALAW
;
3778 case AFMT_MU_LAW
: /* ? */
3779 enc
= AUDIO_ENCODING_ULAW
;
3783 enc
= AUDIO_ENCODING_SLINEAR_LE
;
3787 enc
= AUDIO_ENCODING_SLINEAR_BE
;
3791 enc
= AUDIO_ENCODING_ULINEAR_LE
;
3795 enc
= AUDIO_ENCODING_ULINEAR_BE
;
3799 enc
= AUDIO_ENCODING_SLINEAR_LE
;
3803 enc
= AUDIO_ENCODING_SLINEAR_BE
;
3807 enc
= AUDIO_ENCODING_ULINEAR_LE
;
3811 enc
= AUDIO_ENCODING_ULINEAR_BE
;
3815 enc
= AUDIO_ENCODING_SLINEAR_LE
;
3819 enc
= AUDIO_ENCODING_SLINEAR_BE
;
3823 enc
= AUDIO_ENCODING_ULINEAR_LE
;
3827 enc
= AUDIO_ENCODING_ULINEAR_BE
;
3833 kprintf("Unknown format %x\n", ch
->format
);
3836 if (ch
->format
& AFMT_STEREO
) {
3842 /* for (mode = ...... */
3843 for (i
= 0; i
< sc
->sc_nalts
; i
++) {
3844 const struct usb_audio_streaming_type1_descriptor
*a1d
=
3845 sc
->sc_alts
[i
].asf1desc
;
3846 if (ch
->channels
== a1d
->bNrChannels
&&
3847 ch
->precision
== a1d
->bBitResolution
&&
3849 enc
== sc
->sc_alts
[i
].encoding
) {
3851 enc
== sc
->sc_alts
[i
].encoding
&&
3852 (mode
== AUMODE_PLAY
? UE_DIR_OUT
: UE_DIR_IN
) ==
3853 UE_GET_DIR(sc
->sc_alts
[i
].edesc
->bEndpointAddress
)) {
3855 if (a1d
->bSamFreqType
== UA_SAMP_CONTNUOUS
) {
3856 DPRINTFN(2,("uaudio_set_params: cont %d-%d\n",
3857 UA_SAMP_LO(a1d
), UA_SAMP_HI(a1d
)));
3858 if (UA_SAMP_LO(a1d
) <= ch
->sample_rate
&&
3859 ch
->sample_rate
<= UA_SAMP_HI(a1d
)) {
3860 if (mode
== AUMODE_PLAY
)
3861 sc
->sc_playchan
.altidx
= i
;
3863 sc
->sc_recchan
.altidx
= i
;
3867 for (j
= 0; j
< a1d
->bSamFreqType
; j
++) {
3868 DPRINTFN(2,("uaudio_set_params: disc #"
3869 "%d: %d\n", j
, UA_GETSAMP(a1d
, j
)));
3870 /* XXX allow for some slack */
3871 if (UA_GETSAMP(a1d
, j
) ==
3873 if (mode
== AUMODE_PLAY
)
3874 sc
->sc_playchan
.altidx
= i
;
3876 sc
->sc_recchan
.altidx
= i
;
3883 /* return (EINVAL); */
3884 if (mode
== AUMODE_PLAY
)
3885 kprintf("uaudio: This device can't play in rate=%d.\n", ch
->sample_rate
);
3887 kprintf("uaudio: This device can't record in rate=%d.\n", ch
->sample_rate
);
3892 p
->sw_code
= swcode
;
3894 if (usemode
== mode
)
3895 sc
->sc_curaltidx
= i
;
3899 sample_size
= ch
->precision
* ch
->channels
/ 8;
3900 samples_per_frame
= ch
->sample_rate
/ USB_FRAMES_PER_SECOND
;
3901 ch
->fraction
= ch
->sample_rate
% USB_FRAMES_PER_SECOND
;
3902 ch
->sample_size
= sample_size
;
3903 ch
->bytes_per_frame
= samples_per_frame
* sample_size
;
3906 ch
->cur
= ch
->start
;
3907 ch
->transferred
= 0;
3912 struct uaudio_conversion
{
3914 uint8_t uaudio_prec
;
3915 uint32_t freebsd_fmt
;
3918 const struct uaudio_conversion
const accepted_conversion
[] = {
3919 {AUDIO_ENCODING_ULINEAR_LE
, 8, AFMT_U8
},
3920 {AUDIO_ENCODING_ULINEAR_LE
, 16, AFMT_U16_LE
},
3921 {AUDIO_ENCODING_ULINEAR_LE
, 24, AFMT_U24_LE
},
3922 {AUDIO_ENCODING_ULINEAR_LE
, 32, AFMT_U32_LE
},
3923 {AUDIO_ENCODING_ULINEAR_BE
, 16, AFMT_U16_BE
},
3924 {AUDIO_ENCODING_ULINEAR_BE
, 24, AFMT_U24_BE
},
3925 {AUDIO_ENCODING_ULINEAR_BE
, 32, AFMT_U32_BE
},
3926 {AUDIO_ENCODING_SLINEAR_LE
, 8, AFMT_S8
},
3927 {AUDIO_ENCODING_SLINEAR_LE
, 16, AFMT_S16_LE
},
3928 {AUDIO_ENCODING_SLINEAR_LE
, 24, AFMT_S24_LE
},
3929 {AUDIO_ENCODING_SLINEAR_LE
, 32, AFMT_S32_LE
},
3930 {AUDIO_ENCODING_SLINEAR_BE
, 16, AFMT_S16_BE
},
3931 {AUDIO_ENCODING_SLINEAR_BE
, 24, AFMT_S24_BE
},
3932 {AUDIO_ENCODING_SLINEAR_BE
, 32, AFMT_S32_BE
},
3933 {AUDIO_ENCODING_ALAW
, 8, AFMT_A_LAW
},
3934 {AUDIO_ENCODING_ULAW
, 8, AFMT_MU_LAW
},
3939 uaudio_query_formats(device_t dev
, int reqdir
, unsigned maxfmt
, struct pcmchan_caps
*cap
)
3941 struct uaudio_softc
*sc
;
3942 const struct usb_audio_streaming_type1_descriptor
*asf1d
;
3943 const struct uaudio_conversion
*iterator
;
3944 unsigned fmtcount
, foundcount
;
3946 uint8_t format
, numchan
, subframesize
, prec
, dir
, iscontinuous
;
3947 int freq
, freq_min
, freq_max
;
3948 char *numchannel_descr
;
3949 char freq_descr
[64];
3952 sc
= device_get_softc(dev
);
3956 cap
->minspeed
= cap
->maxspeed
= 0;
3957 foundcount
= fmtcount
= 0;
3959 for (i
= 0; i
< sc
->sc_nalts
; i
++) {
3960 dir
= UE_GET_DIR(sc
->sc_alts
[i
].edesc
->bEndpointAddress
);
3962 if ((dir
== UE_DIR_OUT
) != (reqdir
== PCMDIR_PLAY
))
3965 asf1d
= sc
->sc_alts
[i
].asf1desc
;
3966 format
= sc
->sc_alts
[i
].encoding
;
3968 numchan
= asf1d
->bNrChannels
;
3969 subframesize
= asf1d
->bSubFrameSize
;
3970 prec
= asf1d
->bBitResolution
; /* precision */
3971 iscontinuous
= asf1d
->bSamFreqType
== UA_SAMP_CONTNUOUS
;
3974 ksnprintf(freq_descr
, sizeof(freq_descr
), "continous min %d max %d", UA_SAMP_LO(asf1d
), UA_SAMP_HI(asf1d
));
3976 ksnprintf(freq_descr
, sizeof(freq_descr
), "fixed frequency (%d listed formats)", asf1d
->bSamFreqType
);
3979 numchannel_descr
= " (mono)";
3980 else if (numchan
== 2)
3981 numchannel_descr
= " (stereo)";
3983 numchannel_descr
= "";
3986 device_printf(dev
, "uaudio_query_formats: found a native %s channel%s %s %dbit %dbytes/subframe X %d channels = %d bytes per sample\n",
3987 (dir
==UE_DIR_OUT
)?"playback":"record",
3988 numchannel_descr
, freq_descr
,
3989 prec
, subframesize
, numchan
, subframesize
*numchan
);
3992 * Now start rejecting the ones that don't map to FreeBSD
3995 if (numchan
!= 1 && numchan
!= 2)
3998 for (iterator
= accepted_conversion
; iterator
->uaudio_fmt
!= 0 ; iterator
++)
3999 if (iterator
->uaudio_fmt
== format
&& iterator
->uaudio_prec
== prec
)
4002 if (iterator
->uaudio_fmt
== 0)
4005 fmt
= iterator
->freebsd_fmt
;
4012 if (fmtcount
>= maxfmt
)
4015 cap
->fmtlist
[fmtcount
++] = fmt
;
4018 freq_min
= UA_SAMP_LO(asf1d
);
4019 freq_max
= UA_SAMP_HI(asf1d
);
4021 if (cap
->minspeed
== 0 || freq_min
< cap
->minspeed
)
4022 cap
->minspeed
= freq_min
;
4023 if (cap
->maxspeed
== 0)
4024 cap
->maxspeed
= cap
->minspeed
;
4025 if (freq_max
> cap
->maxspeed
)
4026 cap
->maxspeed
= freq_max
;
4028 for (r
= 0; r
< asf1d
->bSamFreqType
; r
++) {
4029 freq
= UA_GETSAMP(asf1d
, r
);
4030 if (cap
->minspeed
== 0 || freq
< cap
->minspeed
)
4031 cap
->minspeed
= freq
;
4032 if (cap
->maxspeed
== 0)
4033 cap
->maxspeed
= cap
->minspeed
;
4034 if (freq
> cap
->maxspeed
)
4035 cap
->maxspeed
= freq
;
4039 cap
->fmtlist
[fmtcount
] = 0;
4044 uaudio_chan_set_param_pcm_dma_buff(device_t dev
, u_char
*start
, u_char
*end
,
4045 struct pcm_channel
*pc
, int dir
)
4047 struct uaudio_softc
*sc
;
4050 sc
= device_get_softc(dev
);
4051 #ifndef NO_RECORDING
4052 if (dir
== PCMDIR_PLAY
)
4053 ch
= &sc
->sc_playchan
;
4055 ch
= &sc
->sc_recchan
;
4057 ch
= &sc
->sc_playchan
;
4069 uaudio_chan_set_param_blocksize(device_t dev
, u_int32_t blocksize
, int dir
)
4071 struct uaudio_softc
*sc
;
4074 sc
= device_get_softc(dev
);
4075 #ifndef NO_RECORDING
4076 if (dir
== PCMDIR_PLAY
)
4077 ch
= &sc
->sc_playchan
;
4079 ch
= &sc
->sc_recchan
;
4081 ch
= &sc
->sc_playchan
;
4084 ch
->blksize
= blocksize
;
4090 uaudio_chan_set_param_speed(device_t dev
, u_int32_t speed
, int reqdir
)
4092 const struct uaudio_conversion
*iterator
;
4093 struct uaudio_softc
*sc
;
4095 int i
, r
, score
, hiscore
, bestspeed
;
4097 sc
= device_get_softc(dev
);
4098 #ifndef NO_RECORDING
4099 if (reqdir
== PCMDIR_PLAY
)
4100 ch
= &sc
->sc_playchan
;
4102 ch
= &sc
->sc_recchan
;
4104 ch
= &sc
->sc_playchan
;
4107 * We are successful if we find an endpoint that matches our selected format and it
4108 * supports the requested speed.
4112 for (i
= 0; i
< sc
->sc_nalts
; i
++) {
4113 int dir
= UE_GET_DIR(sc
->sc_alts
[i
].edesc
->bEndpointAddress
);
4114 int format
= sc
->sc_alts
[i
].encoding
;
4115 const struct usb_audio_streaming_type1_descriptor
*asf1d
= sc
->sc_alts
[i
].asf1desc
;
4116 int iscontinuous
= asf1d
->bSamFreqType
== UA_SAMP_CONTNUOUS
;
4118 if ((dir
== UE_DIR_OUT
) != (reqdir
== PCMDIR_PLAY
))
4121 for (iterator
= accepted_conversion
; iterator
->uaudio_fmt
!= 0 ; iterator
++)
4122 if (iterator
->uaudio_fmt
!= format
|| iterator
->freebsd_fmt
!= (ch
->format
&0xfffffff))
4125 if (speed
>= UA_SAMP_LO(asf1d
) && speed
<= UA_SAMP_HI(asf1d
)) {
4126 ch
->sample_rate
= speed
;
4128 } else if (speed
< UA_SAMP_LO(asf1d
)) {
4129 score
= 0xfff * speed
/ UA_SAMP_LO(asf1d
);
4130 if (score
> hiscore
) {
4131 bestspeed
= UA_SAMP_LO(asf1d
);
4134 } else if (speed
< UA_SAMP_HI(asf1d
)) {
4135 score
= 0xfff * UA_SAMP_HI(asf1d
) / speed
;
4136 if (score
> hiscore
) {
4137 bestspeed
= UA_SAMP_HI(asf1d
);
4143 for (r
= 0; r
< asf1d
->bSamFreqType
; r
++) {
4144 if (speed
== UA_GETSAMP(asf1d
, r
)) {
4145 ch
->sample_rate
= speed
;
4148 if (speed
> UA_GETSAMP(asf1d
, r
))
4149 score
= 0xfff * UA_GETSAMP(asf1d
, r
) / speed
;
4151 score
= 0xfff * speed
/ UA_GETSAMP(asf1d
, r
);
4152 if (score
> hiscore
) {
4153 bestspeed
= UA_GETSAMP(asf1d
, r
);
4158 if (bestspeed
!= 1) {
4159 ch
->sample_rate
= bestspeed
;
4167 uaudio_chan_getptr(device_t dev
, int dir
)
4169 struct uaudio_softc
*sc
;
4173 sc
= device_get_softc(dev
);
4174 #ifndef NO_RECORDING
4175 if (dir
== PCMDIR_PLAY
)
4176 ch
= &sc
->sc_playchan
;
4178 ch
= &sc
->sc_recchan
;
4180 ch
= &sc
->sc_playchan
;
4183 ptr
= ch
->cur
- ch
->start
;
4189 uaudio_chan_set_param_format(device_t dev
, u_int32_t format
, int dir
)
4191 struct uaudio_softc
*sc
;
4194 sc
= device_get_softc(dev
);
4195 #ifndef NO_RECORDING
4196 if (dir
== PCMDIR_PLAY
)
4197 ch
= &sc
->sc_playchan
;
4199 ch
= &sc
->sc_recchan
;
4201 ch
= &sc
->sc_playchan
;
4204 ch
->format
= format
;
4210 uaudio_halt_out_dma(device_t dev
)
4212 struct uaudio_softc
*sc
;
4214 sc
= device_get_softc(dev
);
4216 DPRINTF(("uaudio_halt_out_dma: enter\n"));
4217 if (sc
->sc_playchan
.pipe
!= NULL
) {
4218 uaudio_chan_close(sc
, &sc
->sc_playchan
);
4219 sc
->sc_playchan
.pipe
= 0;
4220 uaudio_chan_free_buffers(sc
, &sc
->sc_playchan
);
4226 uaudio_halt_in_dma(device_t dev
)
4228 struct uaudio_softc
*sc
;
4230 sc
= device_get_softc(dev
);
4235 DPRINTF(("uaudio_halt_in_dma: enter\n"));
4236 if (sc
->sc_recchan
.pipe
!= NULL
) {
4237 uaudio_chan_close(sc
, &sc
->sc_recchan
);
4238 sc
->sc_recchan
.pipe
= NULL
;
4239 uaudio_chan_free_buffers(sc
, &sc
->sc_recchan
);
4240 /* sc->sc_recchan.intr = NULL; */
4246 uaudio_trigger_input(device_t dev
)
4248 struct uaudio_softc
*sc
;
4252 #if !defined(__DragonFly__)
4256 sc
= device_get_softc(dev
);
4257 ch
= &sc
->sc_recchan
;
4262 /* uaudio_chan_set_param(ch, start, end, blksize) */
4263 if (uaudio_init_params(sc
, ch
, AUMODE_RECORD
))
4266 err
= uaudio_chan_alloc_buffers(sc
, ch
);
4270 err
= uaudio_chan_open(sc
, ch
);
4272 uaudio_chan_free_buffers(sc
, ch
);
4279 #if defined(__DragonFly__)
4284 for (i
= 0; i
< UAUDIO_NCHANBUFS
-1; i
++) /* XXX -1 shouldn't be needed */
4285 uaudio_chan_rtransfer(ch
);
4286 #if defined(__DragonFly__)
4296 uaudio_trigger_output(device_t dev
)
4298 struct uaudio_softc
*sc
;
4302 #if !defined(__DragonFly__)
4306 sc
= device_get_softc(dev
);
4307 ch
= &sc
->sc_playchan
;
4312 if (uaudio_init_params(sc
, ch
, AUMODE_PLAY
))
4315 err
= uaudio_chan_alloc_buffers(sc
, ch
);
4319 err
= uaudio_chan_open(sc
, ch
);
4321 uaudio_chan_free_buffers(sc
, ch
);
4325 #if defined(__DragonFly__)
4330 for (i
= 0; i
< UAUDIO_NCHANBUFS
-1; i
++) /* XXX */
4331 uaudio_chan_ptransfer(ch
);
4332 #if defined(__DragonFly__)
4342 uaudio_query_mix_info(device_t dev
)
4346 struct uaudio_softc
*sc
;
4347 struct mixerctl
*mc
;
4349 sc
= device_get_softc(dev
);
4350 for (i
=0; i
< sc
->sc_nctls
; i
++) {
4351 mc
= &sc
->sc_ctls
[i
];
4352 if (mc
->ctl
!= SOUND_MIXER_NRDEVICES
) {
4353 /* Set device mask bits.
4354 See /usr/include/machine/soundcard.h */
4355 mask
|= (1 << mc
->ctl
);
4362 uaudio_query_recsrc_info(device_t dev
)
4364 int i
, rec_selector_id
;
4366 struct uaudio_softc
*sc
;
4367 struct mixerctl
*mc
;
4369 sc
= device_get_softc(dev
);
4370 rec_selector_id
= -1;
4371 for (i
=0; i
< sc
->sc_nctls
; i
++) {
4372 mc
= &sc
->sc_ctls
[i
];
4373 if (mc
->ctl
== SOUND_MIXER_NRDEVICES
&&
4374 mc
->type
== MIX_SELECTOR
&& mc
->class == UAC_RECORD
) {
4375 if (rec_selector_id
== -1) {
4376 rec_selector_id
= i
;
4378 kprintf("There are many selectors. Can't recognize which selector is a record source selector.\n");
4383 if (rec_selector_id
== -1)
4385 mc
= &sc
->sc_ctls
[rec_selector_id
];
4386 for (i
= mc
->minval
; i
<= mc
->maxval
; i
++) {
4387 if (mc
->slctrtype
[i
- 1] == SOUND_MIXER_NRDEVICES
)
4389 mask
|= 1 << mc
->slctrtype
[i
- 1];
4395 uaudio_mixer_set(device_t dev
, unsigned type
, unsigned left
, unsigned right
)
4398 struct uaudio_softc
*sc
;
4399 struct mixerctl
*mc
;
4401 sc
= device_get_softc(dev
);
4402 for (i
=0; i
< sc
->sc_nctls
; i
++) {
4403 mc
= &sc
->sc_ctls
[i
];
4404 if (mc
->ctl
== type
) {
4405 if (mc
->nchan
== 2) {
4407 uaudio_ctl_set(sc
, SET_CUR
, mc
, 1, (int)(right
*255)/100);
4409 /* set Left or Mono */
4410 uaudio_ctl_set(sc
, SET_CUR
, mc
, 0, (int)(left
*255)/100);
4417 uaudio_mixer_setrecsrc(device_t dev
, u_int32_t src
)
4419 int i
, rec_selector_id
;
4420 struct uaudio_softc
*sc
;
4421 struct mixerctl
*mc
;
4423 sc
= device_get_softc(dev
);
4424 rec_selector_id
= -1;
4425 for (i
=0; i
< sc
->sc_nctls
; i
++) {
4426 mc
= &sc
->sc_ctls
[i
];
4427 if (mc
->ctl
== SOUND_MIXER_NRDEVICES
&&
4428 mc
->type
== MIX_SELECTOR
&& mc
->class == UAC_RECORD
) {
4429 if (rec_selector_id
== -1) {
4430 rec_selector_id
= i
;
4432 return src
; /* Can't recognize which selector is record source selector */
4436 if (rec_selector_id
== -1)
4438 mc
= &sc
->sc_ctls
[rec_selector_id
];
4439 for (i
= mc
->minval
; i
<= mc
->maxval
; i
++) {
4440 if (src
!= (1 << mc
->slctrtype
[i
- 1]))
4442 uaudio_ctl_set(sc
, SET_CUR
, mc
, 0, i
);
4443 return (1 << mc
->slctrtype
[i
- 1]);
4445 uaudio_ctl_set(sc
, SET_CUR
, mc
, 0, mc
->minval
);
4446 return (1 << mc
->slctrtype
[mc
->minval
- 1]);
4450 uaudio_sndstat_prepare_pcm(struct sbuf
*s
, device_t dev
, int verbose
)
4452 struct snddev_info
*d
;
4453 struct snddev_channel
*sce
;
4454 struct pcm_channel
*c
;
4455 struct pcm_feeder
*f
;
4457 device_t pa_dev
= device_get_parent(dev
);
4458 struct uaudio_softc
*sc
= device_get_softc(pa_dev
);
4463 d
= device_get_softc(dev
);
4467 snd_mtxlock(d
->lock
);
4468 if (SLIST_EMPTY(&d
->channels
)) {
4469 sbuf_printf(s
, " (mixer only)");
4470 snd_mtxunlock(d
->lock
);
4474 SLIST_FOREACH(sce
, &d
->channels
, link
) {
4476 if (c
->direction
== PCMDIR_PLAY
) {
4477 if (c
->flags
& CHN_F_VIRTUAL
)
4484 sbuf_printf(s
, " (%dp/%dr/%dv channels%s%s)",
4485 d
->playcount
, d
->reccount
, d
->vchancount
,
4486 (d
->flags
& SD_F_SIMPLEX
)? "" : " duplex",
4488 (device_get_unit(dev
) == snd_unit
)? " default" : ""
4494 if (sc
->uaudio_sndstat_flag
!= 0) {
4495 sbuf_cat(s
, sbuf_data(&(sc
->uaudio_sndstat
)));
4499 snd_mtxunlock(d
->lock
);
4503 SLIST_FOREACH(sce
, &d
->channels
, link
) {
4505 sbuf_printf(s
, "\n\t");
4507 KASSERT(c
->bufhard
!= NULL
&& c
->bufsoft
!= NULL
,
4508 ("hosed pcm channel setup"));
4510 /* it would be better to indent child channels */
4511 sbuf_printf(s
, "%s[%s]: ", c
->parentchannel
? c
->parentchannel
->name
: "", c
->name
);
4512 sbuf_printf(s
, "spd %d", c
->speed
);
4513 if (c
->speed
!= sndbuf_getspd(c
->bufhard
))
4514 sbuf_printf(s
, "/%d", sndbuf_getspd(c
->bufhard
));
4515 sbuf_printf(s
, ", fmt 0x%08x", c
->format
);
4516 if (c
->format
!= sndbuf_getfmt(c
->bufhard
))
4517 sbuf_printf(s
, "/0x%08x", sndbuf_getfmt(c
->bufhard
));
4518 sbuf_printf(s
, ", flags 0x%08x, 0x%08x", c
->flags
, c
->feederflags
);
4520 sbuf_printf(s
, ", pid %d", c
->pid
);
4521 sbuf_printf(s
, "\n\t");
4523 sbuf_printf(s
, "interrupts %d, ", c
->interrupts
);
4524 if (c
->direction
== PCMDIR_REC
)
4525 sbuf_printf(s
, "overruns %d, hfree %d, sfree %d",
4526 c
->xruns
, sndbuf_getfree(c
->bufhard
), sndbuf_getfree(c
->bufsoft
));
4528 sbuf_printf(s
, "underruns %d, ready %d",
4529 c
->xruns
, sndbuf_getready(c
->bufsoft
));
4530 sbuf_printf(s
, "\n\t");
4532 sbuf_printf(s
, "{%s}", (c
->direction
== PCMDIR_REC
)? "hardware" : "userland");
4533 sbuf_printf(s
, " -> ");
4535 while (f
->source
!= NULL
)
4538 sbuf_printf(s
, "%s", f
->class->name
);
4539 if (f
->desc
->type
== FEEDER_FMT
)
4540 sbuf_printf(s
, "(0x%08x -> 0x%08x)", f
->desc
->in
, f
->desc
->out
);
4541 if (f
->desc
->type
== FEEDER_RATE
)
4542 sbuf_printf(s
, "(%d -> %d)", FEEDER_GET(f
, FEEDRATE_SRC
), FEEDER_GET(f
, FEEDRATE_DST
));
4543 if (f
->desc
->type
== FEEDER_ROOT
|| f
->desc
->type
== FEEDER_MIXER
)
4544 sbuf_printf(s
, "(0x%08x)", f
->desc
->out
);
4545 sbuf_printf(s
, " -> ");
4548 sbuf_printf(s
, "{%s}", (c
->direction
== PCMDIR_REC
)? "userland" : "hardware");
4550 snd_mtxunlock(d
->lock
);
4556 uaudio_sndstat_register(device_t dev
)
4558 struct snddev_info
*d
= device_get_softc(dev
);
4559 sndstat_register(dev
, d
->status
, uaudio_sndstat_prepare_pcm
);
4563 audio_attach_mi(device_t dev
)
4566 struct sndcard_func
*func
;
4568 /* Attach the children. */
4570 func
= kmalloc(sizeof(struct sndcard_func
), M_DEVBUF
, M_NOWAIT
);
4573 bzero(func
, sizeof(*func
));
4574 func
->func
= SCF_PCM
;
4575 child
= device_add_child(dev
, "pcm", -1);
4576 device_set_ivars(child
, func
);
4578 bus_generic_attach(dev
);
4580 return 0; /* XXXXX */
4583 DRIVER_MODULE(uaudio
, uhub
, uaudio_driver
, uaudio_devclass
, usbd_driver_load
, 0);
4584 MODULE_VERSION(uaudio
, 1);