uaudio.c revision 1.180 1 1.180 mlelstv /* $NetBSD: uaudio.c,v 1.180 2023/04/23 06:13:35 mlelstv Exp $ */
2 1.1 augustss
3 1.1 augustss /*
4 1.133 mrg * Copyright (c) 1999, 2012 The NetBSD Foundation, Inc.
5 1.1 augustss * All rights reserved.
6 1.1 augustss *
7 1.5 augustss * This code is derived from software contributed to The NetBSD Foundation
8 1.24 augustss * by Lennart Augustsson (lennart (at) augustsson.net) at
9 1.133 mrg * Carlstedt Research & Technology, and Matthew R. Green (mrg (at) eterna.com.au).
10 1.1 augustss *
11 1.1 augustss * Redistribution and use in source and binary forms, with or without
12 1.1 augustss * modification, are permitted provided that the following conditions
13 1.1 augustss * are met:
14 1.1 augustss * 1. Redistributions of source code must retain the above copyright
15 1.1 augustss * notice, this list of conditions and the following disclaimer.
16 1.1 augustss * 2. Redistributions in binary form must reproduce the above copyright
17 1.1 augustss * notice, this list of conditions and the following disclaimer in the
18 1.1 augustss * documentation and/or other materials provided with the distribution.
19 1.1 augustss *
20 1.1 augustss * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 1.1 augustss * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 1.1 augustss * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 1.1 augustss * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 1.1 augustss * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 1.1 augustss * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 1.1 augustss * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 1.1 augustss * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 1.1 augustss * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 1.1 augustss * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 1.1 augustss * POSSIBILITY OF SUCH DAMAGE.
31 1.1 augustss */
32 1.1 augustss
33 1.1 augustss /*
34 1.144 gson * USB audio specs: http://www.usb.org/developers/docs/devclass_docs/audio10.pdf
35 1.144 gson * http://www.usb.org/developers/docs/devclass_docs/frmts10.pdf
36 1.144 gson * http://www.usb.org/developers/docs/devclass_docs/termt10.pdf
37 1.1 augustss */
38 1.44 lukem
39 1.44 lukem #include <sys/cdefs.h>
40 1.180 mlelstv __KERNEL_RCSID(0, "$NetBSD: uaudio.c,v 1.180 2023/04/23 06:13:35 mlelstv Exp $");
41 1.141 gson
42 1.141 gson #ifdef _KERNEL_OPT
43 1.141 gson #include "opt_usb.h"
44 1.141 gson #endif
45 1.1 augustss
46 1.1 augustss #include <sys/param.h>
47 1.1 augustss #include <sys/systm.h>
48 1.1 augustss #include <sys/kernel.h>
49 1.1 augustss #include <sys/malloc.h>
50 1.1 augustss #include <sys/device.h>
51 1.1 augustss #include <sys/ioctl.h>
52 1.1 augustss #include <sys/file.h>
53 1.40 augustss #include <sys/reboot.h> /* for bootverbose */
54 1.1 augustss #include <sys/select.h>
55 1.1 augustss #include <sys/proc.h>
56 1.1 augustss #include <sys/vnode.h>
57 1.1 augustss #include <sys/poll.h>
58 1.114 kent #include <sys/module.h>
59 1.119 jmcneill #include <sys/bus.h>
60 1.122 mrg #include <sys/cpu.h>
61 1.136 wiz #include <sys/atomic.h>
62 1.179 mlelstv #include <sys/sysctl.h>
63 1.1 augustss
64 1.1 augustss #include <sys/audioio.h>
65 1.160 isaki #include <dev/audio/audio_if.h>
66 1.1 augustss
67 1.1 augustss #include <dev/usb/usb.h>
68 1.1 augustss #include <dev/usb/usbdi.h>
69 1.119 jmcneill #include <dev/usb/usbdivar.h>
70 1.1 augustss #include <dev/usb/usbdi_util.h>
71 1.1 augustss #include <dev/usb/usb_quirks.h>
72 1.1 augustss
73 1.120 jakllsch #include <dev/usb/usbdevs.h>
74 1.120 jakllsch
75 1.1 augustss #include <dev/usb/uaudioreg.h>
76 1.1 augustss
77 1.80 kent /* #define UAUDIO_DEBUG */
78 1.175 mlelstv #define UAUDIO_MULTIPLE_ENDPOINTS
79 1.4 augustss #ifdef UAUDIO_DEBUG
80 1.122 mrg #define DPRINTF(x,y...) do { \
81 1.122 mrg if (uaudiodebug) { \
82 1.122 mrg struct lwp *l = curlwp; \
83 1.122 mrg printf("%s[%d:%d]: "x, __func__, l->l_proc->p_pid, l->l_lid, y); \
84 1.122 mrg } \
85 1.122 mrg } while (0)
86 1.122 mrg #define DPRINTFN_CLEAN(n,x...) do { \
87 1.122 mrg if (uaudiodebug > (n)) \
88 1.122 mrg printf(x); \
89 1.122 mrg } while (0)
90 1.122 mrg #define DPRINTFN(n,x,y...) do { \
91 1.122 mrg if (uaudiodebug > (n)) { \
92 1.122 mrg struct lwp *l = curlwp; \
93 1.122 mrg printf("%s[%d:%d]: "x, __func__, l->l_proc->p_pid, l->l_lid, y); \
94 1.122 mrg } \
95 1.122 mrg } while (0)
96 1.135 mrg int uaudiodebug = 0;
97 1.1 augustss #else
98 1.122 mrg #define DPRINTF(x,y...)
99 1.122 mrg #define DPRINTFN_CLEAN(n,x...)
100 1.122 mrg #define DPRINTFN(n,x,y...)
101 1.1 augustss #endif
102 1.1 augustss
103 1.179 mlelstv /* number of outstanding requests */
104 1.179 mlelstv #define UAUDIO_NCHANBUFS 6
105 1.179 mlelstv /* number of USB frames per request, also the number of ms */
106 1.179 mlelstv #define UAUDIO_NFRAMES 10
107 1.179 mlelstv /* number of microframes per requewst (high, super) */
108 1.179 mlelstv #define UAUDIO_NFRAMES_HI (UAUDIO_NFRAMES * USB_UFRAMES_PER_FRAME)
109 1.1 augustss
110 1.1 augustss
111 1.1 augustss #define MIX_MAX_CHAN 8
112 1.175 mlelstv struct range {
113 1.175 mlelstv int minval, maxval, resval;
114 1.175 mlelstv };
115 1.175 mlelstv
116 1.1 augustss struct mixerctl {
117 1.94 kent uint16_t wValue[MIX_MAX_CHAN]; /* using nchan */
118 1.94 kent uint16_t wIndex;
119 1.94 kent uint8_t nchan;
120 1.94 kent uint8_t type;
121 1.175 mlelstv #define MIX_ON_OFF 0x01
122 1.175 mlelstv #define MIX_SELECTOR 0x02
123 1.175 mlelstv #define MIX_SIGNED_8 0x10
124 1.175 mlelstv #define MIX_UNSIGNED_8 0x18
125 1.175 mlelstv #define MIX_SIGNED_16 0x20
126 1.175 mlelstv #define MIX_UNSIGNED_16 0x28
127 1.175 mlelstv #define MIX_SIGNED_32 0x40
128 1.175 mlelstv #define MIX_UNSIGNED_32 0x48
129 1.175 mlelstv #define MIX_SIZE(n) ( \
130 1.175 mlelstv ((n) == MIX_UNSIGNED_32 || (n) == MIX_SIGNED_32) ? 4 : \
131 1.175 mlelstv ((n) == MIX_SIGNED_16 || (n) == MIX_UNSIGNED_16) ? 2 : 1 )
132 1.175 mlelstv #define MIX_UNSIGNED(n) ( \
133 1.175 mlelstv (n) == MIX_UNSIGNED_8 || \
134 1.175 mlelstv (n) == MIX_UNSIGNED_16 || \
135 1.175 mlelstv (n) == MIX_UNSIGNED_32 )
136 1.175 mlelstv struct range range0;
137 1.175 mlelstv struct range *ranges;
138 1.175 mlelstv u_int nranges;
139 1.34 augustss u_int delta;
140 1.34 augustss u_int mul;
141 1.94 kent uint8_t class;
142 1.1 augustss char ctlname[MAX_AUDIO_DEV_LEN];
143 1.99 christos const char *ctlunit;
144 1.1 augustss };
145 1.1 augustss #define MAKE(h,l) (((h) << 8) | (l))
146 1.1 augustss
147 1.1 augustss struct as_info {
148 1.94 kent uint8_t alt;
149 1.94 kent uint8_t encoding;
150 1.175 mlelstv uint8_t nchan;
151 1.94 kent uint8_t attributes; /* Copy of bmAttributes of
152 1.50 kent * usb_audio_streaming_endpoint_descriptor
153 1.50 kent */
154 1.179 mlelstv uint8_t terminal; /* connected Terminal ID */
155 1.146 skrll struct usbd_interface * ifaceh;
156 1.78 kent const usb_interface_descriptor_t *idesc;
157 1.78 kent const usb_endpoint_descriptor_audio_t *edesc;
158 1.80 kent const usb_endpoint_descriptor_audio_t *edesc1;
159 1.175 mlelstv const union usb_audio_streaming_type1_descriptor *asf1desc;
160 1.92 kent struct audio_format *aformat;
161 1.47 jdolecek int sc_busy; /* currently used */
162 1.1 augustss };
163 1.1 augustss
164 1.1 augustss struct chan {
165 1.67 wiz void (*intr)(void *); /* DMA completion intr handler */
166 1.1 augustss void *arg; /* arg for intr() */
167 1.146 skrll struct usbd_pipe *pipe;
168 1.146 skrll struct usbd_pipe *sync_pipe;
169 1.1 augustss
170 1.1 augustss u_int sample_size;
171 1.1 augustss u_int sample_rate;
172 1.1 augustss u_int bytes_per_frame;
173 1.1 augustss u_int fraction; /* fraction/1000 is the extra samples/frame */
174 1.1 augustss u_int residue; /* accumulates the fractional samples */
175 1.1 augustss
176 1.1 augustss u_char *start; /* upper layer buffer start */
177 1.1 augustss u_char *end; /* upper layer buffer end */
178 1.1 augustss u_char *cur; /* current position in upper layer buffer */
179 1.1 augustss int blksize; /* chunk size to report up */
180 1.1 augustss int transferred; /* transferred bytes not reported up */
181 1.1 augustss
182 1.47 jdolecek int altidx; /* currently used altidx */
183 1.31 augustss
184 1.1 augustss int curchanbuf;
185 1.179 mlelstv u_int nframes; /* UAUDIO_NFRAMES or UAUDIO_NFRAMES_HI */
186 1.179 mlelstv u_int nchanbufs; /* 1..UAUDIO_NCHANBUFS */
187 1.1 augustss struct chanbuf {
188 1.56 kent struct chan *chan;
189 1.146 skrll struct usbd_xfer *xfer;
190 1.56 kent u_char *buffer;
191 1.179 mlelstv uint16_t sizes[UAUDIO_NFRAMES_HI];
192 1.179 mlelstv uint16_t offsets[UAUDIO_NFRAMES_HI];
193 1.94 kent uint16_t size;
194 1.1 augustss } chanbufs[UAUDIO_NCHANBUFS];
195 1.8 augustss
196 1.8 augustss struct uaudio_softc *sc; /* our softc */
197 1.1 augustss };
198 1.1 augustss
199 1.121 jmcneill /*
200 1.146 skrll * The MI USB audio subsystem is now MP-SAFE and expects sc_intr_lock to be
201 1.146 skrll * held on entry the callbacks passed to uaudio_trigger_{in,out}put
202 1.121 jmcneill */
203 1.1 augustss struct uaudio_softc {
204 1.118 dyoung device_t sc_dev; /* base device */
205 1.121 jmcneill kmutex_t sc_lock;
206 1.121 jmcneill kmutex_t sc_intr_lock;
207 1.146 skrll struct usbd_device *sc_udev; /* USB device */
208 1.175 mlelstv int sc_version;
209 1.86 kent int sc_ac_iface; /* Audio Control interface */
210 1.146 skrll struct usbd_interface * sc_ac_ifaceh;
211 1.86 kent struct chan sc_playchan; /* play channel */
212 1.86 kent struct chan sc_recchan; /* record channel */
213 1.86 kent int sc_nullalt;
214 1.86 kent int sc_audio_rev;
215 1.86 kent struct as_info *sc_alts; /* alternate settings */
216 1.86 kent int sc_nalts; /* # of alternate settings */
217 1.86 kent int sc_altflags;
218 1.56 kent #define HAS_8 0x01
219 1.56 kent #define HAS_16 0x02
220 1.56 kent #define HAS_8U 0x04
221 1.56 kent #define HAS_ALAW 0x08
222 1.56 kent #define HAS_MULAW 0x10
223 1.47 jdolecek #define UA_NOFRAC 0x20 /* don't do sample rate adjustment */
224 1.51 kent #define HAS_24 0x40
225 1.175 mlelstv #define HAS_32 0x80
226 1.86 kent int sc_mode; /* play/record capability */
227 1.86 kent struct mixerctl *sc_ctls; /* mixer controls */
228 1.86 kent int sc_nctls; /* # of mixer controls */
229 1.117 dyoung device_t sc_audiodev;
230 1.175 mlelstv int sc_nratectls; /* V2 sample rates */
231 1.175 mlelstv int sc_ratectls[AUFMT_MAX_FREQUENCIES];
232 1.178 mlelstv int sc_ratemode[AUFMT_MAX_FREQUENCIES];
233 1.179 mlelstv int sc_playclock;
234 1.179 mlelstv int sc_recclock;
235 1.92 kent struct audio_format *sc_formats;
236 1.92 kent int sc_nformats;
237 1.179 mlelstv uint8_t sc_clock[256]; /* map terminals to clocks */
238 1.92 kent u_int sc_channel_config;
239 1.179 mlelstv u_int sc_usb_frames_per_second;
240 1.86 kent char sc_dying;
241 1.119 jmcneill struct audio_device sc_adev;
242 1.1 augustss };
243 1.1 augustss
244 1.82 kent struct terminal_list {
245 1.82 kent int size;
246 1.82 kent uint16_t terminals[1];
247 1.82 kent };
248 1.82 kent #define TERMINAL_LIST_SIZE(N) (offsetof(struct terminal_list, terminals) \
249 1.82 kent + sizeof(uint16_t) * (N))
250 1.82 kent
251 1.82 kent struct io_terminal {
252 1.82 kent union {
253 1.109 drochner const uaudio_cs_descriptor_t *desc;
254 1.178 mlelstv const union usb_audio_input_terminal *it;
255 1.178 mlelstv const union usb_audio_output_terminal *ot;
256 1.82 kent const struct usb_audio_mixer_unit *mu;
257 1.82 kent const struct usb_audio_selector_unit *su;
258 1.179 mlelstv const union usb_audio_feature_unit *fu;
259 1.82 kent const struct usb_audio_processing_unit *pu;
260 1.82 kent const struct usb_audio_extension_unit *eu;
261 1.175 mlelstv const struct usb_audio_clksrc_unit *cu;
262 1.175 mlelstv const struct usb_audio_clksel_unit *lu;
263 1.82 kent } d;
264 1.82 kent int inputs_size;
265 1.82 kent struct terminal_list **inputs; /* list of source input terminals */
266 1.82 kent struct terminal_list *output; /* list of destination output terminals */
267 1.83 kent int direct; /* directly connected to an output terminal */
268 1.179 mlelstv uint8_t clock;
269 1.82 kent };
270 1.82 kent
271 1.82 kent #define UAC_OUTPUT 0
272 1.82 kent #define UAC_INPUT 1
273 1.82 kent #define UAC_EQUAL 2
274 1.82 kent #define UAC_RECORD 3
275 1.82 kent #define UAC_NCLASSES 4
276 1.82 kent #ifdef UAUDIO_DEBUG
277 1.82 kent Static const char *uac_names[] = {
278 1.175 mlelstv AudioCoutputs, AudioCinputs, AudioCequalization, AudioCrecord
279 1.82 kent };
280 1.82 kent #endif
281 1.1 augustss
282 1.142 gson #ifdef UAUDIO_DEBUG
283 1.142 gson Static void uaudio_dump_tml
284 1.142 gson (struct terminal_list *tml);
285 1.142 gson #endif
286 1.86 kent Static usbd_status uaudio_identify_ac
287 1.86 kent (struct uaudio_softc *, const usb_config_descriptor_t *);
288 1.86 kent Static usbd_status uaudio_identify_as
289 1.86 kent (struct uaudio_softc *, const usb_config_descriptor_t *);
290 1.86 kent Static usbd_status uaudio_process_as
291 1.86 kent (struct uaudio_softc *, const char *, int *, int,
292 1.86 kent const usb_interface_descriptor_t *);
293 1.78 kent
294 1.78 kent Static void uaudio_add_alt(struct uaudio_softc *, const struct as_info *);
295 1.78 kent
296 1.78 kent Static const usb_interface_descriptor_t *uaudio_find_iface
297 1.78 kent (const char *, int, int *, int);
298 1.78 kent
299 1.78 kent Static void uaudio_mixer_add_ctl(struct uaudio_softc *, struct mixerctl *);
300 1.86 kent Static char *uaudio_id_name
301 1.179 mlelstv (struct uaudio_softc *, const struct io_terminal *, uint8_t);
302 1.91 kent #ifdef UAUDIO_DEBUG
303 1.178 mlelstv Static void uaudio_dump_cluster
304 1.178 mlelstv (struct uaudio_softc *, const union usb_audio_cluster *);
305 1.91 kent #endif
306 1.178 mlelstv Static union usb_audio_cluster uaudio_get_cluster
307 1.178 mlelstv (struct uaudio_softc *, int, const struct io_terminal *);
308 1.86 kent Static void uaudio_add_input
309 1.86 kent (struct uaudio_softc *, const struct io_terminal *, int);
310 1.86 kent Static void uaudio_add_output
311 1.86 kent (struct uaudio_softc *, const struct io_terminal *, int);
312 1.86 kent Static void uaudio_add_mixer
313 1.86 kent (struct uaudio_softc *, const struct io_terminal *, int);
314 1.86 kent Static void uaudio_add_selector
315 1.86 kent (struct uaudio_softc *, const struct io_terminal *, int);
316 1.82 kent #ifdef UAUDIO_DEBUG
317 1.82 kent Static const char *uaudio_get_terminal_name(int);
318 1.82 kent #endif
319 1.86 kent Static int uaudio_determine_class
320 1.86 kent (const struct io_terminal *, struct mixerctl *);
321 1.86 kent Static const char *uaudio_feature_name
322 1.179 mlelstv (const struct io_terminal *, uint8_t, int);
323 1.86 kent Static void uaudio_add_feature
324 1.86 kent (struct uaudio_softc *, const struct io_terminal *, int);
325 1.86 kent Static void uaudio_add_processing_updown
326 1.86 kent (struct uaudio_softc *, const struct io_terminal *, int);
327 1.86 kent Static void uaudio_add_processing
328 1.86 kent (struct uaudio_softc *, const struct io_terminal *, int);
329 1.175 mlelstv Static void uaudio_add_effect
330 1.175 mlelstv (struct uaudio_softc *, const struct io_terminal *, int);
331 1.86 kent Static void uaudio_add_extension
332 1.86 kent (struct uaudio_softc *, const struct io_terminal *, int);
333 1.175 mlelstv Static void uaudio_add_clksrc
334 1.175 mlelstv (struct uaudio_softc *, const struct io_terminal *, int);
335 1.175 mlelstv Static void uaudio_add_clksel
336 1.175 mlelstv (struct uaudio_softc *, const struct io_terminal *, int);
337 1.86 kent Static struct terminal_list *uaudio_merge_terminal_list
338 1.86 kent (const struct io_terminal *);
339 1.86 kent Static struct terminal_list *uaudio_io_terminaltype
340 1.178 mlelstv (struct uaudio_softc *, int, struct io_terminal *, int);
341 1.86 kent Static usbd_status uaudio_identify
342 1.86 kent (struct uaudio_softc *, const usb_config_descriptor_t *);
343 1.175 mlelstv Static u_int uaudio_get_rates
344 1.178 mlelstv (struct uaudio_softc *, int, u_int *, u_int);
345 1.175 mlelstv Static void uaudio_build_formats
346 1.175 mlelstv (struct uaudio_softc *);
347 1.78 kent
348 1.78 kent Static int uaudio_signext(int, int);
349 1.78 kent Static int uaudio_value2bsd(struct mixerctl *, int);
350 1.78 kent Static int uaudio_bsd2value(struct mixerctl *, int);
351 1.175 mlelstv Static const char *uaudio_clockname(u_int);
352 1.175 mlelstv Static int uaudio_makename
353 1.175 mlelstv (struct uaudio_softc *, uByte, const char *, uByte, char *, size_t);
354 1.78 kent Static int uaudio_get(struct uaudio_softc *, int, int, int, int, int);
355 1.175 mlelstv Static int uaudio_getbuf(struct uaudio_softc *, int, int, int, int, int, uint8_t *);
356 1.86 kent Static int uaudio_ctl_get
357 1.86 kent (struct uaudio_softc *, int, struct mixerctl *, int);
358 1.86 kent Static void uaudio_set
359 1.86 kent (struct uaudio_softc *, int, int, int, int, int, int);
360 1.86 kent Static void uaudio_ctl_set
361 1.86 kent (struct uaudio_softc *, int, struct mixerctl *, int, int);
362 1.78 kent
363 1.179 mlelstv Static usbd_status uaudio_speed(struct uaudio_softc *, int, int, uint8_t *, int);
364 1.175 mlelstv Static usbd_status uaudio_set_speed(struct uaudio_softc *, int, int, u_int);
365 1.78 kent
366 1.78 kent Static usbd_status uaudio_chan_open(struct uaudio_softc *, struct chan *);
367 1.146 skrll Static void uaudio_chan_abort(struct uaudio_softc *, struct chan *);
368 1.78 kent Static void uaudio_chan_close(struct uaudio_softc *, struct chan *);
369 1.86 kent Static usbd_status uaudio_chan_alloc_buffers
370 1.86 kent (struct uaudio_softc *, struct chan *);
371 1.78 kent Static void uaudio_chan_free_buffers(struct uaudio_softc *, struct chan *);
372 1.86 kent Static void uaudio_chan_init
373 1.179 mlelstv (struct chan *, int, const struct audio_params *, int, bool);
374 1.78 kent Static void uaudio_chan_set_param(struct chan *, u_char *, u_char *, int);
375 1.78 kent Static void uaudio_chan_ptransfer(struct chan *);
376 1.86 kent Static void uaudio_chan_pintr
377 1.146 skrll (struct usbd_xfer *, void *, usbd_status);
378 1.78 kent
379 1.78 kent Static void uaudio_chan_rtransfer(struct chan *);
380 1.86 kent Static void uaudio_chan_rintr
381 1.146 skrll (struct usbd_xfer *, void *, usbd_status);
382 1.78 kent
383 1.78 kent Static int uaudio_open(void *, int);
384 1.160 isaki Static int uaudio_query_format(void *, audio_format_query_t *);
385 1.160 isaki Static int uaudio_set_format
386 1.160 isaki (void *, int, const audio_params_t *, const audio_params_t *,
387 1.160 isaki audio_filter_reg_t *, audio_filter_reg_t *);
388 1.93 kent Static int uaudio_round_blocksize(void *, int, int, const audio_params_t *);
389 1.86 kent Static int uaudio_trigger_output
390 1.86 kent (void *, void *, void *, int, void (*)(void *), void *,
391 1.93 kent const audio_params_t *);
392 1.86 kent Static int uaudio_trigger_input
393 1.86 kent (void *, void *, void *, int, void (*)(void *), void *,
394 1.93 kent const audio_params_t *);
395 1.78 kent Static int uaudio_halt_in_dma(void *);
396 1.78 kent Static int uaudio_halt_out_dma(void *);
397 1.166 jdc Static void uaudio_halt_in_dma_unlocked(struct uaudio_softc *);
398 1.166 jdc Static void uaudio_halt_out_dma_unlocked(struct uaudio_softc *);
399 1.78 kent Static int uaudio_getdev(void *, struct audio_device *);
400 1.78 kent Static int uaudio_mixer_set_port(void *, mixer_ctrl_t *);
401 1.78 kent Static int uaudio_mixer_get_port(void *, mixer_ctrl_t *);
402 1.78 kent Static int uaudio_query_devinfo(void *, mixer_devinfo_t *);
403 1.78 kent Static int uaudio_get_props(void *);
404 1.121 jmcneill Static void uaudio_get_locks(void *, kmutex_t **, kmutex_t **);
405 1.1 augustss
406 1.88 yamt Static const struct audio_hw_if uaudio_hw_if = {
407 1.158 isaki .open = uaudio_open,
408 1.160 isaki .query_format = uaudio_query_format,
409 1.160 isaki .set_format = uaudio_set_format,
410 1.158 isaki .round_blocksize = uaudio_round_blocksize,
411 1.158 isaki .halt_output = uaudio_halt_out_dma,
412 1.158 isaki .halt_input = uaudio_halt_in_dma,
413 1.158 isaki .getdev = uaudio_getdev,
414 1.158 isaki .set_port = uaudio_mixer_set_port,
415 1.158 isaki .get_port = uaudio_mixer_get_port,
416 1.158 isaki .query_devinfo = uaudio_query_devinfo,
417 1.158 isaki .get_props = uaudio_get_props,
418 1.158 isaki .trigger_output = uaudio_trigger_output,
419 1.158 isaki .trigger_input = uaudio_trigger_input,
420 1.158 isaki .get_locks = uaudio_get_locks,
421 1.1 augustss };
422 1.1 augustss
423 1.163 maxv static int uaudio_match(device_t, cfdata_t, void *);
424 1.163 maxv static void uaudio_attach(device_t, device_t, void *);
425 1.163 maxv static int uaudio_detach(device_t, int);
426 1.163 maxv static void uaudio_childdet(device_t, device_t);
427 1.163 maxv static int uaudio_activate(device_t, enum devact);
428 1.111 dyoung
429 1.159 mrg
430 1.113 cube CFATTACH_DECL2_NEW(uaudio, sizeof(struct uaudio_softc),
431 1.111 dyoung uaudio_match, uaudio_attach, uaudio_detach, uaudio_activate, NULL,
432 1.111 dyoung uaudio_childdet);
433 1.1 augustss
434 1.163 maxv static int
435 1.118 dyoung uaudio_match(device_t parent, cfdata_t match, void *aux)
436 1.1 augustss {
437 1.146 skrll struct usbif_attach_arg *uiaa = aux;
438 1.1 augustss
439 1.1 augustss /* Trigger on the control interface. */
440 1.146 skrll if (uiaa->uiaa_class != UICLASS_AUDIO ||
441 1.146 skrll uiaa->uiaa_subclass != UISUBCLASS_AUDIOCONTROL ||
442 1.146 skrll (usbd_get_quirks(uiaa->uiaa_device)->uq_flags & UQ_BAD_AUDIO))
443 1.94 kent return UMATCH_NONE;
444 1.1 augustss
445 1.94 kent return UMATCH_IFACECLASS_IFACESUBCLASS;
446 1.1 augustss }
447 1.1 augustss
448 1.163 maxv static void
449 1.118 dyoung uaudio_attach(device_t parent, device_t self, void *aux)
450 1.1 augustss {
451 1.118 dyoung struct uaudio_softc *sc = device_private(self);
452 1.146 skrll struct usbif_attach_arg *uiaa = aux;
453 1.1 augustss usb_interface_descriptor_t *id;
454 1.1 augustss usb_config_descriptor_t *cdesc;
455 1.98 augustss char *devinfop;
456 1.9 augustss usbd_status err;
457 1.37 mycroft int i, j, found;
458 1.1 augustss
459 1.113 cube sc->sc_dev = self;
460 1.146 skrll sc->sc_udev = uiaa->uiaa_device;
461 1.121 jmcneill mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
462 1.146 skrll mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SOFTUSB);
463 1.116 plunky
464 1.119 jmcneill strlcpy(sc->sc_adev.name, "USB audio", sizeof(sc->sc_adev.name));
465 1.119 jmcneill strlcpy(sc->sc_adev.version, "", sizeof(sc->sc_adev.version));
466 1.119 jmcneill snprintf(sc->sc_adev.config, sizeof(sc->sc_adev.config), "usb:%08x",
467 1.146 skrll sc->sc_udev->ud_cookie.cookie);
468 1.119 jmcneill
469 1.116 plunky aprint_naive("\n");
470 1.116 plunky aprint_normal("\n");
471 1.113 cube
472 1.146 skrll devinfop = usbd_devinfo_alloc(uiaa->uiaa_device, 0);
473 1.116 plunky aprint_normal_dev(self, "%s\n", devinfop);
474 1.98 augustss usbd_devinfo_free(devinfop);
475 1.1 augustss
476 1.1 augustss cdesc = usbd_get_config_descriptor(sc->sc_udev);
477 1.13 augustss if (cdesc == NULL) {
478 1.113 cube aprint_error_dev(self,
479 1.113 cube "failed to get configuration descriptor\n");
480 1.118 dyoung return;
481 1.13 augustss }
482 1.1 augustss
483 1.9 augustss err = uaudio_identify(sc, cdesc);
484 1.9 augustss if (err) {
485 1.113 cube aprint_error_dev(self,
486 1.113 cube "audio descriptors make no sense, error=%d\n", err);
487 1.118 dyoung return;
488 1.1 augustss }
489 1.1 augustss
490 1.146 skrll sc->sc_ac_ifaceh = uiaa->uiaa_iface;
491 1.1 augustss /* Pick up the AS interface. */
492 1.146 skrll for (i = 0; i < uiaa->uiaa_nifaces; i++) {
493 1.146 skrll if (uiaa->uiaa_ifaces[i] == NULL)
494 1.37 mycroft continue;
495 1.146 skrll id = usbd_get_interface_descriptor(uiaa->uiaa_ifaces[i]);
496 1.37 mycroft if (id == NULL)
497 1.37 mycroft continue;
498 1.37 mycroft found = 0;
499 1.37 mycroft for (j = 0; j < sc->sc_nalts; j++) {
500 1.37 mycroft if (id->bInterfaceNumber ==
501 1.37 mycroft sc->sc_alts[j].idesc->bInterfaceNumber) {
502 1.146 skrll sc->sc_alts[j].ifaceh = uiaa->uiaa_ifaces[i];
503 1.37 mycroft found = 1;
504 1.1 augustss }
505 1.1 augustss }
506 1.37 mycroft if (found)
507 1.146 skrll uiaa->uiaa_ifaces[i] = NULL;
508 1.1 augustss }
509 1.1 augustss
510 1.37 mycroft for (j = 0; j < sc->sc_nalts; j++) {
511 1.37 mycroft if (sc->sc_alts[j].ifaceh == NULL) {
512 1.113 cube aprint_error_dev(self,
513 1.113 cube "alt %d missing AS interface(s)\n", j);
514 1.118 dyoung return;
515 1.37 mycroft }
516 1.1 augustss }
517 1.1 augustss
518 1.113 cube aprint_normal_dev(self, "audio rev %d.%02x\n",
519 1.7 augustss sc->sc_audio_rev >> 8, sc->sc_audio_rev & 0xff);
520 1.7 augustss
521 1.47 jdolecek sc->sc_playchan.sc = sc->sc_recchan.sc = sc;
522 1.60 kent sc->sc_playchan.altidx = -1;
523 1.60 kent sc->sc_recchan.altidx = -1;
524 1.8 augustss
525 1.179 mlelstv switch (sc->sc_udev->ud_speed) {
526 1.179 mlelstv case USB_SPEED_LOW:
527 1.179 mlelstv case USB_SPEED_FULL:
528 1.179 mlelstv sc->sc_usb_frames_per_second = USB_FRAMES_PER_SECOND;
529 1.179 mlelstv sc->sc_playchan.nframes =
530 1.179 mlelstv sc->sc_recchan.nframes = UAUDIO_NFRAMES;
531 1.179 mlelstv break;
532 1.179 mlelstv default: /* HIGH, SUPER, SUPER_PLUS, more ? */
533 1.179 mlelstv sc->sc_usb_frames_per_second = USB_FRAMES_PER_SECOND * USB_UFRAMES_PER_FRAME;
534 1.179 mlelstv sc->sc_playchan.nframes =
535 1.179 mlelstv sc->sc_recchan.nframes = UAUDIO_NFRAMES_HI;
536 1.179 mlelstv break;
537 1.179 mlelstv }
538 1.179 mlelstv sc->sc_playchan.nchanbufs =
539 1.179 mlelstv sc->sc_recchan.nchanbufs = UAUDIO_NCHANBUFS;
540 1.179 mlelstv
541 1.179 mlelstv DPRINTF("usb fps %u, max channel frames %u, max channel buffers %u\n",
542 1.179 mlelstv sc->sc_usb_frames_per_second, sc->sc_playchan.nframes, sc->sc_playchan.nchanbufs);
543 1.179 mlelstv
544 1.31 augustss if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_FRAC)
545 1.47 jdolecek sc->sc_altflags |= UA_NOFRAC;
546 1.31 augustss
547 1.40 augustss #ifndef UAUDIO_DEBUG
548 1.40 augustss if (bootverbose)
549 1.40 augustss #endif
550 1.113 cube aprint_normal_dev(self, "%d mixer controls\n",
551 1.40 augustss sc->sc_nctls);
552 1.40 augustss
553 1.147 msaitoh usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
554 1.41 augustss
555 1.122 mrg DPRINTF("%s", "doing audio_attach_mi\n");
556 1.113 cube sc->sc_audiodev = audio_attach_mi(&uaudio_hw_if, sc, sc->sc_dev);
557 1.17 augustss
558 1.155 maya if (!pmf_device_register(self, NULL, NULL))
559 1.155 maya aprint_error_dev(self, "couldn't establish power handler\n");
560 1.155 maya
561 1.118 dyoung return;
562 1.1 augustss }
563 1.1 augustss
564 1.163 maxv static int
565 1.117 dyoung uaudio_activate(device_t self, enum devact act)
566 1.1 augustss {
567 1.117 dyoung struct uaudio_softc *sc = device_private(self);
568 1.1 augustss
569 1.1 augustss switch (act) {
570 1.1 augustss case DVACT_DEACTIVATE:
571 1.1 augustss sc->sc_dying = 1;
572 1.117 dyoung return 0;
573 1.117 dyoung default:
574 1.117 dyoung return EOPNOTSUPP;
575 1.1 augustss }
576 1.1 augustss }
577 1.1 augustss
578 1.163 maxv static void
579 1.111 dyoung uaudio_childdet(device_t self, device_t child)
580 1.111 dyoung {
581 1.111 dyoung struct uaudio_softc *sc = device_private(self);
582 1.111 dyoung
583 1.111 dyoung KASSERT(sc->sc_audiodev == child);
584 1.111 dyoung sc->sc_audiodev = NULL;
585 1.111 dyoung }
586 1.111 dyoung
587 1.163 maxv static int
588 1.111 dyoung uaudio_detach(device_t self, int flags)
589 1.1 augustss {
590 1.111 dyoung struct uaudio_softc *sc = device_private(self);
591 1.175 mlelstv int rv, i;
592 1.155 maya
593 1.166 jdc sc->sc_dying = 1;
594 1.166 jdc
595 1.155 maya pmf_device_deregister(self);
596 1.1 augustss
597 1.8 augustss /* Wait for outstanding requests to complete. */
598 1.166 jdc uaudio_halt_out_dma_unlocked(sc);
599 1.166 jdc uaudio_halt_in_dma_unlocked(sc);
600 1.8 augustss
601 1.170 mlelstv if (sc->sc_audiodev != NULL) {
602 1.1 augustss rv = config_detach(sc->sc_audiodev, flags);
603 1.170 mlelstv if (rv)
604 1.170 mlelstv return rv;
605 1.170 mlelstv }
606 1.17 augustss
607 1.147 msaitoh usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
608 1.1 augustss
609 1.92 kent if (sc->sc_formats != NULL)
610 1.146 skrll kmem_free(sc->sc_formats,
611 1.146 skrll sizeof(struct audio_format) * sc->sc_nformats);
612 1.121 jmcneill
613 1.175 mlelstv if (sc->sc_ctls != NULL) {
614 1.175 mlelstv for (i=0; i<sc->sc_nctls; ++i) {
615 1.175 mlelstv if (sc->sc_ctls[i].nranges == 0)
616 1.175 mlelstv continue;
617 1.175 mlelstv kmem_free( sc->sc_ctls[i].ranges,
618 1.175 mlelstv sc->sc_ctls[i].nranges * sizeof(struct range));
619 1.175 mlelstv }
620 1.175 mlelstv kmem_free(sc->sc_ctls, sizeof(struct mixerctl) * sc->sc_nctls);
621 1.175 mlelstv }
622 1.175 mlelstv
623 1.175 mlelstv if (sc->sc_alts != NULL)
624 1.175 mlelstv kmem_free(sc->sc_alts, sizeof(struct as_info) * sc->sc_nalts);
625 1.175 mlelstv
626 1.121 jmcneill mutex_destroy(&sc->sc_lock);
627 1.121 jmcneill mutex_destroy(&sc->sc_intr_lock);
628 1.121 jmcneill
629 1.170 mlelstv return 0;
630 1.1 augustss }
631 1.1 augustss
632 1.86 kent Static int
633 1.160 isaki uaudio_query_format(void *addr, audio_format_query_t *afp)
634 1.1 augustss {
635 1.94 kent struct uaudio_softc *sc;
636 1.1 augustss
637 1.94 kent sc = addr;
638 1.160 isaki return audio_query_format(sc->sc_formats, sc->sc_nformats, afp);
639 1.1 augustss }
640 1.1 augustss
641 1.86 kent Static const usb_interface_descriptor_t *
642 1.99 christos uaudio_find_iface(const char *tbuf, int size, int *offsp, int subtype)
643 1.1 augustss {
644 1.78 kent const usb_interface_descriptor_t *d;
645 1.1 augustss
646 1.172 mlelstv while (*offsp + sizeof(*d) <= size) {
647 1.99 christos d = (const void *)(tbuf + *offsp);
648 1.172 mlelstv DPRINTFN(3, "%d + %d <= %d type %d class %d/%d iface %d\n",
649 1.172 mlelstv *offsp, d->bLength, size,
650 1.172 mlelstv d->bDescriptorType,
651 1.172 mlelstv d->bInterfaceClass,
652 1.172 mlelstv d->bInterfaceSubClass,
653 1.172 mlelstv d->bInterfaceNumber);
654 1.1 augustss *offsp += d->bLength;
655 1.1 augustss if (d->bDescriptorType == UDESC_INTERFACE &&
656 1.19 augustss d->bInterfaceClass == UICLASS_AUDIO &&
657 1.1 augustss d->bInterfaceSubClass == subtype)
658 1.94 kent return d;
659 1.1 augustss }
660 1.94 kent return NULL;
661 1.1 augustss }
662 1.1 augustss
663 1.86 kent Static void
664 1.26 augustss uaudio_mixer_add_ctl(struct uaudio_softc *sc, struct mixerctl *mc)
665 1.1 augustss {
666 1.33 augustss int res;
667 1.175 mlelstv size_t len, count, msz;
668 1.84 kent struct mixerctl *nmc;
669 1.175 mlelstv struct range *r;
670 1.175 mlelstv uint8_t *buf, *p;
671 1.175 mlelstv int i;
672 1.33 augustss
673 1.82 kent if (mc->class < UAC_NCLASSES) {
674 1.122 mrg DPRINTF("adding %s.%s\n", uac_names[mc->class], mc->ctlname);
675 1.82 kent } else {
676 1.122 mrg DPRINTF("adding %s\n", mc->ctlname);
677 1.82 kent }
678 1.84 kent len = sizeof(*mc) * (sc->sc_nctls + 1);
679 1.146 skrll nmc = kmem_alloc(len, KM_SLEEP);
680 1.84 kent /* Copy old data, if there was any */
681 1.84 kent if (sc->sc_nctls != 0) {
682 1.175 mlelstv memcpy(nmc, sc->sc_ctls, sizeof(*mc) * sc->sc_nctls);
683 1.175 mlelstv for (i = 0; i<sc->sc_nctls; ++i) {
684 1.175 mlelstv if (sc->sc_ctls[i].ranges == &sc->sc_ctls[i].range0)
685 1.175 mlelstv nmc[i].ranges = &nmc[i].range0;
686 1.175 mlelstv }
687 1.146 skrll kmem_free(sc->sc_ctls, sizeof(*mc) * sc->sc_nctls);
688 1.84 kent }
689 1.42 christos sc->sc_ctls = nmc;
690 1.1 augustss
691 1.175 mlelstv /*
692 1.175 mlelstv * preset
693 1.175 mlelstv * - mc->class
694 1.175 mlelstv * - mc->ctlname
695 1.175 mlelstv * - mc->ctlunit
696 1.175 mlelstv * - mc->wIndex
697 1.175 mlelstv * - mc->wValue[]
698 1.175 mlelstv * - mc->type
699 1.175 mlelstv * - mc->nchan
700 1.175 mlelstv *
701 1.175 mlelstv * - mc->range0, mc->mul for MIX_SELECTOR
702 1.175 mlelstv */
703 1.175 mlelstv sc->sc_ctls[sc->sc_nctls] = *mc;
704 1.175 mlelstv mc = &sc->sc_ctls[sc->sc_nctls++];
705 1.175 mlelstv msz = MIX_SIZE(mc->type);
706 1.175 mlelstv
707 1.33 augustss mc->delta = 0;
708 1.175 mlelstv mc->nranges = 0;
709 1.175 mlelstv mc->ranges = r = &mc->range0;
710 1.175 mlelstv mc->mul = 0;
711 1.79 kent if (mc->type == MIX_ON_OFF) {
712 1.175 mlelstv r->minval = 0;
713 1.175 mlelstv r->maxval = 1;
714 1.175 mlelstv r->resval = 1;
715 1.175 mlelstv res = r->resval;
716 1.79 kent } else if (mc->type == MIX_SELECTOR) {
717 1.175 mlelstv /* range0 already set by uaudio_add_selector */
718 1.175 mlelstv res = r->resval;
719 1.175 mlelstv } else if (sc->sc_version == UAUDIO_VERSION1) {
720 1.1 augustss /* Determine min and max values. */
721 1.175 mlelstv r->minval = uaudio_signext(mc->type,
722 1.56 kent uaudio_get(sc, GET_MIN, UT_READ_CLASS_INTERFACE,
723 1.175 mlelstv mc->wValue[0], mc->wIndex, msz));
724 1.175 mlelstv r->maxval = uaudio_signext(mc->type,
725 1.1 augustss uaudio_get(sc, GET_MAX, UT_READ_CLASS_INTERFACE,
726 1.175 mlelstv mc->wValue[0], mc->wIndex, msz));
727 1.175 mlelstv r->resval = uaudio_get(sc, GET_RES, UT_READ_CLASS_INTERFACE,
728 1.175 mlelstv mc->wValue[0], mc->wIndex, msz);
729 1.175 mlelstv mc->mul = r->maxval - r->minval;
730 1.175 mlelstv res = r->resval;
731 1.175 mlelstv } else { /* UAUDIO_VERSION2 */
732 1.178 mlelstv count = (uint16_t)uaudio_get(sc, V2_RANGES,
733 1.178 mlelstv UT_READ_CLASS_INTERFACE,
734 1.178 mlelstv mc->wValue[0], mc->wIndex, 2);
735 1.178 mlelstv
736 1.178 mlelstv if (count == 0 || count == (uint16_t)-1) {
737 1.178 mlelstv DPRINTF("invalid range count %zu\n", count);
738 1.178 mlelstv return;
739 1.178 mlelstv }
740 1.175 mlelstv
741 1.175 mlelstv if (count > 1) {
742 1.175 mlelstv r = kmem_alloc(sizeof(struct range) * count,
743 1.175 mlelstv KM_SLEEP);
744 1.175 mlelstv mc->ranges = r;
745 1.175 mlelstv mc->nranges = count;
746 1.175 mlelstv }
747 1.175 mlelstv
748 1.175 mlelstv mc->ranges[0].minval = 0;
749 1.175 mlelstv mc->ranges[0].maxval = 0;
750 1.175 mlelstv mc->ranges[0].resval = 1;
751 1.175 mlelstv
752 1.175 mlelstv /* again with the required buffer size */
753 1.175 mlelstv len = 2 + count * 3 * msz;
754 1.175 mlelstv buf = kmem_alloc(len, KM_SLEEP);
755 1.175 mlelstv uaudio_getbuf(sc, V2_RANGES, UT_READ_CLASS_INTERFACE,
756 1.175 mlelstv mc->wValue[0], mc->wIndex, len, buf);
757 1.175 mlelstv res = 0;
758 1.175 mlelstv p = &buf[2];
759 1.175 mlelstv for (i=0, p=buf+2; i<count; ++i) {
760 1.175 mlelstv uint32_t minval, maxval, resval;
761 1.175 mlelstv switch (msz) {
762 1.175 mlelstv case 1:
763 1.175 mlelstv minval = *p++;
764 1.175 mlelstv maxval = *p++;
765 1.175 mlelstv resval = *p++;
766 1.175 mlelstv break;
767 1.175 mlelstv case 2:
768 1.175 mlelstv minval = p[0] | p[1] << 8;
769 1.175 mlelstv p += 2;
770 1.175 mlelstv maxval = p[0] | p[1] << 8;
771 1.175 mlelstv p += 2;
772 1.175 mlelstv resval = p[0] | p[1] << 8;
773 1.175 mlelstv p += 2;
774 1.175 mlelstv break;
775 1.175 mlelstv case 3:
776 1.175 mlelstv minval = p[0] | p[1] << 8 | p[2] << 16;
777 1.175 mlelstv p += 3;
778 1.175 mlelstv maxval = p[0] | p[1] << 8 | p[2] << 16;
779 1.175 mlelstv p += 3;
780 1.175 mlelstv resval = p[0] | p[1] << 8 | p[2] << 16;
781 1.175 mlelstv p += 3;
782 1.175 mlelstv break;
783 1.175 mlelstv case 4:
784 1.175 mlelstv minval = p[0] | p[1] << 8 \
785 1.175 mlelstv | p[2] << 16 | p[3] << 24;
786 1.175 mlelstv p += 4;
787 1.175 mlelstv maxval = p[0] | p[1] << 8 \
788 1.175 mlelstv | p[2] << 16 | p[3] << 24;
789 1.175 mlelstv p += 4;
790 1.175 mlelstv resval = p[0] | p[1] << 8 \
791 1.175 mlelstv | p[2] << 16 | p[3] << 24;
792 1.175 mlelstv p += 4;
793 1.175 mlelstv break;
794 1.175 mlelstv default: /* not allowed */
795 1.175 mlelstv minval = maxval = 0;
796 1.175 mlelstv resval = 1;
797 1.175 mlelstv break;
798 1.175 mlelstv }
799 1.175 mlelstv mc->ranges[i].minval = uaudio_signext(mc->type, minval);
800 1.175 mlelstv mc->ranges[i].maxval = uaudio_signext(mc->type, maxval);
801 1.175 mlelstv mc->ranges[i].resval = uaudio_signext(mc->type, resval);
802 1.175 mlelstv if (mc->ranges[i].resval > res)
803 1.175 mlelstv res = mc->ranges[i].resval;
804 1.175 mlelstv }
805 1.175 mlelstv kmem_free(buf, len);
806 1.175 mlelstv
807 1.175 mlelstv mc->mul = mc->ranges[count - 1].maxval - mc->ranges[0].minval;
808 1.175 mlelstv
809 1.175 mlelstv /*
810 1.175 mlelstv * use resolution 1 (ideally the lcd) for
811 1.175 mlelstv * multiple (valid) resolution values.
812 1.175 mlelstv */
813 1.175 mlelstv if (count > 1 && res > 0)
814 1.175 mlelstv res = 1;
815 1.1 augustss }
816 1.1 augustss
817 1.175 mlelstv if (mc->mul == 0)
818 1.175 mlelstv mc->mul = 1;
819 1.179 mlelstv
820 1.179 mlelstv mc->delta = (res * 255 + mc->mul - 1) / mc->mul;
821 1.1 augustss
822 1.4 augustss #ifdef UAUDIO_DEBUG
823 1.1 augustss if (uaudiodebug > 2) {
824 1.122 mrg DPRINTFN_CLEAN(2, "wValue=%04x", mc->wValue[0]);
825 1.1 augustss for (i = 1; i < mc->nchan; i++)
826 1.122 mrg DPRINTFN_CLEAN(2, ",%04x", mc->wValue[i]);
827 1.175 mlelstv DPRINTFN_CLEAN(2, "\n");
828 1.175 mlelstv count = mc->nranges > 0 ? mc->nranges : 1;
829 1.175 mlelstv for (i = 0; i < count; i++)
830 1.175 mlelstv DPRINTFN_CLEAN(2, "%d: wIndex=%04x type=%d name='%s' "
831 1.175 mlelstv "unit='%s' min=%d max=%d res=%d\n",
832 1.175 mlelstv i, mc->wIndex, mc->type, mc->ctlname, mc->ctlunit,
833 1.175 mlelstv mc->ranges[i].minval,
834 1.175 mlelstv mc->ranges[i].maxval,
835 1.175 mlelstv mc->ranges[i].resval);
836 1.1 augustss }
837 1.1 augustss #endif
838 1.1 augustss }
839 1.1 augustss
840 1.86 kent Static char *
841 1.107 christos uaudio_id_name(struct uaudio_softc *sc,
842 1.179 mlelstv const struct io_terminal *iot, uint8_t id)
843 1.1 augustss {
844 1.99 christos static char tbuf[32];
845 1.94 kent
846 1.179 mlelstv snprintf(tbuf, sizeof(tbuf), "i%u", id);
847 1.179 mlelstv
848 1.99 christos return tbuf;
849 1.1 augustss }
850 1.1 augustss
851 1.91 kent #ifdef UAUDIO_DEBUG
852 1.91 kent Static void
853 1.178 mlelstv uaudio_dump_cluster(struct uaudio_softc *sc, const union usb_audio_cluster *cl)
854 1.91 kent {
855 1.178 mlelstv static const char *channel_v1_names[16] = {
856 1.91 kent "LEFT", "RIGHT", "CENTER", "LFE",
857 1.91 kent "LEFT_SURROUND", "RIGHT_SURROUND", "LEFT_CENTER", "RIGHT_CENTER",
858 1.91 kent "SURROUND", "LEFT_SIDE", "RIGHT_SIDE", "TOP",
859 1.91 kent "RESERVED12", "RESERVED13", "RESERVED14", "RESERVED15",
860 1.91 kent };
861 1.178 mlelstv static const char *channel_v2_names[32] = {
862 1.178 mlelstv "LEFT", "RIGHT", "CENTER", "LFE",
863 1.178 mlelstv "BACK_LEFT", "BACK_RIGHT", "FLC", "FRC",
864 1.178 mlelstv "BACK_CENTER", "SIDE_LEFT", "SIDE_RIGHT", "TOP CENTER",
865 1.178 mlelstv "TFL", "TFC", "TFR", "TBL", "TBC", "TBR",
866 1.178 mlelstv "TFLC", "TFRC", "LLFE", "RLFE", "TSL", "TSR",
867 1.178 mlelstv "BC", "BLC", "BRC",
868 1.178 mlelstv "RESERVED27", "RESERVED28", "RESERVED29", "RESERVED30",
869 1.178 mlelstv "RAW_DATA"
870 1.178 mlelstv };
871 1.178 mlelstv const char **channel_names;
872 1.178 mlelstv uint32_t cc;
873 1.178 mlelstv int i, first, icn;
874 1.178 mlelstv
875 1.178 mlelstv switch (sc->sc_version) {
876 1.178 mlelstv case UAUDIO_VERSION1:
877 1.178 mlelstv channel_names = channel_v1_names;
878 1.178 mlelstv cc = UGETW(cl->v1.wChannelConfig);
879 1.178 mlelstv icn = cl->v1.iChannelNames;
880 1.178 mlelstv printf("cluster: bNrChannels=%u wChannelConfig=%#.4x",
881 1.178 mlelstv cl->v1.bNrChannels, cc);
882 1.178 mlelstv break;
883 1.178 mlelstv case UAUDIO_VERSION2:
884 1.178 mlelstv channel_names = channel_v2_names;
885 1.178 mlelstv cc = UGETDW(cl->v2.bmChannelConfig);
886 1.178 mlelstv icn = cl->v2.iChannelNames;
887 1.178 mlelstv printf("cluster: bNrChannels=%u bmChannelConfig=%#.8x",
888 1.178 mlelstv cl->v2.bNrChannels, cc);
889 1.178 mlelstv break;
890 1.178 mlelstv default:
891 1.178 mlelstv return;
892 1.178 mlelstv }
893 1.91 kent
894 1.91 kent first = TRUE;
895 1.91 kent for (i = 0; cc != 0; i++) {
896 1.91 kent if (cc & 1) {
897 1.118 dyoung printf("%c%s", first ? '<' : ',', channel_names[i]);
898 1.91 kent first = FALSE;
899 1.91 kent }
900 1.91 kent cc = cc >> 1;
901 1.91 kent }
902 1.178 mlelstv printf("> iChannelNames=%u", icn);
903 1.91 kent }
904 1.91 kent #endif
905 1.91 kent
906 1.178 mlelstv Static union usb_audio_cluster
907 1.178 mlelstv uaudio_get_cluster(struct uaudio_softc *sc, int id, const struct io_terminal *iot)
908 1.1 augustss {
909 1.178 mlelstv union usb_audio_cluster r;
910 1.109 drochner const uaudio_cs_descriptor_t *dp;
911 1.179 mlelstv u_int pins;
912 1.1 augustss int i;
913 1.1 augustss
914 1.1 augustss for (i = 0; i < 25; i++) { /* avoid infinite loops */
915 1.82 kent dp = iot[id].d.desc;
916 1.1 augustss if (dp == 0)
917 1.1 augustss goto bad;
918 1.178 mlelstv
919 1.1 augustss switch (dp->bDescriptorSubtype) {
920 1.1 augustss case UDESCSUB_AC_INPUT:
921 1.178 mlelstv switch (sc->sc_version) {
922 1.178 mlelstv case UAUDIO_VERSION1:
923 1.178 mlelstv r.v1.bNrChannels = iot[id].d.it->v1.bNrChannels;
924 1.179 mlelstv USETW(r.v1.wChannelConfig,
925 1.179 mlelstv UGETW(iot[id].d.it->v1.wChannelConfig));
926 1.178 mlelstv r.v1.iChannelNames = iot[id].d.it->v1.iChannelNames;
927 1.178 mlelstv break;
928 1.178 mlelstv case UAUDIO_VERSION2:
929 1.178 mlelstv r.v2.bNrChannels = iot[id].d.it->v2.bNrChannels;
930 1.179 mlelstv USETDW(r.v2.bmChannelConfig,
931 1.179 mlelstv UGETW(iot[id].d.it->v2.bmChannelConfig));
932 1.178 mlelstv r.v2.iChannelNames = iot[id].d.it->v2.iChannelNames;
933 1.178 mlelstv break;
934 1.178 mlelstv }
935 1.94 kent return r;
936 1.1 augustss case UDESCSUB_AC_OUTPUT:
937 1.179 mlelstv /* XXX This is not really right */
938 1.178 mlelstv id = iot[id].d.ot->v1.bSourceId;
939 1.1 augustss break;
940 1.1 augustss case UDESCSUB_AC_MIXER:
941 1.179 mlelstv switch (sc->sc_version) {
942 1.179 mlelstv case UAUDIO_VERSION1:
943 1.179 mlelstv pins = iot[id].d.mu->bNrInPins;
944 1.179 mlelstv r.v1 = *(const struct usb_audio_v1_cluster *)
945 1.179 mlelstv &iot[id].d.mu->baSourceId[pins];
946 1.179 mlelstv break;
947 1.179 mlelstv case UAUDIO_VERSION2:
948 1.179 mlelstv pins = iot[id].d.mu->bNrInPins;
949 1.179 mlelstv r.v2 = *(const struct usb_audio_v2_cluster *)
950 1.179 mlelstv &iot[id].d.mu->baSourceId[pins];
951 1.179 mlelstv break;
952 1.179 mlelstv }
953 1.94 kent return r;
954 1.1 augustss case UDESCSUB_AC_SELECTOR:
955 1.1 augustss /* XXX This is not really right */
956 1.82 kent id = iot[id].d.su->baSourceId[0];
957 1.1 augustss break;
958 1.1 augustss case UDESCSUB_AC_FEATURE:
959 1.179 mlelstv /* XXX This is not really right */
960 1.179 mlelstv switch (sc->sc_version) {
961 1.179 mlelstv case UAUDIO_VERSION1:
962 1.179 mlelstv id = iot[id].d.fu->v1.bSourceId;
963 1.179 mlelstv break;
964 1.179 mlelstv case UAUDIO_VERSION2:
965 1.179 mlelstv id = iot[id].d.fu->v2.bSourceId;
966 1.179 mlelstv break;
967 1.179 mlelstv }
968 1.1 augustss break;
969 1.1 augustss case UDESCSUB_AC_PROCESSING:
970 1.179 mlelstv switch (sc->sc_version) {
971 1.179 mlelstv case UAUDIO_VERSION1:
972 1.179 mlelstv pins = iot[id].d.pu->bNrInPins;
973 1.179 mlelstv r.v1 = *(const struct usb_audio_v1_cluster *)
974 1.179 mlelstv &iot[id].d.pu->baSourceId[pins];
975 1.179 mlelstv break;
976 1.179 mlelstv case UAUDIO_VERSION2:
977 1.179 mlelstv pins = iot[id].d.pu->bNrInPins;
978 1.179 mlelstv r.v2 = *(const struct usb_audio_v2_cluster *)
979 1.179 mlelstv &iot[id].d.pu->baSourceId[pins];
980 1.179 mlelstv break;
981 1.179 mlelstv }
982 1.94 kent return r;
983 1.1 augustss case UDESCSUB_AC_EXTENSION:
984 1.179 mlelstv switch (sc->sc_version) {
985 1.179 mlelstv case UAUDIO_VERSION1:
986 1.179 mlelstv pins = iot[id].d.eu->bNrInPins;
987 1.179 mlelstv r.v1 = *(const struct usb_audio_v1_cluster *)
988 1.179 mlelstv &iot[id].d.eu->baSourceId[pins];
989 1.179 mlelstv break;
990 1.179 mlelstv case UAUDIO_VERSION2:
991 1.179 mlelstv pins = iot[id].d.eu->bNrInPins;
992 1.179 mlelstv r.v2 = *(const struct usb_audio_v2_cluster *)
993 1.179 mlelstv &iot[id].d.eu->baSourceId[pins];
994 1.179 mlelstv break;
995 1.179 mlelstv }
996 1.94 kent return r;
997 1.1 augustss default:
998 1.1 augustss goto bad;
999 1.1 augustss }
1000 1.1 augustss }
1001 1.1 augustss bad:
1002 1.113 cube aprint_error("uaudio_get_cluster: bad data\n");
1003 1.146 skrll memset(&r, 0, sizeof(r));
1004 1.94 kent return r;
1005 1.1 augustss
1006 1.1 augustss }
1007 1.1 augustss
1008 1.86 kent Static void
1009 1.82 kent uaudio_add_input(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
1010 1.1 augustss {
1011 1.178 mlelstv const union usb_audio_input_terminal *d;
1012 1.1 augustss
1013 1.94 kent d = iot[id].d.it;
1014 1.178 mlelstv switch (sc->sc_version) {
1015 1.178 mlelstv case UAUDIO_VERSION1:
1016 1.92 kent #ifdef UAUDIO_DEBUG
1017 1.178 mlelstv DPRINTFN(2,"bTerminalId=%d wTerminalType=0x%04x "
1018 1.178 mlelstv "bAssocTerminal=%d bNrChannels=%d wChannelConfig=%d "
1019 1.178 mlelstv "iChannelNames=%d iTerminal=%d\n",
1020 1.178 mlelstv d->v1.bTerminalId, UGETW(d->v1.wTerminalType), d->v1.bAssocTerminal,
1021 1.178 mlelstv d->v1.bNrChannels, UGETW(d->v1.wChannelConfig),
1022 1.178 mlelstv d->v1.iChannelNames, d->v1.iTerminal);
1023 1.1 augustss #endif
1024 1.178 mlelstv /* If USB input terminal, record wChannelConfig */
1025 1.179 mlelstv if ((UGETW(d->v1.wTerminalType) & 0xff00) != UAT_UNDEFINED)
1026 1.178 mlelstv return;
1027 1.178 mlelstv sc->sc_channel_config = UGETW(d->v1.wChannelConfig);
1028 1.179 mlelstv sc->sc_clock[id] = 0;
1029 1.178 mlelstv break;
1030 1.178 mlelstv case UAUDIO_VERSION2:
1031 1.178 mlelstv #ifdef UAUDIO_DEBUG
1032 1.178 mlelstv DPRINTFN(2,"bTerminalId=%d wTerminalType=0x%04x "
1033 1.178 mlelstv "bAssocTerminal=%d bNrChannels=%d bmChannelConfig=%x "
1034 1.178 mlelstv "iChannelNames=%d bCSourceId=%d iTerminal=%d\n",
1035 1.178 mlelstv d->v2.bTerminalId, UGETW(d->v2.wTerminalType), d->v2.bAssocTerminal,
1036 1.178 mlelstv d->v2.bNrChannels, UGETDW(d->v2.bmChannelConfig),
1037 1.178 mlelstv d->v2.iChannelNames, d->v2.bCSourceId, d->v2.iTerminal);
1038 1.178 mlelstv #endif
1039 1.178 mlelstv /* If USB input terminal, record wChannelConfig */
1040 1.179 mlelstv if ((UGETW(d->v2.wTerminalType) & 0xff00) != UAT_UNDEFINED)
1041 1.178 mlelstv return;
1042 1.178 mlelstv sc->sc_channel_config = UGETDW(d->v2.bmChannelConfig);
1043 1.179 mlelstv sc->sc_clock[id] = d->v2.bCSourceId;
1044 1.178 mlelstv break;
1045 1.178 mlelstv }
1046 1.1 augustss }
1047 1.1 augustss
1048 1.86 kent Static void
1049 1.107 christos uaudio_add_output(struct uaudio_softc *sc,
1050 1.107 christos const struct io_terminal *iot, int id)
1051 1.1 augustss {
1052 1.4 augustss #ifdef UAUDIO_DEBUG
1053 1.178 mlelstv const union usb_audio_output_terminal *d;
1054 1.1 augustss
1055 1.94 kent d = iot[id].d.ot;
1056 1.178 mlelstv switch (sc->sc_version) {
1057 1.178 mlelstv case UAUDIO_VERSION1:
1058 1.178 mlelstv DPRINTFN(2,"bTerminalId=%d wTerminalType=0x%04x "
1059 1.178 mlelstv "bAssocTerminal=%d bSourceId=%d iTerminal=%d\n",
1060 1.178 mlelstv d->v1.bTerminalId, UGETW(d->v1.wTerminalType), d->v1.bAssocTerminal,
1061 1.178 mlelstv d->v1.bSourceId, d->v1.iTerminal);
1062 1.179 mlelstv sc->sc_clock[id] = 0;
1063 1.178 mlelstv break;
1064 1.178 mlelstv case UAUDIO_VERSION2:
1065 1.178 mlelstv DPRINTFN(2,"bTerminalId=%d wTerminalType=0x%04x "
1066 1.178 mlelstv "bAssocTerminal=%d bSourceId=%d bCSourceId=%d, iTerminal=%d\n",
1067 1.178 mlelstv d->v2.bTerminalId, UGETW(d->v2.wTerminalType), d->v2.bAssocTerminal,
1068 1.178 mlelstv d->v2.bSourceId, d->v2.bCSourceId, d->v2.iTerminal);
1069 1.179 mlelstv sc->sc_clock[id] = d->v2.bCSourceId;
1070 1.178 mlelstv break;
1071 1.178 mlelstv }
1072 1.1 augustss #endif
1073 1.1 augustss }
1074 1.1 augustss
1075 1.86 kent Static void
1076 1.82 kent uaudio_add_mixer(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
1077 1.1 augustss {
1078 1.94 kent const struct usb_audio_mixer_unit *d;
1079 1.178 mlelstv const union usb_audio_mixer_unit_1 *d1;
1080 1.179 mlelstv int c, chs, ichs, ochs, nchs, i, o, bno, p, k;
1081 1.179 mlelstv size_t bm_size;
1082 1.99 christos const uByte *bm;
1083 1.1 augustss struct mixerctl mix;
1084 1.1 augustss
1085 1.94 kent d = iot[id].d.mu;
1086 1.179 mlelstv d1 = (const union usb_audio_mixer_unit_1 *)&d->baSourceId[d->bNrInPins];
1087 1.122 mrg DPRINTFN(2,"bUnitId=%d bNrInPins=%d\n",
1088 1.122 mrg d->bUnitId, d->bNrInPins);
1089 1.56 kent
1090 1.179 mlelstv mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
1091 1.179 mlelstv uaudio_determine_class(&iot[id], &mix);
1092 1.179 mlelstv mix.type = MIX_SIGNED_16;
1093 1.179 mlelstv mix.ctlunit = AudioNvolume;
1094 1.178 mlelstv
1095 1.1 augustss /* Compute the number of input channels */
1096 1.178 mlelstv /* and the number of output channels */
1097 1.1 augustss ichs = 0;
1098 1.178 mlelstv switch (sc->sc_version) {
1099 1.178 mlelstv case UAUDIO_VERSION1:
1100 1.178 mlelstv for (i = 0; i < d->bNrInPins; i++)
1101 1.178 mlelstv ichs += uaudio_get_cluster(sc, d->baSourceId[i], iot).v1.bNrChannels;
1102 1.178 mlelstv ochs = d1->v1.bNrChannels;
1103 1.178 mlelstv DPRINTFN(2,"ichs=%d ochs=%d\n", ichs, ochs);
1104 1.178 mlelstv bm = d1->v1.bmControls;
1105 1.178 mlelstv break;
1106 1.178 mlelstv case UAUDIO_VERSION2:
1107 1.178 mlelstv for (i = 0; i < d->bNrInPins; i++)
1108 1.178 mlelstv ichs += uaudio_get_cluster(sc, d->baSourceId[i], iot).v2.bNrChannels;
1109 1.178 mlelstv ochs = d1->v2.bNrChannels;
1110 1.178 mlelstv DPRINTFN(2,"ichs=%d ochs=%d\n", ichs, ochs);
1111 1.179 mlelstv bm = d1->v2.bmMixerControls;
1112 1.179 mlelstv bm_size = ichs * ochs / 8 + ((ichs * ochs % 8) ? 1 : 0);
1113 1.179 mlelstv /* bmControls */
1114 1.179 mlelstv if ((bm[bm_size] & UA_MIX_CLUSTER_MASK) != UA_MIX_CLUSTER_RW)
1115 1.179 mlelstv return;
1116 1.178 mlelstv break;
1117 1.178 mlelstv default:
1118 1.178 mlelstv return;
1119 1.178 mlelstv }
1120 1.179 mlelstv
1121 1.1 augustss for (p = i = 0; i < d->bNrInPins; i++) {
1122 1.178 mlelstv switch (sc->sc_version) {
1123 1.178 mlelstv case UAUDIO_VERSION1:
1124 1.179 mlelstv chs = uaudio_get_cluster(sc, d->baSourceId[i], iot)
1125 1.179 mlelstv .v1.bNrChannels;
1126 1.178 mlelstv break;
1127 1.178 mlelstv case UAUDIO_VERSION2:
1128 1.179 mlelstv chs = uaudio_get_cluster(sc, d->baSourceId[i], iot)
1129 1.179 mlelstv .v2.bNrChannels;
1130 1.178 mlelstv break;
1131 1.178 mlelstv default:
1132 1.179 mlelstv continue;
1133 1.178 mlelstv }
1134 1.179 mlelstv
1135 1.179 mlelstv #define _BIT(bno) ((bm[bno / 8] >> (7 - bno % 8)) & 1)
1136 1.179 mlelstv
1137 1.179 mlelstv nchs = chs < MIX_MAX_CHAN ? chs : MIX_MAX_CHAN;
1138 1.179 mlelstv
1139 1.179 mlelstv k = 0;
1140 1.179 mlelstv for (c = 0; c < nchs; c++) {
1141 1.1 augustss for (o = 0; o < ochs; o++) {
1142 1.1 augustss bno = (p + c) * ochs + o;
1143 1.101 dyoung if (_BIT(bno))
1144 1.179 mlelstv mix.wValue[k++] =
1145 1.179 mlelstv MAKE(p+c+1, o+1);
1146 1.1 augustss }
1147 1.1 augustss }
1148 1.179 mlelstv mix.nchan = nchs;
1149 1.179 mlelstv
1150 1.179 mlelstv snprintf(mix.ctlname, sizeof(mix.ctlname),
1151 1.179 mlelstv "mix%d-%s", d->bUnitId,
1152 1.179 mlelstv uaudio_id_name(sc, iot, d->baSourceId[i])
1153 1.179 mlelstv );
1154 1.179 mlelstv uaudio_mixer_add_ctl(sc, &mix);
1155 1.179 mlelstv
1156 1.101 dyoung #undef _BIT
1157 1.179 mlelstv
1158 1.1 augustss p += chs;
1159 1.1 augustss }
1160 1.1 augustss }
1161 1.1 augustss
1162 1.86 kent Static void
1163 1.82 kent uaudio_add_selector(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
1164 1.1 augustss {
1165 1.94 kent const struct usb_audio_selector_unit *d;
1166 1.79 kent struct mixerctl mix;
1167 1.79 kent int i, wp;
1168 1.1 augustss
1169 1.94 kent d = iot[id].d.su;
1170 1.122 mrg DPRINTFN(2,"bUnitId=%d bNrInPins=%d\n",
1171 1.122 mrg d->bUnitId, d->bNrInPins);
1172 1.79 kent mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
1173 1.179 mlelstv if (sc->sc_version == UAUDIO_VERSION2)
1174 1.179 mlelstv mix.wValue[0] = MAKE(V2_CUR_SELECTOR, 0);
1175 1.179 mlelstv else
1176 1.179 mlelstv mix.wValue[0] = MAKE(0, 0);
1177 1.82 kent uaudio_determine_class(&iot[id], &mix);
1178 1.79 kent mix.nchan = 1;
1179 1.79 kent mix.type = MIX_SELECTOR;
1180 1.79 kent mix.ctlunit = "";
1181 1.175 mlelstv mix.range0.minval = 1;
1182 1.175 mlelstv mix.range0.maxval = d->bNrInPins;
1183 1.175 mlelstv mix.range0.resval = 1;
1184 1.175 mlelstv mix.mul = mix.range0.maxval - mix.range0.minval;
1185 1.81 kent wp = snprintf(mix.ctlname, MAX_AUDIO_DEV_LEN, "sel%d-", d->bUnitId);
1186 1.79 kent for (i = 1; i <= d->bNrInPins; i++) {
1187 1.179 mlelstv wp += strlcpy(mix.ctlname + wp,
1188 1.179 mlelstv uaudio_id_name(sc, iot, d->baSourceId[i-1]),
1189 1.179 mlelstv MAX_AUDIO_DEV_LEN - wp);
1190 1.79 kent if (wp > MAX_AUDIO_DEV_LEN - 1)
1191 1.79 kent break;
1192 1.79 kent }
1193 1.79 kent uaudio_mixer_add_ctl(sc, &mix);
1194 1.1 augustss }
1195 1.1 augustss
1196 1.82 kent #ifdef UAUDIO_DEBUG
1197 1.86 kent Static const char *
1198 1.82 kent uaudio_get_terminal_name(int terminal_type)
1199 1.82 kent {
1200 1.99 christos static char tbuf[100];
1201 1.82 kent
1202 1.82 kent switch (terminal_type) {
1203 1.87 kent /* USB terminal types */
1204 1.87 kent case UAT_UNDEFINED: return "UAT_UNDEFINED";
1205 1.82 kent case UAT_STREAM: return "UAT_STREAM";
1206 1.87 kent case UAT_VENDOR: return "UAT_VENDOR";
1207 1.87 kent /* input terminal types */
1208 1.87 kent case UATI_UNDEFINED: return "UATI_UNDEFINED";
1209 1.82 kent case UATI_MICROPHONE: return "UATI_MICROPHONE";
1210 1.82 kent case UATI_DESKMICROPHONE: return "UATI_DESKMICROPHONE";
1211 1.82 kent case UATI_PERSONALMICROPHONE: return "UATI_PERSONALMICROPHONE";
1212 1.82 kent case UATI_OMNIMICROPHONE: return "UATI_OMNIMICROPHONE";
1213 1.82 kent case UATI_MICROPHONEARRAY: return "UATI_MICROPHONEARRAY";
1214 1.82 kent case UATI_PROCMICROPHONEARR: return "UATI_PROCMICROPHONEARR";
1215 1.87 kent /* output terminal types */
1216 1.87 kent case UATO_UNDEFINED: return "UATO_UNDEFINED";
1217 1.82 kent case UATO_SPEAKER: return "UATO_SPEAKER";
1218 1.87 kent case UATO_HEADPHONES: return "UATO_HEADPHONES";
1219 1.87 kent case UATO_DISPLAYAUDIO: return "UATO_DISPLAYAUDIO";
1220 1.82 kent case UATO_DESKTOPSPEAKER: return "UATO_DESKTOPSPEAKER";
1221 1.82 kent case UATO_ROOMSPEAKER: return "UATO_ROOMSPEAKER";
1222 1.82 kent case UATO_COMMSPEAKER: return "UATO_COMMSPEAKER";
1223 1.82 kent case UATO_SUBWOOFER: return "UATO_SUBWOOFER";
1224 1.87 kent /* bidir terminal types */
1225 1.82 kent case UATB_UNDEFINED: return "UATB_UNDEFINED";
1226 1.82 kent case UATB_HANDSET: return "UATB_HANDSET";
1227 1.82 kent case UATB_HEADSET: return "UATB_HEADSET";
1228 1.82 kent case UATB_SPEAKERPHONE: return "UATB_SPEAKERPHONE";
1229 1.82 kent case UATB_SPEAKERPHONEESUP: return "UATB_SPEAKERPHONEESUP";
1230 1.82 kent case UATB_SPEAKERPHONEECANC: return "UATB_SPEAKERPHONEECANC";
1231 1.87 kent /* telephony terminal types */
1232 1.82 kent case UATT_UNDEFINED: return "UATT_UNDEFINED";
1233 1.82 kent case UATT_PHONELINE: return "UATT_PHONELINE";
1234 1.82 kent case UATT_TELEPHONE: return "UATT_TELEPHONE";
1235 1.82 kent case UATT_DOWNLINEPHONE: return "UATT_DOWNLINEPHONE";
1236 1.87 kent /* external terminal types */
1237 1.82 kent case UATE_UNDEFINED: return "UATE_UNDEFINED";
1238 1.87 kent case UATE_ANALOGCONN: return "UATE_ANALOGCONN";
1239 1.87 kent case UATE_LINECONN: return "UATE_LINECONN";
1240 1.87 kent case UATE_LEGACYCONN: return "UATE_LEGACYCONN";
1241 1.87 kent case UATE_DIGITALAUIFC: return "UATE_DIGITALAUIFC";
1242 1.87 kent case UATE_SPDIF: return "UATE_SPDIF";
1243 1.87 kent case UATE_1394DA: return "UATE_1394DA";
1244 1.87 kent case UATE_1394DV: return "UATE_1394DV";
1245 1.87 kent /* embedded function terminal types */
1246 1.82 kent case UATF_UNDEFINED: return "UATF_UNDEFINED";
1247 1.82 kent case UATF_CALIBNOISE: return "UATF_CALIBNOISE";
1248 1.82 kent case UATF_EQUNOISE: return "UATF_EQUNOISE";
1249 1.87 kent case UATF_CDPLAYER: return "UATF_CDPLAYER";
1250 1.82 kent case UATF_DAT: return "UATF_DAT";
1251 1.82 kent case UATF_DCC: return "UATF_DCC";
1252 1.82 kent case UATF_MINIDISK: return "UATF_MINIDISK";
1253 1.82 kent case UATF_ANALOGTAPE: return "UATF_ANALOGTAPE";
1254 1.82 kent case UATF_PHONOGRAPH: return "UATF_PHONOGRAPH";
1255 1.82 kent case UATF_VCRAUDIO: return "UATF_VCRAUDIO";
1256 1.87 kent case UATF_VIDEODISCAUDIO: return "UATF_VIDEODISCAUDIO";
1257 1.87 kent case UATF_DVDAUDIO: return "UATF_DVDAUDIO";
1258 1.87 kent case UATF_TVTUNERAUDIO: return "UATF_TVTUNERAUDIO";
1259 1.82 kent case UATF_SATELLITE: return "UATF_SATELLITE";
1260 1.82 kent case UATF_CABLETUNER: return "UATF_CABLETUNER";
1261 1.82 kent case UATF_DSS: return "UATF_DSS";
1262 1.82 kent case UATF_RADIORECV: return "UATF_RADIORECV";
1263 1.82 kent case UATF_RADIOXMIT: return "UATF_RADIOXMIT";
1264 1.82 kent case UATF_MULTITRACK: return "UATF_MULTITRACK";
1265 1.87 kent case UATF_SYNTHESIZER: return "UATF_SYNTHESIZER";
1266 1.82 kent default:
1267 1.164 christos snprintf(tbuf, sizeof(tbuf), "unknown type (%#.4x)", terminal_type);
1268 1.99 christos return tbuf;
1269 1.82 kent }
1270 1.82 kent }
1271 1.82 kent #endif
1272 1.82 kent
1273 1.86 kent Static int
1274 1.82 kent uaudio_determine_class(const struct io_terminal *iot, struct mixerctl *mix)
1275 1.82 kent {
1276 1.82 kent int terminal_type;
1277 1.82 kent
1278 1.82 kent if (iot == NULL || iot->output == NULL) {
1279 1.82 kent mix->class = UAC_OUTPUT;
1280 1.82 kent return 0;
1281 1.82 kent }
1282 1.82 kent terminal_type = 0;
1283 1.82 kent if (iot->output->size == 1)
1284 1.82 kent terminal_type = iot->output->terminals[0];
1285 1.82 kent /*
1286 1.82 kent * If the only output terminal is USB,
1287 1.82 kent * the class is UAC_RECORD.
1288 1.82 kent */
1289 1.82 kent if ((terminal_type & 0xff00) == (UAT_UNDEFINED & 0xff00)) {
1290 1.82 kent mix->class = UAC_RECORD;
1291 1.82 kent if (iot->inputs_size == 1
1292 1.82 kent && iot->inputs[0] != NULL
1293 1.82 kent && iot->inputs[0]->size == 1)
1294 1.82 kent return iot->inputs[0]->terminals[0];
1295 1.82 kent else
1296 1.82 kent return 0;
1297 1.82 kent }
1298 1.82 kent /*
1299 1.83 kent * If the ultimate destination of the unit is just one output
1300 1.82 kent * terminal and the unit is connected to the output terminal
1301 1.82 kent * directly, the class is UAC_OUTPUT.
1302 1.82 kent */
1303 1.82 kent if (terminal_type != 0 && iot->direct) {
1304 1.82 kent mix->class = UAC_OUTPUT;
1305 1.82 kent return terminal_type;
1306 1.82 kent }
1307 1.82 kent /*
1308 1.82 kent * If the unit is connected to just one input terminal,
1309 1.82 kent * the class is UAC_INPUT.
1310 1.82 kent */
1311 1.82 kent if (iot->inputs_size == 1 && iot->inputs[0] != NULL
1312 1.82 kent && iot->inputs[0]->size == 1) {
1313 1.82 kent mix->class = UAC_INPUT;
1314 1.82 kent return iot->inputs[0]->terminals[0];
1315 1.82 kent }
1316 1.82 kent /*
1317 1.82 kent * Otherwise, the class is UAC_OUTPUT.
1318 1.82 kent */
1319 1.82 kent mix->class = UAC_OUTPUT;
1320 1.82 kent return terminal_type;
1321 1.82 kent }
1322 1.82 kent
1323 1.86 kent Static const char *
1324 1.179 mlelstv uaudio_feature_name(const struct io_terminal *iot,
1325 1.179 mlelstv uint8_t class, int terminal_type)
1326 1.82 kent {
1327 1.82 kent
1328 1.179 mlelstv if (class == UAC_RECORD && terminal_type == 0)
1329 1.82 kent return AudioNmixerout;
1330 1.179 mlelstv
1331 1.122 mrg DPRINTF("terminal_type=%s\n", uaudio_get_terminal_name(terminal_type));
1332 1.82 kent switch (terminal_type) {
1333 1.82 kent case UAT_STREAM:
1334 1.82 kent return AudioNdac;
1335 1.82 kent
1336 1.82 kent case UATI_MICROPHONE:
1337 1.82 kent case UATI_DESKMICROPHONE:
1338 1.82 kent case UATI_PERSONALMICROPHONE:
1339 1.82 kent case UATI_OMNIMICROPHONE:
1340 1.82 kent case UATI_MICROPHONEARRAY:
1341 1.82 kent case UATI_PROCMICROPHONEARR:
1342 1.82 kent return AudioNmicrophone;
1343 1.82 kent
1344 1.82 kent case UATO_SPEAKER:
1345 1.82 kent case UATO_DESKTOPSPEAKER:
1346 1.82 kent case UATO_ROOMSPEAKER:
1347 1.82 kent case UATO_COMMSPEAKER:
1348 1.82 kent return AudioNspeaker;
1349 1.82 kent
1350 1.82 kent case UATO_HEADPHONES:
1351 1.82 kent return AudioNheadphone;
1352 1.82 kent
1353 1.87 kent case UATO_SUBWOOFER:
1354 1.87 kent return AudioNlfe;
1355 1.87 kent
1356 1.87 kent /* telephony terminal types */
1357 1.87 kent case UATT_UNDEFINED:
1358 1.87 kent case UATT_PHONELINE:
1359 1.87 kent case UATT_TELEPHONE:
1360 1.87 kent case UATT_DOWNLINEPHONE:
1361 1.87 kent return "phone";
1362 1.87 kent
1363 1.82 kent case UATE_ANALOGCONN:
1364 1.82 kent case UATE_LINECONN:
1365 1.82 kent case UATE_LEGACYCONN:
1366 1.82 kent return AudioNline;
1367 1.82 kent
1368 1.82 kent case UATE_DIGITALAUIFC:
1369 1.82 kent case UATE_SPDIF:
1370 1.82 kent case UATE_1394DA:
1371 1.82 kent case UATE_1394DV:
1372 1.82 kent return AudioNaux;
1373 1.82 kent
1374 1.82 kent case UATF_CDPLAYER:
1375 1.82 kent return AudioNcd;
1376 1.82 kent
1377 1.82 kent case UATF_SYNTHESIZER:
1378 1.82 kent return AudioNfmsynth;
1379 1.82 kent
1380 1.82 kent case UATF_VIDEODISCAUDIO:
1381 1.82 kent case UATF_DVDAUDIO:
1382 1.82 kent case UATF_TVTUNERAUDIO:
1383 1.82 kent return AudioNvideo;
1384 1.82 kent
1385 1.82 kent case UAT_UNDEFINED:
1386 1.82 kent case UAT_VENDOR:
1387 1.82 kent case UATI_UNDEFINED:
1388 1.82 kent /* output terminal types */
1389 1.82 kent case UATO_UNDEFINED:
1390 1.82 kent case UATO_DISPLAYAUDIO:
1391 1.82 kent /* bidir terminal types */
1392 1.82 kent case UATB_UNDEFINED:
1393 1.82 kent case UATB_HANDSET:
1394 1.82 kent case UATB_HEADSET:
1395 1.82 kent case UATB_SPEAKERPHONE:
1396 1.82 kent case UATB_SPEAKERPHONEESUP:
1397 1.82 kent case UATB_SPEAKERPHONEECANC:
1398 1.82 kent /* external terminal types */
1399 1.82 kent case UATE_UNDEFINED:
1400 1.82 kent /* embedded function terminal types */
1401 1.82 kent case UATF_UNDEFINED:
1402 1.82 kent case UATF_CALIBNOISE:
1403 1.82 kent case UATF_EQUNOISE:
1404 1.82 kent case UATF_DAT:
1405 1.82 kent case UATF_DCC:
1406 1.82 kent case UATF_MINIDISK:
1407 1.82 kent case UATF_ANALOGTAPE:
1408 1.82 kent case UATF_PHONOGRAPH:
1409 1.82 kent case UATF_VCRAUDIO:
1410 1.82 kent case UATF_SATELLITE:
1411 1.82 kent case UATF_CABLETUNER:
1412 1.82 kent case UATF_DSS:
1413 1.82 kent case UATF_RADIORECV:
1414 1.82 kent case UATF_RADIOXMIT:
1415 1.82 kent case UATF_MULTITRACK:
1416 1.82 kent case 0xffff:
1417 1.82 kent default:
1418 1.164 christos DPRINTF("'master' for %#.4x\n", terminal_type);
1419 1.82 kent return AudioNmaster;
1420 1.82 kent }
1421 1.82 kent return AudioNmaster;
1422 1.82 kent }
1423 1.82 kent
1424 1.179 mlelstv static void
1425 1.179 mlelstv uaudio_add_feature_mixer(struct uaudio_softc *sc, const struct io_terminal *iot,
1426 1.179 mlelstv int unit, int ctl, struct mixerctl *mc)
1427 1.179 mlelstv {
1428 1.179 mlelstv const char *mixername, *attr = NULL;
1429 1.179 mlelstv int terminal_type;
1430 1.179 mlelstv
1431 1.179 mlelstv mc->wIndex = MAKE(unit, sc->sc_ac_iface);
1432 1.179 mlelstv terminal_type = uaudio_determine_class(iot, mc);
1433 1.179 mlelstv mixername = uaudio_feature_name(iot, mc->class, terminal_type);
1434 1.179 mlelstv switch (ctl) {
1435 1.179 mlelstv case MUTE_CONTROL:
1436 1.179 mlelstv mc->type = MIX_ON_OFF;
1437 1.179 mlelstv mc->ctlunit = "";
1438 1.179 mlelstv attr = AudioNmute;
1439 1.179 mlelstv break;
1440 1.179 mlelstv case VOLUME_CONTROL:
1441 1.179 mlelstv mc->type = MIX_SIGNED_16;
1442 1.179 mlelstv mc->ctlunit = AudioNvolume;
1443 1.179 mlelstv attr = NULL;
1444 1.179 mlelstv break;
1445 1.179 mlelstv case BASS_CONTROL:
1446 1.179 mlelstv mc->type = MIX_SIGNED_8;
1447 1.179 mlelstv mc->ctlunit = AudioNbass;
1448 1.179 mlelstv attr = AudioNbass;
1449 1.179 mlelstv break;
1450 1.179 mlelstv case MID_CONTROL:
1451 1.179 mlelstv mc->type = MIX_SIGNED_8;
1452 1.179 mlelstv mc->ctlunit = AudioNmid;
1453 1.179 mlelstv attr = AudioNmid;
1454 1.179 mlelstv break;
1455 1.179 mlelstv case TREBLE_CONTROL:
1456 1.179 mlelstv mc->type = MIX_SIGNED_8;
1457 1.179 mlelstv mc->ctlunit = AudioNtreble;
1458 1.179 mlelstv attr = AudioNtreble;
1459 1.179 mlelstv break;
1460 1.179 mlelstv case GRAPHIC_EQUALIZER_CONTROL:
1461 1.179 mlelstv return; /* XXX don't add anything */
1462 1.179 mlelstv break;
1463 1.179 mlelstv case AGC_CONTROL:
1464 1.179 mlelstv mc->type = MIX_ON_OFF;
1465 1.179 mlelstv mc->ctlunit = "";
1466 1.179 mlelstv attr = AudioNagc;
1467 1.179 mlelstv break;
1468 1.179 mlelstv case DELAY_CONTROL:
1469 1.179 mlelstv mc->type = MIX_UNSIGNED_16;
1470 1.179 mlelstv mc->ctlunit = "4 ms";
1471 1.179 mlelstv attr = AudioNdelay;
1472 1.179 mlelstv break;
1473 1.179 mlelstv case BASS_BOOST_CONTROL:
1474 1.179 mlelstv mc->type = MIX_ON_OFF;
1475 1.179 mlelstv mc->ctlunit = "";
1476 1.179 mlelstv attr = AudioNbassboost;
1477 1.179 mlelstv break;
1478 1.179 mlelstv case LOUDNESS_CONTROL:
1479 1.179 mlelstv mc->type = MIX_ON_OFF;
1480 1.179 mlelstv mc->ctlunit = "";
1481 1.179 mlelstv attr = AudioNloudness;
1482 1.179 mlelstv break;
1483 1.179 mlelstv case GAIN_CONTROL:
1484 1.179 mlelstv mc->type = MIX_SIGNED_16;
1485 1.179 mlelstv mc->ctlunit = "gain";
1486 1.179 mlelstv attr = "gain";;
1487 1.179 mlelstv break;
1488 1.179 mlelstv case GAINPAD_CONTROL:
1489 1.179 mlelstv mc->type = MIX_SIGNED_16;
1490 1.179 mlelstv mc->ctlunit = "gainpad";
1491 1.179 mlelstv attr = "gainpad";;
1492 1.179 mlelstv break;
1493 1.179 mlelstv case PHASEINV_CONTROL:
1494 1.179 mlelstv mc->type = MIX_ON_OFF;
1495 1.179 mlelstv mc->ctlunit = "";
1496 1.179 mlelstv attr = "phaseinv";;
1497 1.179 mlelstv break;
1498 1.179 mlelstv case UNDERFLOW_CONTROL:
1499 1.179 mlelstv mc->type = MIX_ON_OFF;
1500 1.179 mlelstv mc->ctlunit = "";
1501 1.179 mlelstv attr = "underflow";;
1502 1.179 mlelstv break;
1503 1.179 mlelstv case OVERFLOW_CONTROL:
1504 1.179 mlelstv mc->type = MIX_ON_OFF;
1505 1.179 mlelstv mc->ctlunit = "";
1506 1.179 mlelstv attr = "overflow";;
1507 1.179 mlelstv break;
1508 1.179 mlelstv default:
1509 1.179 mlelstv return; /* XXX don't add anything */
1510 1.179 mlelstv break;
1511 1.179 mlelstv }
1512 1.179 mlelstv
1513 1.179 mlelstv if (attr != NULL) {
1514 1.179 mlelstv snprintf(mc->ctlname, sizeof(mc->ctlname),
1515 1.179 mlelstv "%s.%s", mixername, attr);
1516 1.179 mlelstv } else {
1517 1.179 mlelstv snprintf(mc->ctlname, sizeof(mc->ctlname),
1518 1.179 mlelstv "%s", mixername);
1519 1.179 mlelstv }
1520 1.179 mlelstv
1521 1.179 mlelstv uaudio_mixer_add_ctl(sc, mc);
1522 1.179 mlelstv }
1523 1.179 mlelstv
1524 1.86 kent Static void
1525 1.82 kent uaudio_add_feature(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
1526 1.1 augustss {
1527 1.179 mlelstv const union usb_audio_feature_unit *d;
1528 1.94 kent const uByte *ctls;
1529 1.179 mlelstv const uDWord *ctls2;
1530 1.94 kent int ctlsize;
1531 1.94 kent int nchan;
1532 1.1 augustss u_int fumask, mmask, cmask;
1533 1.1 augustss struct mixerctl mix;
1534 1.1 augustss int chan, ctl, i, unit;
1535 1.1 augustss
1536 1.179 mlelstv d = iot[id].d.fu;
1537 1.179 mlelstv
1538 1.179 mlelstv switch (sc->sc_version) {
1539 1.179 mlelstv case UAUDIO_VERSION1:
1540 1.179 mlelstv
1541 1.179 mlelstv #define GETV1(i) (ctls[(i)*ctlsize] | \
1542 1.1 augustss (ctlsize > 1 ? ctls[(i)*ctlsize+1] << 8 : 0))
1543 1.179 mlelstv
1544 1.179 mlelstv ctls = d->v1.bmaControls;
1545 1.179 mlelstv ctlsize = d->v1.bControlSize;
1546 1.179 mlelstv if (ctlsize == 0) {
1547 1.179 mlelstv DPRINTF("ignoring feature %d with controlSize of zero\n", id);
1548 1.179 mlelstv return;
1549 1.179 mlelstv }
1550 1.179 mlelstv
1551 1.179 mlelstv /* offsetof bmaControls + sizeof iFeature == 7 */
1552 1.179 mlelstv nchan = (d->v1.bLength - 7) / ctlsize;
1553 1.179 mlelstv mmask = GETV1(0);
1554 1.179 mlelstv /* Figure out what we can control */
1555 1.179 mlelstv for (cmask = 0, chan = 1; chan < nchan; chan++) {
1556 1.179 mlelstv DPRINTFN(9,"chan=%d mask=%x\n",
1557 1.179 mlelstv chan, GETV1(chan));
1558 1.179 mlelstv cmask |= GETV1(chan);
1559 1.179 mlelstv }
1560 1.179 mlelstv
1561 1.179 mlelstv DPRINTFN(1,"bUnitId=%d, "
1562 1.179 mlelstv "%d channels, mmask=0x%04x, cmask=0x%04x\n",
1563 1.179 mlelstv d->v1.bUnitId, nchan, mmask, cmask);
1564 1.179 mlelstv
1565 1.179 mlelstv if (nchan > MIX_MAX_CHAN)
1566 1.179 mlelstv nchan = MIX_MAX_CHAN;
1567 1.179 mlelstv unit = d->v1.bUnitId;
1568 1.179 mlelstv
1569 1.179 mlelstv for (ctl = MUTE_CONTROL; ctl <= LOUDNESS_CONTROL; ctl++) {
1570 1.179 mlelstv fumask = FU_MASK(ctl);
1571 1.179 mlelstv DPRINTFN(4,"ctl=%d fumask=0x%04x\n",
1572 1.179 mlelstv ctl, fumask);
1573 1.179 mlelstv if (mmask & fumask) {
1574 1.179 mlelstv mix.nchan = 1;
1575 1.179 mlelstv mix.wValue[0] = MAKE(ctl, 0);
1576 1.179 mlelstv } else if (cmask & fumask) {
1577 1.179 mlelstv mix.nchan = nchan - 1;
1578 1.179 mlelstv for (i = 1; i < nchan; i++) {
1579 1.179 mlelstv if (GETV1(i) & fumask)
1580 1.179 mlelstv mix.wValue[i-1] = MAKE(ctl, i);
1581 1.179 mlelstv else
1582 1.179 mlelstv mix.wValue[i-1] = -1;
1583 1.179 mlelstv }
1584 1.179 mlelstv } else {
1585 1.179 mlelstv continue;
1586 1.1 augustss }
1587 1.179 mlelstv
1588 1.179 mlelstv uaudio_add_feature_mixer(sc, &iot[id], unit, ctl, &mix);
1589 1.179 mlelstv }
1590 1.179 mlelstv #undef GETV1
1591 1.179 mlelstv break;
1592 1.179 mlelstv
1593 1.179 mlelstv case UAUDIO_VERSION2:
1594 1.179 mlelstv
1595 1.179 mlelstv #define GETV2(i) UGETDW(ctls2[(i)])
1596 1.179 mlelstv
1597 1.179 mlelstv ctls2 = d->v2.bmaControls;
1598 1.179 mlelstv
1599 1.179 mlelstv /* offsetof bmaControls + sizeof iFeature == 6 */
1600 1.179 mlelstv nchan = (d->v2.bLength - 6) / 4;
1601 1.179 mlelstv if (nchan <= 0) {
1602 1.179 mlelstv DPRINTF("ignoring feature %d with no controls\n", id);
1603 1.179 mlelstv return;
1604 1.1 augustss }
1605 1.179 mlelstv
1606 1.179 mlelstv mmask = GETV2(0);
1607 1.179 mlelstv /* Figure out what we can control */
1608 1.179 mlelstv for (cmask = 0, chan = 1; chan < nchan; chan++) {
1609 1.179 mlelstv DPRINTFN(9,"chan=%d mask=%x\n",
1610 1.179 mlelstv chan, GETV2(chan));
1611 1.179 mlelstv cmask |= GETV2(chan);
1612 1.179 mlelstv }
1613 1.179 mlelstv
1614 1.179 mlelstv DPRINTFN(1,"bUnitId=%d, "
1615 1.179 mlelstv "%d channels, mmask=0x%04x, cmask=0x%04x\n",
1616 1.179 mlelstv d->v2.bUnitId, nchan, mmask, cmask);
1617 1.179 mlelstv
1618 1.179 mlelstv if (nchan > MIX_MAX_CHAN)
1619 1.179 mlelstv nchan = MIX_MAX_CHAN;
1620 1.179 mlelstv unit = d->v2.bUnitId;
1621 1.179 mlelstv
1622 1.179 mlelstv for (ctl = MUTE_CONTROL; ctl <= OVERFLOW_CONTROL; ctl++) {
1623 1.179 mlelstv fumask = V2_FU_MASK(ctl);
1624 1.179 mlelstv DPRINTFN(4,"ctl=%d fumask=0x%08x\n",
1625 1.179 mlelstv ctl, fumask);
1626 1.179 mlelstv
1627 1.179 mlelstv if (mmask & fumask) {
1628 1.179 mlelstv mix.nchan = 1;
1629 1.179 mlelstv mix.wValue[0] = MAKE(ctl, 0);
1630 1.179 mlelstv } else if (cmask & fumask) {
1631 1.179 mlelstv mix.nchan = nchan-1;
1632 1.179 mlelstv for (i = 1; i < nchan; ++i) {
1633 1.179 mlelstv if (GETV2(i) & fumask)
1634 1.179 mlelstv mix.wValue[i-1] = MAKE(ctl, i);
1635 1.179 mlelstv else
1636 1.179 mlelstv mix.wValue[i-1] = -1;
1637 1.179 mlelstv }
1638 1.179 mlelstv } else {
1639 1.179 mlelstv continue;
1640 1.179 mlelstv }
1641 1.179 mlelstv
1642 1.179 mlelstv uaudio_add_feature_mixer(sc, &iot[id], unit, ctl, &mix);
1643 1.1 augustss }
1644 1.179 mlelstv
1645 1.179 mlelstv #undef GETV2
1646 1.179 mlelstv break;
1647 1.1 augustss }
1648 1.1 augustss }
1649 1.1 augustss
1650 1.86 kent Static void
1651 1.78 kent uaudio_add_processing_updown(struct uaudio_softc *sc,
1652 1.82 kent const struct io_terminal *iot, int id)
1653 1.78 kent {
1654 1.94 kent const struct usb_audio_processing_unit *d;
1655 1.94 kent const struct usb_audio_processing_unit_1 *d1;
1656 1.94 kent const struct usb_audio_processing_unit_updown *ud;
1657 1.16 augustss struct mixerctl mix;
1658 1.16 augustss int i;
1659 1.16 augustss
1660 1.94 kent d = iot[id].d.pu;
1661 1.94 kent d1 = (const struct usb_audio_processing_unit_1 *)
1662 1.94 kent &d->baSourceId[d->bNrInPins];
1663 1.94 kent ud = (const struct usb_audio_processing_unit_updown *)
1664 1.94 kent &d1->bmControls[d1->bControlSize];
1665 1.122 mrg DPRINTFN(2,"bUnitId=%d bNrModes=%d\n",
1666 1.122 mrg d->bUnitId, ud->bNrModes);
1667 1.16 augustss
1668 1.16 augustss if (!(d1->bmControls[0] & UA_PROC_MASK(UD_MODE_SELECT_CONTROL))) {
1669 1.122 mrg DPRINTF("%s", "no mode select\n");
1670 1.16 augustss return;
1671 1.16 augustss }
1672 1.16 augustss
1673 1.16 augustss mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
1674 1.16 augustss mix.nchan = 1;
1675 1.16 augustss mix.wValue[0] = MAKE(UD_MODE_SELECT_CONTROL, 0);
1676 1.82 kent uaudio_determine_class(&iot[id], &mix);
1677 1.16 augustss mix.type = MIX_ON_OFF; /* XXX */
1678 1.16 augustss mix.ctlunit = "";
1679 1.70 itojun snprintf(mix.ctlname, sizeof(mix.ctlname), "pro%d-mode", d->bUnitId);
1680 1.16 augustss
1681 1.16 augustss for (i = 0; i < ud->bNrModes; i++) {
1682 1.164 christos DPRINTFN(2,"i=%d bm=%#x\n",
1683 1.122 mrg i, UGETW(ud->waModes[i]));
1684 1.16 augustss /* XXX */
1685 1.16 augustss }
1686 1.16 augustss uaudio_mixer_add_ctl(sc, &mix);
1687 1.16 augustss }
1688 1.16 augustss
1689 1.86 kent Static void
1690 1.82 kent uaudio_add_processing(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
1691 1.1 augustss {
1692 1.94 kent const struct usb_audio_processing_unit *d;
1693 1.94 kent const struct usb_audio_processing_unit_1 *d1;
1694 1.94 kent int ptype;
1695 1.15 augustss struct mixerctl mix;
1696 1.15 augustss
1697 1.94 kent d = iot[id].d.pu;
1698 1.94 kent d1 = (const struct usb_audio_processing_unit_1 *)
1699 1.94 kent &d->baSourceId[d->bNrInPins];
1700 1.94 kent ptype = UGETW(d->wProcessType);
1701 1.122 mrg DPRINTFN(2,"wProcessType=%d bUnitId=%d "
1702 1.122 mrg "bNrInPins=%d\n", ptype, d->bUnitId, d->bNrInPins);
1703 1.15 augustss
1704 1.15 augustss if (d1->bmControls[0] & UA_PROC_ENABLE_MASK) {
1705 1.15 augustss mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
1706 1.15 augustss mix.nchan = 1;
1707 1.15 augustss mix.wValue[0] = MAKE(XX_ENABLE_CONTROL, 0);
1708 1.82 kent uaudio_determine_class(&iot[id], &mix);
1709 1.15 augustss mix.type = MIX_ON_OFF;
1710 1.15 augustss mix.ctlunit = "";
1711 1.70 itojun snprintf(mix.ctlname, sizeof(mix.ctlname), "pro%d.%d-enable",
1712 1.70 itojun d->bUnitId, ptype);
1713 1.15 augustss uaudio_mixer_add_ctl(sc, &mix);
1714 1.15 augustss }
1715 1.1 augustss
1716 1.15 augustss switch(ptype) {
1717 1.15 augustss case UPDOWNMIX_PROCESS:
1718 1.82 kent uaudio_add_processing_updown(sc, iot, id);
1719 1.16 augustss break;
1720 1.15 augustss case DOLBY_PROLOGIC_PROCESS:
1721 1.15 augustss case P3D_STEREO_EXTENDER_PROCESS:
1722 1.15 augustss case REVERBATION_PROCESS:
1723 1.15 augustss case CHORUS_PROCESS:
1724 1.15 augustss case DYN_RANGE_COMP_PROCESS:
1725 1.15 augustss default:
1726 1.15 augustss #ifdef UAUDIO_DEBUG
1727 1.113 cube aprint_debug(
1728 1.113 cube "uaudio_add_processing: unit %d, type=%d not impl.\n",
1729 1.113 cube d->bUnitId, ptype);
1730 1.1 augustss #endif
1731 1.15 augustss break;
1732 1.15 augustss }
1733 1.1 augustss }
1734 1.1 augustss
1735 1.86 kent Static void
1736 1.175 mlelstv uaudio_add_effect(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
1737 1.175 mlelstv {
1738 1.178 mlelstv
1739 1.178 mlelstv #ifdef UAUDIO_DEBUG
1740 1.178 mlelstv aprint_debug("uaudio_add_effect: not impl.\n");
1741 1.178 mlelstv #endif
1742 1.175 mlelstv }
1743 1.175 mlelstv
1744 1.175 mlelstv Static void
1745 1.82 kent uaudio_add_extension(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
1746 1.1 augustss {
1747 1.94 kent const struct usb_audio_extension_unit *d;
1748 1.94 kent const struct usb_audio_extension_unit_1 *d1;
1749 1.1 augustss struct mixerctl mix;
1750 1.1 augustss
1751 1.94 kent d = iot[id].d.eu;
1752 1.94 kent d1 = (const struct usb_audio_extension_unit_1 *)
1753 1.94 kent &d->baSourceId[d->bNrInPins];
1754 1.122 mrg DPRINTFN(2,"bUnitId=%d bNrInPins=%d\n",
1755 1.122 mrg d->bUnitId, d->bNrInPins);
1756 1.28 augustss
1757 1.31 augustss if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_XU)
1758 1.28 augustss return;
1759 1.1 augustss
1760 1.15 augustss if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) {
1761 1.1 augustss mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
1762 1.1 augustss mix.nchan = 1;
1763 1.1 augustss mix.wValue[0] = MAKE(UA_EXT_ENABLE, 0);
1764 1.82 kent uaudio_determine_class(&iot[id], &mix);
1765 1.1 augustss mix.type = MIX_ON_OFF;
1766 1.1 augustss mix.ctlunit = "";
1767 1.70 itojun snprintf(mix.ctlname, sizeof(mix.ctlname), "ext%d-enable",
1768 1.70 itojun d->bUnitId);
1769 1.1 augustss uaudio_mixer_add_ctl(sc, &mix);
1770 1.1 augustss }
1771 1.1 augustss }
1772 1.1 augustss
1773 1.175 mlelstv Static void
1774 1.175 mlelstv uaudio_add_clksrc(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
1775 1.175 mlelstv {
1776 1.175 mlelstv const struct usb_audio_clksrc_unit *d;
1777 1.175 mlelstv struct mixerctl mix;
1778 1.175 mlelstv
1779 1.175 mlelstv d = iot[id].d.cu;
1780 1.178 mlelstv DPRINTFN(2,"bClockId=%d bmAttributes=%d bmControls=%d bAssocTerminal=%d iClockSource=%d\n",
1781 1.178 mlelstv d->bClockId, d->bmAttributes, d->bmControls, d->bAssocTerminal, d->iClockSource);
1782 1.178 mlelstv mix.wIndex = MAKE(d->bClockId, sc->sc_ac_iface);
1783 1.175 mlelstv uaudio_determine_class(&iot[id], &mix);
1784 1.175 mlelstv mix.nchan = 1;
1785 1.175 mlelstv mix.wValue[0] = MAKE(V2_CUR_CLKFREQ, 0);
1786 1.175 mlelstv mix.type = MIX_UNSIGNED_32;
1787 1.175 mlelstv mix.ctlunit = "";
1788 1.175 mlelstv
1789 1.175 mlelstv uaudio_makename(sc, d->iClockSource, uaudio_clockname(d->bmAttributes),
1790 1.175 mlelstv d->bClockId, mix.ctlname, sizeof(mix.ctlname));
1791 1.175 mlelstv uaudio_mixer_add_ctl(sc, &mix);
1792 1.175 mlelstv }
1793 1.175 mlelstv
1794 1.175 mlelstv Static void
1795 1.175 mlelstv uaudio_add_clksel(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
1796 1.175 mlelstv {
1797 1.175 mlelstv const struct usb_audio_clksel_unit *d;
1798 1.175 mlelstv struct mixerctl mix;
1799 1.175 mlelstv int i, wp;
1800 1.175 mlelstv uByte sel;
1801 1.175 mlelstv
1802 1.175 mlelstv d = iot[id].d.lu;
1803 1.175 mlelstv sel = ((const uByte *)&d->baCSourceId[d->bNrInPins])[2]; /* iClockSelector */
1804 1.176 mlelstv DPRINTFN(2,"bClockId=%d bNrInPins=%d iClockSelector=%d\n",
1805 1.176 mlelstv d->bClockId, d->bNrInPins, sel);
1806 1.175 mlelstv mix.wIndex = MAKE(d->bClockId, sc->sc_ac_iface);
1807 1.175 mlelstv uaudio_determine_class(&iot[id], &mix);
1808 1.175 mlelstv mix.nchan = 1;
1809 1.175 mlelstv mix.wValue[0] = MAKE(V2_CUR_CLKSEL, 0);
1810 1.175 mlelstv mix.type = MIX_SELECTOR;
1811 1.175 mlelstv mix.ctlunit = "";
1812 1.175 mlelstv mix.range0.minval = 1;
1813 1.175 mlelstv mix.range0.maxval = d->bNrInPins;
1814 1.175 mlelstv mix.range0.resval = 1;
1815 1.175 mlelstv mix.mul = mix.range0.maxval - mix.range0.minval;
1816 1.175 mlelstv wp = uaudio_makename(sc, sel, "clksel", d->bClockId, mix.ctlname, MAX_AUDIO_DEV_LEN);
1817 1.175 mlelstv for (i = 1; i <= d->bNrInPins; i++) {
1818 1.175 mlelstv wp += snprintf(mix.ctlname + wp, MAX_AUDIO_DEV_LEN - wp,
1819 1.175 mlelstv "%si%d", i == 1 ? "-" : "", d->baCSourceId[i - 1]);
1820 1.175 mlelstv if (wp > MAX_AUDIO_DEV_LEN - 1)
1821 1.175 mlelstv break;
1822 1.175 mlelstv }
1823 1.175 mlelstv uaudio_mixer_add_ctl(sc, &mix);
1824 1.175 mlelstv }
1825 1.175 mlelstv
1826 1.86 kent Static struct terminal_list*
1827 1.82 kent uaudio_merge_terminal_list(const struct io_terminal *iot)
1828 1.82 kent {
1829 1.82 kent struct terminal_list *tml;
1830 1.82 kent uint16_t *ptm;
1831 1.82 kent int i, len;
1832 1.82 kent
1833 1.82 kent len = 0;
1834 1.82 kent if (iot->inputs == NULL)
1835 1.82 kent return NULL;
1836 1.82 kent for (i = 0; i < iot->inputs_size; i++) {
1837 1.82 kent if (iot->inputs[i] != NULL)
1838 1.82 kent len += iot->inputs[i]->size;
1839 1.82 kent }
1840 1.82 kent tml = malloc(TERMINAL_LIST_SIZE(len), M_TEMP, M_NOWAIT);
1841 1.82 kent if (tml == NULL) {
1842 1.113 cube aprint_error("uaudio_merge_terminal_list: no memory\n");
1843 1.82 kent return NULL;
1844 1.82 kent }
1845 1.82 kent tml->size = 0;
1846 1.82 kent ptm = tml->terminals;
1847 1.82 kent for (i = 0; i < iot->inputs_size; i++) {
1848 1.82 kent if (iot->inputs[i] == NULL)
1849 1.82 kent continue;
1850 1.82 kent if (iot->inputs[i]->size > len)
1851 1.82 kent break;
1852 1.82 kent memcpy(ptm, iot->inputs[i]->terminals,
1853 1.82 kent iot->inputs[i]->size * sizeof(uint16_t));
1854 1.82 kent tml->size += iot->inputs[i]->size;
1855 1.82 kent ptm += iot->inputs[i]->size;
1856 1.82 kent len -= iot->inputs[i]->size;
1857 1.82 kent }
1858 1.82 kent return tml;
1859 1.82 kent }
1860 1.82 kent
1861 1.86 kent Static struct terminal_list *
1862 1.178 mlelstv uaudio_io_terminaltype(struct uaudio_softc *sc, int outtype, struct io_terminal *iot, int id)
1863 1.82 kent {
1864 1.82 kent struct terminal_list *tml;
1865 1.82 kent struct io_terminal *it;
1866 1.82 kent int src_id, i;
1867 1.82 kent
1868 1.82 kent it = &iot[id];
1869 1.82 kent if (it->output != NULL) {
1870 1.82 kent /* already has outtype? */
1871 1.82 kent for (i = 0; i < it->output->size; i++)
1872 1.82 kent if (it->output->terminals[i] == outtype)
1873 1.82 kent return uaudio_merge_terminal_list(it);
1874 1.82 kent tml = malloc(TERMINAL_LIST_SIZE(it->output->size + 1),
1875 1.82 kent M_TEMP, M_NOWAIT);
1876 1.82 kent if (tml == NULL) {
1877 1.113 cube aprint_error("uaudio_io_terminaltype: no memory\n");
1878 1.82 kent return uaudio_merge_terminal_list(it);
1879 1.82 kent }
1880 1.82 kent memcpy(tml, it->output, TERMINAL_LIST_SIZE(it->output->size));
1881 1.82 kent tml->terminals[it->output->size] = outtype;
1882 1.82 kent tml->size++;
1883 1.82 kent free(it->output, M_TEMP);
1884 1.82 kent it->output = tml;
1885 1.82 kent if (it->inputs != NULL) {
1886 1.82 kent for (i = 0; i < it->inputs_size; i++)
1887 1.82 kent if (it->inputs[i] != NULL)
1888 1.82 kent free(it->inputs[i], M_TEMP);
1889 1.82 kent free(it->inputs, M_TEMP);
1890 1.82 kent }
1891 1.82 kent it->inputs_size = 0;
1892 1.82 kent it->inputs = NULL;
1893 1.82 kent } else { /* end `iot[id] != NULL' */
1894 1.82 kent it->inputs_size = 0;
1895 1.82 kent it->inputs = NULL;
1896 1.82 kent it->output = malloc(TERMINAL_LIST_SIZE(1), M_TEMP, M_NOWAIT);
1897 1.82 kent if (it->output == NULL) {
1898 1.113 cube aprint_error("uaudio_io_terminaltype: no memory\n");
1899 1.82 kent return NULL;
1900 1.82 kent }
1901 1.82 kent it->output->terminals[0] = outtype;
1902 1.82 kent it->output->size = 1;
1903 1.82 kent it->direct = FALSE;
1904 1.82 kent }
1905 1.82 kent
1906 1.82 kent switch (it->d.desc->bDescriptorSubtype) {
1907 1.82 kent case UDESCSUB_AC_INPUT:
1908 1.82 kent it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
1909 1.82 kent if (it->inputs == NULL) {
1910 1.113 cube aprint_error("uaudio_io_terminaltype: no memory\n");
1911 1.82 kent return NULL;
1912 1.82 kent }
1913 1.82 kent tml = malloc(TERMINAL_LIST_SIZE(1), M_TEMP, M_NOWAIT);
1914 1.82 kent if (tml == NULL) {
1915 1.113 cube aprint_error("uaudio_io_terminaltype: no memory\n");
1916 1.82 kent free(it->inputs, M_TEMP);
1917 1.82 kent it->inputs = NULL;
1918 1.82 kent return NULL;
1919 1.82 kent }
1920 1.82 kent it->inputs[0] = tml;
1921 1.178 mlelstv switch (sc->sc_version) {
1922 1.178 mlelstv case UAUDIO_VERSION1:
1923 1.178 mlelstv tml->terminals[0] = UGETW(it->d.it->v1.wTerminalType);
1924 1.178 mlelstv break;
1925 1.178 mlelstv case UAUDIO_VERSION2:
1926 1.178 mlelstv tml->terminals[0] = UGETW(it->d.it->v2.wTerminalType);
1927 1.178 mlelstv break;
1928 1.178 mlelstv default:
1929 1.178 mlelstv free(tml, M_TEMP);
1930 1.178 mlelstv free(it->inputs, M_TEMP);
1931 1.178 mlelstv it->inputs = NULL;
1932 1.178 mlelstv return NULL;
1933 1.178 mlelstv }
1934 1.82 kent tml->size = 1;
1935 1.82 kent it->inputs_size = 1;
1936 1.82 kent return uaudio_merge_terminal_list(it);
1937 1.82 kent case UDESCSUB_AC_FEATURE:
1938 1.179 mlelstv switch (sc->sc_version) {
1939 1.179 mlelstv case UAUDIO_VERSION1:
1940 1.179 mlelstv src_id = it->d.fu->v1.bSourceId;
1941 1.179 mlelstv break;
1942 1.179 mlelstv case UAUDIO_VERSION2:
1943 1.179 mlelstv src_id = it->d.fu->v2.bSourceId;
1944 1.179 mlelstv break;
1945 1.179 mlelstv default:
1946 1.179 mlelstv /* cannot happen */
1947 1.179 mlelstv return NULL;
1948 1.179 mlelstv }
1949 1.82 kent it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
1950 1.82 kent if (it->inputs == NULL) {
1951 1.113 cube aprint_error("uaudio_io_terminaltype: no memory\n");
1952 1.178 mlelstv return uaudio_io_terminaltype(sc, outtype, iot, src_id);
1953 1.82 kent }
1954 1.178 mlelstv it->inputs[0] = uaudio_io_terminaltype(sc, outtype, iot, src_id);
1955 1.82 kent it->inputs_size = 1;
1956 1.82 kent return uaudio_merge_terminal_list(it);
1957 1.82 kent case UDESCSUB_AC_OUTPUT:
1958 1.82 kent it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
1959 1.82 kent if (it->inputs == NULL) {
1960 1.113 cube aprint_error("uaudio_io_terminaltype: no memory\n");
1961 1.82 kent return NULL;
1962 1.82 kent }
1963 1.178 mlelstv switch (sc->sc_version) {
1964 1.178 mlelstv case UAUDIO_VERSION1:
1965 1.178 mlelstv src_id = it->d.ot->v1.bSourceId;
1966 1.178 mlelstv break;
1967 1.178 mlelstv case UAUDIO_VERSION2:
1968 1.178 mlelstv src_id = it->d.ot->v2.bSourceId;
1969 1.178 mlelstv break;
1970 1.178 mlelstv default:
1971 1.178 mlelstv free(it->inputs, M_TEMP);
1972 1.178 mlelstv it->inputs = NULL;
1973 1.178 mlelstv return NULL;
1974 1.178 mlelstv }
1975 1.178 mlelstv it->inputs[0] = uaudio_io_terminaltype(sc, outtype, iot, src_id);
1976 1.82 kent it->inputs_size = 1;
1977 1.82 kent iot[src_id].direct = TRUE;
1978 1.82 kent return NULL;
1979 1.82 kent case UDESCSUB_AC_MIXER:
1980 1.82 kent it->inputs_size = 0;
1981 1.82 kent it->inputs = malloc(sizeof(struct terminal_list *)
1982 1.82 kent * it->d.mu->bNrInPins, M_TEMP, M_NOWAIT);
1983 1.82 kent if (it->inputs == NULL) {
1984 1.113 cube aprint_error("uaudio_io_terminaltype: no memory\n");
1985 1.82 kent return NULL;
1986 1.82 kent }
1987 1.82 kent for (i = 0; i < it->d.mu->bNrInPins; i++) {
1988 1.82 kent src_id = it->d.mu->baSourceId[i];
1989 1.178 mlelstv it->inputs[i] = uaudio_io_terminaltype(sc, outtype, iot,
1990 1.82 kent src_id);
1991 1.82 kent it->inputs_size++;
1992 1.82 kent }
1993 1.82 kent return uaudio_merge_terminal_list(it);
1994 1.82 kent case UDESCSUB_AC_SELECTOR:
1995 1.82 kent it->inputs_size = 0;
1996 1.82 kent it->inputs = malloc(sizeof(struct terminal_list *)
1997 1.82 kent * it->d.su->bNrInPins, M_TEMP, M_NOWAIT);
1998 1.82 kent if (it->inputs == NULL) {
1999 1.113 cube aprint_error("uaudio_io_terminaltype: no memory\n");
2000 1.82 kent return NULL;
2001 1.82 kent }
2002 1.82 kent for (i = 0; i < it->d.su->bNrInPins; i++) {
2003 1.82 kent src_id = it->d.su->baSourceId[i];
2004 1.178 mlelstv it->inputs[i] = uaudio_io_terminaltype(sc, outtype, iot,
2005 1.82 kent src_id);
2006 1.82 kent it->inputs_size++;
2007 1.82 kent }
2008 1.82 kent return uaudio_merge_terminal_list(it);
2009 1.82 kent case UDESCSUB_AC_PROCESSING:
2010 1.82 kent it->inputs_size = 0;
2011 1.82 kent it->inputs = malloc(sizeof(struct terminal_list *)
2012 1.82 kent * it->d.pu->bNrInPins, M_TEMP, M_NOWAIT);
2013 1.82 kent if (it->inputs == NULL) {
2014 1.113 cube aprint_error("uaudio_io_terminaltype: no memory\n");
2015 1.82 kent return NULL;
2016 1.82 kent }
2017 1.82 kent for (i = 0; i < it->d.pu->bNrInPins; i++) {
2018 1.82 kent src_id = it->d.pu->baSourceId[i];
2019 1.178 mlelstv it->inputs[i] = uaudio_io_terminaltype(sc, outtype, iot,
2020 1.82 kent src_id);
2021 1.82 kent it->inputs_size++;
2022 1.82 kent }
2023 1.82 kent return uaudio_merge_terminal_list(it);
2024 1.82 kent case UDESCSUB_AC_EXTENSION:
2025 1.82 kent it->inputs_size = 0;
2026 1.82 kent it->inputs = malloc(sizeof(struct terminal_list *)
2027 1.82 kent * it->d.eu->bNrInPins, M_TEMP, M_NOWAIT);
2028 1.82 kent if (it->inputs == NULL) {
2029 1.113 cube aprint_error("uaudio_io_terminaltype: no memory\n");
2030 1.82 kent return NULL;
2031 1.82 kent }
2032 1.82 kent for (i = 0; i < it->d.eu->bNrInPins; i++) {
2033 1.82 kent src_id = it->d.eu->baSourceId[i];
2034 1.178 mlelstv it->inputs[i] = uaudio_io_terminaltype(sc, outtype, iot,
2035 1.82 kent src_id);
2036 1.82 kent it->inputs_size++;
2037 1.82 kent }
2038 1.82 kent return uaudio_merge_terminal_list(it);
2039 1.82 kent case UDESCSUB_AC_HEADER:
2040 1.82 kent default:
2041 1.82 kent return NULL;
2042 1.82 kent }
2043 1.82 kent }
2044 1.82 kent
2045 1.86 kent Static usbd_status
2046 1.78 kent uaudio_identify(struct uaudio_softc *sc, const usb_config_descriptor_t *cdesc)
2047 1.1 augustss {
2048 1.9 augustss usbd_status err;
2049 1.1 augustss
2050 1.9 augustss err = uaudio_identify_ac(sc, cdesc);
2051 1.9 augustss if (err)
2052 1.94 kent return err;
2053 1.175 mlelstv err = uaudio_identify_as(sc, cdesc);
2054 1.175 mlelstv if (err)
2055 1.175 mlelstv return err;
2056 1.175 mlelstv
2057 1.175 mlelstv uaudio_build_formats(sc);
2058 1.175 mlelstv return 0;
2059 1.1 augustss }
2060 1.1 augustss
2061 1.86 kent Static void
2062 1.78 kent uaudio_add_alt(struct uaudio_softc *sc, const struct as_info *ai)
2063 1.1 augustss {
2064 1.84 kent size_t len;
2065 1.84 kent struct as_info *nai;
2066 1.42 christos
2067 1.84 kent len = sizeof(*ai) * (sc->sc_nalts + 1);
2068 1.146 skrll nai = kmem_alloc(len, KM_SLEEP);
2069 1.84 kent /* Copy old data, if there was any */
2070 1.84 kent if (sc->sc_nalts != 0) {
2071 1.84 kent memcpy(nai, sc->sc_alts, sizeof(*ai) * (sc->sc_nalts));
2072 1.146 skrll kmem_free(sc->sc_alts, sizeof(*ai) * sc->sc_nalts);
2073 1.84 kent }
2074 1.42 christos sc->sc_alts = nai;
2075 1.122 mrg DPRINTFN(2,"adding alt=%d, enc=%d\n",
2076 1.122 mrg ai->alt, ai->encoding);
2077 1.1 augustss sc->sc_alts[sc->sc_nalts++] = *ai;
2078 1.1 augustss }
2079 1.1 augustss
2080 1.86 kent Static usbd_status
2081 1.99 christos uaudio_process_as(struct uaudio_softc *sc, const char *tbuf, int *offsp,
2082 1.78 kent int size, const usb_interface_descriptor_t *id)
2083 1.1 augustss {
2084 1.175 mlelstv const union usb_audio_streaming_interface_descriptor *asid;
2085 1.175 mlelstv const union usb_audio_streaming_type1_descriptor *asf1d;
2086 1.78 kent const usb_endpoint_descriptor_audio_t *ed;
2087 1.80 kent const usb_endpoint_descriptor_audio_t *epdesc1;
2088 1.78 kent const struct usb_audio_streaming_endpoint_descriptor *sed;
2089 1.179 mlelstv int format, chan __unused, prec, bps, enc, terminal;
2090 1.172 mlelstv int dir, type, sync, epcount;
2091 1.1 augustss struct as_info ai;
2092 1.138 martin const char *format_str __unused;
2093 1.172 mlelstv const uaudio_cs_descriptor_t *desc;
2094 1.172 mlelstv
2095 1.172 mlelstv DPRINTF("offset = %d < %d\n", *offsp, size);
2096 1.172 mlelstv
2097 1.172 mlelstv epcount = 0;
2098 1.172 mlelstv asid = NULL;
2099 1.172 mlelstv asf1d = NULL;
2100 1.172 mlelstv ed = NULL;
2101 1.172 mlelstv epdesc1 = NULL;
2102 1.172 mlelstv sed = NULL;
2103 1.1 augustss
2104 1.172 mlelstv while (*offsp < size) {
2105 1.172 mlelstv desc = (const uaudio_cs_descriptor_t *)(tbuf + *offsp);
2106 1.172 mlelstv if (*offsp + desc->bLength > size)
2107 1.172 mlelstv return USBD_INVAL;
2108 1.78 kent
2109 1.172 mlelstv switch (desc->bDescriptorType) {
2110 1.172 mlelstv case UDESC_CS_INTERFACE:
2111 1.172 mlelstv switch (desc->bDescriptorSubtype) {
2112 1.172 mlelstv case AS_GENERAL:
2113 1.172 mlelstv if (asid != NULL)
2114 1.172 mlelstv goto ignore;
2115 1.175 mlelstv asid = (const union usb_audio_streaming_interface_descriptor *) desc;
2116 1.176 mlelstv DPRINTF("asid: bTerminalLink=%d wFormatTag=%d bmFormats=0x%x bLength=%d\n",
2117 1.175 mlelstv asid->v1.bTerminalLink, UGETW(asid->v1.wFormatTag),
2118 1.176 mlelstv UGETDW(asid->v2.bmFormats), asid->v1.bLength);
2119 1.172 mlelstv break;
2120 1.172 mlelstv case FORMAT_TYPE:
2121 1.172 mlelstv if (asf1d != NULL)
2122 1.172 mlelstv goto ignore;
2123 1.175 mlelstv asf1d = (const union usb_audio_streaming_type1_descriptor *) desc;
2124 1.172 mlelstv DPRINTF("asf1d: bDescriptorType=%d bDescriptorSubtype=%d\n",
2125 1.175 mlelstv asf1d->v1.bDescriptorType, asf1d->v1.bDescriptorSubtype);
2126 1.175 mlelstv if (asf1d->v1.bFormatType != FORMAT_TYPE_I) {
2127 1.172 mlelstv aprint_normal_dev(sc->sc_dev,
2128 1.175 mlelstv "ignored setting with type %d format\n", asf1d->v1.bFormatType);
2129 1.172 mlelstv return USBD_NORMAL_COMPLETION;
2130 1.172 mlelstv }
2131 1.172 mlelstv break;
2132 1.172 mlelstv default:
2133 1.172 mlelstv goto ignore;
2134 1.172 mlelstv }
2135 1.172 mlelstv break;
2136 1.172 mlelstv case UDESC_ENDPOINT:
2137 1.172 mlelstv epcount++;
2138 1.172 mlelstv if (epcount > id->bNumEndpoints)
2139 1.172 mlelstv goto ignore;
2140 1.172 mlelstv switch (epcount) {
2141 1.172 mlelstv case 1:
2142 1.172 mlelstv ed = (const usb_endpoint_descriptor_audio_t *) desc;
2143 1.172 mlelstv DPRINTF("endpoint[0] bLength=%d bDescriptorType=%d "
2144 1.172 mlelstv "bEndpointAddress=%d bmAttributes=%#x wMaxPacketSize=%d "
2145 1.172 mlelstv "bInterval=%d bRefresh=%d bSynchAddress=%d\n",
2146 1.172 mlelstv ed->bLength, ed->bDescriptorType, ed->bEndpointAddress,
2147 1.172 mlelstv ed->bmAttributes, UGETW(ed->wMaxPacketSize),
2148 1.179 mlelstv ed->bInterval,
2149 1.179 mlelstv ed->bLength > 7 ? ed->bRefresh : 0,
2150 1.179 mlelstv ed->bLength > 8 ? ed->bSynchAddress : 0);
2151 1.172 mlelstv if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
2152 1.172 mlelstv return USBD_INVAL;
2153 1.172 mlelstv break;
2154 1.172 mlelstv case 2:
2155 1.172 mlelstv epdesc1 = (const usb_endpoint_descriptor_audio_t *) desc;
2156 1.172 mlelstv DPRINTF("endpoint[1] bLength=%d "
2157 1.172 mlelstv "bDescriptorType=%d bEndpointAddress=%d "
2158 1.172 mlelstv "bmAttributes=%#x wMaxPacketSize=%d bInterval=%d "
2159 1.172 mlelstv "bRefresh=%d bSynchAddress=%d\n",
2160 1.172 mlelstv epdesc1->bLength, epdesc1->bDescriptorType,
2161 1.172 mlelstv epdesc1->bEndpointAddress, epdesc1->bmAttributes,
2162 1.172 mlelstv UGETW(epdesc1->wMaxPacketSize), epdesc1->bInterval,
2163 1.179 mlelstv epdesc1->bLength > 7 ? epdesc1->bRefresh : 0,
2164 1.179 mlelstv epdesc1->bLength > 8 ? epdesc1->bSynchAddress : 0);
2165 1.175 mlelstv #if 0
2166 1.179 mlelstv if (epdesc1->bLength > 8 && epdesc1->bSynchAddress != 0) {
2167 1.172 mlelstv aprint_error_dev(sc->sc_dev,
2168 1.172 mlelstv "invalid endpoint: bSynchAddress=0\n");
2169 1.172 mlelstv return USBD_INVAL;
2170 1.172 mlelstv }
2171 1.175 mlelstv #endif
2172 1.172 mlelstv if (UE_GET_XFERTYPE(epdesc1->bmAttributes) != UE_ISOCHRONOUS) {
2173 1.172 mlelstv aprint_error_dev(sc->sc_dev,
2174 1.172 mlelstv "invalid endpoint: bmAttributes=%#x\n",
2175 1.172 mlelstv epdesc1->bmAttributes);
2176 1.172 mlelstv return USBD_INVAL;
2177 1.172 mlelstv }
2178 1.175 mlelstv #if 0
2179 1.179 mlelstv if (ed->bLength > 8 && epdesc1->bEndpointAddress != ed->bSynchAddress) {
2180 1.172 mlelstv aprint_error_dev(sc->sc_dev,
2181 1.172 mlelstv "invalid endpoint addresses: "
2182 1.172 mlelstv "ep[0]->bSynchAddress=%#x "
2183 1.172 mlelstv "ep[1]->bEndpointAddress=%#x\n",
2184 1.172 mlelstv ed->bSynchAddress, epdesc1->bEndpointAddress);
2185 1.172 mlelstv return USBD_INVAL;
2186 1.172 mlelstv }
2187 1.175 mlelstv #endif
2188 1.172 mlelstv /* UE_GET_ADDR(epdesc1->bEndpointAddress), and epdesc1->bRefresh */
2189 1.172 mlelstv break;
2190 1.172 mlelstv default:
2191 1.172 mlelstv goto ignore;
2192 1.172 mlelstv }
2193 1.172 mlelstv break;
2194 1.172 mlelstv case UDESC_CS_ENDPOINT:
2195 1.172 mlelstv switch (desc->bDescriptorSubtype) {
2196 1.172 mlelstv case AS_GENERAL:
2197 1.172 mlelstv if (sed != NULL)
2198 1.172 mlelstv goto ignore;
2199 1.172 mlelstv sed = (const struct usb_audio_streaming_endpoint_descriptor *) desc;
2200 1.172 mlelstv DPRINTF(" streadming_endpoint: offset=%d bLength=%d\n", *offsp, sed->bLength);
2201 1.172 mlelstv break;
2202 1.172 mlelstv default:
2203 1.172 mlelstv goto ignore;
2204 1.172 mlelstv }
2205 1.172 mlelstv break;
2206 1.172 mlelstv case UDESC_INTERFACE:
2207 1.172 mlelstv case UDESC_DEVICE:
2208 1.172 mlelstv goto leave;
2209 1.172 mlelstv default:
2210 1.172 mlelstv ignore:
2211 1.172 mlelstv aprint_normal_dev(sc->sc_dev,
2212 1.172 mlelstv "ignored descriptor type %d subtype %d\n",
2213 1.172 mlelstv desc->bDescriptorType, desc->bDescriptorSubtype);
2214 1.172 mlelstv break;
2215 1.172 mlelstv }
2216 1.1 augustss
2217 1.172 mlelstv *offsp += desc->bLength;
2218 1.3 augustss }
2219 1.172 mlelstv leave:
2220 1.3 augustss
2221 1.172 mlelstv if (asid == NULL) {
2222 1.172 mlelstv DPRINTF("%s", "No streaming interface descriptor found\n");
2223 1.172 mlelstv return USBD_INVAL;
2224 1.172 mlelstv }
2225 1.172 mlelstv if (asf1d == NULL) {
2226 1.172 mlelstv DPRINTF("%s", "No format type descriptor found\n");
2227 1.94 kent return USBD_INVAL;
2228 1.172 mlelstv }
2229 1.172 mlelstv if (ed == NULL) {
2230 1.172 mlelstv DPRINTF("%s", "No endpoint descriptor found\n");
2231 1.94 kent return USBD_INVAL;
2232 1.172 mlelstv }
2233 1.172 mlelstv if (sed == NULL) {
2234 1.172 mlelstv DPRINTF("%s", "No streaming endpoint descriptor found\n");
2235 1.94 kent return USBD_INVAL;
2236 1.172 mlelstv }
2237 1.5 augustss
2238 1.5 augustss dir = UE_GET_DIR(ed->bEndpointAddress);
2239 1.5 augustss type = UE_GET_ISO_TYPE(ed->bmAttributes);
2240 1.31 augustss if ((usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_INP_ASYNC) &&
2241 1.31 augustss dir == UE_DIR_IN && type == UE_ISO_ADAPT)
2242 1.31 augustss type = UE_ISO_ASYNC;
2243 1.40 augustss /* We can't handle endpoints that need a sync pipe yet. */
2244 1.80 kent sync = FALSE;
2245 1.78 kent if (dir == UE_DIR_IN && type == UE_ISO_ADAPT) {
2246 1.80 kent sync = TRUE;
2247 1.80 kent #ifndef UAUDIO_MULTIPLE_ENDPOINTS
2248 1.156 nakayama aprint_normal_dev(sc->sc_dev,
2249 1.113 cube "ignored input endpoint of type adaptive\n");
2250 1.94 kent return USBD_NORMAL_COMPLETION;
2251 1.80 kent #endif
2252 1.78 kent }
2253 1.78 kent if (dir != UE_DIR_IN && type == UE_ISO_ASYNC) {
2254 1.80 kent sync = TRUE;
2255 1.80 kent #ifndef UAUDIO_MULTIPLE_ENDPOINTS
2256 1.156 nakayama aprint_normal_dev(sc->sc_dev,
2257 1.113 cube "ignored output endpoint of type async\n");
2258 1.94 kent return USBD_NORMAL_COMPLETION;
2259 1.80 kent #endif
2260 1.1 augustss }
2261 1.102 christos #ifdef UAUDIO_MULTIPLE_ENDPOINTS
2262 1.80 kent if (sync && id->bNumEndpoints <= 1) {
2263 1.113 cube aprint_error_dev(sc->sc_dev,
2264 1.113 cube "a sync-pipe endpoint but no other endpoint\n");
2265 1.80 kent return USBD_INVAL;
2266 1.80 kent }
2267 1.102 christos #endif
2268 1.80 kent if (!sync && id->bNumEndpoints > 1) {
2269 1.113 cube aprint_error_dev(sc->sc_dev,
2270 1.113 cube "non sync-pipe endpoint but multiple endpoints\n");
2271 1.80 kent return USBD_INVAL;
2272 1.80 kent }
2273 1.80 kent
2274 1.175 mlelstv switch (sc->sc_version) {
2275 1.175 mlelstv case UAUDIO_VERSION1:
2276 1.175 mlelstv format = UGETW(asid->v1.wFormatTag);
2277 1.175 mlelstv chan = asf1d->v1.bNrChannels;
2278 1.175 mlelstv prec = asf1d->v1.bBitResolution;
2279 1.175 mlelstv bps = asf1d->v1.bSubFrameSize;
2280 1.175 mlelstv break;
2281 1.175 mlelstv case UAUDIO_VERSION2:
2282 1.175 mlelstv format = UGETDW(asid->v2.bmFormats);
2283 1.175 mlelstv chan = asid->v2.bNrChannels;
2284 1.175 mlelstv prec = asf1d->v2.bBitResolution;
2285 1.175 mlelstv bps = asf1d->v2.bSubslotSize;
2286 1.175 mlelstv break;
2287 1.175 mlelstv default:
2288 1.175 mlelstv aprint_error_dev(sc->sc_dev,
2289 1.175 mlelstv "Unknown audio class %d\n", sc->sc_version);
2290 1.175 mlelstv return USBD_INVAL;
2291 1.175 mlelstv }
2292 1.175 mlelstv if ((prec != 8 && prec != 16 && prec != 24 && prec != 32) || (bps < 1 || bps > 4)) {
2293 1.156 nakayama aprint_normal_dev(sc->sc_dev,
2294 1.175 mlelstv "ignored setting with precision %d bps %d\n", prec, bps);
2295 1.94 kent return USBD_NORMAL_COMPLETION;
2296 1.1 augustss }
2297 1.175 mlelstv enc = AUDIO_ENCODING_NONE;
2298 1.175 mlelstv switch (sc->sc_version) {
2299 1.175 mlelstv case UAUDIO_VERSION1:
2300 1.179 mlelstv terminal = 0;
2301 1.175 mlelstv switch (format) {
2302 1.175 mlelstv case UA_FMT_PCM:
2303 1.175 mlelstv if (prec == 8) {
2304 1.175 mlelstv sc->sc_altflags |= HAS_8;
2305 1.175 mlelstv } else if (prec == 16) {
2306 1.175 mlelstv sc->sc_altflags |= HAS_16;
2307 1.175 mlelstv } else if (prec == 24) {
2308 1.175 mlelstv sc->sc_altflags |= HAS_24;
2309 1.175 mlelstv } else if (prec == 32) {
2310 1.175 mlelstv sc->sc_altflags |= HAS_32;
2311 1.175 mlelstv }
2312 1.175 mlelstv enc = AUDIO_ENCODING_SLINEAR_LE;
2313 1.175 mlelstv format_str = "pcm";
2314 1.175 mlelstv break;
2315 1.175 mlelstv case UA_FMT_PCM8:
2316 1.175 mlelstv enc = AUDIO_ENCODING_ULINEAR_LE;
2317 1.175 mlelstv sc->sc_altflags |= HAS_8U;
2318 1.175 mlelstv format_str = "pcm8";
2319 1.175 mlelstv break;
2320 1.175 mlelstv case UA_FMT_ALAW:
2321 1.175 mlelstv enc = AUDIO_ENCODING_ALAW;
2322 1.175 mlelstv sc->sc_altflags |= HAS_ALAW;
2323 1.175 mlelstv format_str = "alaw";
2324 1.175 mlelstv break;
2325 1.175 mlelstv case UA_FMT_MULAW:
2326 1.175 mlelstv enc = AUDIO_ENCODING_ULAW;
2327 1.175 mlelstv sc->sc_altflags |= HAS_MULAW;
2328 1.175 mlelstv format_str = "mulaw";
2329 1.175 mlelstv break;
2330 1.175 mlelstv #ifdef notyet
2331 1.175 mlelstv case UA_FMT_IEEE_FLOAT:
2332 1.175 mlelstv break;
2333 1.175 mlelstv #endif
2334 1.51 kent }
2335 1.1 augustss break;
2336 1.175 mlelstv case UAUDIO_VERSION2:
2337 1.179 mlelstv terminal = asid->v2.bTerminalLink;
2338 1.175 mlelstv if (format & UA_V2_FMT_PCM) {
2339 1.175 mlelstv if (prec == 8) {
2340 1.175 mlelstv sc->sc_altflags |= HAS_8;
2341 1.175 mlelstv } else if (prec == 16) {
2342 1.175 mlelstv sc->sc_altflags |= HAS_16;
2343 1.175 mlelstv } else if (prec == 24) {
2344 1.175 mlelstv sc->sc_altflags |= HAS_24;
2345 1.175 mlelstv } else if (prec == 32) {
2346 1.175 mlelstv sc->sc_altflags |= HAS_32;
2347 1.175 mlelstv }
2348 1.175 mlelstv enc = AUDIO_ENCODING_SLINEAR_LE;
2349 1.175 mlelstv format_str = "pcm";
2350 1.175 mlelstv } else if (format & UA_V2_FMT_PCM8) {
2351 1.175 mlelstv enc = AUDIO_ENCODING_ULINEAR_LE;
2352 1.175 mlelstv sc->sc_altflags |= HAS_8U;
2353 1.175 mlelstv format_str = "pcm8";
2354 1.175 mlelstv } else if (format & UA_V2_FMT_ALAW) {
2355 1.175 mlelstv enc = AUDIO_ENCODING_ALAW;
2356 1.175 mlelstv sc->sc_altflags |= HAS_ALAW;
2357 1.175 mlelstv format_str = "alaw";
2358 1.175 mlelstv } else if (format & UA_V2_FMT_MULAW) {
2359 1.175 mlelstv enc = AUDIO_ENCODING_ULAW;
2360 1.175 mlelstv sc->sc_altflags |= HAS_MULAW;
2361 1.175 mlelstv format_str = "mulaw";
2362 1.175 mlelstv #ifdef notyet
2363 1.175 mlelstv } else if (format & UA_V2_FMT_IEEE_FLOAT) {
2364 1.175 mlelstv #endif
2365 1.175 mlelstv }
2366 1.1 augustss break;
2367 1.175 mlelstv }
2368 1.175 mlelstv if (enc == AUDIO_ENCODING_NONE) {
2369 1.156 nakayama aprint_normal_dev(sc->sc_dev,
2370 1.175 mlelstv "ignored setting with format 0x%08x\n", format);
2371 1.94 kent return USBD_NORMAL_COMPLETION;
2372 1.1 augustss }
2373 1.78 kent #ifdef UAUDIO_DEBUG
2374 1.179 mlelstv aprint_debug_dev(sc->sc_dev, "%s: %dch, %d/%dbit, %s,",
2375 1.179 mlelstv dir == UE_DIR_IN ? "recording" : "playback",
2376 1.179 mlelstv chan, prec, bps * 8, format_str);
2377 1.176 mlelstv switch (sc->sc_version) {
2378 1.176 mlelstv case UAUDIO_VERSION1:
2379 1.176 mlelstv if (asf1d->v1.bSamFreqType == UA_SAMP_CONTINUOUS) {
2380 1.176 mlelstv aprint_debug(" %d-%dHz\n", UA_SAMP_LO(&asf1d->v1),
2381 1.176 mlelstv UA_SAMP_HI(&asf1d->v1));
2382 1.176 mlelstv } else {
2383 1.176 mlelstv int r;
2384 1.176 mlelstv aprint_debug(" %d", UA_GETSAMP(&asf1d->v1, 0));
2385 1.176 mlelstv for (r = 1; r < asf1d->v1.bSamFreqType; r++)
2386 1.176 mlelstv aprint_debug(",%d", UA_GETSAMP(&asf1d->v1, r));
2387 1.176 mlelstv aprint_debug("Hz\n");
2388 1.176 mlelstv }
2389 1.176 mlelstv break;
2390 1.179 mlelstv /* UAUDIO_VERSION2 has no frequency information in the format */
2391 1.78 kent }
2392 1.78 kent #endif
2393 1.1 augustss ai.alt = id->bAlternateSetting;
2394 1.1 augustss ai.encoding = enc;
2395 1.50 kent ai.attributes = sed->bmAttributes;
2396 1.1 augustss ai.idesc = id;
2397 1.1 augustss ai.edesc = ed;
2398 1.80 kent ai.edesc1 = epdesc1;
2399 1.1 augustss ai.asf1desc = asf1d;
2400 1.50 kent ai.sc_busy = 0;
2401 1.175 mlelstv ai.nchan = chan;
2402 1.103 mrg ai.aformat = NULL;
2403 1.103 mrg ai.ifaceh = NULL;
2404 1.179 mlelstv ai.terminal = terminal;
2405 1.1 augustss uaudio_add_alt(sc, &ai);
2406 1.50 kent #ifdef UAUDIO_DEBUG
2407 1.78 kent if (ai.attributes & UA_SED_FREQ_CONTROL)
2408 1.122 mrg DPRINTFN(1, "%s", "FREQ_CONTROL\n");
2409 1.78 kent if (ai.attributes & UA_SED_PITCH_CONTROL)
2410 1.122 mrg DPRINTFN(1, "%s", "PITCH_CONTROL\n");
2411 1.50 kent #endif
2412 1.47 jdolecek sc->sc_mode |= (dir == UE_DIR_OUT) ? AUMODE_PLAY : AUMODE_RECORD;
2413 1.47 jdolecek
2414 1.94 kent return USBD_NORMAL_COMPLETION;
2415 1.1 augustss }
2416 1.56 kent
2417 1.86 kent Static usbd_status
2418 1.78 kent uaudio_identify_as(struct uaudio_softc *sc,
2419 1.78 kent const usb_config_descriptor_t *cdesc)
2420 1.1 augustss {
2421 1.78 kent const usb_interface_descriptor_t *id;
2422 1.99 christos const char *tbuf;
2423 1.1 augustss int size, offs;
2424 1.1 augustss
2425 1.1 augustss size = UGETW(cdesc->wTotalLength);
2426 1.99 christos tbuf = (const char *)cdesc;
2427 1.1 augustss
2428 1.1 augustss /* Locate the AudioStreaming interface descriptor. */
2429 1.1 augustss offs = 0;
2430 1.99 christos id = uaudio_find_iface(tbuf, size, &offs, UISUBCLASS_AUDIOSTREAM);
2431 1.9 augustss if (id == NULL)
2432 1.94 kent return USBD_INVAL;
2433 1.1 augustss
2434 1.1 augustss /* Loop through all the alternate settings. */
2435 1.1 augustss while (offs <= size) {
2436 1.122 mrg DPRINTFN(2, "interface=%d offset=%d\n",
2437 1.122 mrg id->bInterfaceNumber, offs);
2438 1.1 augustss switch (id->bNumEndpoints) {
2439 1.1 augustss case 0:
2440 1.122 mrg DPRINTFN(2, "AS null alt=%d\n",
2441 1.122 mrg id->bAlternateSetting);
2442 1.1 augustss sc->sc_nullalt = id->bAlternateSetting;
2443 1.1 augustss break;
2444 1.1 augustss case 1:
2445 1.80 kent #ifdef UAUDIO_MULTIPLE_ENDPOINTS
2446 1.80 kent case 2:
2447 1.80 kent #endif
2448 1.99 christos uaudio_process_as(sc, tbuf, &offs, size, id);
2449 1.1 augustss break;
2450 1.1 augustss default:
2451 1.113 cube aprint_error_dev(sc->sc_dev,
2452 1.113 cube "ignored audio interface with %d endpoints\n",
2453 1.113 cube id->bNumEndpoints);
2454 1.1 augustss break;
2455 1.1 augustss }
2456 1.168 ryoon id = uaudio_find_iface(tbuf, size, &offs, UISUBCLASS_AUDIOSTREAM);
2457 1.9 augustss if (id == NULL)
2458 1.1 augustss break;
2459 1.1 augustss }
2460 1.1 augustss if (offs > size)
2461 1.94 kent return USBD_INVAL;
2462 1.122 mrg DPRINTF("%d alts available\n", sc->sc_nalts);
2463 1.47 jdolecek
2464 1.74 mycroft if (sc->sc_mode == 0) {
2465 1.113 cube aprint_error_dev(sc->sc_dev, "no usable endpoint found\n");
2466 1.94 kent return USBD_INVAL;
2467 1.5 augustss }
2468 1.47 jdolecek
2469 1.175 mlelstv if (sc->sc_nalts == 0) {
2470 1.175 mlelstv aprint_error_dev(sc->sc_dev, "no audio formats found\n");
2471 1.175 mlelstv return USBD_INVAL;
2472 1.175 mlelstv }
2473 1.175 mlelstv
2474 1.175 mlelstv return USBD_NORMAL_COMPLETION;
2475 1.175 mlelstv }
2476 1.175 mlelstv
2477 1.175 mlelstv
2478 1.175 mlelstv Static u_int
2479 1.178 mlelstv uaudio_get_rates(struct uaudio_softc *sc, int mode, u_int *freqs, u_int len)
2480 1.175 mlelstv {
2481 1.175 mlelstv struct mixerctl *mc;
2482 1.180 mlelstv u_int freq, start, end, step;
2483 1.180 mlelstv u_int i, n;
2484 1.180 mlelstv u_int k, count;
2485 1.180 mlelstv int j;
2486 1.175 mlelstv
2487 1.180 mlelstv /*
2488 1.180 mlelstv * With UAC2 the sample rate isn't part of the data format,
2489 1.180 mlelstv * instead, you have separate clock sources that may be
2490 1.180 mlelstv * assigned to individual terminals (inputs, outputs).
2491 1.180 mlelstv *
2492 1.180 mlelstv * For audio(4) we only distinguish between input and output
2493 1.180 mlelstv * formats and collect the unique rates from all possible clock
2494 1.180 mlelstv * sources.
2495 1.180 mlelstv */
2496 1.175 mlelstv n = 0;
2497 1.175 mlelstv for (j = 0; j < sc->sc_nratectls; ++j) {
2498 1.178 mlelstv
2499 1.178 mlelstv /*
2500 1.178 mlelstv * skip rates not associated with a terminal
2501 1.178 mlelstv * of the required mode (record/play)
2502 1.178 mlelstv */
2503 1.178 mlelstv if ((sc->sc_ratemode[j] & mode) == 0)
2504 1.178 mlelstv continue;
2505 1.178 mlelstv
2506 1.175 mlelstv mc = &sc->sc_ctls[sc->sc_ratectls[j]];
2507 1.175 mlelstv count = mc->nranges ? mc->nranges : 1;
2508 1.175 mlelstv for (k = 0; k < count; ++k) {
2509 1.175 mlelstv start = (u_int) mc->ranges[k].minval;
2510 1.175 mlelstv end = (u_int) mc->ranges[k].maxval;
2511 1.175 mlelstv step = (u_int) mc->ranges[k].resval;
2512 1.175 mlelstv for (freq = start; freq <= end; freq += step) {
2513 1.180 mlelstv /* remove duplicates */
2514 1.180 mlelstv for (i = 0; i < n; ++i) {
2515 1.180 mlelstv if (freqs[i] == freq)
2516 1.180 mlelstv break;
2517 1.180 mlelstv }
2518 1.180 mlelstv if (i < n) {
2519 1.180 mlelstv if (step == 0)
2520 1.180 mlelstv break;
2521 1.180 mlelstv continue;
2522 1.180 mlelstv }
2523 1.180 mlelstv
2524 1.180 mlelstv /* store or count */
2525 1.175 mlelstv if (len != 0) {
2526 1.175 mlelstv if (n >= len)
2527 1.175 mlelstv goto done;
2528 1.175 mlelstv freqs[n] = freq;
2529 1.175 mlelstv }
2530 1.175 mlelstv ++n;
2531 1.175 mlelstv if (step == 0)
2532 1.175 mlelstv break;
2533 1.175 mlelstv }
2534 1.175 mlelstv }
2535 1.175 mlelstv }
2536 1.175 mlelstv
2537 1.175 mlelstv done:
2538 1.175 mlelstv return n;
2539 1.175 mlelstv }
2540 1.175 mlelstv
2541 1.175 mlelstv Static void
2542 1.175 mlelstv uaudio_build_formats(struct uaudio_softc *sc)
2543 1.175 mlelstv {
2544 1.175 mlelstv struct audio_format *auf;
2545 1.175 mlelstv const struct as_info *as;
2546 1.175 mlelstv const union usb_audio_streaming_type1_descriptor *t1desc;
2547 1.175 mlelstv int i, j;
2548 1.175 mlelstv
2549 1.92 kent /* build audio_format array */
2550 1.162 isaki sc->sc_formats = kmem_zalloc(sizeof(struct audio_format) * sc->sc_nalts,
2551 1.146 skrll KM_SLEEP);
2552 1.92 kent sc->sc_nformats = sc->sc_nalts;
2553 1.175 mlelstv
2554 1.92 kent for (i = 0; i < sc->sc_nalts; i++) {
2555 1.92 kent auf = &sc->sc_formats[i];
2556 1.175 mlelstv as = &sc->sc_alts[i];
2557 1.175 mlelstv t1desc = as->asf1desc;
2558 1.175 mlelstv if (UE_GET_DIR(as->edesc->bEndpointAddress) == UE_DIR_OUT)
2559 1.92 kent auf->mode = AUMODE_PLAY;
2560 1.92 kent else
2561 1.92 kent auf->mode = AUMODE_RECORD;
2562 1.175 mlelstv auf->encoding = as->encoding;
2563 1.92 kent auf->channel_mask = sc->sc_channel_config;
2564 1.175 mlelstv
2565 1.175 mlelstv switch (sc->sc_version) {
2566 1.175 mlelstv case UAUDIO_VERSION1:
2567 1.175 mlelstv auf->validbits = t1desc->v1.bBitResolution;
2568 1.175 mlelstv auf->precision = t1desc->v1.bSubFrameSize * 8;
2569 1.175 mlelstv auf->channels = t1desc->v1.bNrChannels;
2570 1.175 mlelstv
2571 1.175 mlelstv auf->frequency_type = t1desc->v1.bSamFreqType;
2572 1.175 mlelstv if (t1desc->v1.bSamFreqType == UA_SAMP_CONTINUOUS) {
2573 1.175 mlelstv auf->frequency[0] = UA_SAMP_LO(&t1desc->v1);
2574 1.175 mlelstv auf->frequency[1] = UA_SAMP_HI(&t1desc->v1);
2575 1.175 mlelstv } else {
2576 1.175 mlelstv for (j = 0; j < t1desc->v1.bSamFreqType; j++) {
2577 1.175 mlelstv if (j >= AUFMT_MAX_FREQUENCIES) {
2578 1.175 mlelstv aprint_error("%s: please increase "
2579 1.175 mlelstv "AUFMT_MAX_FREQUENCIES to %d\n",
2580 1.175 mlelstv __func__, t1desc->v1.bSamFreqType);
2581 1.175 mlelstv auf->frequency_type =
2582 1.175 mlelstv AUFMT_MAX_FREQUENCIES;
2583 1.175 mlelstv break;
2584 1.175 mlelstv }
2585 1.175 mlelstv auf->frequency[j] = UA_GETSAMP(&t1desc->v1, j);
2586 1.130 bouyer }
2587 1.92 kent }
2588 1.175 mlelstv break;
2589 1.175 mlelstv case UAUDIO_VERSION2:
2590 1.175 mlelstv auf->validbits = t1desc->v2.bBitResolution;
2591 1.175 mlelstv auf->precision = t1desc->v2.bSubslotSize * 8;
2592 1.175 mlelstv auf->channels = as->nchan;
2593 1.175 mlelstv
2594 1.175 mlelstv #if 0
2595 1.178 mlelstv auf->frequency_type = uaudio_get_rates(sc, auf->mode, NULL, 0);
2596 1.175 mlelstv if (auf->frequency_type >= AUFMT_MAX_FREQUENCIES) {
2597 1.175 mlelstv aprint_error("%s: please increase "
2598 1.175 mlelstv "AUFMT_MAX_FREQUENCIES to %d\n",
2599 1.175 mlelstv __func__, auf->frequency_type);
2600 1.175 mlelstv }
2601 1.175 mlelstv #endif
2602 1.175 mlelstv
2603 1.178 mlelstv auf->frequency_type = uaudio_get_rates(sc,
2604 1.178 mlelstv auf->mode, auf->frequency, AUFMT_MAX_FREQUENCIES);
2605 1.178 mlelstv
2606 1.178 mlelstv /*
2607 1.178 mlelstv * if rate query failed, guess a rate
2608 1.178 mlelstv */
2609 1.178 mlelstv if (auf->frequency_type == UA_SAMP_CONTINUOUS) {
2610 1.178 mlelstv auf->frequency[0] = 48000;
2611 1.178 mlelstv auf->frequency[1] = 48000;
2612 1.178 mlelstv }
2613 1.178 mlelstv
2614 1.175 mlelstv break;
2615 1.92 kent }
2616 1.175 mlelstv
2617 1.179 mlelstv DPRINTF("alt[%d] = %d/%d %dch %u[%u,%u,...] alt %u\n", i,
2618 1.179 mlelstv auf->validbits, auf->precision, auf->channels, auf->frequency_type,
2619 1.179 mlelstv auf->frequency[0], auf->frequency[1],
2620 1.179 mlelstv as->idesc->bAlternateSetting);
2621 1.179 mlelstv
2622 1.92 kent sc->sc_alts[i].aformat = auf;
2623 1.92 kent }
2624 1.1 augustss }
2625 1.1 augustss
2626 1.142 gson #ifdef UAUDIO_DEBUG
2627 1.142 gson Static void
2628 1.142 gson uaudio_dump_tml(struct terminal_list *tml) {
2629 1.142 gson if (tml == NULL) {
2630 1.142 gson printf("NULL");
2631 1.142 gson } else {
2632 1.142 gson int i;
2633 1.142 gson for (i = 0; i < tml->size; i++)
2634 1.142 gson printf("%s ", uaudio_get_terminal_name
2635 1.142 gson (tml->terminals[i]));
2636 1.142 gson }
2637 1.142 gson printf("\n");
2638 1.142 gson }
2639 1.142 gson #endif
2640 1.142 gson
2641 1.86 kent Static usbd_status
2642 1.78 kent uaudio_identify_ac(struct uaudio_softc *sc, const usb_config_descriptor_t *cdesc)
2643 1.1 augustss {
2644 1.82 kent struct io_terminal* iot;
2645 1.78 kent const usb_interface_descriptor_t *id;
2646 1.78 kent const struct usb_audio_control_descriptor *acdp;
2647 1.109 drochner const uaudio_cs_descriptor_t *dp;
2648 1.178 mlelstv const union usb_audio_output_terminal *pot;
2649 1.82 kent struct terminal_list *tml;
2650 1.99 christos const char *tbuf, *ibuf, *ibufend;
2651 1.120 jakllsch int size, offs, ndps, i, j;
2652 1.1 augustss
2653 1.1 augustss size = UGETW(cdesc->wTotalLength);
2654 1.99 christos tbuf = (const char *)cdesc;
2655 1.1 augustss
2656 1.1 augustss /* Locate the AudioControl interface descriptor. */
2657 1.1 augustss offs = 0;
2658 1.99 christos id = uaudio_find_iface(tbuf, size, &offs, UISUBCLASS_AUDIOCONTROL);
2659 1.14 augustss if (id == NULL)
2660 1.94 kent return USBD_INVAL;
2661 1.146 skrll if (offs + sizeof(*acdp) > size)
2662 1.94 kent return USBD_INVAL;
2663 1.1 augustss sc->sc_ac_iface = id->bInterfaceNumber;
2664 1.122 mrg DPRINTFN(2,"AC interface is %d\n", sc->sc_ac_iface);
2665 1.1 augustss
2666 1.1 augustss /* A class-specific AC interface header should follow. */
2667 1.99 christos ibuf = tbuf + offs;
2668 1.120 jakllsch ibufend = tbuf + size;
2669 1.78 kent acdp = (const struct usb_audio_control_descriptor *)ibuf;
2670 1.1 augustss if (acdp->bDescriptorType != UDESC_CS_INTERFACE ||
2671 1.1 augustss acdp->bDescriptorSubtype != UDESCSUB_AC_HEADER)
2672 1.94 kent return USBD_INVAL;
2673 1.5 augustss
2674 1.175 mlelstv if (!(usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_BAD_ADC)) {
2675 1.175 mlelstv sc->sc_version = UGETW(acdp->bcdADC);
2676 1.175 mlelstv } else {
2677 1.175 mlelstv sc->sc_version = UAUDIO_VERSION1;
2678 1.175 mlelstv }
2679 1.175 mlelstv
2680 1.175 mlelstv switch (sc->sc_version) {
2681 1.175 mlelstv case UAUDIO_VERSION1:
2682 1.175 mlelstv case UAUDIO_VERSION2:
2683 1.175 mlelstv break;
2684 1.175 mlelstv default:
2685 1.94 kent return USBD_INVAL;
2686 1.175 mlelstv }
2687 1.1 augustss
2688 1.7 augustss sc->sc_audio_rev = UGETW(acdp->bcdADC);
2689 1.122 mrg DPRINTFN(2, "found AC header, vers=%03x\n", sc->sc_audio_rev);
2690 1.1 augustss
2691 1.1 augustss sc->sc_nullalt = -1;
2692 1.1 augustss
2693 1.1 augustss /* Scan through all the AC specific descriptors */
2694 1.109 drochner dp = (const uaudio_cs_descriptor_t *)ibuf;
2695 1.1 augustss ndps = 0;
2696 1.82 kent iot = malloc(sizeof(struct io_terminal) * 256, M_TEMP, M_NOWAIT | M_ZERO);
2697 1.82 kent if (iot == NULL) {
2698 1.113 cube aprint_error("%s: no memory\n", __func__);
2699 1.82 kent return USBD_NOMEM;
2700 1.82 kent }
2701 1.1 augustss for (;;) {
2702 1.1 augustss ibuf += dp->bLength;
2703 1.1 augustss if (ibuf >= ibufend)
2704 1.1 augustss break;
2705 1.109 drochner dp = (const uaudio_cs_descriptor_t *)ibuf;
2706 1.97 martin if (ibuf + dp->bLength > ibufend) {
2707 1.97 martin free(iot, M_TEMP);
2708 1.94 kent return USBD_INVAL;
2709 1.97 martin }
2710 1.120 jakllsch if (dp->bDescriptorType != UDESC_CS_INTERFACE)
2711 1.120 jakllsch break;
2712 1.178 mlelstv switch (sc->sc_version) {
2713 1.178 mlelstv case UAUDIO_VERSION1:
2714 1.178 mlelstv i = ((const union usb_audio_input_terminal *)dp)->v1.bTerminalId;
2715 1.178 mlelstv break;
2716 1.178 mlelstv case UAUDIO_VERSION2:
2717 1.178 mlelstv i = ((const union usb_audio_input_terminal *)dp)->v2.bTerminalId;
2718 1.178 mlelstv break;
2719 1.178 mlelstv default:
2720 1.178 mlelstv free(iot, M_TEMP);
2721 1.178 mlelstv return USBD_INVAL;
2722 1.178 mlelstv }
2723 1.82 kent iot[i].d.desc = dp;
2724 1.1 augustss if (i > ndps)
2725 1.1 augustss ndps = i;
2726 1.1 augustss }
2727 1.1 augustss ndps++;
2728 1.1 augustss
2729 1.82 kent /* construct io_terminal */
2730 1.82 kent for (i = 0; i < ndps; i++) {
2731 1.82 kent dp = iot[i].d.desc;
2732 1.82 kent if (dp == NULL)
2733 1.82 kent continue;
2734 1.82 kent if (dp->bDescriptorSubtype != UDESCSUB_AC_OUTPUT)
2735 1.82 kent continue;
2736 1.82 kent pot = iot[i].d.ot;
2737 1.178 mlelstv switch (sc->sc_version) {
2738 1.178 mlelstv case UAUDIO_VERSION1:
2739 1.178 mlelstv tml = uaudio_io_terminaltype(sc, UGETW(pot->v1.wTerminalType), iot, i);
2740 1.178 mlelstv break;
2741 1.178 mlelstv case UAUDIO_VERSION2:
2742 1.178 mlelstv tml = uaudio_io_terminaltype(sc, UGETW(pot->v2.wTerminalType), iot, i);
2743 1.178 mlelstv break;
2744 1.178 mlelstv default:
2745 1.178 mlelstv tml = NULL;
2746 1.178 mlelstv break;
2747 1.178 mlelstv }
2748 1.82 kent if (tml != NULL)
2749 1.82 kent free(tml, M_TEMP);
2750 1.82 kent }
2751 1.82 kent
2752 1.82 kent #ifdef UAUDIO_DEBUG
2753 1.82 kent for (i = 0; i < 256; i++) {
2754 1.178 mlelstv union usb_audio_cluster cluster;
2755 1.91 kent
2756 1.82 kent if (iot[i].d.desc == NULL)
2757 1.82 kent continue;
2758 1.118 dyoung printf("id %d:\t", i);
2759 1.82 kent switch (iot[i].d.desc->bDescriptorSubtype) {
2760 1.82 kent case UDESCSUB_AC_INPUT:
2761 1.118 dyoung printf("AC_INPUT type=%s\n", uaudio_get_terminal_name
2762 1.178 mlelstv (UGETW(iot[i].d.it->v1.wTerminalType)));
2763 1.118 dyoung printf("\t");
2764 1.178 mlelstv cluster = uaudio_get_cluster(sc, i, iot);
2765 1.178 mlelstv uaudio_dump_cluster(sc, &cluster);
2766 1.118 dyoung printf("\n");
2767 1.82 kent break;
2768 1.82 kent case UDESCSUB_AC_OUTPUT:
2769 1.118 dyoung printf("AC_OUTPUT type=%s ", uaudio_get_terminal_name
2770 1.178 mlelstv (UGETW(iot[i].d.ot->v1.wTerminalType)));
2771 1.178 mlelstv printf("src=%d\n", iot[i].d.ot->v1.bSourceId);
2772 1.82 kent break;
2773 1.82 kent case UDESCSUB_AC_MIXER:
2774 1.118 dyoung printf("AC_MIXER src=");
2775 1.82 kent for (j = 0; j < iot[i].d.mu->bNrInPins; j++)
2776 1.118 dyoung printf("%d ", iot[i].d.mu->baSourceId[j]);
2777 1.118 dyoung printf("\n\t");
2778 1.178 mlelstv cluster = uaudio_get_cluster(sc, i, iot);
2779 1.178 mlelstv uaudio_dump_cluster(sc, &cluster);
2780 1.118 dyoung printf("\n");
2781 1.82 kent break;
2782 1.82 kent case UDESCSUB_AC_SELECTOR:
2783 1.118 dyoung printf("AC_SELECTOR src=");
2784 1.82 kent for (j = 0; j < iot[i].d.su->bNrInPins; j++)
2785 1.118 dyoung printf("%d ", iot[i].d.su->baSourceId[j]);
2786 1.118 dyoung printf("\n");
2787 1.82 kent break;
2788 1.82 kent case UDESCSUB_AC_FEATURE:
2789 1.179 mlelstv switch (sc->sc_version) {
2790 1.179 mlelstv case UAUDIO_VERSION1:
2791 1.179 mlelstv printf("AC_FEATURE src=%d\n", iot[i].d.fu->v1.bSourceId);
2792 1.179 mlelstv break;
2793 1.179 mlelstv case UAUDIO_VERSION2:
2794 1.179 mlelstv printf("AC_FEATURE src=%d\n", iot[i].d.fu->v2.bSourceId);
2795 1.179 mlelstv break;
2796 1.179 mlelstv }
2797 1.82 kent break;
2798 1.175 mlelstv case UDESCSUB_AC_EFFECT:
2799 1.179 mlelstv switch (sc->sc_version) {
2800 1.179 mlelstv case UAUDIO_VERSION1:
2801 1.179 mlelstv printf("AC_EFFECT src=%d\n", iot[i].d.fu->v1.bSourceId);
2802 1.179 mlelstv break;
2803 1.179 mlelstv case UAUDIO_VERSION2:
2804 1.179 mlelstv printf("AC_EFFECT src=%d\n", iot[i].d.fu->v2.bSourceId);
2805 1.179 mlelstv break;
2806 1.179 mlelstv }
2807 1.175 mlelstv break;
2808 1.82 kent case UDESCSUB_AC_PROCESSING:
2809 1.118 dyoung printf("AC_PROCESSING src=");
2810 1.82 kent for (j = 0; j < iot[i].d.pu->bNrInPins; j++)
2811 1.118 dyoung printf("%d ", iot[i].d.pu->baSourceId[j]);
2812 1.118 dyoung printf("\n\t");
2813 1.178 mlelstv cluster = uaudio_get_cluster(sc, i, iot);
2814 1.178 mlelstv uaudio_dump_cluster(sc, &cluster);
2815 1.118 dyoung printf("\n");
2816 1.82 kent break;
2817 1.82 kent case UDESCSUB_AC_EXTENSION:
2818 1.118 dyoung printf("AC_EXTENSION src=");
2819 1.82 kent for (j = 0; j < iot[i].d.eu->bNrInPins; j++)
2820 1.118 dyoung printf("%d ", iot[i].d.eu->baSourceId[j]);
2821 1.118 dyoung printf("\n\t");
2822 1.178 mlelstv cluster = uaudio_get_cluster(sc, i, iot);
2823 1.178 mlelstv uaudio_dump_cluster(sc, &cluster);
2824 1.118 dyoung printf("\n");
2825 1.82 kent break;
2826 1.175 mlelstv case UDESCSUB_AC_CLKSRC:
2827 1.176 mlelstv printf("AC_CLKSRC src=%d\n", iot[i].d.cu->iClockSource);
2828 1.175 mlelstv break;
2829 1.175 mlelstv case UDESCSUB_AC_CLKSEL:
2830 1.175 mlelstv printf("AC_CLKSEL src=");
2831 1.175 mlelstv for (j = 0; j < iot[i].d.su->bNrInPins; j++)
2832 1.176 mlelstv printf("%d ", iot[i].d.su->baSourceId[j]);
2833 1.175 mlelstv printf("\n");
2834 1.175 mlelstv break;
2835 1.175 mlelstv case UDESCSUB_AC_CLKMULT:
2836 1.175 mlelstv printf("AC_CLKMULT not supported\n");
2837 1.175 mlelstv break;
2838 1.175 mlelstv case UDESCSUB_AC_RATECONV:
2839 1.175 mlelstv printf("AC_RATEVONC not supported\n");
2840 1.175 mlelstv break;
2841 1.82 kent default:
2842 1.118 dyoung printf("unknown audio control (subtype=%d)\n",
2843 1.89 kent iot[i].d.desc->bDescriptorSubtype);
2844 1.82 kent }
2845 1.82 kent for (j = 0; j < iot[i].inputs_size; j++) {
2846 1.118 dyoung printf("\tinput%d: ", j);
2847 1.142 gson uaudio_dump_tml(iot[i].inputs[j]);
2848 1.82 kent }
2849 1.118 dyoung printf("\toutput: ");
2850 1.142 gson uaudio_dump_tml(iot[i].output);
2851 1.82 kent }
2852 1.82 kent #endif
2853 1.82 kent
2854 1.175 mlelstv sc->sc_nratectls = 0;
2855 1.1 augustss for (i = 0; i < ndps; i++) {
2856 1.82 kent dp = iot[i].d.desc;
2857 1.14 augustss if (dp == NULL)
2858 1.1 augustss continue;
2859 1.122 mrg DPRINTF("id=%d subtype=%d\n", i, dp->bDescriptorSubtype);
2860 1.1 augustss switch (dp->bDescriptorSubtype) {
2861 1.1 augustss case UDESCSUB_AC_HEADER:
2862 1.113 cube aprint_error("uaudio_identify_ac: unexpected AC header\n");
2863 1.1 augustss break;
2864 1.1 augustss case UDESCSUB_AC_INPUT:
2865 1.82 kent uaudio_add_input(sc, iot, i);
2866 1.1 augustss break;
2867 1.1 augustss case UDESCSUB_AC_OUTPUT:
2868 1.82 kent uaudio_add_output(sc, iot, i);
2869 1.1 augustss break;
2870 1.1 augustss case UDESCSUB_AC_MIXER:
2871 1.82 kent uaudio_add_mixer(sc, iot, i);
2872 1.1 augustss break;
2873 1.1 augustss case UDESCSUB_AC_SELECTOR:
2874 1.82 kent uaudio_add_selector(sc, iot, i);
2875 1.1 augustss break;
2876 1.1 augustss case UDESCSUB_AC_FEATURE:
2877 1.82 kent uaudio_add_feature(sc, iot, i);
2878 1.1 augustss break;
2879 1.175 mlelstv case UDESCSUB_AC_EFFECT:
2880 1.175 mlelstv uaudio_add_effect(sc, iot, i);
2881 1.175 mlelstv break;
2882 1.1 augustss case UDESCSUB_AC_PROCESSING:
2883 1.82 kent uaudio_add_processing(sc, iot, i);
2884 1.1 augustss break;
2885 1.1 augustss case UDESCSUB_AC_EXTENSION:
2886 1.82 kent uaudio_add_extension(sc, iot, i);
2887 1.1 augustss break;
2888 1.175 mlelstv case UDESCSUB_AC_CLKSRC:
2889 1.175 mlelstv uaudio_add_clksrc(sc, iot, i);
2890 1.175 mlelstv /* record ids of clock sources */
2891 1.175 mlelstv if (sc->sc_nratectls < AUFMT_MAX_FREQUENCIES)
2892 1.175 mlelstv sc->sc_ratectls[sc->sc_nratectls++] = sc->sc_nctls - 1;
2893 1.175 mlelstv break;
2894 1.175 mlelstv case UDESCSUB_AC_CLKSEL:
2895 1.175 mlelstv uaudio_add_clksel(sc, iot, i);
2896 1.175 mlelstv break;
2897 1.175 mlelstv case UDESCSUB_AC_CLKMULT:
2898 1.175 mlelstv /* not yet */
2899 1.175 mlelstv break;
2900 1.175 mlelstv case UDESCSUB_AC_RATECONV:
2901 1.175 mlelstv /* not yet */
2902 1.175 mlelstv break;
2903 1.1 augustss default:
2904 1.113 cube aprint_error(
2905 1.165 christos "uaudio_identify_ac: bad AC desc subtype=0x%02x\n",
2906 1.113 cube dp->bDescriptorSubtype);
2907 1.1 augustss break;
2908 1.1 augustss }
2909 1.1 augustss }
2910 1.82 kent
2911 1.178 mlelstv switch (sc->sc_version) {
2912 1.178 mlelstv case UAUDIO_VERSION2:
2913 1.178 mlelstv /*
2914 1.178 mlelstv * UAC2 has separate rate controls which effectively creates
2915 1.178 mlelstv * a set of audio_formats per input and output and their
2916 1.178 mlelstv * associated clock sources.
2917 1.178 mlelstv *
2918 1.178 mlelstv * audio(4) can only handle audio_formats per direction.
2919 1.178 mlelstv * - ignore stream terminals
2920 1.178 mlelstv * - mark rates for record or play if associated with an input
2921 1.178 mlelstv * or output terminal respectively.
2922 1.178 mlelstv */
2923 1.178 mlelstv for (j = 0; j < sc->sc_nratectls; ++j) {
2924 1.178 mlelstv uint16_t wi = sc->sc_ctls[sc->sc_ratectls[j]].wIndex;
2925 1.178 mlelstv sc->sc_ratemode[j] = 0;
2926 1.178 mlelstv for (i = 0; i < ndps; i++) {
2927 1.178 mlelstv dp = iot[i].d.desc;
2928 1.178 mlelstv if (dp == NULL)
2929 1.178 mlelstv continue;
2930 1.178 mlelstv switch (dp->bDescriptorSubtype) {
2931 1.178 mlelstv case UDESCSUB_AC_INPUT:
2932 1.178 mlelstv if (UGETW(iot[i].d.it->v2.wTerminalType) != UAT_STREAM &&
2933 1.179 mlelstv wi == MAKE(iot[i].d.it->v2.bCSourceId, sc->sc_ac_iface)) {
2934 1.178 mlelstv sc->sc_ratemode[j] |= AUMODE_RECORD;
2935 1.179 mlelstv }
2936 1.178 mlelstv break;
2937 1.178 mlelstv case UDESCSUB_AC_OUTPUT:
2938 1.178 mlelstv if (UGETW(iot[i].d.it->v2.wTerminalType) != UAT_STREAM &&
2939 1.179 mlelstv wi == MAKE(iot[i].d.ot->v2.bCSourceId, sc->sc_ac_iface)) {
2940 1.178 mlelstv sc->sc_ratemode[j] |= AUMODE_PLAY;
2941 1.179 mlelstv }
2942 1.178 mlelstv break;
2943 1.178 mlelstv }
2944 1.178 mlelstv }
2945 1.178 mlelstv }
2946 1.178 mlelstv break;
2947 1.178 mlelstv }
2948 1.178 mlelstv
2949 1.82 kent /* delete io_terminal */
2950 1.82 kent for (i = 0; i < 256; i++) {
2951 1.82 kent if (iot[i].d.desc == NULL)
2952 1.82 kent continue;
2953 1.82 kent if (iot[i].inputs != NULL) {
2954 1.82 kent for (j = 0; j < iot[i].inputs_size; j++) {
2955 1.82 kent if (iot[i].inputs[j] != NULL)
2956 1.82 kent free(iot[i].inputs[j], M_TEMP);
2957 1.82 kent }
2958 1.82 kent free(iot[i].inputs, M_TEMP);
2959 1.82 kent }
2960 1.82 kent if (iot[i].output != NULL)
2961 1.82 kent free(iot[i].output, M_TEMP);
2962 1.82 kent iot[i].d.desc = NULL;
2963 1.82 kent }
2964 1.82 kent free(iot, M_TEMP);
2965 1.82 kent
2966 1.94 kent return USBD_NORMAL_COMPLETION;
2967 1.1 augustss }
2968 1.1 augustss
2969 1.86 kent Static int
2970 1.26 augustss uaudio_query_devinfo(void *addr, mixer_devinfo_t *mi)
2971 1.1 augustss {
2972 1.94 kent struct uaudio_softc *sc;
2973 1.1 augustss struct mixerctl *mc;
2974 1.79 kent int n, nctls, i;
2975 1.1 augustss
2976 1.133 mrg DPRINTFN(7, "index=%d\n", mi->index);
2977 1.94 kent sc = addr;
2978 1.1 augustss if (sc->sc_dying)
2979 1.94 kent return EIO;
2980 1.56 kent
2981 1.1 augustss n = mi->index;
2982 1.1 augustss nctls = sc->sc_nctls;
2983 1.1 augustss
2984 1.63 augustss switch (n) {
2985 1.63 augustss case UAC_OUTPUT:
2986 1.63 augustss mi->type = AUDIO_MIXER_CLASS;
2987 1.63 augustss mi->mixer_class = UAC_OUTPUT;
2988 1.63 augustss mi->next = mi->prev = AUDIO_MIXER_LAST;
2989 1.71 itojun strlcpy(mi->label.name, AudioCoutputs, sizeof(mi->label.name));
2990 1.94 kent return 0;
2991 1.63 augustss case UAC_INPUT:
2992 1.63 augustss mi->type = AUDIO_MIXER_CLASS;
2993 1.63 augustss mi->mixer_class = UAC_INPUT;
2994 1.63 augustss mi->next = mi->prev = AUDIO_MIXER_LAST;
2995 1.71 itojun strlcpy(mi->label.name, AudioCinputs, sizeof(mi->label.name));
2996 1.94 kent return 0;
2997 1.63 augustss case UAC_EQUAL:
2998 1.63 augustss mi->type = AUDIO_MIXER_CLASS;
2999 1.63 augustss mi->mixer_class = UAC_EQUAL;
3000 1.63 augustss mi->next = mi->prev = AUDIO_MIXER_LAST;
3001 1.71 itojun strlcpy(mi->label.name, AudioCequalization,
3002 1.71 itojun sizeof(mi->label.name));
3003 1.94 kent return 0;
3004 1.82 kent case UAC_RECORD:
3005 1.82 kent mi->type = AUDIO_MIXER_CLASS;
3006 1.82 kent mi->mixer_class = UAC_RECORD;
3007 1.82 kent mi->next = mi->prev = AUDIO_MIXER_LAST;
3008 1.82 kent strlcpy(mi->label.name, AudioCrecord, sizeof(mi->label.name));
3009 1.82 kent return 0;
3010 1.63 augustss default:
3011 1.63 augustss break;
3012 1.1 augustss }
3013 1.63 augustss
3014 1.63 augustss n -= UAC_NCLASSES;
3015 1.63 augustss if (n < 0 || n >= nctls)
3016 1.94 kent return ENXIO;
3017 1.63 augustss
3018 1.1 augustss mc = &sc->sc_ctls[n];
3019 1.71 itojun strlcpy(mi->label.name, mc->ctlname, sizeof(mi->label.name));
3020 1.1 augustss mi->mixer_class = mc->class;
3021 1.1 augustss mi->next = mi->prev = AUDIO_MIXER_LAST; /* XXX */
3022 1.1 augustss switch (mc->type) {
3023 1.1 augustss case MIX_ON_OFF:
3024 1.1 augustss mi->type = AUDIO_MIXER_ENUM;
3025 1.1 augustss mi->un.e.num_mem = 2;
3026 1.71 itojun strlcpy(mi->un.e.member[0].label.name, AudioNoff,
3027 1.71 itojun sizeof(mi->un.e.member[0].label.name));
3028 1.1 augustss mi->un.e.member[0].ord = 0;
3029 1.71 itojun strlcpy(mi->un.e.member[1].label.name, AudioNon,
3030 1.71 itojun sizeof(mi->un.e.member[1].label.name));
3031 1.1 augustss mi->un.e.member[1].ord = 1;
3032 1.1 augustss break;
3033 1.79 kent case MIX_SELECTOR:
3034 1.175 mlelstv n = uimin(mc->ranges[0].maxval - mc->ranges[0].minval + 1,
3035 1.175 mlelstv __arraycount(mi->un.e.member));
3036 1.79 kent mi->type = AUDIO_MIXER_ENUM;
3037 1.175 mlelstv mi->un.e.num_mem = n;
3038 1.175 mlelstv for (i = 0; i < n; i++) {
3039 1.79 kent snprintf(mi->un.e.member[i].label.name,
3040 1.79 kent sizeof(mi->un.e.member[i].label.name),
3041 1.175 mlelstv "%d", i + mc->ranges[0].minval);
3042 1.175 mlelstv mi->un.e.member[i].ord = i + mc->ranges[0].minval;
3043 1.79 kent }
3044 1.79 kent break;
3045 1.1 augustss default:
3046 1.1 augustss mi->type = AUDIO_MIXER_VALUE;
3047 1.1 augustss strncpy(mi->un.v.units.name, mc->ctlunit, MAX_AUDIO_DEV_LEN);
3048 1.1 augustss mi->un.v.num_channels = mc->nchan;
3049 1.33 augustss mi->un.v.delta = mc->delta;
3050 1.1 augustss break;
3051 1.1 augustss }
3052 1.94 kent return 0;
3053 1.1 augustss }
3054 1.1 augustss
3055 1.86 kent Static int
3056 1.26 augustss uaudio_open(void *addr, int flags)
3057 1.1 augustss {
3058 1.94 kent struct uaudio_softc *sc;
3059 1.1 augustss
3060 1.95 dsainty sc = addr;
3061 1.122 mrg DPRINTF("sc=%p\n", sc);
3062 1.1 augustss if (sc->sc_dying)
3063 1.94 kent return EIO;
3064 1.1 augustss
3065 1.77 mycroft if ((flags & FWRITE) && !(sc->sc_mode & AUMODE_PLAY))
3066 1.94 kent return EACCES;
3067 1.77 mycroft if ((flags & FREAD) && !(sc->sc_mode & AUMODE_RECORD))
3068 1.94 kent return EACCES;
3069 1.1 augustss
3070 1.94 kent return 0;
3071 1.1 augustss }
3072 1.1 augustss
3073 1.86 kent Static int
3074 1.26 augustss uaudio_halt_out_dma(void *addr)
3075 1.1 augustss {
3076 1.121 jmcneill struct uaudio_softc *sc = addr;
3077 1.1 augustss
3078 1.122 mrg DPRINTF("%s", "enter\n");
3079 1.121 jmcneill
3080 1.146 skrll mutex_exit(&sc->sc_intr_lock);
3081 1.166 jdc uaudio_halt_out_dma_unlocked(sc);
3082 1.166 jdc mutex_enter(&sc->sc_intr_lock);
3083 1.166 jdc
3084 1.166 jdc return 0;
3085 1.166 jdc }
3086 1.166 jdc
3087 1.166 jdc Static void
3088 1.166 jdc uaudio_halt_out_dma_unlocked(struct uaudio_softc *sc)
3089 1.166 jdc {
3090 1.47 jdolecek if (sc->sc_playchan.pipe != NULL) {
3091 1.146 skrll uaudio_chan_abort(sc, &sc->sc_playchan);
3092 1.146 skrll uaudio_chan_free_buffers(sc, &sc->sc_playchan);
3093 1.47 jdolecek uaudio_chan_close(sc, &sc->sc_playchan);
3094 1.74 mycroft sc->sc_playchan.intr = NULL;
3095 1.1 augustss }
3096 1.1 augustss }
3097 1.1 augustss
3098 1.86 kent Static int
3099 1.26 augustss uaudio_halt_in_dma(void *addr)
3100 1.1 augustss {
3101 1.121 jmcneill struct uaudio_softc *sc = addr;
3102 1.1 augustss
3103 1.122 mrg DPRINTF("%s", "enter\n");
3104 1.121 jmcneill
3105 1.146 skrll mutex_exit(&sc->sc_intr_lock);
3106 1.166 jdc uaudio_halt_in_dma_unlocked(sc);
3107 1.166 jdc mutex_enter(&sc->sc_intr_lock);
3108 1.166 jdc
3109 1.166 jdc return 0;
3110 1.166 jdc }
3111 1.166 jdc
3112 1.166 jdc Static void
3113 1.166 jdc uaudio_halt_in_dma_unlocked(struct uaudio_softc *sc)
3114 1.166 jdc {
3115 1.47 jdolecek if (sc->sc_recchan.pipe != NULL) {
3116 1.146 skrll uaudio_chan_abort(sc, &sc->sc_recchan);
3117 1.146 skrll uaudio_chan_free_buffers(sc, &sc->sc_recchan);
3118 1.47 jdolecek uaudio_chan_close(sc, &sc->sc_recchan);
3119 1.74 mycroft sc->sc_recchan.intr = NULL;
3120 1.5 augustss }
3121 1.1 augustss }
3122 1.1 augustss
3123 1.86 kent Static int
3124 1.26 augustss uaudio_getdev(void *addr, struct audio_device *retp)
3125 1.1 augustss {
3126 1.94 kent struct uaudio_softc *sc;
3127 1.1 augustss
3128 1.122 mrg DPRINTF("%s", "\n");
3129 1.94 kent sc = addr;
3130 1.1 augustss if (sc->sc_dying)
3131 1.94 kent return EIO;
3132 1.56 kent
3133 1.119 jmcneill *retp = sc->sc_adev;
3134 1.94 kent return 0;
3135 1.1 augustss }
3136 1.1 augustss
3137 1.1 augustss /*
3138 1.1 augustss * Make sure the block size is large enough to hold all outstanding transfers.
3139 1.1 augustss */
3140 1.86 kent Static int
3141 1.93 kent uaudio_round_blocksize(void *addr, int blk,
3142 1.93 kent int mode, const audio_params_t *param)
3143 1.1 augustss {
3144 1.94 kent struct uaudio_softc *sc;
3145 1.96 kent int b;
3146 1.1 augustss
3147 1.94 kent sc = addr;
3148 1.122 mrg DPRINTF("blk=%d mode=%s\n", blk,
3149 1.122 mrg mode == AUMODE_PLAY ? "AUMODE_PLAY" : "AUMODE_RECORD");
3150 1.96 kent
3151 1.96 kent /* chan.bytes_per_frame can be 0. */
3152 1.96 kent if (mode == AUMODE_PLAY || sc->sc_recchan.bytes_per_frame <= 0) {
3153 1.179 mlelstv b = param->sample_rate * sc->sc_recchan.nframes
3154 1.179 mlelstv * sc->sc_recchan.nchanbufs;
3155 1.96 kent
3156 1.96 kent /*
3157 1.96 kent * This does not make accurate value in the case
3158 1.179 mlelstv * of b % usb_frames_per_second != 0
3159 1.96 kent */
3160 1.179 mlelstv b /= sc->sc_usb_frames_per_second;
3161 1.96 kent
3162 1.96 kent b *= param->precision / 8 * param->channels;
3163 1.47 jdolecek } else {
3164 1.96 kent /*
3165 1.96 kent * use wMaxPacketSize in bytes_per_frame.
3166 1.160 isaki * See uaudio_set_format() and uaudio_chan_init()
3167 1.96 kent */
3168 1.96 kent b = sc->sc_recchan.bytes_per_frame
3169 1.179 mlelstv * sc->sc_recchan.nframes * sc->sc_recchan.nchanbufs;
3170 1.47 jdolecek }
3171 1.1 augustss
3172 1.96 kent if (b <= 0)
3173 1.96 kent b = 1;
3174 1.96 kent blk = blk <= b ? b : blk / b * b;
3175 1.1 augustss
3176 1.5 augustss #ifdef DIAGNOSTIC
3177 1.5 augustss if (blk <= 0) {
3178 1.113 cube aprint_debug("uaudio_round_blocksize: blk=%d\n", blk);
3179 1.5 augustss blk = 512;
3180 1.5 augustss }
3181 1.5 augustss #endif
3182 1.5 augustss
3183 1.122 mrg DPRINTF("resultant blk=%d\n", blk);
3184 1.94 kent return blk;
3185 1.1 augustss }
3186 1.1 augustss
3187 1.86 kent Static int
3188 1.107 christos uaudio_get_props(void *addr)
3189 1.1 augustss {
3190 1.161 isaki struct uaudio_softc *sc;
3191 1.161 isaki int props;
3192 1.161 isaki
3193 1.161 isaki sc = addr;
3194 1.161 isaki props = 0;
3195 1.161 isaki if ((sc->sc_mode & AUMODE_PLAY))
3196 1.161 isaki props |= AUDIO_PROP_PLAYBACK;
3197 1.161 isaki if ((sc->sc_mode & AUMODE_RECORD))
3198 1.161 isaki props |= AUDIO_PROP_CAPTURE;
3199 1.161 isaki
3200 1.161 isaki /* XXX I'm not sure all bidirectional devices support FULLDUP&INDEP */
3201 1.161 isaki if (props == (AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE))
3202 1.161 isaki props |= AUDIO_PROP_FULLDUPLEX | AUDIO_PROP_INDEPENDENT;
3203 1.1 augustss
3204 1.161 isaki return props;
3205 1.1 augustss }
3206 1.1 augustss
3207 1.121 jmcneill Static void
3208 1.121 jmcneill uaudio_get_locks(void *addr, kmutex_t **intr, kmutex_t **thread)
3209 1.121 jmcneill {
3210 1.121 jmcneill struct uaudio_softc *sc;
3211 1.121 jmcneill
3212 1.121 jmcneill sc = addr;
3213 1.121 jmcneill *intr = &sc->sc_intr_lock;
3214 1.121 jmcneill *thread = &sc->sc_lock;
3215 1.121 jmcneill }
3216 1.121 jmcneill
3217 1.86 kent Static int
3218 1.27 augustss uaudio_get(struct uaudio_softc *sc, int which, int type, int wValue,
3219 1.26 augustss int wIndex, int len)
3220 1.1 augustss {
3221 1.1 augustss usb_device_request_t req;
3222 1.146 skrll uint8_t data[4];
3223 1.9 augustss usbd_status err;
3224 1.1 augustss int val;
3225 1.1 augustss
3226 1.1 augustss if (wValue == -1)
3227 1.94 kent return 0;
3228 1.1 augustss
3229 1.1 augustss req.bmRequestType = type;
3230 1.1 augustss req.bRequest = which;
3231 1.1 augustss USETW(req.wValue, wValue);
3232 1.1 augustss USETW(req.wIndex, wIndex);
3233 1.1 augustss USETW(req.wLength, len);
3234 1.165 christos DPRINTFN(2,"type=0x%02x req=0x%02x wValue=0x%04x "
3235 1.165 christos "wIndex=0x%04x len=%d\n",
3236 1.122 mrg type, which, wValue, wIndex, len);
3237 1.47 jdolecek err = usbd_do_request(sc->sc_udev, &req, data);
3238 1.9 augustss if (err) {
3239 1.122 mrg DPRINTF("err=%s\n", usbd_errstr(err));
3240 1.94 kent return -1;
3241 1.1 augustss }
3242 1.1 augustss switch (len) {
3243 1.1 augustss case 1:
3244 1.1 augustss val = data[0];
3245 1.1 augustss break;
3246 1.1 augustss case 2:
3247 1.175 mlelstv val = data[0];
3248 1.175 mlelstv val |= data[1] << 8;
3249 1.175 mlelstv break;
3250 1.175 mlelstv case 3:
3251 1.175 mlelstv val = data[0];
3252 1.175 mlelstv val |= data[1] << 8;
3253 1.175 mlelstv val |= data[2] << 16;
3254 1.175 mlelstv break;
3255 1.175 mlelstv case 4:
3256 1.175 mlelstv val = data[0];
3257 1.175 mlelstv val |= data[1] << 8;
3258 1.175 mlelstv val |= data[2] << 16;
3259 1.175 mlelstv val |= data[3] << 24;
3260 1.1 augustss break;
3261 1.1 augustss default:
3262 1.122 mrg DPRINTF("bad length=%d\n", len);
3263 1.94 kent return -1;
3264 1.1 augustss }
3265 1.122 mrg DPRINTFN(2,"val=%d\n", val);
3266 1.94 kent return val;
3267 1.1 augustss }
3268 1.1 augustss
3269 1.175 mlelstv Static int
3270 1.175 mlelstv uaudio_getbuf(struct uaudio_softc *sc, int which, int type, int wValue,
3271 1.175 mlelstv int wIndex, int len, uint8_t *data)
3272 1.175 mlelstv {
3273 1.175 mlelstv usb_device_request_t req;
3274 1.175 mlelstv usbd_status err;
3275 1.175 mlelstv
3276 1.175 mlelstv req.bmRequestType = type;
3277 1.175 mlelstv req.bRequest = which;
3278 1.175 mlelstv USETW(req.wValue, wValue);
3279 1.175 mlelstv USETW(req.wIndex, wIndex);
3280 1.175 mlelstv USETW(req.wLength, len);
3281 1.175 mlelstv DPRINTFN(2,"type=0x%02x req=0x%02x wValue=0x%04x "
3282 1.175 mlelstv "wIndex=0x%04x len=%d\n",
3283 1.175 mlelstv type, which, wValue, wIndex, len);
3284 1.175 mlelstv err = usbd_do_request(sc->sc_udev, &req, data);
3285 1.175 mlelstv if (err) {
3286 1.175 mlelstv DPRINTF("err=%s\n", usbd_errstr(err));
3287 1.175 mlelstv return -1;
3288 1.175 mlelstv }
3289 1.175 mlelstv
3290 1.175 mlelstv DPRINTFN(2,"val@%p\n", data);
3291 1.175 mlelstv return 0;
3292 1.175 mlelstv }
3293 1.175 mlelstv
3294 1.86 kent Static void
3295 1.27 augustss uaudio_set(struct uaudio_softc *sc, int which, int type, int wValue,
3296 1.26 augustss int wIndex, int len, int val)
3297 1.1 augustss {
3298 1.1 augustss usb_device_request_t req;
3299 1.146 skrll uint8_t data[4];
3300 1.138 martin int err __unused;
3301 1.1 augustss
3302 1.1 augustss if (wValue == -1)
3303 1.1 augustss return;
3304 1.1 augustss
3305 1.1 augustss req.bmRequestType = type;
3306 1.1 augustss req.bRequest = which;
3307 1.1 augustss USETW(req.wValue, wValue);
3308 1.1 augustss USETW(req.wIndex, wIndex);
3309 1.1 augustss USETW(req.wLength, len);
3310 1.175 mlelstv
3311 1.175 mlelstv data[0] = val;
3312 1.175 mlelstv data[1] = val >> 8;
3313 1.175 mlelstv data[2] = val >> 16;
3314 1.175 mlelstv data[3] = val >> 24;
3315 1.175 mlelstv
3316 1.165 christos DPRINTFN(2,"type=0x%02x req=0x%02x wValue=0x%04x "
3317 1.165 christos "wIndex=0x%04x len=%d, val=%d\n",
3318 1.175 mlelstv type, which, wValue, wIndex, len, val);
3319 1.47 jdolecek err = usbd_do_request(sc->sc_udev, &req, data);
3320 1.4 augustss #ifdef UAUDIO_DEBUG
3321 1.12 augustss if (err)
3322 1.179 mlelstv DPRINTF("err=%s\n", usbd_errstr(err));
3323 1.1 augustss #endif
3324 1.1 augustss }
3325 1.1 augustss
3326 1.86 kent Static int
3327 1.26 augustss uaudio_signext(int type, int val)
3328 1.1 augustss {
3329 1.175 mlelstv if (MIX_UNSIGNED(type)) {
3330 1.175 mlelstv switch (MIX_SIZE(type)) {
3331 1.175 mlelstv case 1:
3332 1.175 mlelstv val = (uint8_t)val;
3333 1.175 mlelstv break;
3334 1.175 mlelstv case 2:
3335 1.175 mlelstv val = (uint16_t)val;
3336 1.175 mlelstv break;
3337 1.175 mlelstv case 3:
3338 1.175 mlelstv val = ((uint32_t)val << 8) >> 8;
3339 1.175 mlelstv break;
3340 1.175 mlelstv case 4:
3341 1.175 mlelstv val = (uint32_t)val;
3342 1.175 mlelstv break;
3343 1.175 mlelstv }
3344 1.175 mlelstv } else {
3345 1.175 mlelstv switch (MIX_SIZE(type)) {
3346 1.175 mlelstv case 1:
3347 1.175 mlelstv val = (int8_t)val;
3348 1.175 mlelstv break;
3349 1.175 mlelstv case 2:
3350 1.1 augustss val = (int16_t)val;
3351 1.175 mlelstv break;
3352 1.175 mlelstv case 3:
3353 1.175 mlelstv val = ((int32_t)val << 8) >> 8;
3354 1.175 mlelstv break;
3355 1.175 mlelstv case 4:
3356 1.175 mlelstv val = (int32_t)val;
3357 1.175 mlelstv break;
3358 1.175 mlelstv }
3359 1.1 augustss }
3360 1.94 kent return val;
3361 1.1 augustss }
3362 1.1 augustss
3363 1.86 kent Static int
3364 1.26 augustss uaudio_value2bsd(struct mixerctl *mc, int val)
3365 1.1 augustss {
3366 1.122 mrg DPRINTFN(5, "type=%03x val=%d min=%d max=%d ",
3367 1.175 mlelstv mc->type, val, mc->ranges[0].minval, mc->ranges[0].maxval);
3368 1.79 kent if (mc->type == MIX_ON_OFF) {
3369 1.47 jdolecek val = (val != 0);
3370 1.79 kent } else if (mc->type == MIX_SELECTOR) {
3371 1.179 mlelstv if (val < mc->ranges[0].minval)
3372 1.175 mlelstv val = mc->ranges[0].minval;
3373 1.179 mlelstv if (val > mc->ranges[0].maxval)
3374 1.179 mlelstv val = mc->ranges[0].maxval;
3375 1.179 mlelstv } else if (mc->mul > 0) {
3376 1.179 mlelstv val = ((uaudio_signext(mc->type, val) - mc->ranges[0].minval)
3377 1.179 mlelstv * 255 + mc->mul - 1) / mc->mul;
3378 1.79 kent } else
3379 1.179 mlelstv val = 0;
3380 1.122 mrg DPRINTFN_CLEAN(5, "val'=%d\n", val);
3381 1.94 kent return val;
3382 1.1 augustss }
3383 1.1 augustss
3384 1.175 mlelstv Static int
3385 1.26 augustss uaudio_bsd2value(struct mixerctl *mc, int val)
3386 1.1 augustss {
3387 1.179 mlelstv int i;
3388 1.179 mlelstv
3389 1.122 mrg DPRINTFN(5,"type=%03x val=%d min=%d max=%d ",
3390 1.175 mlelstv mc->type, val, mc->ranges[0].minval, mc->ranges[0].maxval);
3391 1.79 kent if (mc->type == MIX_ON_OFF) {
3392 1.47 jdolecek val = (val != 0);
3393 1.79 kent } else if (mc->type == MIX_SELECTOR) {
3394 1.179 mlelstv if (val < mc->ranges[0].minval)
3395 1.175 mlelstv val = mc->ranges[0].minval;
3396 1.179 mlelstv if (val > mc->ranges[0].maxval)
3397 1.179 mlelstv val = mc->ranges[0].maxval;
3398 1.175 mlelstv } else {
3399 1.175 mlelstv if (val < 0)
3400 1.175 mlelstv val = 0;
3401 1.179 mlelstv else if (val > 255)
3402 1.179 mlelstv val = 255;
3403 1.175 mlelstv
3404 1.179 mlelstv val = val * (mc->mul + 1) / 256 + mc->ranges[0].minval;
3405 1.175 mlelstv
3406 1.179 mlelstv for (i=0; i<mc->nranges; ++i) {
3407 1.179 mlelstv struct range *r = &mc->ranges[i];
3408 1.175 mlelstv
3409 1.179 mlelstv if (r->resval == 0)
3410 1.179 mlelstv continue;
3411 1.179 mlelstv if (val > r->maxval)
3412 1.179 mlelstv continue;
3413 1.179 mlelstv if (val < r->minval)
3414 1.179 mlelstv val = r->minval;
3415 1.179 mlelstv val = (val - r->minval + r->resval/2)
3416 1.179 mlelstv / r->resval * r->resval
3417 1.179 mlelstv + r->minval;
3418 1.179 mlelstv break;
3419 1.175 mlelstv }
3420 1.175 mlelstv }
3421 1.122 mrg DPRINTFN_CLEAN(5, "val'=%d\n", val);
3422 1.94 kent return val;
3423 1.1 augustss }
3424 1.1 augustss
3425 1.175 mlelstv Static const char *
3426 1.175 mlelstv uaudio_clockname(u_int attr)
3427 1.175 mlelstv {
3428 1.175 mlelstv static const char *names[] = {
3429 1.179 mlelstv "clkext",
3430 1.179 mlelstv "clkfixed",
3431 1.179 mlelstv "clkvar",
3432 1.179 mlelstv "clkprog"
3433 1.175 mlelstv };
3434 1.175 mlelstv
3435 1.175 mlelstv return names[attr & 3];
3436 1.175 mlelstv }
3437 1.175 mlelstv
3438 1.175 mlelstv Static int
3439 1.175 mlelstv uaudio_makename(struct uaudio_softc *sc, uByte idx, const char *defname, uByte id, char *buf, size_t len)
3440 1.175 mlelstv {
3441 1.175 mlelstv char *tmp;
3442 1.175 mlelstv int err, count;
3443 1.175 mlelstv
3444 1.175 mlelstv tmp = kmem_alloc(USB_MAX_ENCODED_STRING_LEN, KM_SLEEP);
3445 1.175 mlelstv err = usbd_get_string0(sc->sc_udev, idx, tmp, true);
3446 1.179 mlelstv
3447 1.179 mlelstv if (id != 0 || err)
3448 1.179 mlelstv count = snprintf(buf, len, "%s%d", err ? defname : tmp, id);
3449 1.179 mlelstv else
3450 1.179 mlelstv count = snprintf(buf, len, "%s", err ? defname : tmp);
3451 1.179 mlelstv
3452 1.175 mlelstv kmem_free(tmp, USB_MAX_ENCODED_STRING_LEN);
3453 1.175 mlelstv
3454 1.175 mlelstv return count;
3455 1.175 mlelstv }
3456 1.175 mlelstv
3457 1.175 mlelstv
3458 1.86 kent Static int
3459 1.56 kent uaudio_ctl_get(struct uaudio_softc *sc, int which, struct mixerctl *mc,
3460 1.26 augustss int chan)
3461 1.1 augustss {
3462 1.1 augustss int val;
3463 1.1 augustss
3464 1.179 mlelstv DPRINTFN(5,"which=%d chan=%d ctl=%s type=%d\n", which, chan, mc->ctlname, mc->type);
3465 1.133 mrg mutex_exit(&sc->sc_lock);
3466 1.1 augustss val = uaudio_get(sc, which, UT_READ_CLASS_INTERFACE, mc->wValue[chan],
3467 1.1 augustss mc->wIndex, MIX_SIZE(mc->type));
3468 1.133 mrg mutex_enter(&sc->sc_lock);
3469 1.94 kent return uaudio_value2bsd(mc, val);
3470 1.1 augustss }
3471 1.1 augustss
3472 1.86 kent Static void
3473 1.26 augustss uaudio_ctl_set(struct uaudio_softc *sc, int which, struct mixerctl *mc,
3474 1.26 augustss int chan, int val)
3475 1.1 augustss {
3476 1.124 mrg
3477 1.179 mlelstv DPRINTFN(5,"which=%d chan=%d ctl=%s type=%d\n", which, chan, mc->ctlname, mc->type);
3478 1.1 augustss val = uaudio_bsd2value(mc, val);
3479 1.133 mrg mutex_exit(&sc->sc_lock);
3480 1.1 augustss uaudio_set(sc, which, UT_WRITE_CLASS_INTERFACE, mc->wValue[chan],
3481 1.1 augustss mc->wIndex, MIX_SIZE(mc->type), val);
3482 1.133 mrg mutex_enter(&sc->sc_lock);
3483 1.1 augustss }
3484 1.1 augustss
3485 1.86 kent Static int
3486 1.26 augustss uaudio_mixer_get_port(void *addr, mixer_ctrl_t *cp)
3487 1.1 augustss {
3488 1.94 kent struct uaudio_softc *sc;
3489 1.1 augustss struct mixerctl *mc;
3490 1.1 augustss int i, n, vals[MIX_MAX_CHAN], val;
3491 1.179 mlelstv int req;
3492 1.1 augustss
3493 1.122 mrg DPRINTFN(2, "index=%d\n", cp->dev);
3494 1.94 kent sc = addr;
3495 1.1 augustss if (sc->sc_dying)
3496 1.94 kent return EIO;
3497 1.56 kent
3498 1.179 mlelstv req = sc->sc_version == UAUDIO_VERSION2 ? V2_CUR : GET_CUR;
3499 1.179 mlelstv
3500 1.63 augustss n = cp->dev - UAC_NCLASSES;
3501 1.1 augustss if (n < 0 || n >= sc->sc_nctls)
3502 1.94 kent return ENXIO;
3503 1.1 augustss mc = &sc->sc_ctls[n];
3504 1.1 augustss
3505 1.1 augustss if (mc->type == MIX_ON_OFF) {
3506 1.1 augustss if (cp->type != AUDIO_MIXER_ENUM)
3507 1.94 kent return EINVAL;
3508 1.179 mlelstv cp->un.ord = uaudio_ctl_get(sc, req, mc, 0);
3509 1.79 kent } else if (mc->type == MIX_SELECTOR) {
3510 1.79 kent if (cp->type != AUDIO_MIXER_ENUM)
3511 1.94 kent return EINVAL;
3512 1.179 mlelstv cp->un.ord = uaudio_ctl_get(sc, req, mc, 0);
3513 1.1 augustss } else {
3514 1.1 augustss if (cp->type != AUDIO_MIXER_VALUE)
3515 1.94 kent return EINVAL;
3516 1.1 augustss if (cp->un.value.num_channels != 1 &&
3517 1.1 augustss cp->un.value.num_channels != mc->nchan)
3518 1.94 kent return EINVAL;
3519 1.1 augustss for (i = 0; i < mc->nchan; i++)
3520 1.179 mlelstv vals[i] = uaudio_ctl_get(sc, req, mc, i);
3521 1.1 augustss if (cp->un.value.num_channels == 1 && mc->nchan != 1) {
3522 1.1 augustss for (val = 0, i = 0; i < mc->nchan; i++)
3523 1.1 augustss val += vals[i];
3524 1.1 augustss vals[0] = val / mc->nchan;
3525 1.1 augustss }
3526 1.1 augustss for (i = 0; i < cp->un.value.num_channels; i++)
3527 1.1 augustss cp->un.value.level[i] = vals[i];
3528 1.1 augustss }
3529 1.1 augustss
3530 1.94 kent return 0;
3531 1.1 augustss }
3532 1.56 kent
3533 1.86 kent Static int
3534 1.26 augustss uaudio_mixer_set_port(void *addr, mixer_ctrl_t *cp)
3535 1.1 augustss {
3536 1.94 kent struct uaudio_softc *sc;
3537 1.1 augustss struct mixerctl *mc;
3538 1.1 augustss int i, n, vals[MIX_MAX_CHAN];
3539 1.179 mlelstv int req;
3540 1.1 augustss
3541 1.122 mrg DPRINTFN(2, "index = %d\n", cp->dev);
3542 1.94 kent sc = addr;
3543 1.1 augustss if (sc->sc_dying)
3544 1.94 kent return EIO;
3545 1.56 kent
3546 1.179 mlelstv req = sc->sc_version == UAUDIO_VERSION2 ? V2_CUR : SET_CUR;
3547 1.179 mlelstv
3548 1.63 augustss n = cp->dev - UAC_NCLASSES;
3549 1.1 augustss if (n < 0 || n >= sc->sc_nctls)
3550 1.94 kent return ENXIO;
3551 1.1 augustss mc = &sc->sc_ctls[n];
3552 1.1 augustss
3553 1.1 augustss if (mc->type == MIX_ON_OFF) {
3554 1.1 augustss if (cp->type != AUDIO_MIXER_ENUM)
3555 1.94 kent return EINVAL;
3556 1.179 mlelstv uaudio_ctl_set(sc, req, mc, 0, cp->un.ord);
3557 1.79 kent } else if (mc->type == MIX_SELECTOR) {
3558 1.79 kent if (cp->type != AUDIO_MIXER_ENUM)
3559 1.94 kent return EINVAL;
3560 1.179 mlelstv uaudio_ctl_set(sc, req, mc, 0, cp->un.ord);
3561 1.1 augustss } else {
3562 1.1 augustss if (cp->type != AUDIO_MIXER_VALUE)
3563 1.94 kent return EINVAL;
3564 1.1 augustss if (cp->un.value.num_channels == 1)
3565 1.1 augustss for (i = 0; i < mc->nchan; i++)
3566 1.1 augustss vals[i] = cp->un.value.level[0];
3567 1.1 augustss else if (cp->un.value.num_channels == mc->nchan)
3568 1.1 augustss for (i = 0; i < mc->nchan; i++)
3569 1.1 augustss vals[i] = cp->un.value.level[i];
3570 1.1 augustss else
3571 1.94 kent return EINVAL;
3572 1.1 augustss for (i = 0; i < mc->nchan; i++)
3573 1.179 mlelstv uaudio_ctl_set(sc, req, mc, i, vals[i]);
3574 1.1 augustss }
3575 1.94 kent return 0;
3576 1.1 augustss }
3577 1.1 augustss
3578 1.86 kent Static int
3579 1.26 augustss uaudio_trigger_input(void *addr, void *start, void *end, int blksize,
3580 1.26 augustss void (*intr)(void *), void *arg,
3581 1.107 christos const audio_params_t *param)
3582 1.1 augustss {
3583 1.94 kent struct uaudio_softc *sc;
3584 1.94 kent struct chan *ch;
3585 1.9 augustss usbd_status err;
3586 1.133 mrg int i;
3587 1.1 augustss
3588 1.94 kent sc = addr;
3589 1.1 augustss if (sc->sc_dying)
3590 1.94 kent return EIO;
3591 1.1 augustss
3592 1.173 mlelstv mutex_exit(&sc->sc_intr_lock);
3593 1.173 mlelstv
3594 1.122 mrg DPRINTFN(3, "sc=%p start=%p end=%p "
3595 1.122 mrg "blksize=%d\n", sc, start, end, blksize);
3596 1.94 kent ch = &sc->sc_recchan;
3597 1.54 kent uaudio_chan_set_param(ch, start, end, blksize);
3598 1.122 mrg DPRINTFN(3, "sample_size=%d bytes/frame=%d "
3599 1.5 augustss "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame,
3600 1.122 mrg ch->fraction);
3601 1.5 augustss
3602 1.146 skrll err = uaudio_chan_open(sc, ch);
3603 1.121 jmcneill if (err) {
3604 1.173 mlelstv mutex_enter(&sc->sc_intr_lock);
3605 1.173 mlelstv device_printf(sc->sc_dev,"%s open channel err=%s\n",__func__, usbd_errstr(err));
3606 1.94 kent return EIO;
3607 1.121 jmcneill }
3608 1.5 augustss
3609 1.146 skrll err = uaudio_chan_alloc_buffers(sc, ch);
3610 1.9 augustss if (err) {
3611 1.146 skrll uaudio_chan_close(sc, ch);
3612 1.173 mlelstv device_printf(sc->sc_dev,"%s alloc buffers err=%s\n",__func__, usbd_errstr(err));
3613 1.173 mlelstv mutex_enter(&sc->sc_intr_lock);
3614 1.94 kent return EIO;
3615 1.5 augustss }
3616 1.5 augustss
3617 1.146 skrll
3618 1.47 jdolecek ch->intr = intr;
3619 1.47 jdolecek ch->arg = arg;
3620 1.5 augustss
3621 1.154 nat /*
3622 1.154 nat * Start as half as many channels for recording as for playback.
3623 1.154 nat * This stops playback from stuttering in full-duplex operation.
3624 1.154 nat */
3625 1.179 mlelstv for (i = 0; i < ch->nchanbufs / 2; i++) {
3626 1.5 augustss uaudio_chan_rtransfer(ch);
3627 1.146 skrll }
3628 1.146 skrll
3629 1.173 mlelstv mutex_enter(&sc->sc_intr_lock);
3630 1.173 mlelstv
3631 1.94 kent return 0;
3632 1.1 augustss }
3633 1.56 kent
3634 1.86 kent Static int
3635 1.26 augustss uaudio_trigger_output(void *addr, void *start, void *end, int blksize,
3636 1.26 augustss void (*intr)(void *), void *arg,
3637 1.107 christos const audio_params_t *param)
3638 1.1 augustss {
3639 1.94 kent struct uaudio_softc *sc;
3640 1.94 kent struct chan *ch;
3641 1.9 augustss usbd_status err;
3642 1.133 mrg int i;
3643 1.1 augustss
3644 1.94 kent sc = addr;
3645 1.1 augustss if (sc->sc_dying)
3646 1.94 kent return EIO;
3647 1.1 augustss
3648 1.173 mlelstv mutex_exit(&sc->sc_intr_lock);
3649 1.173 mlelstv
3650 1.122 mrg DPRINTFN(3, "sc=%p start=%p end=%p "
3651 1.122 mrg "blksize=%d\n", sc, start, end, blksize);
3652 1.94 kent ch = &sc->sc_playchan;
3653 1.54 kent uaudio_chan_set_param(ch, start, end, blksize);
3654 1.122 mrg DPRINTFN(3, "sample_size=%d bytes/frame=%d "
3655 1.1 augustss "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame,
3656 1.122 mrg ch->fraction);
3657 1.1 augustss
3658 1.146 skrll err = uaudio_chan_open(sc, ch);
3659 1.121 jmcneill if (err) {
3660 1.173 mlelstv mutex_enter(&sc->sc_intr_lock);
3661 1.173 mlelstv device_printf(sc->sc_dev,"%s open channel err=%s\n",__func__, usbd_errstr(err));
3662 1.94 kent return EIO;
3663 1.121 jmcneill }
3664 1.1 augustss
3665 1.146 skrll err = uaudio_chan_alloc_buffers(sc, ch);
3666 1.9 augustss if (err) {
3667 1.146 skrll uaudio_chan_close(sc, ch);
3668 1.173 mlelstv device_printf(sc->sc_dev,"%s alloc buffers err=%s\n",__func__, usbd_errstr(err));
3669 1.173 mlelstv mutex_enter(&sc->sc_intr_lock);
3670 1.94 kent return EIO;
3671 1.1 augustss }
3672 1.1 augustss
3673 1.47 jdolecek ch->intr = intr;
3674 1.47 jdolecek ch->arg = arg;
3675 1.1 augustss
3676 1.179 mlelstv for (i = 0; i < ch->nchanbufs; i++)
3677 1.5 augustss uaudio_chan_ptransfer(ch);
3678 1.1 augustss
3679 1.173 mlelstv mutex_enter(&sc->sc_intr_lock);
3680 1.173 mlelstv
3681 1.94 kent return 0;
3682 1.1 augustss }
3683 1.1 augustss
3684 1.1 augustss /* Set up a pipe for a channel. */
3685 1.86 kent Static usbd_status
3686 1.26 augustss uaudio_chan_open(struct uaudio_softc *sc, struct chan *ch)
3687 1.1 augustss {
3688 1.94 kent struct as_info *as;
3689 1.131 jakllsch usb_device_descriptor_t *ddesc;
3690 1.179 mlelstv int endpt, clkid;
3691 1.9 augustss usbd_status err;
3692 1.1 augustss
3693 1.94 kent as = &sc->sc_alts[ch->altidx];
3694 1.94 kent endpt = as->edesc->bEndpointAddress;
3695 1.179 mlelstv clkid = sc->sc_clock[as->terminal];
3696 1.179 mlelstv DPRINTF("endpt=0x%02x, clkid=%d, speed=%d, alt=%d\n",
3697 1.179 mlelstv endpt, clkid, ch->sample_rate, as->alt);
3698 1.1 augustss
3699 1.1 augustss /* Set alternate interface corresponding to the mode. */
3700 1.37 mycroft err = usbd_set_interface(as->ifaceh, as->alt);
3701 1.9 augustss if (err)
3702 1.94 kent return err;
3703 1.1 augustss
3704 1.90 kent /*
3705 1.90 kent * Roland SD-90 freezes by a SAMPLING_FREQ_CONTROL request.
3706 1.90 kent */
3707 1.131 jakllsch ddesc = usbd_get_device_descriptor(sc->sc_udev);
3708 1.131 jakllsch if ((UGETW(ddesc->idVendor) != USB_VENDOR_ROLAND) &&
3709 1.131 jakllsch (UGETW(ddesc->idProduct) != USB_PRODUCT_ROLAND_SD90)) {
3710 1.179 mlelstv err = uaudio_set_speed(sc, endpt, clkid, ch->sample_rate);
3711 1.105 christos if (err) {
3712 1.122 mrg DPRINTF("set_speed failed err=%s\n", usbd_errstr(err));
3713 1.105 christos }
3714 1.90 kent }
3715 1.1 augustss
3716 1.165 christos DPRINTF("create pipe to 0x%02x\n", endpt);
3717 1.134 jmcneill err = usbd_open_pipe(as->ifaceh, endpt, USBD_MPSAFE, &ch->pipe);
3718 1.83 kent if (err)
3719 1.83 kent return err;
3720 1.83 kent if (as->edesc1 != NULL) {
3721 1.83 kent endpt = as->edesc1->bEndpointAddress;
3722 1.175 mlelstv if (endpt != 0) {
3723 1.175 mlelstv DPRINTF("create sync-pipe to 0x%02x\n", endpt);
3724 1.175 mlelstv err = usbd_open_pipe(as->ifaceh, endpt, USBD_MPSAFE,
3725 1.175 mlelstv &ch->sync_pipe);
3726 1.175 mlelstv }
3727 1.83 kent }
3728 1.175 mlelstv
3729 1.83 kent return err;
3730 1.1 augustss }
3731 1.1 augustss
3732 1.86 kent Static void
3733 1.146 skrll uaudio_chan_abort(struct uaudio_softc *sc, struct chan *ch)
3734 1.1 augustss {
3735 1.146 skrll struct usbd_pipe *pipe;
3736 1.94 kent struct as_info *as;
3737 1.37 mycroft
3738 1.94 kent as = &sc->sc_alts[ch->altidx];
3739 1.58 kent as->sc_busy = 0;
3740 1.1 augustss if (sc->sc_nullalt >= 0) {
3741 1.122 mrg DPRINTF("set null alt=%d\n", sc->sc_nullalt);
3742 1.37 mycroft usbd_set_interface(as->ifaceh, sc->sc_nullalt);
3743 1.1 augustss }
3744 1.146 skrll pipe = ch->pipe;
3745 1.146 skrll if (pipe) {
3746 1.146 skrll usbd_abort_pipe(pipe);
3747 1.146 skrll }
3748 1.146 skrll pipe = ch->sync_pipe;
3749 1.146 skrll if (pipe) {
3750 1.146 skrll usbd_abort_pipe(pipe);
3751 1.146 skrll }
3752 1.146 skrll }
3753 1.146 skrll
3754 1.146 skrll Static void
3755 1.146 skrll uaudio_chan_close(struct uaudio_softc *sc, struct chan *ch)
3756 1.146 skrll {
3757 1.146 skrll struct usbd_pipe *pipe;
3758 1.146 skrll
3759 1.136 wiz pipe = atomic_swap_ptr(&ch->pipe, NULL);
3760 1.136 wiz if (pipe) {
3761 1.136 wiz usbd_close_pipe(pipe);
3762 1.136 wiz }
3763 1.136 wiz pipe = atomic_swap_ptr(&ch->sync_pipe, NULL);
3764 1.136 wiz if (pipe) {
3765 1.136 wiz usbd_close_pipe(pipe);
3766 1.83 kent }
3767 1.1 augustss }
3768 1.1 augustss
3769 1.86 kent Static usbd_status
3770 1.26 augustss uaudio_chan_alloc_buffers(struct uaudio_softc *sc, struct chan *ch)
3771 1.1 augustss {
3772 1.1 augustss int i, size;
3773 1.1 augustss
3774 1.179 mlelstv size = (ch->bytes_per_frame + ch->sample_size) * ch->nframes;
3775 1.179 mlelstv for (i = 0; i < ch->nchanbufs; i++) {
3776 1.146 skrll struct usbd_xfer *xfer;
3777 1.146 skrll
3778 1.179 mlelstv int err = usbd_create_xfer(ch->pipe, size, 0, ch->nframes,
3779 1.146 skrll &xfer);
3780 1.146 skrll if (err)
3781 1.1 augustss goto bad;
3782 1.146 skrll
3783 1.9 augustss ch->chanbufs[i].xfer = xfer;
3784 1.146 skrll ch->chanbufs[i].buffer = usbd_get_buffer(xfer);
3785 1.1 augustss ch->chanbufs[i].chan = ch;
3786 1.1 augustss }
3787 1.1 augustss
3788 1.94 kent return USBD_NORMAL_COMPLETION;
3789 1.1 augustss
3790 1.1 augustss bad:
3791 1.1 augustss while (--i >= 0)
3792 1.1 augustss /* implicit buffer free */
3793 1.146 skrll usbd_destroy_xfer(ch->chanbufs[i].xfer);
3794 1.94 kent return USBD_NOMEM;
3795 1.1 augustss }
3796 1.1 augustss
3797 1.86 kent Static void
3798 1.107 christos uaudio_chan_free_buffers(struct uaudio_softc *sc, struct chan *ch)
3799 1.1 augustss {
3800 1.1 augustss int i;
3801 1.1 augustss
3802 1.179 mlelstv for (i = 0; i < ch->nchanbufs; i++)
3803 1.146 skrll usbd_destroy_xfer(ch->chanbufs[i].xfer);
3804 1.1 augustss }
3805 1.1 augustss
3806 1.86 kent Static void
3807 1.26 augustss uaudio_chan_ptransfer(struct chan *ch)
3808 1.1 augustss {
3809 1.179 mlelstv struct uaudio_softc *sc = ch->sc;
3810 1.1 augustss struct chanbuf *cb;
3811 1.1 augustss int i, n, size, residue, total;
3812 1.1 augustss
3813 1.179 mlelstv if (sc->sc_dying)
3814 1.8 augustss return;
3815 1.8 augustss
3816 1.1 augustss /* Pick the next channel buffer. */
3817 1.1 augustss cb = &ch->chanbufs[ch->curchanbuf];
3818 1.179 mlelstv if (++ch->curchanbuf >= ch->nchanbufs)
3819 1.1 augustss ch->curchanbuf = 0;
3820 1.1 augustss
3821 1.1 augustss /* Compute the size of each frame in the next transfer. */
3822 1.1 augustss residue = ch->residue;
3823 1.1 augustss total = 0;
3824 1.179 mlelstv for (i = 0; i < ch->nframes; i++) {
3825 1.1 augustss size = ch->bytes_per_frame;
3826 1.1 augustss residue += ch->fraction;
3827 1.179 mlelstv if (residue >= sc->sc_usb_frames_per_second) {
3828 1.179 mlelstv if ((sc->sc_altflags & UA_NOFRAC) == 0)
3829 1.31 augustss size += ch->sample_size;
3830 1.179 mlelstv residue -= sc->sc_usb_frames_per_second;
3831 1.1 augustss }
3832 1.1 augustss cb->sizes[i] = size;
3833 1.1 augustss total += size;
3834 1.1 augustss }
3835 1.1 augustss ch->residue = residue;
3836 1.1 augustss cb->size = total;
3837 1.1 augustss
3838 1.56 kent /*
3839 1.1 augustss * Transfer data from upper layer buffer to channel buffer, taking
3840 1.1 augustss * care of wrapping the upper layer buffer.
3841 1.1 augustss */
3842 1.157 riastrad n = uimin(total, ch->end - ch->cur);
3843 1.1 augustss memcpy(cb->buffer, ch->cur, n);
3844 1.1 augustss ch->cur += n;
3845 1.1 augustss if (ch->cur >= ch->end)
3846 1.1 augustss ch->cur = ch->start;
3847 1.1 augustss if (total > n) {
3848 1.1 augustss total -= n;
3849 1.1 augustss memcpy(cb->buffer + n, ch->cur, total);
3850 1.1 augustss ch->cur += total;
3851 1.1 augustss }
3852 1.1 augustss
3853 1.4 augustss #ifdef UAUDIO_DEBUG
3854 1.1 augustss if (uaudiodebug > 8) {
3855 1.122 mrg DPRINTF("buffer=%p, residue=0.%03d\n", cb->buffer, ch->residue);
3856 1.179 mlelstv for (i = 0; i < ch->nframes; i++) {
3857 1.122 mrg DPRINTF(" [%d] length %d\n", i, cb->sizes[i]);
3858 1.1 augustss }
3859 1.1 augustss }
3860 1.1 augustss #endif
3861 1.1 augustss
3862 1.124 mrg //DPRINTFN(5, "ptransfer xfer=%p\n", cb->xfer);
3863 1.1 augustss /* Fill the request */
3864 1.179 mlelstv usbd_setup_isoc_xfer(cb->xfer, cb, cb->sizes, ch->nframes, 0,
3865 1.146 skrll uaudio_chan_pintr);
3866 1.1 augustss
3867 1.173 mlelstv usbd_status err = usbd_transfer(cb->xfer);
3868 1.173 mlelstv if (err != USBD_IN_PROGRESS && err != USBD_NORMAL_COMPLETION)
3869 1.179 mlelstv device_printf(sc->sc_dev, "ptransfer error %d\n", err);
3870 1.1 augustss }
3871 1.1 augustss
3872 1.86 kent Static void
3873 1.146 skrll uaudio_chan_pintr(struct usbd_xfer *xfer, void *priv,
3874 1.26 augustss usbd_status status)
3875 1.1 augustss {
3876 1.179 mlelstv struct uaudio_softc *sc;
3877 1.94 kent struct chanbuf *cb;
3878 1.94 kent struct chan *ch;
3879 1.94 kent uint32_t count;
3880 1.1 augustss
3881 1.94 kent cb = priv;
3882 1.94 kent ch = cb->chan;
3883 1.179 mlelstv sc = ch->sc;
3884 1.1 augustss /* Return if we are aborting. */
3885 1.1 augustss if (status == USBD_CANCELLED)
3886 1.1 augustss return;
3887 1.1 augustss
3888 1.173 mlelstv if (status != USBD_NORMAL_COMPLETION)
3889 1.179 mlelstv device_printf(sc->sc_dev, "pintr error: %s\n",
3890 1.173 mlelstv usbd_errstr(status));
3891 1.173 mlelstv
3892 1.18 augustss usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
3893 1.122 mrg DPRINTFN(5, "count=%d, transferred=%d\n",
3894 1.122 mrg count, ch->transferred);
3895 1.5 augustss #ifdef DIAGNOSTIC
3896 1.5 augustss if (count != cb->size) {
3897 1.179 mlelstv device_printf(sc->sc_dev,
3898 1.171 mlelstv "uaudio_chan_pintr: count(%d) != size(%d), status(%d)\n",
3899 1.171 mlelstv count, cb->size, status);
3900 1.5 augustss }
3901 1.5 augustss #endif
3902 1.5 augustss
3903 1.179 mlelstv mutex_enter(&sc->sc_intr_lock);
3904 1.5 augustss ch->transferred += cb->size;
3905 1.1 augustss /* Call back to upper layer */
3906 1.5 augustss while (ch->transferred >= ch->blksize) {
3907 1.5 augustss ch->transferred -= ch->blksize;
3908 1.122 mrg DPRINTFN(5, "call %p(%p)\n", ch->intr, ch->arg);
3909 1.5 augustss ch->intr(ch->arg);
3910 1.5 augustss }
3911 1.179 mlelstv mutex_exit(&sc->sc_intr_lock);
3912 1.5 augustss
3913 1.5 augustss /* start next transfer */
3914 1.5 augustss uaudio_chan_ptransfer(ch);
3915 1.5 augustss }
3916 1.5 augustss
3917 1.86 kent Static void
3918 1.26 augustss uaudio_chan_rtransfer(struct chan *ch)
3919 1.5 augustss {
3920 1.179 mlelstv struct uaudio_softc *sc = ch->sc;
3921 1.5 augustss struct chanbuf *cb;
3922 1.5 augustss int i, size, residue, total;
3923 1.8 augustss
3924 1.179 mlelstv if (sc->sc_dying)
3925 1.8 augustss return;
3926 1.5 augustss
3927 1.5 augustss /* Pick the next channel buffer. */
3928 1.5 augustss cb = &ch->chanbufs[ch->curchanbuf];
3929 1.179 mlelstv if (++ch->curchanbuf >= ch->nchanbufs)
3930 1.5 augustss ch->curchanbuf = 0;
3931 1.5 augustss
3932 1.5 augustss /* Compute the size of each frame in the next transfer. */
3933 1.5 augustss residue = ch->residue;
3934 1.5 augustss total = 0;
3935 1.179 mlelstv for (i = 0; i < ch->nframes; i++) {
3936 1.5 augustss size = ch->bytes_per_frame;
3937 1.179 mlelstv #if 0
3938 1.179 mlelstv residue += ch->fraction;
3939 1.179 mlelstv if (residue >= sc->sc_usb_frames_per_second) {
3940 1.179 mlelstv if ((sc->sc_altflags & UA_NOFRAC) == 0)
3941 1.179 mlelstv size += ch->sample_size;
3942 1.179 mlelstv residue -= sc->sc_usb_frames_per_second;
3943 1.179 mlelstv }
3944 1.179 mlelstv #endif
3945 1.5 augustss cb->sizes[i] = size;
3946 1.62 toshii cb->offsets[i] = total;
3947 1.5 augustss total += size;
3948 1.5 augustss }
3949 1.5 augustss ch->residue = residue;
3950 1.5 augustss cb->size = total;
3951 1.5 augustss
3952 1.5 augustss #ifdef UAUDIO_DEBUG
3953 1.5 augustss if (uaudiodebug > 8) {
3954 1.122 mrg DPRINTF("buffer=%p, residue=0.%03d\n", cb->buffer, ch->residue);
3955 1.179 mlelstv for (i = 0; i < ch->nframes; i++) {
3956 1.122 mrg DPRINTF(" [%d] length %d\n", i, cb->sizes[i]);
3957 1.5 augustss }
3958 1.5 augustss }
3959 1.5 augustss #endif
3960 1.5 augustss
3961 1.122 mrg DPRINTFN(5, "transfer xfer=%p\n", cb->xfer);
3962 1.5 augustss /* Fill the request */
3963 1.179 mlelstv usbd_setup_isoc_xfer(cb->xfer, cb, cb->sizes, ch->nframes, 0,
3964 1.146 skrll uaudio_chan_rintr);
3965 1.5 augustss
3966 1.173 mlelstv usbd_status err = usbd_transfer(cb->xfer);
3967 1.173 mlelstv if (err != USBD_IN_PROGRESS && err != USBD_NORMAL_COMPLETION)
3968 1.179 mlelstv device_printf(sc->sc_dev, "rtransfer error %d\n", err);
3969 1.5 augustss }
3970 1.5 augustss
3971 1.86 kent Static void
3972 1.146 skrll uaudio_chan_rintr(struct usbd_xfer *xfer, void *priv,
3973 1.26 augustss usbd_status status)
3974 1.5 augustss {
3975 1.179 mlelstv struct uaudio_softc *sc;
3976 1.94 kent struct chanbuf *cb;
3977 1.94 kent struct chan *ch;
3978 1.94 kent uint32_t count;
3979 1.121 jmcneill int i, n, frsize;
3980 1.5 augustss
3981 1.94 kent cb = priv;
3982 1.94 kent ch = cb->chan;
3983 1.179 mlelstv sc = ch->sc;
3984 1.5 augustss /* Return if we are aborting. */
3985 1.5 augustss if (status == USBD_CANCELLED)
3986 1.5 augustss return;
3987 1.5 augustss
3988 1.173 mlelstv if (status != USBD_NORMAL_COMPLETION && status != USBD_SHORT_XFER)
3989 1.179 mlelstv device_printf(sc->sc_dev, "rintr error: %s\n",
3990 1.173 mlelstv usbd_errstr(status));
3991 1.173 mlelstv
3992 1.18 augustss usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
3993 1.122 mrg DPRINTFN(5, "count=%d, transferred=%d\n", count, ch->transferred);
3994 1.31 augustss
3995 1.62 toshii /* count < cb->size is normal for asynchronous source */
3996 1.1 augustss #ifdef DIAGNOSTIC
3997 1.62 toshii if (count > cb->size) {
3998 1.179 mlelstv device_printf(sc->sc_dev,
3999 1.171 mlelstv "uaudio_chan_rintr: count(%d) > size(%d) status(%d)\n",
4000 1.171 mlelstv count, cb->size, status);
4001 1.1 augustss }
4002 1.1 augustss #endif
4003 1.1 augustss
4004 1.56 kent /*
4005 1.5 augustss * Transfer data from channel buffer to upper layer buffer, taking
4006 1.5 augustss * care of wrapping the upper layer buffer.
4007 1.5 augustss */
4008 1.179 mlelstv for (i = 0; i < ch->nframes; i++) {
4009 1.62 toshii frsize = cb->sizes[i];
4010 1.157 riastrad n = uimin(frsize, ch->end - ch->cur);
4011 1.62 toshii memcpy(ch->cur, cb->buffer + cb->offsets[i], n);
4012 1.62 toshii ch->cur += n;
4013 1.62 toshii if (ch->cur >= ch->end)
4014 1.62 toshii ch->cur = ch->start;
4015 1.62 toshii if (frsize > n) {
4016 1.62 toshii memcpy(ch->cur, cb->buffer + cb->offsets[i] + n,
4017 1.62 toshii frsize - n);
4018 1.62 toshii ch->cur += frsize - n;
4019 1.62 toshii }
4020 1.5 augustss }
4021 1.5 augustss
4022 1.5 augustss /* Call back to upper layer */
4023 1.179 mlelstv mutex_enter(&sc->sc_intr_lock);
4024 1.62 toshii ch->transferred += count;
4025 1.1 augustss while (ch->transferred >= ch->blksize) {
4026 1.1 augustss ch->transferred -= ch->blksize;
4027 1.122 mrg DPRINTFN(5, "call %p(%p)\n", ch->intr, ch->arg);
4028 1.1 augustss ch->intr(ch->arg);
4029 1.1 augustss }
4030 1.179 mlelstv mutex_exit(&sc->sc_intr_lock);
4031 1.1 augustss
4032 1.1 augustss /* start next transfer */
4033 1.5 augustss uaudio_chan_rtransfer(ch);
4034 1.1 augustss }
4035 1.1 augustss
4036 1.86 kent Static void
4037 1.179 mlelstv uaudio_chan_init(struct chan *ch, int altidx,
4038 1.179 mlelstv const struct audio_params *param, int maxpktsize, bool isrecord)
4039 1.1 augustss {
4040 1.179 mlelstv struct uaudio_softc *sc = ch->sc;
4041 1.1 augustss int samples_per_frame, sample_size;
4042 1.1 augustss
4043 1.179 mlelstv DPRINTFN(5, "altidx=%d, %d/%d %dch %dHz ufps %u max %d\n",
4044 1.179 mlelstv altidx, param->validbits, param->precision, param->channels,
4045 1.179 mlelstv param->sample_rate, sc->sc_usb_frames_per_second, maxpktsize);
4046 1.179 mlelstv
4047 1.54 kent ch->altidx = altidx;
4048 1.93 kent sample_size = param->precision * param->channels / 8;
4049 1.179 mlelstv
4050 1.179 mlelstv if (isrecord) {
4051 1.179 mlelstv if (maxpktsize >= sample_size)
4052 1.179 mlelstv samples_per_frame = maxpktsize / sample_size;
4053 1.179 mlelstv else
4054 1.179 mlelstv samples_per_frame = param->sample_rate / sc->sc_usb_frames_per_second
4055 1.179 mlelstv + param->channels;
4056 1.179 mlelstv ch->fraction = 0;
4057 1.179 mlelstv } else {
4058 1.179 mlelstv samples_per_frame = param->sample_rate / sc->sc_usb_frames_per_second;
4059 1.179 mlelstv ch->fraction = param->sample_rate % sc->sc_usb_frames_per_second;
4060 1.179 mlelstv }
4061 1.179 mlelstv
4062 1.1 augustss ch->sample_size = sample_size;
4063 1.93 kent ch->sample_rate = param->sample_rate;
4064 1.179 mlelstv ch->bytes_per_frame = samples_per_frame * sample_size;
4065 1.179 mlelstv
4066 1.179 mlelstv if (maxpktsize > 0 && ch->bytes_per_frame > maxpktsize) {
4067 1.179 mlelstv samples_per_frame = maxpktsize / sample_size;
4068 1.65 toshii ch->bytes_per_frame = samples_per_frame * sample_size;
4069 1.65 toshii }
4070 1.179 mlelstv
4071 1.1 augustss ch->residue = 0;
4072 1.54 kent }
4073 1.1 augustss
4074 1.86 kent Static void
4075 1.54 kent uaudio_chan_set_param(struct chan *ch, u_char *start, u_char *end, int blksize)
4076 1.54 kent {
4077 1.94 kent
4078 1.1 augustss ch->start = start;
4079 1.1 augustss ch->end = end;
4080 1.1 augustss ch->cur = start;
4081 1.1 augustss ch->blksize = blksize;
4082 1.1 augustss ch->transferred = 0;
4083 1.1 augustss ch->curchanbuf = 0;
4084 1.1 augustss }
4085 1.1 augustss
4086 1.86 kent Static int
4087 1.160 isaki uaudio_set_format(void *addr, int setmode,
4088 1.160 isaki const audio_params_t *play, const audio_params_t *rec,
4089 1.160 isaki audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
4090 1.1 augustss {
4091 1.94 kent struct uaudio_softc *sc;
4092 1.94 kent int paltidx, raltidx;
4093 1.1 augustss
4094 1.94 kent sc = addr;
4095 1.94 kent paltidx = -1;
4096 1.94 kent raltidx = -1;
4097 1.1 augustss if (sc->sc_dying)
4098 1.94 kent return EIO;
4099 1.1 augustss
4100 1.160 isaki if ((setmode & AUMODE_PLAY) && sc->sc_playchan.altidx != -1) {
4101 1.47 jdolecek sc->sc_alts[sc->sc_playchan.altidx].sc_busy = 0;
4102 1.92 kent }
4103 1.160 isaki if ((setmode & AUMODE_RECORD) && sc->sc_recchan.altidx != -1) {
4104 1.47 jdolecek sc->sc_alts[sc->sc_recchan.altidx].sc_busy = 0;
4105 1.92 kent }
4106 1.47 jdolecek
4107 1.76 mycroft /* Some uaudio devices are unidirectional. Don't try to find a
4108 1.76 mycroft matching mode for the unsupported direction. */
4109 1.76 mycroft setmode &= sc->sc_mode;
4110 1.76 mycroft
4111 1.73 mycroft if ((setmode & AUMODE_PLAY)) {
4112 1.160 isaki paltidx = audio_indexof_format(sc->sc_formats, sc->sc_nformats,
4113 1.160 isaki AUMODE_PLAY, play);
4114 1.160 isaki /* Transfer should have halted */
4115 1.179 mlelstv uaudio_chan_init(&sc->sc_playchan, paltidx, play,
4116 1.179 mlelstv UGETW(sc->sc_alts[paltidx].edesc->wMaxPacketSize), false);
4117 1.47 jdolecek }
4118 1.73 mycroft if ((setmode & AUMODE_RECORD)) {
4119 1.160 isaki raltidx = audio_indexof_format(sc->sc_formats, sc->sc_nformats,
4120 1.160 isaki AUMODE_RECORD, rec);
4121 1.160 isaki /* Transfer should have halted */
4122 1.169 isaki uaudio_chan_init(&sc->sc_recchan, raltidx, rec,
4123 1.179 mlelstv UGETW(sc->sc_alts[raltidx].edesc->wMaxPacketSize), true);
4124 1.47 jdolecek }
4125 1.47 jdolecek
4126 1.160 isaki if ((setmode & AUMODE_PLAY) && sc->sc_playchan.altidx != -1) {
4127 1.73 mycroft sc->sc_alts[sc->sc_playchan.altidx].sc_busy = 1;
4128 1.92 kent }
4129 1.160 isaki if ((setmode & AUMODE_RECORD) && sc->sc_recchan.altidx != -1) {
4130 1.73 mycroft sc->sc_alts[sc->sc_recchan.altidx].sc_busy = 1;
4131 1.92 kent }
4132 1.73 mycroft
4133 1.122 mrg DPRINTF("use altidx=p%d/r%d, altno=p%d/r%d\n",
4134 1.56 kent sc->sc_playchan.altidx, sc->sc_recchan.altidx,
4135 1.47 jdolecek (sc->sc_playchan.altidx >= 0)
4136 1.47 jdolecek ?sc->sc_alts[sc->sc_playchan.altidx].idesc->bAlternateSetting
4137 1.47 jdolecek : -1,
4138 1.47 jdolecek (sc->sc_recchan.altidx >= 0)
4139 1.47 jdolecek ? sc->sc_alts[sc->sc_recchan.altidx].idesc->bAlternateSetting
4140 1.122 mrg : -1);
4141 1.56 kent
4142 1.94 kent return 0;
4143 1.1 augustss }
4144 1.1 augustss
4145 1.86 kent Static usbd_status
4146 1.179 mlelstv uaudio_speed(struct uaudio_softc *sc, int endpt, int clkid,
4147 1.179 mlelstv uint8_t *data, int set)
4148 1.1 augustss {
4149 1.1 augustss usb_device_request_t req;
4150 1.175 mlelstv
4151 1.175 mlelstv switch (sc->sc_version) {
4152 1.175 mlelstv case UAUDIO_VERSION1:
4153 1.179 mlelstv req.bmRequestType = set ?
4154 1.179 mlelstv UT_WRITE_CLASS_ENDPOINT
4155 1.179 mlelstv : UT_READ_CLASS_ENDPOINT;
4156 1.179 mlelstv req.bRequest = set ?
4157 1.179 mlelstv SET_CUR
4158 1.179 mlelstv : GET_CUR;
4159 1.175 mlelstv USETW2(req.wValue, SAMPLING_FREQ_CONTROL, 0);
4160 1.175 mlelstv USETW(req.wIndex, endpt);
4161 1.175 mlelstv USETW(req.wLength, 3);
4162 1.175 mlelstv break;
4163 1.175 mlelstv case UAUDIO_VERSION2:
4164 1.179 mlelstv req.bmRequestType = set ?
4165 1.179 mlelstv UT_WRITE_CLASS_INTERFACE
4166 1.179 mlelstv : UT_READ_CLASS_INTERFACE;
4167 1.175 mlelstv req.bRequest = V2_CUR;
4168 1.175 mlelstv USETW2(req.wValue, SAMPLING_FREQ_CONTROL, 0);
4169 1.179 mlelstv USETW2(req.wIndex, clkid, sc->sc_ac_iface);
4170 1.175 mlelstv USETW(req.wLength, 4);
4171 1.175 mlelstv break;
4172 1.175 mlelstv }
4173 1.1 augustss
4174 1.179 mlelstv return usbd_do_request(sc->sc_udev, &req, data);
4175 1.179 mlelstv }
4176 1.179 mlelstv
4177 1.179 mlelstv Static usbd_status
4178 1.179 mlelstv uaudio_set_speed(struct uaudio_softc *sc, int endpt, int clkid, u_int speed)
4179 1.179 mlelstv {
4180 1.179 mlelstv uint8_t data[4];
4181 1.179 mlelstv
4182 1.179 mlelstv DPRINTFN(5, "endpt=%d clkid=%u speed=%u\n", endpt, clkid, speed);
4183 1.179 mlelstv
4184 1.179 mlelstv data[0] = speed;
4185 1.179 mlelstv data[1] = speed >> 8;
4186 1.179 mlelstv data[2] = speed >> 16;
4187 1.179 mlelstv data[3] = speed >> 24;
4188 1.121 jmcneill
4189 1.179 mlelstv return uaudio_speed(sc, endpt, clkid, data, 1);
4190 1.1 augustss }
4191 1.114 kent
4192 1.179 mlelstv #ifdef UAUDIO_DEBUG
4193 1.179 mlelstv SYSCTL_SETUP(sysctl_hw_uaudio_setup, "sysctl hw.uaudio setup")
4194 1.179 mlelstv {
4195 1.179 mlelstv int err;
4196 1.179 mlelstv const struct sysctlnode *rnode;
4197 1.179 mlelstv const struct sysctlnode *cnode;
4198 1.179 mlelstv
4199 1.179 mlelstv err = sysctl_createv(clog, 0, NULL, &rnode,
4200 1.179 mlelstv CTLFLAG_PERMANENT, CTLTYPE_NODE, "uaudio",
4201 1.179 mlelstv SYSCTL_DESCR("uaudio global controls"),
4202 1.179 mlelstv NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL);
4203 1.179 mlelstv
4204 1.179 mlelstv if (err)
4205 1.179 mlelstv goto fail;
4206 1.179 mlelstv
4207 1.179 mlelstv /* control debugging printfs */
4208 1.179 mlelstv err = sysctl_createv(clog, 0, &rnode, &cnode,
4209 1.179 mlelstv CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
4210 1.179 mlelstv "debug", SYSCTL_DESCR("Enable debugging output"),
4211 1.179 mlelstv NULL, 0, &uaudiodebug, sizeof(uaudiodebug), CTL_CREATE, CTL_EOL);
4212 1.179 mlelstv if (err)
4213 1.179 mlelstv goto fail;
4214 1.179 mlelstv
4215 1.179 mlelstv return;
4216 1.179 mlelstv fail:
4217 1.179 mlelstv aprint_error("%s: sysctl_createv failed (err = %d)\n", __func__, err);
4218 1.179 mlelstv }
4219 1.179 mlelstv #endif
4220 1.179 mlelstv
4221 1.114 kent #ifdef _MODULE
4222 1.114 kent
4223 1.114 kent MODULE(MODULE_CLASS_DRIVER, uaudio, NULL);
4224 1.114 kent
4225 1.114 kent static const struct cfiattrdata audiobuscf_iattrdata = {
4226 1.114 kent "audiobus", 0, { { NULL, NULL, 0 }, }
4227 1.114 kent };
4228 1.114 kent static const struct cfiattrdata * const uaudio_attrs[] = {
4229 1.114 kent &audiobuscf_iattrdata, NULL
4230 1.114 kent };
4231 1.114 kent CFDRIVER_DECL(uaudio, DV_DULL, uaudio_attrs);
4232 1.114 kent extern struct cfattach uaudio_ca;
4233 1.114 kent static int uaudioloc[6/*USBIFIFCF_NLOCS*/] = {
4234 1.114 kent -1/*USBIFIFCF_PORT_DEFAULT*/,
4235 1.114 kent -1/*USBIFIFCF_CONFIGURATION_DEFAULT*/,
4236 1.114 kent -1/*USBIFIFCF_INTERFACE_DEFAULT*/,
4237 1.114 kent -1/*USBIFIFCF_VENDOR_DEFAULT*/,
4238 1.114 kent -1/*USBIFIFCF_PRODUCT_DEFAULT*/,
4239 1.114 kent -1/*USBIFIFCF_RELEASE_DEFAULT*/};
4240 1.114 kent static struct cfparent uhubparent = {
4241 1.114 kent "usbifif", NULL, DVUNIT_ANY
4242 1.114 kent };
4243 1.114 kent static struct cfdata uaudio_cfdata[] = {
4244 1.114 kent {
4245 1.114 kent .cf_name = "uaudio",
4246 1.114 kent .cf_atname = "uaudio",
4247 1.114 kent .cf_unit = 0,
4248 1.114 kent .cf_fstate = FSTATE_STAR,
4249 1.114 kent .cf_loc = uaudioloc,
4250 1.114 kent .cf_flags = 0,
4251 1.114 kent .cf_pspec = &uhubparent,
4252 1.114 kent },
4253 1.114 kent { NULL }
4254 1.114 kent };
4255 1.114 kent
4256 1.114 kent static int
4257 1.114 kent uaudio_modcmd(modcmd_t cmd, void *arg)
4258 1.114 kent {
4259 1.114 kent int err;
4260 1.114 kent
4261 1.114 kent switch (cmd) {
4262 1.114 kent case MODULE_CMD_INIT:
4263 1.114 kent err = config_cfdriver_attach(&uaudio_cd);
4264 1.114 kent if (err) {
4265 1.114 kent return err;
4266 1.114 kent }
4267 1.114 kent err = config_cfattach_attach("uaudio", &uaudio_ca);
4268 1.114 kent if (err) {
4269 1.114 kent config_cfdriver_detach(&uaudio_cd);
4270 1.114 kent return err;
4271 1.114 kent }
4272 1.114 kent err = config_cfdata_attach(uaudio_cfdata, 1);
4273 1.114 kent if (err) {
4274 1.114 kent config_cfattach_detach("uaudio", &uaudio_ca);
4275 1.114 kent config_cfdriver_detach(&uaudio_cd);
4276 1.114 kent return err;
4277 1.114 kent }
4278 1.114 kent return 0;
4279 1.114 kent case MODULE_CMD_FINI:
4280 1.114 kent err = config_cfdata_detach(uaudio_cfdata);
4281 1.114 kent if (err)
4282 1.114 kent return err;
4283 1.114 kent config_cfattach_detach("uaudio", &uaudio_ca);
4284 1.114 kent config_cfdriver_detach(&uaudio_cd);
4285 1.114 kent return 0;
4286 1.114 kent default:
4287 1.114 kent return ENOTTY;
4288 1.114 kent }
4289 1.114 kent }
4290 1.114 kent
4291 1.114 kent #endif
4292