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