1 |
/* $MidnightBSD$ */ |
2 |
/* $NetBSD: uaudio.c,v 1.91 2004/11/05 17:46:14 kent Exp $ */ |
3 |
/* $FreeBSD: stable/10/sys/dev/sound/usb/uaudio.c 345546 2019-03-26 13:53:33Z hselasky $ */ |
4 |
|
5 |
/*- |
6 |
* Copyright (c) 1999 The NetBSD Foundation, Inc. |
7 |
* All rights reserved. |
8 |
* |
9 |
* This code is derived from software contributed to The NetBSD Foundation |
10 |
* by Lennart Augustsson (lennart@augustsson.net) at |
11 |
* Carlstedt Research & Technology. |
12 |
* |
13 |
* Redistribution and use in source and binary forms, with or without |
14 |
* modification, are permitted provided that the following conditions |
15 |
* are met: |
16 |
* 1. Redistributions of source code must retain the above copyright |
17 |
* notice, this list of conditions and the following disclaimer. |
18 |
* 2. Redistributions in binary form must reproduce the above copyright |
19 |
* notice, this list of conditions and the following disclaimer in the |
20 |
* documentation and/or other materials provided with the distribution. |
21 |
* |
22 |
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
23 |
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
24 |
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
25 |
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
26 |
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
27 |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
28 |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
29 |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
30 |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
31 |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
32 |
* POSSIBILITY OF SUCH DAMAGE. |
33 |
*/ |
34 |
|
35 |
#include <sys/cdefs.h> |
36 |
__FBSDID("$FreeBSD: stable/10/sys/dev/sound/usb/uaudio.c 345546 2019-03-26 13:53:33Z hselasky $"); |
37 |
|
38 |
/* |
39 |
* USB audio specs: http://www.usb.org/developers/devclass_docs/audio10.pdf |
40 |
* http://www.usb.org/developers/devclass_docs/frmts10.pdf |
41 |
* http://www.usb.org/developers/devclass_docs/termt10.pdf |
42 |
*/ |
43 |
|
44 |
/* |
45 |
* Also merged: |
46 |
* $NetBSD: uaudio.c,v 1.94 2005/01/15 15:19:53 kent Exp $ |
47 |
* $NetBSD: uaudio.c,v 1.95 2005/01/16 06:02:19 dsainty Exp $ |
48 |
* $NetBSD: uaudio.c,v 1.96 2005/01/16 12:46:00 kent Exp $ |
49 |
* $NetBSD: uaudio.c,v 1.97 2005/02/24 08:19:38 martin Exp $ |
50 |
*/ |
51 |
|
52 |
#include <sys/stdint.h> |
53 |
#include <sys/stddef.h> |
54 |
#include <sys/param.h> |
55 |
#include <sys/queue.h> |
56 |
#include <sys/types.h> |
57 |
#include <sys/systm.h> |
58 |
#include <sys/kernel.h> |
59 |
#include <sys/bus.h> |
60 |
#include <sys/module.h> |
61 |
#include <sys/lock.h> |
62 |
#include <sys/mutex.h> |
63 |
#include <sys/condvar.h> |
64 |
#include <sys/sysctl.h> |
65 |
#include <sys/sx.h> |
66 |
#include <sys/unistd.h> |
67 |
#include <sys/callout.h> |
68 |
#include <sys/malloc.h> |
69 |
#include <sys/priv.h> |
70 |
|
71 |
#include "usbdevs.h" |
72 |
#include <dev/usb/usb.h> |
73 |
#include <dev/usb/usbdi.h> |
74 |
#include <dev/usb/usbdi_util.h> |
75 |
#include <dev/usb/usbhid.h> |
76 |
#include <dev/usb/usb_request.h> |
77 |
#include <dev/usb/usb_process.h> |
78 |
|
79 |
#define USB_DEBUG_VAR uaudio_debug |
80 |
#include <dev/usb/usb_debug.h> |
81 |
|
82 |
#include <dev/usb/quirk/usb_quirk.h> |
83 |
|
84 |
#include <sys/reboot.h> /* for bootverbose */ |
85 |
|
86 |
#ifdef HAVE_KERNEL_OPTION_HEADERS |
87 |
#include "opt_snd.h" |
88 |
#endif |
89 |
|
90 |
#include <dev/sound/pcm/sound.h> |
91 |
#include <dev/sound/usb/uaudioreg.h> |
92 |
#include <dev/sound/usb/uaudio.h> |
93 |
#include <dev/sound/chip.h> |
94 |
#include "feeder_if.h" |
95 |
|
96 |
static int uaudio_default_rate = 0; /* use rate list */ |
97 |
static int uaudio_default_bits = 32; |
98 |
static int uaudio_default_channels = 0; /* use default */ |
99 |
static int uaudio_buffer_ms = 8; |
100 |
|
101 |
#ifdef USB_DEBUG |
102 |
static int uaudio_debug; |
103 |
|
104 |
static SYSCTL_NODE(_hw_usb, OID_AUTO, uaudio, CTLFLAG_RW, 0, "USB uaudio"); |
105 |
|
106 |
SYSCTL_INT(_hw_usb_uaudio, OID_AUTO, debug, CTLFLAG_RW, |
107 |
&uaudio_debug, 0, "uaudio debug level"); |
108 |
|
109 |
TUNABLE_INT("hw.usb.uaudio.default_rate", &uaudio_default_rate); |
110 |
SYSCTL_INT(_hw_usb_uaudio, OID_AUTO, default_rate, CTLFLAG_RW, |
111 |
&uaudio_default_rate, 0, "uaudio default sample rate"); |
112 |
|
113 |
TUNABLE_INT("hw.usb.uaudio.default_bits", &uaudio_default_bits); |
114 |
SYSCTL_INT(_hw_usb_uaudio, OID_AUTO, default_bits, CTLFLAG_RW, |
115 |
&uaudio_default_bits, 0, "uaudio default sample bits"); |
116 |
|
117 |
TUNABLE_INT("hw.usb.uaudio.default_channels", &uaudio_default_channels); |
118 |
SYSCTL_INT(_hw_usb_uaudio, OID_AUTO, default_channels, CTLFLAG_RW, |
119 |
&uaudio_default_channels, 0, "uaudio default sample channels"); |
120 |
|
121 |
static int |
122 |
uaudio_buffer_ms_sysctl(SYSCTL_HANDLER_ARGS) |
123 |
{ |
124 |
int err, val; |
125 |
|
126 |
val = uaudio_buffer_ms; |
127 |
err = sysctl_handle_int(oidp, &val, 0, req); |
128 |
|
129 |
if (err != 0 || req->newptr == NULL || val == uaudio_buffer_ms) |
130 |
return (err); |
131 |
|
132 |
if (val > 8) |
133 |
val = 8; |
134 |
else if (val < 2) |
135 |
val = 2; |
136 |
|
137 |
uaudio_buffer_ms = val; |
138 |
|
139 |
return (0); |
140 |
} |
141 |
SYSCTL_PROC(_hw_usb_uaudio, OID_AUTO, buffer_ms, CTLTYPE_INT | CTLFLAG_RWTUN, |
142 |
0, sizeof(int), uaudio_buffer_ms_sysctl, "I", |
143 |
"uaudio buffering delay from 2ms to 8ms"); |
144 |
#else |
145 |
#define uaudio_debug 0 |
146 |
#endif |
147 |
|
148 |
#define UAUDIO_NFRAMES 64 /* must be factor of 8 due HS-USB */ |
149 |
#define UAUDIO_NCHANBUFS 2 /* number of outstanding request */ |
150 |
#define UAUDIO_RECURSE_LIMIT 255 /* rounds */ |
151 |
#define UAUDIO_CHANNELS_MAX MIN(64, AFMT_CHANNEL_MAX) |
152 |
#define UAUDIO_MATRIX_MAX 8 /* channels */ |
153 |
|
154 |
#define MAKE_WORD(h,l) (((h) << 8) | (l)) |
155 |
#define BIT_TEST(bm,bno) (((bm)[(bno) / 8] >> (7 - ((bno) % 8))) & 1) |
156 |
#define UAUDIO_MAX_CHAN(x) (x) |
157 |
#define MIX(sc) ((sc)->sc_mixer_node) |
158 |
|
159 |
union uaudio_asid { |
160 |
const struct usb_audio_streaming_interface_descriptor *v1; |
161 |
const struct usb_audio20_streaming_interface_descriptor *v2; |
162 |
}; |
163 |
|
164 |
union uaudio_asf1d { |
165 |
const struct usb_audio_streaming_type1_descriptor *v1; |
166 |
const struct usb_audio20_streaming_type1_descriptor *v2; |
167 |
}; |
168 |
|
169 |
union uaudio_sed { |
170 |
const struct usb_audio_streaming_endpoint_descriptor *v1; |
171 |
const struct usb_audio20_streaming_endpoint_descriptor *v2; |
172 |
}; |
173 |
|
174 |
struct uaudio_mixer_node { |
175 |
const char *name; |
176 |
|
177 |
int32_t minval; |
178 |
int32_t maxval; |
179 |
#define MIX_MAX_CHAN 16 |
180 |
int32_t wValue[MIX_MAX_CHAN]; /* using nchan */ |
181 |
uint32_t mul; |
182 |
uint32_t ctl; |
183 |
|
184 |
int wData[MIX_MAX_CHAN]; /* using nchan */ |
185 |
uint16_t wIndex; |
186 |
|
187 |
uint8_t update[(MIX_MAX_CHAN + 7) / 8]; |
188 |
uint8_t nchan; |
189 |
uint8_t type; |
190 |
#define MIX_ON_OFF 1 |
191 |
#define MIX_SIGNED_16 2 |
192 |
#define MIX_UNSIGNED_16 3 |
193 |
#define MIX_SIGNED_8 4 |
194 |
#define MIX_SELECTOR 5 |
195 |
#define MIX_UNKNOWN 6 |
196 |
#define MIX_SIZE(n) ((((n) == MIX_SIGNED_16) || \ |
197 |
((n) == MIX_UNSIGNED_16)) ? 2 : 1) |
198 |
#define MIX_UNSIGNED(n) ((n) == MIX_UNSIGNED_16) |
199 |
|
200 |
#define MAX_SELECTOR_INPUT_PIN 256 |
201 |
uint8_t slctrtype[MAX_SELECTOR_INPUT_PIN]; |
202 |
uint8_t class; |
203 |
uint8_t val_default; |
204 |
|
205 |
uint8_t desc[64]; |
206 |
|
207 |
struct uaudio_mixer_node *next; |
208 |
}; |
209 |
|
210 |
struct uaudio_configure_msg { |
211 |
struct usb_proc_msg hdr; |
212 |
struct uaudio_softc *sc; |
213 |
}; |
214 |
|
215 |
#define CHAN_MAX_ALT 24 |
216 |
|
217 |
struct uaudio_chan_alt { |
218 |
union uaudio_asf1d p_asf1d; |
219 |
union uaudio_sed p_sed; |
220 |
const usb_endpoint_descriptor_audio_t *p_ed1; |
221 |
const struct uaudio_format *p_fmt; |
222 |
const struct usb_config *usb_cfg; |
223 |
uint32_t sample_rate; /* in Hz */ |
224 |
uint16_t sample_size; |
225 |
uint8_t iface_index; |
226 |
uint8_t iface_alt_index; |
227 |
uint8_t channels; |
228 |
}; |
229 |
|
230 |
struct uaudio_chan { |
231 |
struct pcmchan_caps pcm_cap; /* capabilities */ |
232 |
struct uaudio_chan_alt usb_alt[CHAN_MAX_ALT]; |
233 |
struct snd_dbuf *pcm_buf; |
234 |
struct mtx *pcm_mtx; /* lock protecting this structure */ |
235 |
struct uaudio_softc *priv_sc; |
236 |
struct pcm_channel *pcm_ch; |
237 |
struct usb_xfer *xfer[UAUDIO_NCHANBUFS + 1]; |
238 |
|
239 |
uint8_t *buf; /* pointer to buffer */ |
240 |
uint8_t *start; /* upper layer buffer start */ |
241 |
uint8_t *end; /* upper layer buffer end */ |
242 |
uint8_t *cur; /* current position in upper layer |
243 |
* buffer */ |
244 |
|
245 |
uint32_t intr_frames; /* in units */ |
246 |
uint32_t frames_per_second; |
247 |
uint32_t sample_rem; |
248 |
uint32_t sample_curr; |
249 |
uint32_t max_buf; |
250 |
int32_t jitter_rem; |
251 |
int32_t jitter_curr; |
252 |
|
253 |
int feedback_rate; |
254 |
|
255 |
uint32_t pcm_format[2]; |
256 |
|
257 |
uint16_t bytes_per_frame[2]; |
258 |
|
259 |
uint32_t intr_counter; |
260 |
uint32_t running; |
261 |
uint32_t num_alt; |
262 |
uint32_t cur_alt; |
263 |
uint32_t set_alt; |
264 |
uint32_t operation; |
265 |
#define CHAN_OP_NONE 0 |
266 |
#define CHAN_OP_START 1 |
267 |
#define CHAN_OP_STOP 2 |
268 |
#define CHAN_OP_DRAIN 3 |
269 |
}; |
270 |
|
271 |
#define UMIDI_EMB_JACK_MAX 16 /* units */ |
272 |
#define UMIDI_TX_FRAMES 256 /* units */ |
273 |
#define UMIDI_TX_BUFFER (UMIDI_TX_FRAMES * 4) /* bytes */ |
274 |
|
275 |
enum { |
276 |
UMIDI_TX_TRANSFER, |
277 |
UMIDI_RX_TRANSFER, |
278 |
UMIDI_N_TRANSFER, |
279 |
}; |
280 |
|
281 |
struct umidi_sub_chan { |
282 |
struct usb_fifo_sc fifo; |
283 |
uint8_t *temp_cmd; |
284 |
uint8_t temp_0[4]; |
285 |
uint8_t temp_1[4]; |
286 |
uint8_t state; |
287 |
#define UMIDI_ST_UNKNOWN 0 /* scan for command */ |
288 |
#define UMIDI_ST_1PARAM 1 |
289 |
#define UMIDI_ST_2PARAM_1 2 |
290 |
#define UMIDI_ST_2PARAM_2 3 |
291 |
#define UMIDI_ST_SYSEX_0 4 |
292 |
#define UMIDI_ST_SYSEX_1 5 |
293 |
#define UMIDI_ST_SYSEX_2 6 |
294 |
|
295 |
uint8_t read_open:1; |
296 |
uint8_t write_open:1; |
297 |
uint8_t unused:6; |
298 |
}; |
299 |
|
300 |
struct umidi_chan { |
301 |
|
302 |
struct umidi_sub_chan sub[UMIDI_EMB_JACK_MAX]; |
303 |
struct mtx mtx; |
304 |
|
305 |
struct usb_xfer *xfer[UMIDI_N_TRANSFER]; |
306 |
|
307 |
uint8_t iface_index; |
308 |
uint8_t iface_alt_index; |
309 |
|
310 |
uint8_t read_open_refcount; |
311 |
uint8_t write_open_refcount; |
312 |
|
313 |
uint8_t curr_cable; |
314 |
uint8_t max_emb_jack; |
315 |
uint8_t valid; |
316 |
uint8_t single_command; |
317 |
}; |
318 |
|
319 |
struct uaudio_search_result { |
320 |
uint8_t bit_input[(256 + 7) / 8]; |
321 |
uint8_t bit_output[(256 + 7) / 8]; |
322 |
uint8_t recurse_level; |
323 |
uint8_t id_max; |
324 |
uint8_t is_input; |
325 |
}; |
326 |
|
327 |
enum { |
328 |
UAUDIO_HID_RX_TRANSFER, |
329 |
UAUDIO_HID_N_TRANSFER, |
330 |
}; |
331 |
|
332 |
struct uaudio_hid { |
333 |
struct usb_xfer *xfer[UAUDIO_HID_N_TRANSFER]; |
334 |
struct hid_location volume_up_loc; |
335 |
struct hid_location volume_down_loc; |
336 |
struct hid_location mute_loc; |
337 |
uint32_t flags; |
338 |
#define UAUDIO_HID_VALID 0x0001 |
339 |
#define UAUDIO_HID_HAS_ID 0x0002 |
340 |
#define UAUDIO_HID_HAS_VOLUME_UP 0x0004 |
341 |
#define UAUDIO_HID_HAS_VOLUME_DOWN 0x0008 |
342 |
#define UAUDIO_HID_HAS_MUTE 0x0010 |
343 |
uint8_t iface_index; |
344 |
uint8_t volume_up_id; |
345 |
uint8_t volume_down_id; |
346 |
uint8_t mute_id; |
347 |
}; |
348 |
|
349 |
#define UAUDIO_SPDIF_OUT 0x01 /* Enable S/PDIF output */ |
350 |
#define UAUDIO_SPDIF_OUT_48K 0x02 /* Out sample rate = 48K */ |
351 |
#define UAUDIO_SPDIF_OUT_96K 0x04 /* Out sample rate = 96K */ |
352 |
#define UAUDIO_SPDIF_IN_MIX 0x10 /* Input mix enable */ |
353 |
|
354 |
struct uaudio_softc { |
355 |
struct sbuf sc_sndstat; |
356 |
struct sndcard_func sc_sndcard_func; |
357 |
struct uaudio_chan sc_rec_chan; |
358 |
struct uaudio_chan sc_play_chan; |
359 |
struct umidi_chan sc_midi_chan; |
360 |
struct uaudio_hid sc_hid; |
361 |
struct uaudio_search_result sc_mixer_clocks; |
362 |
struct uaudio_mixer_node sc_mixer_node; |
363 |
struct uaudio_configure_msg sc_config_msg[2]; |
364 |
|
365 |
struct mtx *sc_mixer_lock; |
366 |
struct snd_mixer *sc_mixer_dev; |
367 |
struct usb_device *sc_udev; |
368 |
struct usb_xfer *sc_mixer_xfer[1]; |
369 |
struct uaudio_mixer_node *sc_mixer_root; |
370 |
struct uaudio_mixer_node *sc_mixer_curr; |
371 |
int (*sc_set_spdif_fn) (struct uaudio_softc *, int); |
372 |
|
373 |
uint32_t sc_mix_info; |
374 |
uint32_t sc_recsrc_info; |
375 |
|
376 |
uint16_t sc_audio_rev; |
377 |
uint16_t sc_mixer_count; |
378 |
|
379 |
uint8_t sc_sndstat_valid; |
380 |
uint8_t sc_mixer_iface_index; |
381 |
uint8_t sc_mixer_iface_no; |
382 |
uint8_t sc_mixer_chan; |
383 |
uint8_t sc_pcm_registered:1; |
384 |
uint8_t sc_mixer_init:1; |
385 |
uint8_t sc_uq_audio_swap_lr:1; |
386 |
uint8_t sc_uq_au_inp_async:1; |
387 |
uint8_t sc_uq_au_no_xu:1; |
388 |
uint8_t sc_uq_bad_adc:1; |
389 |
uint8_t sc_uq_au_vendor_class:1; |
390 |
uint8_t sc_pcm_bitperfect:1; |
391 |
}; |
392 |
|
393 |
struct uaudio_terminal_node { |
394 |
union { |
395 |
const struct usb_descriptor *desc; |
396 |
const struct usb_audio_input_terminal *it_v1; |
397 |
const struct usb_audio_output_terminal *ot_v1; |
398 |
const struct usb_audio_mixer_unit_0 *mu_v1; |
399 |
const struct usb_audio_selector_unit *su_v1; |
400 |
const struct usb_audio_feature_unit *fu_v1; |
401 |
const struct usb_audio_processing_unit_0 *pu_v1; |
402 |
const struct usb_audio_extension_unit_0 *eu_v1; |
403 |
const struct usb_audio20_clock_source_unit *csrc_v2; |
404 |
const struct usb_audio20_clock_selector_unit_0 *csel_v2; |
405 |
const struct usb_audio20_clock_multiplier_unit *cmul_v2; |
406 |
const struct usb_audio20_input_terminal *it_v2; |
407 |
const struct usb_audio20_output_terminal *ot_v2; |
408 |
const struct usb_audio20_mixer_unit_0 *mu_v2; |
409 |
const struct usb_audio20_selector_unit *su_v2; |
410 |
const struct usb_audio20_feature_unit *fu_v2; |
411 |
const struct usb_audio20_sample_rate_unit *ru_v2; |
412 |
const struct usb_audio20_processing_unit_0 *pu_v2; |
413 |
const struct usb_audio20_extension_unit_0 *eu_v2; |
414 |
const struct usb_audio20_effect_unit *ef_v2; |
415 |
} u; |
416 |
struct uaudio_search_result usr; |
417 |
struct uaudio_terminal_node *root; |
418 |
}; |
419 |
|
420 |
struct uaudio_format { |
421 |
uint16_t wFormat; |
422 |
uint8_t bPrecision; |
423 |
uint32_t freebsd_fmt; |
424 |
const char *description; |
425 |
}; |
426 |
|
427 |
static const struct uaudio_format uaudio10_formats[] = { |
428 |
|
429 |
{UA_FMT_PCM8, 8, AFMT_U8, "8-bit U-LE PCM"}, |
430 |
{UA_FMT_PCM8, 16, AFMT_U16_LE, "16-bit U-LE PCM"}, |
431 |
{UA_FMT_PCM8, 24, AFMT_U24_LE, "24-bit U-LE PCM"}, |
432 |
{UA_FMT_PCM8, 32, AFMT_U32_LE, "32-bit U-LE PCM"}, |
433 |
|
434 |
{UA_FMT_PCM, 8, AFMT_S8, "8-bit S-LE PCM"}, |
435 |
{UA_FMT_PCM, 16, AFMT_S16_LE, "16-bit S-LE PCM"}, |
436 |
{UA_FMT_PCM, 24, AFMT_S24_LE, "24-bit S-LE PCM"}, |
437 |
{UA_FMT_PCM, 32, AFMT_S32_LE, "32-bit S-LE PCM"}, |
438 |
|
439 |
{UA_FMT_ALAW, 8, AFMT_A_LAW, "8-bit A-Law"}, |
440 |
{UA_FMT_MULAW, 8, AFMT_MU_LAW, "8-bit mu-Law"}, |
441 |
|
442 |
{0, 0, 0, NULL} |
443 |
}; |
444 |
|
445 |
static const struct uaudio_format uaudio20_formats[] = { |
446 |
|
447 |
{UA20_FMT_PCM, 8, AFMT_S8, "8-bit S-LE PCM"}, |
448 |
{UA20_FMT_PCM, 16, AFMT_S16_LE, "16-bit S-LE PCM"}, |
449 |
{UA20_FMT_PCM, 24, AFMT_S24_LE, "24-bit S-LE PCM"}, |
450 |
{UA20_FMT_PCM, 32, AFMT_S32_LE, "32-bit S-LE PCM"}, |
451 |
|
452 |
{UA20_FMT_PCM8, 8, AFMT_U8, "8-bit U-LE PCM"}, |
453 |
{UA20_FMT_PCM8, 16, AFMT_U16_LE, "16-bit U-LE PCM"}, |
454 |
{UA20_FMT_PCM8, 24, AFMT_U24_LE, "24-bit U-LE PCM"}, |
455 |
{UA20_FMT_PCM8, 32, AFMT_U32_LE, "32-bit U-LE PCM"}, |
456 |
|
457 |
{UA20_FMT_ALAW, 8, AFMT_A_LAW, "8-bit A-Law"}, |
458 |
{UA20_FMT_MULAW, 8, AFMT_MU_LAW, "8-bit mu-Law"}, |
459 |
|
460 |
{0, 0, 0, NULL} |
461 |
}; |
462 |
|
463 |
#define UAC_OUTPUT 0 |
464 |
#define UAC_INPUT 1 |
465 |
#define UAC_EQUAL 2 |
466 |
#define UAC_RECORD 3 |
467 |
#define UAC_NCLASSES 4 |
468 |
|
469 |
#ifdef USB_DEBUG |
470 |
static const char *uac_names[] = { |
471 |
"outputs", "inputs", "equalization", "record" |
472 |
}; |
473 |
|
474 |
#endif |
475 |
|
476 |
/* prototypes */ |
477 |
|
478 |
static device_probe_t uaudio_probe; |
479 |
static device_attach_t uaudio_attach; |
480 |
static device_detach_t uaudio_detach; |
481 |
|
482 |
static usb_callback_t uaudio_chan_play_callback; |
483 |
static usb_callback_t uaudio_chan_play_sync_callback; |
484 |
static usb_callback_t uaudio_chan_record_callback; |
485 |
static usb_callback_t uaudio_chan_record_sync_callback; |
486 |
static usb_callback_t uaudio_mixer_write_cfg_callback; |
487 |
static usb_callback_t umidi_bulk_read_callback; |
488 |
static usb_callback_t umidi_bulk_write_callback; |
489 |
static usb_callback_t uaudio_hid_rx_callback; |
490 |
|
491 |
static usb_proc_callback_t uaudio_configure_msg; |
492 |
|
493 |
/* ==== USB mixer ==== */ |
494 |
|
495 |
static int uaudio_mixer_sysctl_handler(SYSCTL_HANDLER_ARGS); |
496 |
static void uaudio_mixer_ctl_free(struct uaudio_softc *); |
497 |
static void uaudio_mixer_register_sysctl(struct uaudio_softc *, device_t); |
498 |
static void uaudio_mixer_reload_all(struct uaudio_softc *); |
499 |
static void uaudio_mixer_controls_create_ftu(struct uaudio_softc *); |
500 |
|
501 |
/* ==== USB audio v1.0 ==== */ |
502 |
|
503 |
static void uaudio_mixer_add_mixer(struct uaudio_softc *, |
504 |
const struct uaudio_terminal_node *, int); |
505 |
static void uaudio_mixer_add_selector(struct uaudio_softc *, |
506 |
const struct uaudio_terminal_node *, int); |
507 |
static uint32_t uaudio_mixer_feature_get_bmaControls( |
508 |
const struct usb_audio_feature_unit *, uint8_t); |
509 |
static void uaudio_mixer_add_feature(struct uaudio_softc *, |
510 |
const struct uaudio_terminal_node *, int); |
511 |
static void uaudio_mixer_add_processing_updown(struct uaudio_softc *, |
512 |
const struct uaudio_terminal_node *, int); |
513 |
static void uaudio_mixer_add_processing(struct uaudio_softc *, |
514 |
const struct uaudio_terminal_node *, int); |
515 |
static void uaudio_mixer_add_extension(struct uaudio_softc *, |
516 |
const struct uaudio_terminal_node *, int); |
517 |
static struct usb_audio_cluster uaudio_mixer_get_cluster(uint8_t, |
518 |
const struct uaudio_terminal_node *); |
519 |
static uint16_t uaudio_mixer_determine_class(const struct uaudio_terminal_node *, |
520 |
struct uaudio_mixer_node *); |
521 |
static uint16_t uaudio_mixer_feature_name(const struct uaudio_terminal_node *, |
522 |
struct uaudio_mixer_node *); |
523 |
static void uaudio_mixer_find_inputs_sub(struct uaudio_terminal_node *, |
524 |
const uint8_t *, uint8_t, struct uaudio_search_result *); |
525 |
static const void *uaudio_mixer_verify_desc(const void *, uint32_t); |
526 |
static usb_error_t uaudio_set_speed(struct usb_device *, uint8_t, uint32_t); |
527 |
static int uaudio_mixer_get(struct usb_device *, uint16_t, uint8_t, |
528 |
struct uaudio_mixer_node *); |
529 |
|
530 |
/* ==== USB audio v2.0 ==== */ |
531 |
|
532 |
static void uaudio20_mixer_add_mixer(struct uaudio_softc *, |
533 |
const struct uaudio_terminal_node *, int); |
534 |
static void uaudio20_mixer_add_selector(struct uaudio_softc *, |
535 |
const struct uaudio_terminal_node *, int); |
536 |
static void uaudio20_mixer_add_feature(struct uaudio_softc *, |
537 |
const struct uaudio_terminal_node *, int); |
538 |
static struct usb_audio20_cluster uaudio20_mixer_get_cluster(uint8_t, |
539 |
const struct uaudio_terminal_node *); |
540 |
static uint16_t uaudio20_mixer_determine_class(const struct uaudio_terminal_node *, |
541 |
struct uaudio_mixer_node *); |
542 |
static uint16_t uaudio20_mixer_feature_name(const struct uaudio_terminal_node *, |
543 |
struct uaudio_mixer_node *); |
544 |
static void uaudio20_mixer_find_inputs_sub(struct uaudio_terminal_node *, |
545 |
const uint8_t *, uint8_t, struct uaudio_search_result *); |
546 |
static const void *uaudio20_mixer_verify_desc(const void *, uint32_t); |
547 |
static usb_error_t uaudio20_set_speed(struct usb_device *, uint8_t, |
548 |
uint8_t, uint32_t); |
549 |
|
550 |
/* USB audio v1.0 and v2.0 */ |
551 |
|
552 |
static void uaudio_chan_fill_info_sub(struct uaudio_softc *, |
553 |
struct usb_device *, uint32_t, uint8_t, uint8_t); |
554 |
static void uaudio_chan_fill_info(struct uaudio_softc *, |
555 |
struct usb_device *); |
556 |
static void uaudio_mixer_add_ctl_sub(struct uaudio_softc *, |
557 |
struct uaudio_mixer_node *); |
558 |
static void uaudio_mixer_add_ctl(struct uaudio_softc *, |
559 |
struct uaudio_mixer_node *); |
560 |
static void uaudio_mixer_fill_info(struct uaudio_softc *, |
561 |
struct usb_device *, void *); |
562 |
static void uaudio_mixer_ctl_set(struct uaudio_softc *, |
563 |
struct uaudio_mixer_node *, uint8_t, int32_t val); |
564 |
static int uaudio_mixer_signext(uint8_t, int); |
565 |
static int uaudio_mixer_bsd2value(struct uaudio_mixer_node *, int32_t val); |
566 |
static void uaudio_mixer_init(struct uaudio_softc *); |
567 |
static const struct uaudio_terminal_node *uaudio_mixer_get_input( |
568 |
const struct uaudio_terminal_node *, uint8_t); |
569 |
static const struct uaudio_terminal_node *uaudio_mixer_get_output( |
570 |
const struct uaudio_terminal_node *, uint8_t); |
571 |
static void uaudio_mixer_find_outputs_sub(struct uaudio_terminal_node *, |
572 |
uint8_t, uint8_t, struct uaudio_search_result *); |
573 |
static uint8_t umidi_convert_to_usb(struct umidi_sub_chan *, uint8_t, uint8_t); |
574 |
static struct umidi_sub_chan *umidi_sub_by_fifo(struct usb_fifo *); |
575 |
static void umidi_start_read(struct usb_fifo *); |
576 |
static void umidi_stop_read(struct usb_fifo *); |
577 |
static void umidi_start_write(struct usb_fifo *); |
578 |
static void umidi_stop_write(struct usb_fifo *); |
579 |
static int umidi_open(struct usb_fifo *, int); |
580 |
static int umidi_ioctl(struct usb_fifo *, u_long cmd, void *, int); |
581 |
static void umidi_close(struct usb_fifo *, int); |
582 |
static void umidi_init(device_t dev); |
583 |
static int umidi_probe(device_t dev); |
584 |
static int umidi_detach(device_t dev); |
585 |
static int uaudio_hid_probe(struct uaudio_softc *sc, |
586 |
struct usb_attach_arg *uaa); |
587 |
static void uaudio_hid_detach(struct uaudio_softc *sc); |
588 |
|
589 |
#ifdef USB_DEBUG |
590 |
static void uaudio_chan_dump_ep_desc( |
591 |
const usb_endpoint_descriptor_audio_t *); |
592 |
#endif |
593 |
|
594 |
static const struct usb_config |
595 |
uaudio_cfg_record[UAUDIO_NCHANBUFS + 1] = { |
596 |
[0] = { |
597 |
.type = UE_ISOCHRONOUS, |
598 |
.endpoint = UE_ADDR_ANY, |
599 |
.direction = UE_DIR_IN, |
600 |
.bufsize = 0, /* use "wMaxPacketSize * frames" */ |
601 |
.frames = UAUDIO_NFRAMES, |
602 |
.flags = {.short_xfer_ok = 1,}, |
603 |
.callback = &uaudio_chan_record_callback, |
604 |
}, |
605 |
|
606 |
[1] = { |
607 |
.type = UE_ISOCHRONOUS, |
608 |
.endpoint = UE_ADDR_ANY, |
609 |
.direction = UE_DIR_IN, |
610 |
.bufsize = 0, /* use "wMaxPacketSize * frames" */ |
611 |
.frames = UAUDIO_NFRAMES, |
612 |
.flags = {.short_xfer_ok = 1,}, |
613 |
.callback = &uaudio_chan_record_callback, |
614 |
}, |
615 |
|
616 |
[2] = { |
617 |
.type = UE_ISOCHRONOUS, |
618 |
.endpoint = UE_ADDR_ANY, |
619 |
.direction = UE_DIR_OUT, |
620 |
.bufsize = 0, /* use "wMaxPacketSize * frames" */ |
621 |
.frames = 1, |
622 |
.flags = {.no_pipe_ok = 1,.short_xfer_ok = 1,}, |
623 |
.callback = &uaudio_chan_record_sync_callback, |
624 |
}, |
625 |
}; |
626 |
|
627 |
static const struct usb_config |
628 |
uaudio_cfg_play[UAUDIO_NCHANBUFS + 1] = { |
629 |
[0] = { |
630 |
.type = UE_ISOCHRONOUS, |
631 |
.endpoint = UE_ADDR_ANY, |
632 |
.direction = UE_DIR_OUT, |
633 |
.bufsize = 0, /* use "wMaxPacketSize * frames" */ |
634 |
.frames = UAUDIO_NFRAMES, |
635 |
.flags = {.short_xfer_ok = 1,}, |
636 |
.callback = &uaudio_chan_play_callback, |
637 |
}, |
638 |
|
639 |
[1] = { |
640 |
.type = UE_ISOCHRONOUS, |
641 |
.endpoint = UE_ADDR_ANY, |
642 |
.direction = UE_DIR_OUT, |
643 |
.bufsize = 0, /* use "wMaxPacketSize * frames" */ |
644 |
.frames = UAUDIO_NFRAMES, |
645 |
.flags = {.short_xfer_ok = 1,}, |
646 |
.callback = &uaudio_chan_play_callback, |
647 |
}, |
648 |
|
649 |
[2] = { |
650 |
.type = UE_ISOCHRONOUS, |
651 |
.endpoint = UE_ADDR_ANY, |
652 |
.direction = UE_DIR_IN, |
653 |
.bufsize = 0, /* use "wMaxPacketSize * frames" */ |
654 |
.frames = 1, |
655 |
.flags = {.no_pipe_ok = 1,.short_xfer_ok = 1,}, |
656 |
.callback = &uaudio_chan_play_sync_callback, |
657 |
}, |
658 |
}; |
659 |
|
660 |
static const struct usb_config |
661 |
uaudio_mixer_config[1] = { |
662 |
[0] = { |
663 |
.type = UE_CONTROL, |
664 |
.endpoint = 0x00, /* Control pipe */ |
665 |
.direction = UE_DIR_ANY, |
666 |
.bufsize = (sizeof(struct usb_device_request) + 4), |
667 |
.callback = &uaudio_mixer_write_cfg_callback, |
668 |
.timeout = 1000, /* 1 second */ |
669 |
}, |
670 |
}; |
671 |
|
672 |
static const |
673 |
uint8_t umidi_cmd_to_len[16] = { |
674 |
[0x0] = 0, /* reserved */ |
675 |
[0x1] = 0, /* reserved */ |
676 |
[0x2] = 2, /* bytes */ |
677 |
[0x3] = 3, /* bytes */ |
678 |
[0x4] = 3, /* bytes */ |
679 |
[0x5] = 1, /* bytes */ |
680 |
[0x6] = 2, /* bytes */ |
681 |
[0x7] = 3, /* bytes */ |
682 |
[0x8] = 3, /* bytes */ |
683 |
[0x9] = 3, /* bytes */ |
684 |
[0xA] = 3, /* bytes */ |
685 |
[0xB] = 3, /* bytes */ |
686 |
[0xC] = 2, /* bytes */ |
687 |
[0xD] = 2, /* bytes */ |
688 |
[0xE] = 3, /* bytes */ |
689 |
[0xF] = 1, /* bytes */ |
690 |
}; |
691 |
|
692 |
static const struct usb_config |
693 |
umidi_config[UMIDI_N_TRANSFER] = { |
694 |
[UMIDI_TX_TRANSFER] = { |
695 |
.type = UE_BULK, |
696 |
.endpoint = UE_ADDR_ANY, |
697 |
.direction = UE_DIR_OUT, |
698 |
.bufsize = UMIDI_TX_BUFFER, |
699 |
.flags = {.no_pipe_ok = 1}, |
700 |
.callback = &umidi_bulk_write_callback, |
701 |
}, |
702 |
|
703 |
[UMIDI_RX_TRANSFER] = { |
704 |
.type = UE_BULK, |
705 |
.endpoint = UE_ADDR_ANY, |
706 |
.direction = UE_DIR_IN, |
707 |
.bufsize = 4, /* bytes */ |
708 |
.flags = {.short_xfer_ok = 1,.proxy_buffer = 1,.no_pipe_ok = 1}, |
709 |
.callback = &umidi_bulk_read_callback, |
710 |
}, |
711 |
}; |
712 |
|
713 |
static const struct usb_config |
714 |
uaudio_hid_config[UAUDIO_HID_N_TRANSFER] = { |
715 |
[UAUDIO_HID_RX_TRANSFER] = { |
716 |
.type = UE_INTERRUPT, |
717 |
.endpoint = UE_ADDR_ANY, |
718 |
.direction = UE_DIR_IN, |
719 |
.bufsize = 0, /* use wMaxPacketSize */ |
720 |
.flags = {.short_xfer_ok = 1,}, |
721 |
.callback = &uaudio_hid_rx_callback, |
722 |
}, |
723 |
}; |
724 |
|
725 |
static devclass_t uaudio_devclass; |
726 |
|
727 |
static device_method_t uaudio_methods[] = { |
728 |
DEVMETHOD(device_probe, uaudio_probe), |
729 |
DEVMETHOD(device_attach, uaudio_attach), |
730 |
DEVMETHOD(device_detach, uaudio_detach), |
731 |
DEVMETHOD(device_suspend, bus_generic_suspend), |
732 |
DEVMETHOD(device_resume, bus_generic_resume), |
733 |
DEVMETHOD(device_shutdown, bus_generic_shutdown), |
734 |
|
735 |
DEVMETHOD_END |
736 |
}; |
737 |
|
738 |
static driver_t uaudio_driver = { |
739 |
.name = "uaudio", |
740 |
.methods = uaudio_methods, |
741 |
.size = sizeof(struct uaudio_softc), |
742 |
}; |
743 |
|
744 |
/* The following table is derived from Linux's quirks-table.h */ |
745 |
static const STRUCT_USB_HOST_ID uaudio_vendor_midi[] = { |
746 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1000, 0) }, /* UX256 */ |
747 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1001, 0) }, /* MU1000 */ |
748 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1002, 0) }, /* MU2000 */ |
749 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1003, 0) }, /* MU500 */ |
750 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1004, 3) }, /* UW500 */ |
751 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1005, 0) }, /* MOTIF6 */ |
752 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1006, 0) }, /* MOTIF7 */ |
753 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1007, 0) }, /* MOTIF8 */ |
754 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1008, 0) }, /* UX96 */ |
755 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1009, 0) }, /* UX16 */ |
756 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x100a, 3) }, /* EOS BX */ |
757 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x100c, 0) }, /* UC-MX */ |
758 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x100d, 0) }, /* UC-KX */ |
759 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x100e, 0) }, /* S08 */ |
760 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x100f, 0) }, /* CLP-150 */ |
761 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1010, 0) }, /* CLP-170 */ |
762 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1011, 0) }, /* P-250 */ |
763 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1012, 0) }, /* TYROS */ |
764 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1013, 0) }, /* PF-500 */ |
765 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1014, 0) }, /* S90 */ |
766 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1015, 0) }, /* MOTIF-R */ |
767 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1016, 0) }, /* MDP-5 */ |
768 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1017, 0) }, /* CVP-204 */ |
769 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1018, 0) }, /* CVP-206 */ |
770 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1019, 0) }, /* CVP-208 */ |
771 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x101a, 0) }, /* CVP-210 */ |
772 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x101b, 0) }, /* PSR-1100 */ |
773 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x101c, 0) }, /* PSR-2100 */ |
774 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x101d, 0) }, /* CLP-175 */ |
775 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x101e, 0) }, /* PSR-K1 */ |
776 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x101f, 0) }, /* EZ-J24 */ |
777 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1020, 0) }, /* EZ-250i */ |
778 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1021, 0) }, /* MOTIF ES 6 */ |
779 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1022, 0) }, /* MOTIF ES 7 */ |
780 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1023, 0) }, /* MOTIF ES 8 */ |
781 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1024, 0) }, /* CVP-301 */ |
782 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1025, 0) }, /* CVP-303 */ |
783 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1026, 0) }, /* CVP-305 */ |
784 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1027, 0) }, /* CVP-307 */ |
785 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1028, 0) }, /* CVP-309 */ |
786 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1029, 0) }, /* CVP-309GP */ |
787 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x102a, 0) }, /* PSR-1500 */ |
788 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x102b, 0) }, /* PSR-3000 */ |
789 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x102e, 0) }, /* ELS-01/01C */ |
790 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1030, 0) }, /* PSR-295/293 */ |
791 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1031, 0) }, /* DGX-205/203 */ |
792 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1032, 0) }, /* DGX-305 */ |
793 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1033, 0) }, /* DGX-505 */ |
794 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1034, 0) }, /* NULL */ |
795 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1035, 0) }, /* NULL */ |
796 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1036, 0) }, /* NULL */ |
797 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1037, 0) }, /* NULL */ |
798 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1038, 0) }, /* NULL */ |
799 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1039, 0) }, /* NULL */ |
800 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x103a, 0) }, /* NULL */ |
801 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x103b, 0) }, /* NULL */ |
802 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x103c, 0) }, /* NULL */ |
803 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x103d, 0) }, /* NULL */ |
804 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x103e, 0) }, /* NULL */ |
805 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x103f, 0) }, /* NULL */ |
806 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1040, 0) }, /* NULL */ |
807 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1041, 0) }, /* NULL */ |
808 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1042, 0) }, /* NULL */ |
809 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1043, 0) }, /* NULL */ |
810 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1044, 0) }, /* NULL */ |
811 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1045, 0) }, /* NULL */ |
812 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x104e, 0) }, /* NULL */ |
813 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x104f, 0) }, /* NULL */ |
814 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1050, 0) }, /* NULL */ |
815 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1051, 0) }, /* NULL */ |
816 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1052, 0) }, /* NULL */ |
817 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1053, 0) }, /* NULL */ |
818 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1054, 0) }, /* NULL */ |
819 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1055, 0) }, /* NULL */ |
820 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1056, 0) }, /* NULL */ |
821 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1057, 0) }, /* NULL */ |
822 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1058, 0) }, /* NULL */ |
823 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1059, 0) }, /* NULL */ |
824 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x105a, 0) }, /* NULL */ |
825 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x105b, 0) }, /* NULL */ |
826 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x105c, 0) }, /* NULL */ |
827 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x105d, 0) }, /* NULL */ |
828 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1503, 3) }, /* MOX6/MOX8 */ |
829 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x2000, 0) }, /* DGP-7 */ |
830 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x2001, 0) }, /* DGP-5 */ |
831 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x2002, 0) }, /* NULL */ |
832 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x2003, 0) }, /* NULL */ |
833 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x5000, 0) }, /* CS1D */ |
834 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x5001, 0) }, /* DSP1D */ |
835 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x5002, 0) }, /* DME32 */ |
836 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x5003, 0) }, /* DM2000 */ |
837 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x5004, 0) }, /* 02R96 */ |
838 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x5005, 0) }, /* ACU16-C */ |
839 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x5006, 0) }, /* NHB32-C */ |
840 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x5007, 0) }, /* DM1000 */ |
841 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x5008, 0) }, /* 01V96 */ |
842 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x5009, 0) }, /* SPX2000 */ |
843 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x500a, 0) }, /* PM5D */ |
844 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x500b, 0) }, /* DME64N */ |
845 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x500c, 0) }, /* DME24N */ |
846 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x500d, 0) }, /* NULL */ |
847 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x500e, 0) }, /* NULL */ |
848 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x500f, 0) }, /* NULL */ |
849 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x7000, 0) }, /* DTX */ |
850 |
{ USB_VPI(USB_VENDOR_YAMAHA, 0x7010, 0) }, /* UB99 */ |
851 |
}; |
852 |
|
853 |
static const STRUCT_USB_HOST_ID __used uaudio_devs[] = { |
854 |
/* Generic USB audio class match */ |
855 |
{USB_IFACE_CLASS(UICLASS_AUDIO), |
856 |
USB_IFACE_SUBCLASS(UISUBCLASS_AUDIOCONTROL),}, |
857 |
/* Generic USB MIDI class match */ |
858 |
{USB_IFACE_CLASS(UICLASS_AUDIO), |
859 |
USB_IFACE_SUBCLASS(UISUBCLASS_MIDISTREAM),}, |
860 |
}; |
861 |
|
862 |
static int |
863 |
uaudio_probe(device_t dev) |
864 |
{ |
865 |
struct usb_attach_arg *uaa = device_get_ivars(dev); |
866 |
|
867 |
if (uaa->usb_mode != USB_MODE_HOST) |
868 |
return (ENXIO); |
869 |
|
870 |
/* lookup non-standard device(s) */ |
871 |
|
872 |
if (usbd_lookup_id_by_uaa(uaudio_vendor_midi, |
873 |
sizeof(uaudio_vendor_midi), uaa) == 0) { |
874 |
return (BUS_PROBE_SPECIFIC); |
875 |
} |
876 |
|
877 |
if (uaa->info.bInterfaceClass != UICLASS_AUDIO) { |
878 |
if (uaa->info.bInterfaceClass != UICLASS_VENDOR || |
879 |
usb_test_quirk(uaa, UQ_AU_VENDOR_CLASS) == 0) |
880 |
return (ENXIO); |
881 |
} |
882 |
|
883 |
/* check for AUDIO control interface */ |
884 |
|
885 |
if (uaa->info.bInterfaceSubClass == UISUBCLASS_AUDIOCONTROL) { |
886 |
if (usb_test_quirk(uaa, UQ_BAD_AUDIO)) |
887 |
return (ENXIO); |
888 |
else |
889 |
return (BUS_PROBE_GENERIC); |
890 |
} |
891 |
|
892 |
/* check for MIDI stream */ |
893 |
|
894 |
if (uaa->info.bInterfaceSubClass == UISUBCLASS_MIDISTREAM) { |
895 |
if (usb_test_quirk(uaa, UQ_BAD_MIDI)) |
896 |
return (ENXIO); |
897 |
else |
898 |
return (BUS_PROBE_GENERIC); |
899 |
} |
900 |
return (ENXIO); |
901 |
} |
902 |
|
903 |
/* |
904 |
* Set Cmedia CM6206 S/PDIF settings |
905 |
* Source: CM6206 Datasheet v2.3. |
906 |
*/ |
907 |
static int |
908 |
uaudio_set_spdif_cm6206(struct uaudio_softc *sc, int flags) |
909 |
{ |
910 |
uint8_t cmd[2][4] = { |
911 |
{0x20, 0x20, 0x00, 0}, |
912 |
{0x20, 0x30, 0x02, 1} |
913 |
}; |
914 |
int i; |
915 |
|
916 |
if (flags & UAUDIO_SPDIF_OUT) |
917 |
cmd[1][1] = 0x00; |
918 |
else |
919 |
cmd[1][1] = 0x02; |
920 |
|
921 |
if (flags & UAUDIO_SPDIF_OUT_96K) |
922 |
cmd[0][1] = 0x60; /* 96K: 3'b110 */ |
923 |
|
924 |
if (flags & UAUDIO_SPDIF_IN_MIX) |
925 |
cmd[1][1] = 0x03; /* SPDIFMIX */ |
926 |
|
927 |
for (i = 0; i < 2; i++) { |
928 |
if (usbd_req_set_report(sc->sc_udev, NULL, |
929 |
cmd[i], sizeof(cmd[0]), |
930 |
sc->sc_mixer_iface_index, UHID_OUTPUT_REPORT, 0) != 0) { |
931 |
return (ENXIO); |
932 |
} |
933 |
} |
934 |
return (0); |
935 |
} |
936 |
|
937 |
static int |
938 |
uaudio_set_spdif_dummy(struct uaudio_softc *sc, int flags) |
939 |
{ |
940 |
return (0); |
941 |
} |
942 |
|
943 |
static int |
944 |
uaudio_attach(device_t dev) |
945 |
{ |
946 |
struct usb_attach_arg *uaa = device_get_ivars(dev); |
947 |
struct uaudio_softc *sc = device_get_softc(dev); |
948 |
struct usb_interface_descriptor *id; |
949 |
usb_error_t err; |
950 |
device_t child; |
951 |
|
952 |
sc->sc_play_chan.priv_sc = sc; |
953 |
sc->sc_rec_chan.priv_sc = sc; |
954 |
sc->sc_udev = uaa->device; |
955 |
sc->sc_mixer_iface_index = uaa->info.bIfaceIndex; |
956 |
sc->sc_mixer_iface_no = uaa->info.bIfaceNum; |
957 |
sc->sc_config_msg[0].hdr.pm_callback = &uaudio_configure_msg; |
958 |
sc->sc_config_msg[0].sc = sc; |
959 |
sc->sc_config_msg[1].hdr.pm_callback = &uaudio_configure_msg; |
960 |
sc->sc_config_msg[1].sc = sc; |
961 |
|
962 |
if (usb_test_quirk(uaa, UQ_AUDIO_SWAP_LR)) |
963 |
sc->sc_uq_audio_swap_lr = 1; |
964 |
|
965 |
if (usb_test_quirk(uaa, UQ_AU_INP_ASYNC)) |
966 |
sc->sc_uq_au_inp_async = 1; |
967 |
|
968 |
if (usb_test_quirk(uaa, UQ_AU_NO_XU)) |
969 |
sc->sc_uq_au_no_xu = 1; |
970 |
|
971 |
if (usb_test_quirk(uaa, UQ_BAD_ADC)) |
972 |
sc->sc_uq_bad_adc = 1; |
973 |
|
974 |
if (usb_test_quirk(uaa, UQ_AU_VENDOR_CLASS)) |
975 |
sc->sc_uq_au_vendor_class = 1; |
976 |
|
977 |
/* set S/PDIF function */ |
978 |
if (usb_test_quirk(uaa, UQ_AU_SET_SPDIF_CM6206)) |
979 |
sc->sc_set_spdif_fn = uaudio_set_spdif_cm6206; |
980 |
else |
981 |
sc->sc_set_spdif_fn = uaudio_set_spdif_dummy; |
982 |
|
983 |
umidi_init(dev); |
984 |
|
985 |
device_set_usb_desc(dev); |
986 |
|
987 |
id = usbd_get_interface_descriptor(uaa->iface); |
988 |
|
989 |
/* must fill mixer info before channel info */ |
990 |
uaudio_mixer_fill_info(sc, uaa->device, id); |
991 |
|
992 |
/* fill channel info */ |
993 |
uaudio_chan_fill_info(sc, uaa->device); |
994 |
|
995 |
DPRINTF("audio rev %d.%02x\n", |
996 |
sc->sc_audio_rev >> 8, |
997 |
sc->sc_audio_rev & 0xff); |
998 |
|
999 |
if (sc->sc_mixer_count == 0) { |
1000 |
if (uaa->info.idVendor == USB_VENDOR_MAUDIO && |
1001 |
(uaa->info.idProduct == USB_PRODUCT_MAUDIO_FASTTRACKULTRA || |
1002 |
uaa->info.idProduct == USB_PRODUCT_MAUDIO_FASTTRACKULTRA8R)) { |
1003 |
DPRINTF("Generating mixer descriptors\n"); |
1004 |
uaudio_mixer_controls_create_ftu(sc); |
1005 |
} |
1006 |
} |
1007 |
|
1008 |
DPRINTF("%d mixer controls\n", |
1009 |
sc->sc_mixer_count); |
1010 |
|
1011 |
if (sc->sc_play_chan.num_alt > 0) { |
1012 |
uint8_t x; |
1013 |
|
1014 |
/* |
1015 |
* Need to set a default alternate interface, else |
1016 |
* some USB audio devices might go into an infinte |
1017 |
* re-enumeration loop: |
1018 |
*/ |
1019 |
err = usbd_set_alt_interface_index(sc->sc_udev, |
1020 |
sc->sc_play_chan.usb_alt[0].iface_index, |
1021 |
sc->sc_play_chan.usb_alt[0].iface_alt_index); |
1022 |
if (err) { |
1023 |
DPRINTF("setting of alternate index failed: %s!\n", |
1024 |
usbd_errstr(err)); |
1025 |
} |
1026 |
for (x = 0; x != sc->sc_play_chan.num_alt; x++) { |
1027 |
device_printf(dev, "Play: %d Hz, %d ch, %s format, " |
1028 |
"2x8ms buffer.\n", |
1029 |
sc->sc_play_chan.usb_alt[x].sample_rate, |
1030 |
sc->sc_play_chan.usb_alt[x].channels, |
1031 |
sc->sc_play_chan.usb_alt[x].p_fmt->description); |
1032 |
} |
1033 |
} else { |
1034 |
device_printf(dev, "No playback.\n"); |
1035 |
} |
1036 |
|
1037 |
if (sc->sc_rec_chan.num_alt > 0) { |
1038 |
uint8_t x; |
1039 |
|
1040 |
/* |
1041 |
* Need to set a default alternate interface, else |
1042 |
* some USB audio devices might go into an infinte |
1043 |
* re-enumeration loop: |
1044 |
*/ |
1045 |
err = usbd_set_alt_interface_index(sc->sc_udev, |
1046 |
sc->sc_rec_chan.usb_alt[0].iface_index, |
1047 |
sc->sc_rec_chan.usb_alt[0].iface_alt_index); |
1048 |
if (err) { |
1049 |
DPRINTF("setting of alternate index failed: %s!\n", |
1050 |
usbd_errstr(err)); |
1051 |
} |
1052 |
for (x = 0; x != sc->sc_rec_chan.num_alt; x++) { |
1053 |
device_printf(dev, "Record: %d Hz, %d ch, %s format, " |
1054 |
"2x8ms buffer.\n", |
1055 |
sc->sc_rec_chan.usb_alt[x].sample_rate, |
1056 |
sc->sc_rec_chan.usb_alt[x].channels, |
1057 |
sc->sc_rec_chan.usb_alt[x].p_fmt->description); |
1058 |
} |
1059 |
} else { |
1060 |
device_printf(dev, "No recording.\n"); |
1061 |
} |
1062 |
|
1063 |
if (sc->sc_midi_chan.valid == 0) { |
1064 |
if (usbd_lookup_id_by_uaa(uaudio_vendor_midi, |
1065 |
sizeof(uaudio_vendor_midi), uaa) == 0) { |
1066 |
sc->sc_midi_chan.iface_index = |
1067 |
(uint8_t)uaa->driver_info; |
1068 |
sc->sc_midi_chan.iface_alt_index = 0; |
1069 |
sc->sc_midi_chan.valid = 1; |
1070 |
} |
1071 |
} |
1072 |
|
1073 |
if (sc->sc_midi_chan.valid) { |
1074 |
|
1075 |
if (umidi_probe(dev)) { |
1076 |
goto detach; |
1077 |
} |
1078 |
device_printf(dev, "MIDI sequencer.\n"); |
1079 |
} else { |
1080 |
device_printf(dev, "No MIDI sequencer.\n"); |
1081 |
} |
1082 |
|
1083 |
DPRINTF("doing child attach\n"); |
1084 |
|
1085 |
/* attach the children */ |
1086 |
|
1087 |
sc->sc_sndcard_func.func = SCF_PCM; |
1088 |
|
1089 |
/* |
1090 |
* Only attach a PCM device if we have a playback, recording |
1091 |
* or mixer device present: |
1092 |
*/ |
1093 |
if (sc->sc_play_chan.num_alt > 0 || |
1094 |
sc->sc_rec_chan.num_alt > 0 || |
1095 |
sc->sc_mix_info) { |
1096 |
child = device_add_child(dev, "pcm", -1); |
1097 |
|
1098 |
if (child == NULL) { |
1099 |
DPRINTF("out of memory\n"); |
1100 |
goto detach; |
1101 |
} |
1102 |
device_set_ivars(child, &sc->sc_sndcard_func); |
1103 |
} |
1104 |
|
1105 |
if (bus_generic_attach(dev)) { |
1106 |
DPRINTF("child attach failed\n"); |
1107 |
goto detach; |
1108 |
} |
1109 |
|
1110 |
if (uaudio_hid_probe(sc, uaa) == 0) { |
1111 |
device_printf(dev, "HID volume keys found.\n"); |
1112 |
} else { |
1113 |
device_printf(dev, "No HID volume keys found.\n"); |
1114 |
} |
1115 |
|
1116 |
/* reload all mixer settings */ |
1117 |
uaudio_mixer_reload_all(sc); |
1118 |
|
1119 |
/* enable S/PDIF output, if any */ |
1120 |
if (sc->sc_set_spdif_fn(sc, |
1121 |
UAUDIO_SPDIF_OUT | UAUDIO_SPDIF_OUT_48K) != 0) { |
1122 |
device_printf(dev, "Failed to enable S/PDIF at 48K\n"); |
1123 |
} |
1124 |
return (0); /* success */ |
1125 |
|
1126 |
detach: |
1127 |
uaudio_detach(dev); |
1128 |
return (ENXIO); |
1129 |
} |
1130 |
|
1131 |
static void |
1132 |
uaudio_pcm_setflags(device_t dev, uint32_t flags) |
1133 |
{ |
1134 |
pcm_setflags(dev, pcm_getflags(dev) | flags); |
1135 |
} |
1136 |
|
1137 |
int |
1138 |
uaudio_attach_sub(device_t dev, kobj_class_t mixer_class, kobj_class_t chan_class) |
1139 |
{ |
1140 |
struct uaudio_softc *sc = device_get_softc(device_get_parent(dev)); |
1141 |
char status[SND_STATUSLEN]; |
1142 |
|
1143 |
uaudio_mixer_init(sc); |
1144 |
|
1145 |
if (sc->sc_uq_audio_swap_lr) { |
1146 |
DPRINTF("hardware has swapped left and right\n"); |
1147 |
/* uaudio_pcm_setflags(dev, SD_F_PSWAPLR); */ |
1148 |
} |
1149 |
if (!(sc->sc_mix_info & SOUND_MASK_PCM)) { |
1150 |
|
1151 |
DPRINTF("emulating master volume\n"); |
1152 |
|
1153 |
/* |
1154 |
* Emulate missing pcm mixer controller |
1155 |
* through FEEDER_VOLUME |
1156 |
*/ |
1157 |
uaudio_pcm_setflags(dev, SD_F_SOFTPCMVOL); |
1158 |
} |
1159 |
if (sc->sc_pcm_bitperfect) { |
1160 |
DPRINTF("device needs bitperfect by default\n"); |
1161 |
uaudio_pcm_setflags(dev, SD_F_BITPERFECT); |
1162 |
} |
1163 |
if (mixer_init(dev, mixer_class, sc)) |
1164 |
goto detach; |
1165 |
sc->sc_mixer_init = 1; |
1166 |
|
1167 |
mixer_hwvol_init(dev); |
1168 |
|
1169 |
snprintf(status, sizeof(status), "at ? %s", PCM_KLDSTRING(snd_uaudio)); |
1170 |
|
1171 |
if (pcm_register(dev, sc, |
1172 |
(sc->sc_play_chan.num_alt > 0) ? 1 : 0, |
1173 |
(sc->sc_rec_chan.num_alt > 0) ? 1 : 0)) { |
1174 |
goto detach; |
1175 |
} |
1176 |
|
1177 |
uaudio_pcm_setflags(dev, SD_F_MPSAFE); |
1178 |
sc->sc_pcm_registered = 1; |
1179 |
|
1180 |
if (sc->sc_play_chan.num_alt > 0) { |
1181 |
pcm_addchan(dev, PCMDIR_PLAY, chan_class, sc); |
1182 |
} |
1183 |
if (sc->sc_rec_chan.num_alt > 0) { |
1184 |
pcm_addchan(dev, PCMDIR_REC, chan_class, sc); |
1185 |
} |
1186 |
pcm_setstatus(dev, status); |
1187 |
|
1188 |
uaudio_mixer_register_sysctl(sc, dev); |
1189 |
|
1190 |
SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), |
1191 |
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, |
1192 |
"feedback_rate", CTLFLAG_RD, &sc->sc_play_chan.feedback_rate, |
1193 |
0, "Feedback sample rate in Hz"); |
1194 |
|
1195 |
return (0); /* success */ |
1196 |
|
1197 |
detach: |
1198 |
uaudio_detach_sub(dev); |
1199 |
return (ENXIO); |
1200 |
} |
1201 |
|
1202 |
int |
1203 |
uaudio_detach_sub(device_t dev) |
1204 |
{ |
1205 |
struct uaudio_softc *sc = device_get_softc(device_get_parent(dev)); |
1206 |
int error = 0; |
1207 |
|
1208 |
/* disable S/PDIF output, if any */ |
1209 |
(void) sc->sc_set_spdif_fn(sc, 0); |
1210 |
|
1211 |
repeat: |
1212 |
if (sc->sc_pcm_registered) { |
1213 |
error = pcm_unregister(dev); |
1214 |
} else { |
1215 |
if (sc->sc_mixer_init) { |
1216 |
error = mixer_uninit(dev); |
1217 |
} |
1218 |
} |
1219 |
|
1220 |
if (error) { |
1221 |
device_printf(dev, "Waiting for sound application to exit!\n"); |
1222 |
usb_pause_mtx(NULL, 2 * hz); |
1223 |
goto repeat; /* try again */ |
1224 |
} |
1225 |
return (0); /* success */ |
1226 |
} |
1227 |
|
1228 |
static int |
1229 |
uaudio_detach(device_t dev) |
1230 |
{ |
1231 |
struct uaudio_softc *sc = device_get_softc(dev); |
1232 |
|
1233 |
/* |
1234 |
* Stop USB transfers early so that any audio applications |
1235 |
* will time out and close opened /dev/dspX.Y device(s), if |
1236 |
* any. |
1237 |
*/ |
1238 |
usb_proc_explore_lock(sc->sc_udev); |
1239 |
sc->sc_play_chan.operation = CHAN_OP_DRAIN; |
1240 |
sc->sc_rec_chan.operation = CHAN_OP_DRAIN; |
1241 |
usb_proc_explore_mwait(sc->sc_udev, |
1242 |
&sc->sc_config_msg[0], &sc->sc_config_msg[1]); |
1243 |
usb_proc_explore_unlock(sc->sc_udev); |
1244 |
|
1245 |
usbd_transfer_unsetup(sc->sc_play_chan.xfer, UAUDIO_NCHANBUFS + 1); |
1246 |
usbd_transfer_unsetup(sc->sc_rec_chan.xfer, UAUDIO_NCHANBUFS + 1); |
1247 |
|
1248 |
uaudio_hid_detach(sc); |
1249 |
|
1250 |
if (bus_generic_detach(dev) != 0) { |
1251 |
DPRINTF("detach failed!\n"); |
1252 |
} |
1253 |
sbuf_delete(&sc->sc_sndstat); |
1254 |
sc->sc_sndstat_valid = 0; |
1255 |
|
1256 |
umidi_detach(dev); |
1257 |
|
1258 |
/* free mixer data */ |
1259 |
|
1260 |
uaudio_mixer_ctl_free(sc); |
1261 |
|
1262 |
return (0); |
1263 |
} |
1264 |
|
1265 |
static uint32_t |
1266 |
uaudio_get_buffer_size(struct uaudio_chan *ch, uint8_t alt) |
1267 |
{ |
1268 |
struct uaudio_chan_alt *chan_alt = &ch->usb_alt[alt]; |
1269 |
/* We use 2 times 8ms of buffer */ |
1270 |
uint32_t buf_size = (((chan_alt->sample_rate * (UAUDIO_NFRAMES / 8)) + |
1271 |
1000 - 1) / 1000) * chan_alt->sample_size; |
1272 |
return (buf_size); |
1273 |
} |
1274 |
|
1275 |
static void |
1276 |
uaudio_configure_msg_sub(struct uaudio_softc *sc, |
1277 |
struct uaudio_chan *chan, int dir) |
1278 |
{ |
1279 |
struct uaudio_chan_alt *chan_alt; |
1280 |
uint32_t frames; |
1281 |
uint32_t buf_size; |
1282 |
uint16_t fps; |
1283 |
uint8_t set_alt; |
1284 |
uint8_t fps_shift; |
1285 |
uint8_t operation; |
1286 |
usb_error_t err; |
1287 |
|
1288 |
if (chan->num_alt <= 0) |
1289 |
return; |
1290 |
|
1291 |
DPRINTF("\n"); |
1292 |
|
1293 |
usb_proc_explore_lock(sc->sc_udev); |
1294 |
operation = chan->operation; |
1295 |
chan->operation = CHAN_OP_NONE; |
1296 |
usb_proc_explore_unlock(sc->sc_udev); |
1297 |
|
1298 |
mtx_lock(chan->pcm_mtx); |
1299 |
if (chan->cur_alt != chan->set_alt) |
1300 |
set_alt = chan->set_alt; |
1301 |
else |
1302 |
set_alt = CHAN_MAX_ALT; |
1303 |
mtx_unlock(chan->pcm_mtx); |
1304 |
|
1305 |
if (set_alt >= chan->num_alt) |
1306 |
goto done; |
1307 |
|
1308 |
chan_alt = chan->usb_alt + set_alt; |
1309 |
|
1310 |
usbd_transfer_unsetup(chan->xfer, UAUDIO_NCHANBUFS + 1); |
1311 |
|
1312 |
err = usbd_set_alt_interface_index(sc->sc_udev, |
1313 |
chan_alt->iface_index, chan_alt->iface_alt_index); |
1314 |
if (err) { |
1315 |
DPRINTF("setting of alternate index failed: %s!\n", |
1316 |
usbd_errstr(err)); |
1317 |
goto error; |
1318 |
} |
1319 |
|
1320 |
/* |
1321 |
* Only set the sample rate if the channel reports that it |
1322 |
* supports the frequency control. |
1323 |
*/ |
1324 |
|
1325 |
if (sc->sc_audio_rev >= UAUDIO_VERSION_30) { |
1326 |
/* FALLTHROUGH */ |
1327 |
} else if (sc->sc_audio_rev >= UAUDIO_VERSION_20) { |
1328 |
unsigned int x; |
1329 |
|
1330 |
for (x = 0; x != 256; x++) { |
1331 |
if (dir == PCMDIR_PLAY) { |
1332 |
if (!(sc->sc_mixer_clocks.bit_output[x / 8] & |
1333 |
(1 << (x % 8)))) { |
1334 |
continue; |
1335 |
} |
1336 |
} else { |
1337 |
if (!(sc->sc_mixer_clocks.bit_input[x / 8] & |
1338 |
(1 << (x % 8)))) { |
1339 |
continue; |
1340 |
} |
1341 |
} |
1342 |
|
1343 |
if (uaudio20_set_speed(sc->sc_udev, |
1344 |
sc->sc_mixer_iface_no, x, chan_alt->sample_rate)) { |
1345 |
/* |
1346 |
* If the endpoint is adaptive setting |
1347 |
* the speed may fail. |
1348 |
*/ |
1349 |
DPRINTF("setting of sample rate failed! " |
1350 |
"(continuing anyway)\n"); |
1351 |
} |
1352 |
} |
1353 |
} else if (chan_alt->p_sed.v1->bmAttributes & UA_SED_FREQ_CONTROL) { |
1354 |
if (uaudio_set_speed(sc->sc_udev, |
1355 |
chan_alt->p_ed1->bEndpointAddress, chan_alt->sample_rate)) { |
1356 |
/* |
1357 |
* If the endpoint is adaptive setting the |
1358 |
* speed may fail. |
1359 |
*/ |
1360 |
DPRINTF("setting of sample rate failed! " |
1361 |
"(continuing anyway)\n"); |
1362 |
} |
1363 |
} |
1364 |
if (usbd_transfer_setup(sc->sc_udev, &chan_alt->iface_index, chan->xfer, |
1365 |
chan_alt->usb_cfg, UAUDIO_NCHANBUFS + 1, chan, chan->pcm_mtx)) { |
1366 |
DPRINTF("could not allocate USB transfers!\n"); |
1367 |
goto error; |
1368 |
} |
1369 |
|
1370 |
fps = usbd_get_isoc_fps(sc->sc_udev); |
1371 |
|
1372 |
if (fps < 8000) { |
1373 |
/* FULL speed USB */ |
1374 |
frames = uaudio_buffer_ms; |
1375 |
} else { |
1376 |
/* HIGH speed USB */ |
1377 |
frames = uaudio_buffer_ms * 8; |
1378 |
} |
1379 |
|
1380 |
fps_shift = usbd_xfer_get_fps_shift(chan->xfer[0]); |
1381 |
|
1382 |
/* down shift number of frames per second, if any */ |
1383 |
fps >>= fps_shift; |
1384 |
frames >>= fps_shift; |
1385 |
|
1386 |
/* bytes per frame should not be zero */ |
1387 |
chan->bytes_per_frame[0] = |
1388 |
((chan_alt->sample_rate / fps) * chan_alt->sample_size); |
1389 |
chan->bytes_per_frame[1] = |
1390 |
(((chan_alt->sample_rate + fps - 1) / fps) * chan_alt->sample_size); |
1391 |
|
1392 |
/* setup data rate dithering, if any */ |
1393 |
chan->frames_per_second = fps; |
1394 |
chan->sample_rem = chan_alt->sample_rate % fps; |
1395 |
chan->sample_curr = 0; |
1396 |
|
1397 |
/* compute required buffer size */ |
1398 |
buf_size = (chan->bytes_per_frame[1] * frames); |
1399 |
|
1400 |
if (buf_size > (chan->end - chan->start)) { |
1401 |
DPRINTF("buffer size is too big\n"); |
1402 |
goto error; |
1403 |
} |
1404 |
|
1405 |
chan->intr_frames = frames; |
1406 |
|
1407 |
DPRINTF("fps=%d sample_rem=%d\n", (int)fps, (int)chan->sample_rem); |
1408 |
|
1409 |
if (chan->intr_frames == 0) { |
1410 |
DPRINTF("frame shift is too high!\n"); |
1411 |
goto error; |
1412 |
} |
1413 |
|
1414 |
mtx_lock(chan->pcm_mtx); |
1415 |
chan->cur_alt = set_alt; |
1416 |
mtx_unlock(chan->pcm_mtx); |
1417 |
|
1418 |
done: |
1419 |
#if (UAUDIO_NCHANBUFS != 2) |
1420 |
#error "please update code" |
1421 |
#endif |
1422 |
switch (operation) { |
1423 |
case CHAN_OP_START: |
1424 |
mtx_lock(chan->pcm_mtx); |
1425 |
usbd_transfer_start(chan->xfer[0]); |
1426 |
usbd_transfer_start(chan->xfer[1]); |
1427 |
mtx_unlock(chan->pcm_mtx); |
1428 |
break; |
1429 |
case CHAN_OP_STOP: |
1430 |
mtx_lock(chan->pcm_mtx); |
1431 |
usbd_transfer_stop(chan->xfer[0]); |
1432 |
usbd_transfer_stop(chan->xfer[1]); |
1433 |
mtx_unlock(chan->pcm_mtx); |
1434 |
break; |
1435 |
default: |
1436 |
break; |
1437 |
} |
1438 |
return; |
1439 |
|
1440 |
error: |
1441 |
usbd_transfer_unsetup(chan->xfer, UAUDIO_NCHANBUFS + 1); |
1442 |
|
1443 |
mtx_lock(chan->pcm_mtx); |
1444 |
chan->cur_alt = CHAN_MAX_ALT; |
1445 |
mtx_unlock(chan->pcm_mtx); |
1446 |
} |
1447 |
|
1448 |
static void |
1449 |
uaudio_configure_msg(struct usb_proc_msg *pm) |
1450 |
{ |
1451 |
struct uaudio_softc *sc = ((struct uaudio_configure_msg *)pm)->sc; |
1452 |
|
1453 |
usb_proc_explore_unlock(sc->sc_udev); |
1454 |
uaudio_configure_msg_sub(sc, &sc->sc_play_chan, PCMDIR_PLAY); |
1455 |
uaudio_configure_msg_sub(sc, &sc->sc_rec_chan, PCMDIR_REC); |
1456 |
usb_proc_explore_lock(sc->sc_udev); |
1457 |
} |
1458 |
|
1459 |
/*========================================================================* |
1460 |
* AS - Audio Stream - routines |
1461 |
*========================================================================*/ |
1462 |
|
1463 |
#ifdef USB_DEBUG |
1464 |
static void |
1465 |
uaudio_chan_dump_ep_desc(const usb_endpoint_descriptor_audio_t *ed) |
1466 |
{ |
1467 |
if (ed) { |
1468 |
DPRINTF("endpoint=%p bLength=%d bDescriptorType=%d \n" |
1469 |
"bEndpointAddress=%d bmAttributes=0x%x \n" |
1470 |
"wMaxPacketSize=%d bInterval=%d \n" |
1471 |
"bRefresh=%d bSynchAddress=%d\n", |
1472 |
ed, ed->bLength, ed->bDescriptorType, |
1473 |
ed->bEndpointAddress, ed->bmAttributes, |
1474 |
UGETW(ed->wMaxPacketSize), ed->bInterval, |
1475 |
UEP_HAS_REFRESH(ed) ? ed->bRefresh : 0, |
1476 |
UEP_HAS_SYNCADDR(ed) ? ed->bSynchAddress : 0); |
1477 |
} |
1478 |
} |
1479 |
|
1480 |
#endif |
1481 |
|
1482 |
/* |
1483 |
* The following is a workaround for broken no-name USB audio devices |
1484 |
* sold by dealextreme called "3D sound". The problem is that the |
1485 |
* manufacturer computed wMaxPacketSize is too small to hold the |
1486 |
* actual data sent. In other words the device sometimes sends more |
1487 |
* data than it actually reports it can send in a single isochronous |
1488 |
* packet. |
1489 |
*/ |
1490 |
static void |
1491 |
uaudio_record_fix_fs(usb_endpoint_descriptor_audio_t *ep, |
1492 |
uint32_t xps, uint32_t add) |
1493 |
{ |
1494 |
uint32_t mps; |
1495 |
|
1496 |
mps = UGETW(ep->wMaxPacketSize); |
1497 |
|
1498 |
/* |
1499 |
* If the device indicates it can send more data than what the |
1500 |
* sample rate indicates, we apply the workaround. |
1501 |
*/ |
1502 |
if (mps > xps) { |
1503 |
|
1504 |
/* allow additional data */ |
1505 |
xps += add; |
1506 |
|
1507 |
/* check against the maximum USB 1.x length */ |
1508 |
if (xps > 1023) |
1509 |
xps = 1023; |
1510 |
|
1511 |
/* check if we should do an update */ |
1512 |
if (mps < xps) { |
1513 |
/* simply update the wMaxPacketSize field */ |
1514 |
USETW(ep->wMaxPacketSize, xps); |
1515 |
DPRINTF("Workaround: Updated wMaxPacketSize " |
1516 |
"from %d to %d bytes.\n", |
1517 |
(int)mps, (int)xps); |
1518 |
} |
1519 |
} |
1520 |
} |
1521 |
|
1522 |
static usb_error_t |
1523 |
uaudio20_check_rate(struct usb_device *udev, uint8_t iface_no, |
1524 |
uint8_t clockid, uint32_t rate) |
1525 |
{ |
1526 |
struct usb_device_request req; |
1527 |
usb_error_t error; |
1528 |
#define UAUDIO20_MAX_RATES 32 /* we support at maxium 32 rates */ |
1529 |
uint8_t data[2 + UAUDIO20_MAX_RATES * 12]; |
1530 |
uint16_t actlen; |
1531 |
uint16_t rates; |
1532 |
uint16_t x; |
1533 |
|
1534 |
DPRINTFN(6, "ifaceno=%d clockid=%d rate=%u\n", |
1535 |
iface_no, clockid, rate); |
1536 |
|
1537 |
req.bmRequestType = UT_READ_CLASS_INTERFACE; |
1538 |
req.bRequest = UA20_CS_RANGE; |
1539 |
USETW2(req.wValue, UA20_CS_SAM_FREQ_CONTROL, 0); |
1540 |
USETW2(req.wIndex, clockid, iface_no); |
1541 |
/* |
1542 |
* Assume there is at least one rate to begin with, else some |
1543 |
* devices might refuse to return the USB descriptor: |
1544 |
*/ |
1545 |
USETW(req.wLength, (2 + 1 * 12)); |
1546 |
|
1547 |
error = usbd_do_request_flags(udev, NULL, &req, data, |
1548 |
USB_SHORT_XFER_OK, &actlen, USB_DEFAULT_TIMEOUT); |
1549 |
|
1550 |
if (error != 0 || actlen < 2) { |
1551 |
/* |
1552 |
* Likely the descriptor doesn't fit into the supplied |
1553 |
* buffer. Try using a larger buffer and see if that |
1554 |
* helps: |
1555 |
*/ |
1556 |
rates = MIN(UAUDIO20_MAX_RATES, (255 - 2) / 12); |
1557 |
error = USB_ERR_INVAL; |
1558 |
} else { |
1559 |
rates = UGETW(data); |
1560 |
|
1561 |
if (rates > UAUDIO20_MAX_RATES) { |
1562 |
DPRINTF("Too many rates truncating to %d\n", UAUDIO20_MAX_RATES); |
1563 |
rates = UAUDIO20_MAX_RATES; |
1564 |
error = USB_ERR_INVAL; |
1565 |
} else if (rates > 1) { |
1566 |
DPRINTF("Need to read full rate descriptor\n"); |
1567 |
error = USB_ERR_INVAL; |
1568 |
} |
1569 |
} |
1570 |
|
1571 |
if (error != 0) { |
1572 |
/* |
1573 |
* Try to read full rate descriptor. |
1574 |
*/ |
1575 |
actlen = (2 + rates * 12); |
1576 |
|
1577 |
USETW(req.wLength, actlen); |
1578 |
|
1579 |
error = usbd_do_request_flags(udev, NULL, &req, data, |
1580 |
USB_SHORT_XFER_OK, &actlen, USB_DEFAULT_TIMEOUT); |
1581 |
|
1582 |
if (error != 0 || actlen < 2) |
1583 |
return (USB_ERR_INVAL); |
1584 |
|
1585 |
rates = UGETW(data); |
1586 |
} |
1587 |
|
1588 |
actlen = (actlen - 2) / 12; |
1589 |
|
1590 |
if (rates > actlen) { |
1591 |
DPRINTF("Too many rates truncating to %d\n", actlen); |
1592 |
rates = actlen; |
1593 |
} |
1594 |
|
1595 |
for (x = 0; x != rates; x++) { |
1596 |
uint32_t min = UGETDW(data + 2 + (12 * x)); |
1597 |
uint32_t max = UGETDW(data + 6 + (12 * x)); |
1598 |
uint32_t res = UGETDW(data + 10 + (12 * x)); |
1599 |
|
1600 |
if (res == 0) { |
1601 |
DPRINTF("Zero residue\n"); |
1602 |
res = 1; |
1603 |
} |
1604 |
|
1605 |
if (min > max) { |
1606 |
DPRINTF("Swapped max and min\n"); |
1607 |
uint32_t temp; |
1608 |
temp = min; |
1609 |
min = max; |
1610 |
max = temp; |
1611 |
} |
1612 |
|
1613 |
if (rate >= min && rate <= max && |
1614 |
(((rate - min) % res) == 0)) { |
1615 |
return (0); |
1616 |
} |
1617 |
} |
1618 |
return (USB_ERR_INVAL); |
1619 |
} |
1620 |
|
1621 |
static void |
1622 |
uaudio_chan_fill_info_sub(struct uaudio_softc *sc, struct usb_device *udev, |
1623 |
uint32_t rate, uint8_t channels, uint8_t bit_resolution) |
1624 |
{ |
1625 |
struct usb_descriptor *desc = NULL; |
1626 |
union uaudio_asid asid = { NULL }; |
1627 |
union uaudio_asf1d asf1d = { NULL }; |
1628 |
union uaudio_sed sed = { NULL }; |
1629 |
struct usb_midi_streaming_endpoint_descriptor *msid = NULL; |
1630 |
usb_endpoint_descriptor_audio_t *ed1 = NULL; |
1631 |
const struct usb_audio_control_descriptor *acdp = NULL; |
1632 |
struct usb_config_descriptor *cd = usbd_get_config_descriptor(udev); |
1633 |
struct usb_interface_descriptor *id; |
1634 |
const struct uaudio_format *p_fmt = NULL; |
1635 |
struct uaudio_chan *chan; |
1636 |
struct uaudio_chan_alt *chan_alt; |
1637 |
uint32_t format; |
1638 |
uint16_t curidx = 0xFFFF; |
1639 |
uint16_t lastidx = 0xFFFF; |
1640 |
uint16_t alt_index = 0; |
1641 |
uint16_t audio_rev = 0; |
1642 |
uint16_t x; |
1643 |
uint8_t ep_dir; |
1644 |
uint8_t bChannels; |
1645 |
uint8_t bBitResolution; |
1646 |
uint8_t audio_if = 0; |
1647 |
uint8_t midi_if = 0; |
1648 |
uint8_t uma_if_class; |
1649 |
|
1650 |
while ((desc = usb_desc_foreach(cd, desc))) { |
1651 |
|
1652 |
if ((desc->bDescriptorType == UDESC_INTERFACE) && |
1653 |
(desc->bLength >= sizeof(*id))) { |
1654 |
|
1655 |
id = (void *)desc; |
1656 |
|
1657 |
if (id->bInterfaceNumber != lastidx) { |
1658 |
lastidx = id->bInterfaceNumber; |
1659 |
curidx++; |
1660 |
alt_index = 0; |
1661 |
|
1662 |
} else { |
1663 |
alt_index++; |
1664 |
} |
1665 |
|
1666 |
if ((!(sc->sc_hid.flags & UAUDIO_HID_VALID)) && |
1667 |
(id->bInterfaceClass == UICLASS_HID) && |
1668 |
(id->bInterfaceSubClass == 0) && |
1669 |
(id->bInterfaceProtocol == 0) && |
1670 |
(alt_index == 0) && |
1671 |
usbd_get_iface(udev, curidx) != NULL) { |
1672 |
DPRINTF("Found HID interface at %d\n", |
1673 |
curidx); |
1674 |
sc->sc_hid.flags |= UAUDIO_HID_VALID; |
1675 |
sc->sc_hid.iface_index = curidx; |
1676 |
} |
1677 |
|
1678 |
uma_if_class = |
1679 |
((id->bInterfaceClass == UICLASS_AUDIO) || |
1680 |
((id->bInterfaceClass == UICLASS_VENDOR) && |
1681 |
(sc->sc_uq_au_vendor_class != 0))); |
1682 |
|
1683 |
if ((uma_if_class != 0) && |
1684 |
(id->bInterfaceSubClass == UISUBCLASS_AUDIOSTREAM)) { |
1685 |
audio_if = 1; |
1686 |
} else { |
1687 |
audio_if = 0; |
1688 |
} |
1689 |
|
1690 |
if ((uma_if_class != 0) && |
1691 |
(id->bInterfaceSubClass == UISUBCLASS_MIDISTREAM)) { |
1692 |
|
1693 |
/* |
1694 |
* XXX could allow multiple MIDI interfaces |
1695 |
*/ |
1696 |
midi_if = 1; |
1697 |
|
1698 |
if ((sc->sc_midi_chan.valid == 0) && |
1699 |
(usbd_get_iface(udev, curidx) != NULL)) { |
1700 |
sc->sc_midi_chan.iface_index = curidx; |
1701 |
sc->sc_midi_chan.iface_alt_index = alt_index; |
1702 |
sc->sc_midi_chan.valid = 1; |
1703 |
} |
1704 |
} else { |
1705 |
midi_if = 0; |
1706 |
} |
1707 |
asid.v1 = NULL; |
1708 |
asf1d.v1 = NULL; |
1709 |
ed1 = NULL; |
1710 |
sed.v1 = NULL; |
1711 |
|
1712 |
/* |
1713 |
* There can only be one USB audio instance |
1714 |
* per USB device. Grab all USB audio |
1715 |
* interfaces on this USB device so that we |
1716 |
* don't attach USB audio twice: |
1717 |
*/ |
1718 |
if (alt_index == 0 && curidx != sc->sc_mixer_iface_index && |
1719 |
(id->bInterfaceClass == UICLASS_AUDIO || audio_if != 0 || |
1720 |
midi_if != 0)) { |
1721 |
usbd_set_parent_iface(sc->sc_udev, curidx, |
1722 |
sc->sc_mixer_iface_index); |
1723 |
} |
1724 |
} |
1725 |
|
1726 |
if (audio_if == 0) { |
1727 |
if (midi_if == 0) { |
1728 |
if ((acdp == NULL) && |
1729 |
(desc->bDescriptorType == UDESC_CS_INTERFACE) && |
1730 |
(desc->bDescriptorSubtype == UDESCSUB_AC_HEADER) && |
1731 |
(desc->bLength >= sizeof(*acdp))) { |
1732 |
acdp = (void *)desc; |
1733 |
audio_rev = UGETW(acdp->bcdADC); |
1734 |
} |
1735 |
} else { |
1736 |
msid = (void *)desc; |
1737 |
|
1738 |
/* get the maximum number of embedded jacks in use, if any */ |
1739 |
if (msid->bLength >= sizeof(*msid) && |
1740 |
msid->bDescriptorType == UDESC_CS_ENDPOINT && |
1741 |
msid->bDescriptorSubtype == MS_GENERAL && |
1742 |
msid->bNumEmbMIDIJack > sc->sc_midi_chan.max_emb_jack) { |
1743 |
sc->sc_midi_chan.max_emb_jack = msid->bNumEmbMIDIJack; |
1744 |
} |
1745 |
} |
1746 |
/* |
1747 |
* Don't collect any USB audio descriptors if |
1748 |
* this is not an USB audio stream interface. |
1749 |
*/ |
1750 |
continue; |
1751 |
} |
1752 |
|
1753 |
if ((acdp != NULL || sc->sc_uq_au_vendor_class != 0) && |
1754 |
(desc->bDescriptorType == UDESC_CS_INTERFACE) && |
1755 |
(desc->bDescriptorSubtype == AS_GENERAL) && |
1756 |
(asid.v1 == NULL)) { |
1757 |
if (audio_rev >= UAUDIO_VERSION_30) { |
1758 |
/* FALLTHROUGH */ |
1759 |
} else if (audio_rev >= UAUDIO_VERSION_20) { |
1760 |
if (desc->bLength >= sizeof(*asid.v2)) { |
1761 |
asid.v2 = (void *)desc; |
1762 |
} |
1763 |
} else { |
1764 |
if (desc->bLength >= sizeof(*asid.v1)) { |
1765 |
asid.v1 = (void *)desc; |
1766 |
} |
1767 |
} |
1768 |
} |
1769 |
if ((acdp != NULL || sc->sc_uq_au_vendor_class != 0) && |
1770 |
(desc->bDescriptorType == UDESC_CS_INTERFACE) && |
1771 |
(desc->bDescriptorSubtype == FORMAT_TYPE) && |
1772 |
(asf1d.v1 == NULL)) { |
1773 |
if (audio_rev >= UAUDIO_VERSION_30) { |
1774 |
/* FALLTHROUGH */ |
1775 |
} else if (audio_rev >= UAUDIO_VERSION_20) { |
1776 |
if (desc->bLength >= sizeof(*asf1d.v2)) |
1777 |
asf1d.v2 = (void *)desc; |
1778 |
} else { |
1779 |
if (desc->bLength >= sizeof(*asf1d.v1)) { |
1780 |
asf1d.v1 = (void *)desc; |
1781 |
|
1782 |
if (asf1d.v1->bFormatType != FORMAT_TYPE_I) { |
1783 |
DPRINTFN(11, "ignored bFormatType = %d\n", |
1784 |
asf1d.v1->bFormatType); |
1785 |
asf1d.v1 = NULL; |
1786 |
continue; |
1787 |
} |
1788 |
if (desc->bLength < (sizeof(*asf1d.v1) + |
1789 |
((asf1d.v1->bSamFreqType == 0) ? 6 : |
1790 |
(asf1d.v1->bSamFreqType * 3)))) { |
1791 |
DPRINTFN(11, "invalid descriptor, " |
1792 |
"too short\n"); |
1793 |
asf1d.v1 = NULL; |
1794 |
continue; |
1795 |
} |
1796 |
} |
1797 |
} |
1798 |
} |
1799 |
if ((desc->bDescriptorType == UDESC_ENDPOINT) && |
1800 |
(desc->bLength >= UEP_MINSIZE) && |
1801 |
(ed1 == NULL)) { |
1802 |
ed1 = (void *)desc; |
1803 |
if (UE_GET_XFERTYPE(ed1->bmAttributes) != UE_ISOCHRONOUS) { |
1804 |
ed1 = NULL; |
1805 |
continue; |
1806 |
} |
1807 |
} |
1808 |
if ((acdp != NULL || sc->sc_uq_au_vendor_class != 0) && |
1809 |
(desc->bDescriptorType == UDESC_CS_ENDPOINT) && |
1810 |
(desc->bDescriptorSubtype == AS_GENERAL) && |
1811 |
(sed.v1 == NULL)) { |
1812 |
if (audio_rev >= UAUDIO_VERSION_30) { |
1813 |
/* FALLTHROUGH */ |
1814 |
} else if (audio_rev >= UAUDIO_VERSION_20) { |
1815 |
if (desc->bLength >= sizeof(*sed.v2)) |
1816 |
sed.v2 = (void *)desc; |
1817 |
} else { |
1818 |
if (desc->bLength >= sizeof(*sed.v1)) |
1819 |
sed.v1 = (void *)desc; |
1820 |
} |
1821 |
} |
1822 |
if (asid.v1 == NULL || asf1d.v1 == NULL || |
1823 |
ed1 == NULL || sed.v1 == NULL) { |
1824 |
/* need more descriptors */ |
1825 |
continue; |
1826 |
} |
1827 |
|
1828 |
ep_dir = UE_GET_DIR(ed1->bEndpointAddress); |
1829 |
|
1830 |
/* We ignore sync endpoint information until further. */ |
1831 |
|
1832 |
if (audio_rev >= UAUDIO_VERSION_30) { |
1833 |
goto next_ep; |
1834 |
} else if (audio_rev >= UAUDIO_VERSION_20) { |
1835 |
|
1836 |
uint32_t dwFormat; |
1837 |
|
1838 |
dwFormat = UGETDW(asid.v2->bmFormats); |
1839 |
bChannels = asid.v2->bNrChannels; |
1840 |
bBitResolution = asf1d.v2->bSubslotSize * 8; |
1841 |
|
1842 |
if ((bChannels != channels) || |
1843 |
(bBitResolution != bit_resolution)) { |
1844 |
DPRINTF("Wrong number of channels\n"); |
1845 |
goto next_ep; |
1846 |
} |
1847 |
|
1848 |
for (p_fmt = uaudio20_formats; |
1849 |
p_fmt->wFormat != 0; p_fmt++) { |
1850 |
if ((p_fmt->wFormat & dwFormat) && |
1851 |
(p_fmt->bPrecision == bBitResolution)) |
1852 |
break; |
1853 |
} |
1854 |
|
1855 |
if (p_fmt->wFormat == 0) { |
1856 |
DPRINTF("Unsupported audio format\n"); |
1857 |
goto next_ep; |
1858 |
} |
1859 |
|
1860 |
for (x = 0; x != 256; x++) { |
1861 |
if (ep_dir == UE_DIR_OUT) { |
1862 |
if (!(sc->sc_mixer_clocks.bit_output[x / 8] & |
1863 |
(1 << (x % 8)))) { |
1864 |
continue; |
1865 |
} |
1866 |
} else { |
1867 |
if (!(sc->sc_mixer_clocks.bit_input[x / 8] & |
1868 |
(1 << (x % 8)))) { |
1869 |
continue; |
1870 |
} |
1871 |
} |
1872 |
|
1873 |
DPRINTF("Checking clock ID=%d\n", x); |
1874 |
|
1875 |
if (uaudio20_check_rate(udev, |
1876 |
sc->sc_mixer_iface_no, x, rate)) { |
1877 |
DPRINTF("Unsupported sampling " |
1878 |
"rate, id=%d\n", x); |
1879 |
goto next_ep; |
1880 |
} |
1881 |
} |
1882 |
} else { |
1883 |
uint16_t wFormat; |
1884 |
|
1885 |
wFormat = UGETW(asid.v1->wFormatTag); |
1886 |
bChannels = UAUDIO_MAX_CHAN(asf1d.v1->bNrChannels); |
1887 |
bBitResolution = asf1d.v1->bSubFrameSize * 8; |
1888 |
|
1889 |
if (asf1d.v1->bSamFreqType == 0) { |
1890 |
DPRINTFN(16, "Sample rate: %d-%dHz\n", |
1891 |
UA_SAMP_LO(asf1d.v1), |
1892 |
UA_SAMP_HI(asf1d.v1)); |
1893 |
|
1894 |
if ((rate >= UA_SAMP_LO(asf1d.v1)) && |
1895 |
(rate <= UA_SAMP_HI(asf1d.v1))) |
1896 |
goto found_rate; |
1897 |
} else { |
1898 |
|
1899 |
for (x = 0; x < asf1d.v1->bSamFreqType; x++) { |
1900 |
DPRINTFN(16, "Sample rate = %dHz\n", |
1901 |
UA_GETSAMP(asf1d.v1, x)); |
1902 |
|
1903 |
if (rate == UA_GETSAMP(asf1d.v1, x)) |
1904 |
goto found_rate; |
1905 |
} |
1906 |
} |
1907 |
goto next_ep; |
1908 |
|
1909 |
found_rate: |
1910 |
for (p_fmt = uaudio10_formats; |
1911 |
p_fmt->wFormat != 0; p_fmt++) { |
1912 |
if ((p_fmt->wFormat == wFormat) && |
1913 |
(p_fmt->bPrecision == bBitResolution)) |
1914 |
break; |
1915 |
} |
1916 |
if (p_fmt->wFormat == 0) { |
1917 |
DPRINTF("Unsupported audio format\n"); |
1918 |
goto next_ep; |
1919 |
} |
1920 |
|
1921 |
if ((bChannels != channels) || |
1922 |
(bBitResolution != bit_resolution)) { |
1923 |
DPRINTF("Wrong number of channels\n"); |
1924 |
goto next_ep; |
1925 |
} |
1926 |
} |
1927 |
|
1928 |
chan = (ep_dir == UE_DIR_IN) ? |
1929 |
&sc->sc_rec_chan : &sc->sc_play_chan; |
1930 |
|
1931 |
if (usbd_get_iface(udev, curidx) == NULL) { |
1932 |
DPRINTF("Interface is not valid\n"); |
1933 |
goto next_ep; |
1934 |
} |
1935 |
if (chan->num_alt == CHAN_MAX_ALT) { |
1936 |
DPRINTF("Too many alternate settings\n"); |
1937 |
goto next_ep; |
1938 |
} |
1939 |
chan->set_alt = 0; |
1940 |
chan->cur_alt = CHAN_MAX_ALT; |
1941 |
|
1942 |
chan_alt = &chan->usb_alt[chan->num_alt++]; |
1943 |
|
1944 |
#ifdef USB_DEBUG |
1945 |
uaudio_chan_dump_ep_desc(ed1); |
1946 |
#endif |
1947 |
DPRINTF("Sample rate = %dHz, channels = %d, " |
1948 |
"bits = %d, format = %s\n", rate, channels, |
1949 |
bit_resolution, p_fmt->description); |
1950 |
|
1951 |
chan_alt->sample_rate = rate; |
1952 |
chan_alt->p_asf1d = asf1d; |
1953 |
chan_alt->p_ed1 = ed1; |
1954 |
chan_alt->p_fmt = p_fmt; |
1955 |
chan_alt->p_sed = sed; |
1956 |
chan_alt->iface_index = curidx; |
1957 |
chan_alt->iface_alt_index = alt_index; |
1958 |
|
1959 |
if (ep_dir == UE_DIR_IN) |
1960 |
chan_alt->usb_cfg = uaudio_cfg_record; |
1961 |
else |
1962 |
chan_alt->usb_cfg = uaudio_cfg_play; |
1963 |
|
1964 |
chan_alt->sample_size = (UAUDIO_MAX_CHAN(channels) * |
1965 |
p_fmt->bPrecision) / 8; |
1966 |
chan_alt->channels = channels; |
1967 |
|
1968 |
if (ep_dir == UE_DIR_IN && |
1969 |
usbd_get_speed(udev) == USB_SPEED_FULL) { |
1970 |
uaudio_record_fix_fs(ed1, |
1971 |
chan_alt->sample_size * (rate / 1000), |
1972 |
chan_alt->sample_size * (rate / 4000)); |
1973 |
} |
1974 |
|
1975 |
/* setup play/record format */ |
1976 |
|
1977 |
format = chan_alt->p_fmt->freebsd_fmt; |
1978 |
|
1979 |
/* get default SND_FORMAT() */ |
1980 |
format = SND_FORMAT(format, chan_alt->channels, 0); |
1981 |
|
1982 |
switch (chan_alt->channels) { |
1983 |
uint32_t temp_fmt; |
1984 |
case 1: |
1985 |
case 2: |
1986 |
/* mono and stereo */ |
1987 |
break; |
1988 |
default: |
1989 |
/* surround and more */ |
1990 |
temp_fmt = feeder_matrix_default_format(format); |
1991 |
/* if multichannel, then format can be zero */ |
1992 |
if (temp_fmt != 0) |
1993 |
format = temp_fmt; |
1994 |
break; |
1995 |
} |
1996 |
|
1997 |
/* check if format is not supported */ |
1998 |
if (format == 0) { |
1999 |
DPRINTF("The selected audio format is not supported\n"); |
2000 |
chan->num_alt--; |
2001 |
goto next_ep; |
2002 |
} |
2003 |
if (chan->num_alt > 1) { |
2004 |
/* we only accumulate one format at different sample rates */ |
2005 |
if (chan->pcm_format[0] != format) { |
2006 |
DPRINTF("Multiple formats is not supported\n"); |
2007 |
chan->num_alt--; |
2008 |
goto next_ep; |
2009 |
} |
2010 |
/* ignore if duplicate sample rate entry */ |
2011 |
if (rate == chan->usb_alt[chan->num_alt - 2].sample_rate) { |
2012 |
DPRINTF("Duplicate sample rate detected\n"); |
2013 |
chan->num_alt--; |
2014 |
goto next_ep; |
2015 |
} |
2016 |
} |
2017 |
chan->pcm_cap.fmtlist = chan->pcm_format; |
2018 |
chan->pcm_cap.fmtlist[0] = format; |
2019 |
|
2020 |
/* check if device needs bitperfect */ |
2021 |
if (chan_alt->channels > UAUDIO_MATRIX_MAX) |
2022 |
sc->sc_pcm_bitperfect = 1; |
2023 |
|
2024 |
if (rate < chan->pcm_cap.minspeed || chan->pcm_cap.minspeed == 0) |
2025 |
chan->pcm_cap.minspeed = rate; |
2026 |
if (rate > chan->pcm_cap.maxspeed || chan->pcm_cap.maxspeed == 0) |
2027 |
chan->pcm_cap.maxspeed = rate; |
2028 |
|
2029 |
if (sc->sc_sndstat_valid != 0) { |
2030 |
sbuf_printf(&sc->sc_sndstat, "\n\t" |
2031 |
"mode %d.%d:(%s) %dch, %dbit, %s, %dHz", |
2032 |
curidx, alt_index, |
2033 |
(ep_dir == UE_DIR_IN) ? "input" : "output", |
2034 |
channels, p_fmt->bPrecision, |
2035 |
p_fmt->description, rate); |
2036 |
} |
2037 |
|
2038 |
next_ep: |
2039 |
sed.v1 = NULL; |
2040 |
ed1 = NULL; |
2041 |
} |
2042 |
} |
2043 |
|
2044 |
/* This structure defines all the supported rates. */ |
2045 |
|
2046 |
static const uint32_t uaudio_rate_list[CHAN_MAX_ALT] = { |
2047 |
384000, |
2048 |
352800, |
2049 |
192000, |
2050 |
176400, |
2051 |
96000, |
2052 |
88200, |
2053 |
88000, |
2054 |
80000, |
2055 |
72000, |
2056 |
64000, |
2057 |
56000, |
2058 |
48000, |
2059 |
44100, |
2060 |
40000, |
2061 |
32000, |
2062 |
24000, |
2063 |
22050, |
2064 |
16000, |
2065 |
11025, |
2066 |
8000, |
2067 |
0 |
2068 |
}; |
2069 |
|
2070 |
static void |
2071 |
uaudio_chan_fill_info(struct uaudio_softc *sc, struct usb_device *udev) |
2072 |
{ |
2073 |
uint32_t rate = uaudio_default_rate; |
2074 |
uint8_t z; |
2075 |
uint8_t bits = uaudio_default_bits; |
2076 |
uint8_t y; |
2077 |
uint8_t channels = uaudio_default_channels; |
2078 |
uint8_t x; |
2079 |
|
2080 |
bits -= (bits % 8); |
2081 |
if ((bits == 0) || (bits > 32)) { |
2082 |
/* set a valid value */ |
2083 |
bits = 32; |
2084 |
} |
2085 |
if (channels == 0) { |
2086 |
switch (usbd_get_speed(udev)) { |
2087 |
case USB_SPEED_LOW: |
2088 |
case USB_SPEED_FULL: |
2089 |
/* |
2090 |
* Due to high bandwidth usage and problems |
2091 |
* with HIGH-speed split transactions we |
2092 |
* disable surround setups on FULL-speed USB |
2093 |
* by default |
2094 |
*/ |
2095 |
channels = 4; |
2096 |
break; |
2097 |
default: |
2098 |
channels = UAUDIO_CHANNELS_MAX; |
2099 |
break; |
2100 |
} |
2101 |
} else if (channels > UAUDIO_CHANNELS_MAX) |
2102 |
channels = UAUDIO_CHANNELS_MAX; |
2103 |
|
2104 |
if (sbuf_new(&sc->sc_sndstat, NULL, 4096, SBUF_AUTOEXTEND)) |
2105 |
sc->sc_sndstat_valid = 1; |
2106 |
|
2107 |
/* try to search for a valid config */ |
2108 |
|
2109 |
for (x = channels; x; x--) { |
2110 |
for (y = bits; y; y -= 8) { |
2111 |
|
2112 |
/* try user defined rate, if any */ |
2113 |
if (rate != 0) |
2114 |
uaudio_chan_fill_info_sub(sc, udev, rate, x, y); |
2115 |
|
2116 |
/* try find a matching rate, if any */ |
2117 |
for (z = 0; uaudio_rate_list[z]; z++) |
2118 |
uaudio_chan_fill_info_sub(sc, udev, uaudio_rate_list[z], x, y); |
2119 |
} |
2120 |
} |
2121 |
if (sc->sc_sndstat_valid) |
2122 |
sbuf_finish(&sc->sc_sndstat); |
2123 |
} |
2124 |
|
2125 |
static void |
2126 |
uaudio_chan_play_sync_callback(struct usb_xfer *xfer, usb_error_t error) |
2127 |
{ |
2128 |
struct uaudio_chan *ch = usbd_xfer_softc(xfer); |
2129 |
struct usb_page_cache *pc; |
2130 |
uint64_t sample_rate; |
2131 |
uint8_t buf[4]; |
2132 |
uint64_t temp; |
2133 |
int len; |
2134 |
int actlen; |
2135 |
int nframes; |
2136 |
|
2137 |
usbd_xfer_status(xfer, &actlen, NULL, NULL, &nframes); |
2138 |
|
2139 |
switch (USB_GET_STATE(xfer)) { |
2140 |
case USB_ST_TRANSFERRED: |
2141 |
|
2142 |
DPRINTFN(6, "transferred %d bytes\n", actlen); |
2143 |
|
2144 |
if (nframes == 0) |
2145 |
break; |
2146 |
len = usbd_xfer_frame_len(xfer, 0); |
2147 |
if (len == 0) |
2148 |
break; |
2149 |
if (len > sizeof(buf)) |
2150 |
len = sizeof(buf); |
2151 |
|
2152 |
memset(buf, 0, sizeof(buf)); |
2153 |
|
2154 |
pc = usbd_xfer_get_frame(xfer, 0); |
2155 |
usbd_copy_out(pc, 0, buf, len); |
2156 |
|
2157 |
temp = UGETDW(buf); |
2158 |
|
2159 |
DPRINTF("Value = 0x%08x\n", (int)temp); |
2160 |
|
2161 |
/* auto-detect SYNC format */ |
2162 |
|
2163 |
if (len == 4) |
2164 |
temp &= 0x0fffffff; |
2165 |
|
2166 |
/* check for no data */ |
2167 |
|
2168 |
if (temp == 0) |
2169 |
break; |
2170 |
|
2171 |
temp *= 125ULL; |
2172 |
|
2173 |
sample_rate = ch->usb_alt[ch->cur_alt].sample_rate; |
2174 |
|
2175 |
/* auto adjust */ |
2176 |
while (temp < (sample_rate - (sample_rate / 4))) |
2177 |
temp *= 2; |
2178 |
|
2179 |
while (temp > (sample_rate + (sample_rate / 2))) |
2180 |
temp /= 2; |
2181 |
|
2182 |
DPRINTF("Comparing %d Hz :: %d Hz\n", |
2183 |
(int)temp, (int)sample_rate); |
2184 |
|
2185 |
/* |
2186 |
* Use feedback value as fallback when there is no |
2187 |
* recording channel: |
2188 |
*/ |
2189 |
if (ch->priv_sc->sc_rec_chan.num_alt == 0) { |
2190 |
int32_t jitter_max = howmany(sample_rate, 16000); |
2191 |
|
2192 |
/* |
2193 |
* Range check the jitter values to avoid |
2194 |
* bogus sample rate adjustments. The expected |
2195 |
* deviation should not be more than 1Hz per |
2196 |
* second. The USB v2.0 specification also |
2197 |
* mandates this requirement. Refer to chapter |
2198 |
* 5.12.4.2 about feedback. |
2199 |
*/ |
2200 |
ch->jitter_curr = temp - sample_rate; |
2201 |
if (ch->jitter_curr > jitter_max) |
2202 |
ch->jitter_curr = jitter_max; |
2203 |
else if (ch->jitter_curr < -jitter_max) |
2204 |
ch->jitter_curr = -jitter_max; |
2205 |
} |
2206 |
ch->feedback_rate = temp; |
2207 |
break; |
2208 |
|
2209 |
case USB_ST_SETUP: |
2210 |
/* |
2211 |
* Check if the recording stream can be used as a |
2212 |
* source of jitter information to save some |
2213 |
* isochronous bandwidth: |
2214 |
*/ |
2215 |
if (ch->priv_sc->sc_rec_chan.num_alt != 0 && |
2216 |
uaudio_debug == 0) |
2217 |
break; |
2218 |
usbd_xfer_set_frames(xfer, 1); |
2219 |
usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_framelen(xfer)); |
2220 |
usbd_transfer_submit(xfer); |
2221 |
break; |
2222 |
|
2223 |
default: /* Error */ |
2224 |
break; |
2225 |
} |
2226 |
} |
2227 |
|
2228 |
static int |
2229 |
uaudio_chan_is_async(struct uaudio_chan *ch, uint8_t alt) |
2230 |
{ |
2231 |
uint8_t attr = ch->usb_alt[alt].p_ed1->bmAttributes; |
2232 |
return (UE_GET_ISO_TYPE(attr) == UE_ISO_ASYNC); |
2233 |
} |
2234 |
|
2235 |
static void |
2236 |
uaudio_chan_play_callback(struct usb_xfer *xfer, usb_error_t error) |
2237 |
{ |
2238 |
struct uaudio_chan *ch = usbd_xfer_softc(xfer); |
2239 |
struct uaudio_chan *ch_rec; |
2240 |
struct usb_page_cache *pc; |
2241 |
uint32_t mfl; |
2242 |
uint32_t total; |
2243 |
uint32_t blockcount; |
2244 |
uint32_t n; |
2245 |
uint32_t offset; |
2246 |
int sample_size; |
2247 |
int actlen; |
2248 |
int sumlen; |
2249 |
|
2250 |
if (ch->running == 0 || ch->start == ch->end) { |
2251 |
DPRINTF("not running or no buffer!\n"); |
2252 |
return; |
2253 |
} |
2254 |
|
2255 |
/* check if there is a record channel */ |
2256 |
if (ch->priv_sc->sc_rec_chan.num_alt > 0) |
2257 |
ch_rec = &ch->priv_sc->sc_rec_chan; |
2258 |
else |
2259 |
ch_rec = NULL; |
2260 |
|
2261 |
usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); |
2262 |
|
2263 |
switch (USB_GET_STATE(xfer)) { |
2264 |
case USB_ST_SETUP: |
2265 |
tr_setup: |
2266 |
if (ch_rec != NULL) { |
2267 |
/* reset receive jitter counters */ |
2268 |
mtx_lock(ch_rec->pcm_mtx); |
2269 |
ch_rec->jitter_curr = 0; |
2270 |
ch_rec->jitter_rem = 0; |
2271 |
mtx_unlock(ch_rec->pcm_mtx); |
2272 |
} |
2273 |
|
2274 |
/* reset transmit jitter counters */ |
2275 |
ch->jitter_curr = 0; |
2276 |
ch->jitter_rem = 0; |
2277 |
|
2278 |
/* FALLTHROUGH */ |
2279 |
case USB_ST_TRANSFERRED: |
2280 |
if (actlen < sumlen) { |
2281 |
DPRINTF("short transfer, " |
2282 |
"%d of %d bytes\n", actlen, sumlen); |
2283 |
} |
2284 |
chn_intr(ch->pcm_ch); |
2285 |
|
2286 |
/* |
2287 |
* Check for asynchronous playback endpoint and that |
2288 |
* the playback endpoint is properly configured: |
2289 |
*/ |
2290 |
if (ch_rec != NULL && |
2291 |
uaudio_chan_is_async(ch, ch->cur_alt) != 0) { |
2292 |
mtx_lock(ch_rec->pcm_mtx); |
2293 |
if (ch_rec->cur_alt < ch_rec->num_alt) { |
2294 |
int64_t tx_jitter; |
2295 |
int64_t rx_rate; |
2296 |
|
2297 |
/* translate receive jitter into transmit jitter */ |
2298 |
tx_jitter = ch->usb_alt[ch->cur_alt].sample_rate; |
2299 |
tx_jitter = (tx_jitter * ch_rec->jitter_curr) + |
2300 |
ch->jitter_rem; |
2301 |
|
2302 |
/* reset receive jitter counters */ |
2303 |
ch_rec->jitter_curr = 0; |
2304 |
ch_rec->jitter_rem = 0; |
2305 |
|
2306 |
/* compute exact number of transmit jitter samples */ |
2307 |
rx_rate = ch_rec->usb_alt[ch_rec->cur_alt].sample_rate; |
2308 |
ch->jitter_curr += tx_jitter / rx_rate; |
2309 |
ch->jitter_rem = tx_jitter % rx_rate; |
2310 |
} |
2311 |
mtx_unlock(ch_rec->pcm_mtx); |
2312 |
} |
2313 |
|
2314 |
/* start the SYNC transfer one time per second, if any */ |
2315 |
ch->intr_counter += ch->intr_frames; |
2316 |
if (ch->intr_counter >= ch->frames_per_second) { |
2317 |
ch->intr_counter -= ch->frames_per_second; |
2318 |
usbd_transfer_start(ch->xfer[UAUDIO_NCHANBUFS]); |
2319 |
} |
2320 |
|
2321 |
mfl = usbd_xfer_max_framelen(xfer); |
2322 |
|
2323 |
if (ch->bytes_per_frame[1] > mfl) { |
2324 |
DPRINTF("bytes per transfer, %d, " |
2325 |
"exceeds maximum, %d!\n", |
2326 |
ch->bytes_per_frame[1], |
2327 |
mfl); |
2328 |
break; |
2329 |
} |
2330 |
|
2331 |
blockcount = ch->intr_frames; |
2332 |
|
2333 |
/* setup number of frames */ |
2334 |
usbd_xfer_set_frames(xfer, blockcount); |
2335 |
|
2336 |
/* get sample size */ |
2337 |
sample_size = ch->usb_alt[ch->cur_alt].sample_size; |
2338 |
|
2339 |
/* reset total length */ |
2340 |
total = 0; |
2341 |
|
2342 |
/* setup frame lengths */ |
2343 |
for (n = 0; n != blockcount; n++) { |
2344 |
uint32_t frame_len; |
2345 |
|
2346 |
ch->sample_curr += ch->sample_rem; |
2347 |
if (ch->sample_curr >= ch->frames_per_second) { |
2348 |
ch->sample_curr -= ch->frames_per_second; |
2349 |
frame_len = ch->bytes_per_frame[1]; |
2350 |
} else { |
2351 |
frame_len = ch->bytes_per_frame[0]; |
2352 |
} |
2353 |
|
2354 |
/* handle free running clock case */ |
2355 |
if (ch->jitter_curr > 0 && |
2356 |
(frame_len + sample_size) <= mfl) { |
2357 |
DPRINTFN(6, "sending one sample more\n"); |
2358 |
ch->jitter_curr--; |
2359 |
frame_len += sample_size; |
2360 |
} else if (ch->jitter_curr < 0 && |
2361 |
frame_len >= sample_size) { |
2362 |
DPRINTFN(6, "sending one sample less\n"); |
2363 |
ch->jitter_curr++; |
2364 |
frame_len -= sample_size; |
2365 |
} |
2366 |
usbd_xfer_set_frame_len(xfer, n, frame_len); |
2367 |
total += frame_len; |
2368 |
} |
2369 |
|
2370 |
DPRINTFN(6, "transferring %d bytes\n", total); |
2371 |
|
2372 |
offset = 0; |
2373 |
|
2374 |
pc = usbd_xfer_get_frame(xfer, 0); |
2375 |
while (total > 0) { |
2376 |
|
2377 |
n = (ch->end - ch->cur); |
2378 |
if (n > total) |
2379 |
n = total; |
2380 |
|
2381 |
usbd_copy_in(pc, offset, ch->cur, n); |
2382 |
|
2383 |
total -= n; |
2384 |
ch->cur += n; |
2385 |
offset += n; |
2386 |
|
2387 |
if (ch->cur >= ch->end) |
2388 |
ch->cur = ch->start; |
2389 |
} |
2390 |
usbd_transfer_submit(xfer); |
2391 |
break; |
2392 |
|
2393 |
default: /* Error */ |
2394 |
if (error != USB_ERR_CANCELLED) |
2395 |
goto tr_setup; |
2396 |
break; |
2397 |
} |
2398 |
} |
2399 |
|
2400 |
static void |
2401 |
uaudio_chan_record_sync_callback(struct usb_xfer *xfer, usb_error_t error) |
2402 |
{ |
2403 |
/* TODO */ |
2404 |
} |
2405 |
|
2406 |
static void |
2407 |
uaudio_chan_record_callback(struct usb_xfer *xfer, usb_error_t error) |
2408 |
{ |
2409 |
struct uaudio_chan *ch = usbd_xfer_softc(xfer); |
2410 |
struct usb_page_cache *pc; |
2411 |
uint32_t offset0; |
2412 |
uint32_t mfl; |
2413 |
int m; |
2414 |
int n; |
2415 |
int len; |
2416 |
int actlen; |
2417 |
int nframes; |
2418 |
int expected_bytes; |
2419 |
int sample_size; |
2420 |
|
2421 |
if (ch->start == ch->end) { |
2422 |
DPRINTF("no buffer!\n"); |
2423 |
return; |
2424 |
} |
2425 |
|
2426 |
usbd_xfer_status(xfer, &actlen, NULL, NULL, &nframes); |
2427 |
mfl = usbd_xfer_max_framelen(xfer); |
2428 |
|
2429 |
switch (USB_GET_STATE(xfer)) { |
2430 |
case USB_ST_TRANSFERRED: |
2431 |
|
2432 |
offset0 = 0; |
2433 |
pc = usbd_xfer_get_frame(xfer, 0); |
2434 |
|
2435 |
/* try to compute the number of expected bytes */ |
2436 |
ch->sample_curr += (ch->sample_rem * ch->intr_frames); |
2437 |
|
2438 |
/* compute number of expected bytes */ |
2439 |
expected_bytes = (ch->intr_frames * ch->bytes_per_frame[0]) + |
2440 |
((ch->sample_curr / ch->frames_per_second) * |
2441 |
(ch->bytes_per_frame[1] - ch->bytes_per_frame[0])); |
2442 |
|
2443 |
/* keep remainder */ |
2444 |
ch->sample_curr %= ch->frames_per_second; |
2445 |
|
2446 |
/* get current sample size */ |
2447 |
sample_size = ch->usb_alt[ch->cur_alt].sample_size; |
2448 |
|
2449 |
for (n = 0; n != nframes; n++) { |
2450 |
uint32_t offset1 = offset0; |
2451 |
|
2452 |
len = usbd_xfer_frame_len(xfer, n); |
2453 |
|
2454 |
/* make sure we only receive complete samples */ |
2455 |
len = len - (len % sample_size); |
2456 |
|
2457 |
/* subtract bytes received from expected payload */ |
2458 |
expected_bytes -= len; |
2459 |
|
2460 |
/* don't receive data when not ready */ |
2461 |
if (ch->running == 0 || ch->cur_alt != ch->set_alt) |
2462 |
continue; |
2463 |
|
2464 |
/* fill ring buffer with samples, if any */ |
2465 |
while (len > 0) { |
2466 |
|
2467 |
m = (ch->end - ch->cur); |
2468 |
|
2469 |
if (m > len) |
2470 |
m = len; |
2471 |
|
2472 |
usbd_copy_out(pc, offset1, ch->cur, m); |
2473 |
|
2474 |
len -= m; |
2475 |
offset1 += m; |
2476 |
ch->cur += m; |
2477 |
|
2478 |
if (ch->cur >= ch->end) |
2479 |
ch->cur = ch->start; |
2480 |
} |
2481 |
|
2482 |
offset0 += mfl; |
2483 |
} |
2484 |
|
2485 |
/* update current jitter */ |
2486 |
ch->jitter_curr -= (expected_bytes / sample_size); |
2487 |
|
2488 |
/* don't allow a huge amount of jitter to accumulate */ |
2489 |
nframes = 2 * ch->intr_frames; |
2490 |
|
2491 |
/* range check current jitter */ |
2492 |
if (ch->jitter_curr < -nframes) |
2493 |
ch->jitter_curr = -nframes; |
2494 |
else if (ch->jitter_curr > nframes) |
2495 |
ch->jitter_curr = nframes; |
2496 |
|
2497 |
DPRINTFN(6, "transferred %d bytes, jitter %d samples\n", |
2498 |
actlen, ch->jitter_curr); |
2499 |
|
2500 |
if (ch->running != 0) |
2501 |
chn_intr(ch->pcm_ch); |
2502 |
|
2503 |
case USB_ST_SETUP: |
2504 |
tr_setup: |
2505 |
nframes = ch->intr_frames; |
2506 |
|
2507 |
usbd_xfer_set_frames(xfer, nframes); |
2508 |
for (n = 0; n != nframes; n++) |
2509 |
usbd_xfer_set_frame_len(xfer, n, mfl); |
2510 |
|
2511 |
usbd_transfer_submit(xfer); |
2512 |
break; |
2513 |
|
2514 |
default: /* Error */ |
2515 |
if (error != USB_ERR_CANCELLED) |
2516 |
goto tr_setup; |
2517 |
break; |
2518 |
} |
2519 |
} |
2520 |
|
2521 |
void * |
2522 |
uaudio_chan_init(struct uaudio_softc *sc, struct snd_dbuf *b, |
2523 |
struct pcm_channel *c, int dir) |
2524 |
{ |
2525 |
struct uaudio_chan *ch = ((dir == PCMDIR_PLAY) ? |
2526 |
&sc->sc_play_chan : &sc->sc_rec_chan); |
2527 |
uint32_t buf_size; |
2528 |
uint8_t x; |
2529 |
|
2530 |
/* store mutex and PCM channel */ |
2531 |
|
2532 |
ch->pcm_ch = c; |
2533 |
ch->pcm_mtx = c->lock; |
2534 |
|
2535 |
/* compute worst case buffer */ |
2536 |
|
2537 |
buf_size = 0; |
2538 |
for (x = 0; x != ch->num_alt; x++) { |
2539 |
uint32_t temp = uaudio_get_buffer_size(ch, x); |
2540 |
if (temp > buf_size) |
2541 |
buf_size = temp; |
2542 |
} |
2543 |
|
2544 |
/* allow double buffering */ |
2545 |
buf_size *= 2; |
2546 |
|
2547 |
DPRINTF("Worst case buffer is %d bytes\n", (int)buf_size); |
2548 |
|
2549 |
ch->buf = malloc(buf_size, M_DEVBUF, M_WAITOK | M_ZERO); |
2550 |
if (ch->buf == NULL) |
2551 |
goto error; |
2552 |
if (sndbuf_setup(b, ch->buf, buf_size) != 0) |
2553 |
goto error; |
2554 |
|
2555 |
ch->start = ch->buf; |
2556 |
ch->end = ch->buf + buf_size; |
2557 |
ch->cur = ch->buf; |
2558 |
ch->pcm_buf = b; |
2559 |
ch->max_buf = buf_size; |
2560 |
|
2561 |
if (ch->pcm_mtx == NULL) { |
2562 |
DPRINTF("ERROR: PCM channels does not have a mutex!\n"); |
2563 |
goto error; |
2564 |
} |
2565 |
return (ch); |
2566 |
|
2567 |
error: |
2568 |
uaudio_chan_free(ch); |
2569 |
return (NULL); |
2570 |
} |
2571 |
|
2572 |
int |
2573 |
uaudio_chan_free(struct uaudio_chan *ch) |
2574 |
{ |
2575 |
if (ch->buf != NULL) { |
2576 |
free(ch->buf, M_DEVBUF); |
2577 |
ch->buf = NULL; |
2578 |
} |
2579 |
usbd_transfer_unsetup(ch->xfer, UAUDIO_NCHANBUFS + 1); |
2580 |
|
2581 |
ch->num_alt = 0; |
2582 |
|
2583 |
return (0); |
2584 |
} |
2585 |
|
2586 |
int |
2587 |
uaudio_chan_set_param_blocksize(struct uaudio_chan *ch, uint32_t blocksize) |
2588 |
{ |
2589 |
uint32_t temp = 2 * uaudio_get_buffer_size(ch, ch->set_alt); |
2590 |
sndbuf_setup(ch->pcm_buf, ch->buf, temp); |
2591 |
return (temp / 2); |
2592 |
} |
2593 |
|
2594 |
int |
2595 |
uaudio_chan_set_param_fragments(struct uaudio_chan *ch, uint32_t blocksize, |
2596 |
uint32_t blockcount) |
2597 |
{ |
2598 |
return (1); |
2599 |
} |
2600 |
|
2601 |
int |
2602 |
uaudio_chan_set_param_speed(struct uaudio_chan *ch, uint32_t speed) |
2603 |
{ |
2604 |
struct uaudio_softc *sc; |
2605 |
uint8_t x; |
2606 |
|
2607 |
sc = ch->priv_sc; |
2608 |
|
2609 |
for (x = 0; x < ch->num_alt; x++) { |
2610 |
if (ch->usb_alt[x].sample_rate < speed) { |
2611 |
/* sample rate is too low */ |
2612 |
break; |
2613 |
} |
2614 |
} |
2615 |
|
2616 |
if (x != 0) |
2617 |
x--; |
2618 |
|
2619 |
usb_proc_explore_lock(sc->sc_udev); |
2620 |
ch->set_alt = x; |
2621 |
usb_proc_explore_unlock(sc->sc_udev); |
2622 |
|
2623 |
DPRINTF("Selecting alt %d\n", (int)x); |
2624 |
|
2625 |
return (ch->usb_alt[x].sample_rate); |
2626 |
} |
2627 |
|
2628 |
int |
2629 |
uaudio_chan_getptr(struct uaudio_chan *ch) |
2630 |
{ |
2631 |
return (ch->cur - ch->start); |
2632 |
} |
2633 |
|
2634 |
struct pcmchan_caps * |
2635 |
uaudio_chan_getcaps(struct uaudio_chan *ch) |
2636 |
{ |
2637 |
return (&ch->pcm_cap); |
2638 |
} |
2639 |
|
2640 |
static struct pcmchan_matrix uaudio_chan_matrix_swap_2_0 = { |
2641 |
.id = SND_CHN_MATRIX_DRV, |
2642 |
.channels = 2, |
2643 |
.ext = 0, |
2644 |
.map = { |
2645 |
/* Right */ |
2646 |
[0] = { |
2647 |
.type = SND_CHN_T_FR, |
2648 |
.members = |
2649 |
SND_CHN_T_MASK_FR | SND_CHN_T_MASK_FC | |
2650 |
SND_CHN_T_MASK_LF | SND_CHN_T_MASK_BR | |
2651 |
SND_CHN_T_MASK_BC | SND_CHN_T_MASK_SR |
2652 |
}, |
2653 |
/* Left */ |
2654 |
[1] = { |
2655 |
.type = SND_CHN_T_FL, |
2656 |
.members = |
2657 |
SND_CHN_T_MASK_FL | SND_CHN_T_MASK_FC | |
2658 |
SND_CHN_T_MASK_LF | SND_CHN_T_MASK_BL | |
2659 |
SND_CHN_T_MASK_BC | SND_CHN_T_MASK_SL |
2660 |
}, |
2661 |
[2] = { |
2662 |
.type = SND_CHN_T_MAX, |
2663 |
.members = 0 |
2664 |
} |
2665 |
}, |
2666 |
.mask = SND_CHN_T_MASK_FR | SND_CHN_T_MASK_FL, |
2667 |
.offset = { 1, 0, -1, -1, -1, -1, -1, -1, -1, |
2668 |
-1, -1, -1, -1, -1, -1, -1, -1, -1 } |
2669 |
}; |
2670 |
|
2671 |
struct pcmchan_matrix * |
2672 |
uaudio_chan_getmatrix(struct uaudio_chan *ch, uint32_t format) |
2673 |
{ |
2674 |
struct uaudio_softc *sc; |
2675 |
|
2676 |
sc = ch->priv_sc; |
2677 |
|
2678 |
if (sc != NULL && sc->sc_uq_audio_swap_lr != 0 && |
2679 |
AFMT_CHANNEL(format) == 2) |
2680 |
return (&uaudio_chan_matrix_swap_2_0); |
2681 |
|
2682 |
return (feeder_matrix_format_map(format)); |
2683 |
} |
2684 |
|
2685 |
int |
2686 |
uaudio_chan_set_param_format(struct uaudio_chan *ch, uint32_t format) |
2687 |
{ |
2688 |
DPRINTF("Selecting format 0x%08x\n", (unsigned int)format); |
2689 |
return (0); |
2690 |
} |
2691 |
|
2692 |
static void |
2693 |
uaudio_chan_start_sub(struct uaudio_chan *ch) |
2694 |
{ |
2695 |
struct uaudio_softc *sc = ch->priv_sc; |
2696 |
int do_start = 0; |
2697 |
|
2698 |
if (ch->operation != CHAN_OP_DRAIN) { |
2699 |
if (ch->cur_alt == ch->set_alt && |
2700 |
ch->operation == CHAN_OP_NONE && |
2701 |
mtx_owned(ch->pcm_mtx) != 0) { |
2702 |
/* save doing the explore task */ |
2703 |
do_start = 1; |
2704 |
} else { |
2705 |
ch->operation = CHAN_OP_START; |
2706 |
(void)usb_proc_explore_msignal(sc->sc_udev, |
2707 |
&sc->sc_config_msg[0], &sc->sc_config_msg[1]); |
2708 |
} |
2709 |
} |
2710 |
if (do_start) { |
2711 |
usbd_transfer_start(ch->xfer[0]); |
2712 |
usbd_transfer_start(ch->xfer[1]); |
2713 |
} |
2714 |
} |
2715 |
|
2716 |
static int |
2717 |
uaudio_chan_need_both(struct uaudio_softc *sc) |
2718 |
{ |
2719 |
return (sc->sc_play_chan.num_alt > 0 && |
2720 |
sc->sc_play_chan.running != 0 && |
2721 |
uaudio_chan_is_async(&sc->sc_play_chan, |
2722 |
sc->sc_play_chan.set_alt) != 0 && |
2723 |
sc->sc_rec_chan.num_alt > 0 && |
2724 |
sc->sc_rec_chan.running == 0); |
2725 |
} |
2726 |
|
2727 |
static int |
2728 |
uaudio_chan_need_none(struct uaudio_softc *sc) |
2729 |
{ |
2730 |
return (sc->sc_play_chan.num_alt > 0 && |
2731 |
sc->sc_play_chan.running == 0 && |
2732 |
sc->sc_rec_chan.num_alt > 0 && |
2733 |
sc->sc_rec_chan.running == 0); |
2734 |
} |
2735 |
|
2736 |
void |
2737 |
uaudio_chan_start(struct uaudio_chan *ch) |
2738 |
{ |
2739 |
struct uaudio_softc *sc = ch->priv_sc; |
2740 |
|
2741 |
/* make operation atomic */ |
2742 |
usb_proc_explore_lock(sc->sc_udev); |
2743 |
|
2744 |
/* check if not running */ |
2745 |
if (ch->running == 0) { |
2746 |
uint32_t temp; |
2747 |
|
2748 |
/* get current buffer size */ |
2749 |
temp = 2 * uaudio_get_buffer_size(ch, ch->set_alt); |
2750 |
|
2751 |
/* set running flag */ |
2752 |
ch->running = 1; |
2753 |
|
2754 |
/* ensure the hardware buffer is reset */ |
2755 |
ch->start = ch->buf; |
2756 |
ch->end = ch->buf + temp; |
2757 |
ch->cur = ch->buf; |
2758 |
|
2759 |
if (uaudio_chan_need_both(sc)) { |
2760 |
/* |
2761 |
* Start both endpoints because of need for |
2762 |
* jitter information: |
2763 |
*/ |
2764 |
uaudio_chan_start_sub(&sc->sc_rec_chan); |
2765 |
uaudio_chan_start_sub(&sc->sc_play_chan); |
2766 |
} else { |
2767 |
uaudio_chan_start_sub(ch); |
2768 |
} |
2769 |
} |
2770 |
|
2771 |
/* exit atomic operation */ |
2772 |
usb_proc_explore_unlock(sc->sc_udev); |
2773 |
} |
2774 |
|
2775 |
static void |
2776 |
uaudio_chan_stop_sub(struct uaudio_chan *ch) |
2777 |
{ |
2778 |
struct uaudio_softc *sc = ch->priv_sc; |
2779 |
int do_stop = 0; |
2780 |
|
2781 |
if (ch->operation != CHAN_OP_DRAIN) { |
2782 |
if (ch->cur_alt == ch->set_alt && |
2783 |
ch->operation == CHAN_OP_NONE && |
2784 |
mtx_owned(ch->pcm_mtx) != 0) { |
2785 |
/* save doing the explore task */ |
2786 |
do_stop = 1; |
2787 |
} else { |
2788 |
ch->operation = CHAN_OP_STOP; |
2789 |
(void)usb_proc_explore_msignal(sc->sc_udev, |
2790 |
&sc->sc_config_msg[0], &sc->sc_config_msg[1]); |
2791 |
} |
2792 |
} |
2793 |
if (do_stop) { |
2794 |
usbd_transfer_stop(ch->xfer[0]); |
2795 |
usbd_transfer_stop(ch->xfer[1]); |
2796 |
} |
2797 |
} |
2798 |
|
2799 |
void |
2800 |
uaudio_chan_stop(struct uaudio_chan *ch) |
2801 |
{ |
2802 |
struct uaudio_softc *sc = ch->priv_sc; |
2803 |
|
2804 |
/* make operation atomic */ |
2805 |
usb_proc_explore_lock(sc->sc_udev); |
2806 |
|
2807 |
/* check if running */ |
2808 |
if (ch->running != 0) { |
2809 |
/* clear running flag */ |
2810 |
ch->running = 0; |
2811 |
|
2812 |
if (uaudio_chan_need_both(sc)) { |
2813 |
/* |
2814 |
* Leave the endpoints running because we need |
2815 |
* information about jitter! |
2816 |
*/ |
2817 |
} else if (uaudio_chan_need_none(sc)) { |
2818 |
/* |
2819 |
* Stop both endpoints in case the one was used for |
2820 |
* jitter information: |
2821 |
*/ |
2822 |
uaudio_chan_stop_sub(&sc->sc_rec_chan); |
2823 |
uaudio_chan_stop_sub(&sc->sc_play_chan); |
2824 |
} else { |
2825 |
uaudio_chan_stop_sub(ch); |
2826 |
} |
2827 |
} |
2828 |
|
2829 |
/* exit atomic operation */ |
2830 |
usb_proc_explore_unlock(sc->sc_udev); |
2831 |
} |
2832 |
|
2833 |
/*========================================================================* |
2834 |
* AC - Audio Controller - routines |
2835 |
*========================================================================*/ |
2836 |
|
2837 |
static int |
2838 |
uaudio_mixer_sysctl_handler(SYSCTL_HANDLER_ARGS) |
2839 |
{ |
2840 |
struct uaudio_softc *sc; |
2841 |
struct uaudio_mixer_node *pmc; |
2842 |
int hint; |
2843 |
int error; |
2844 |
int temp = 0; |
2845 |
int chan = 0; |
2846 |
|
2847 |
sc = (struct uaudio_softc *)oidp->oid_arg1; |
2848 |
hint = oidp->oid_arg2; |
2849 |
|
2850 |
if (sc->sc_mixer_lock == NULL) |
2851 |
return (ENXIO); |
2852 |
|
2853 |
/* lookup mixer node */ |
2854 |
|
2855 |
mtx_lock(sc->sc_mixer_lock); |
2856 |
for (pmc = sc->sc_mixer_root; pmc != NULL; pmc = pmc->next) { |
2857 |
for (chan = 0; chan != (int)pmc->nchan; chan++) { |
2858 |
if (pmc->wValue[chan] != -1 && |
2859 |
pmc->wValue[chan] == hint) { |
2860 |
temp = pmc->wData[chan]; |
2861 |
goto found; |
2862 |
} |
2863 |
} |
2864 |
} |
2865 |
found: |
2866 |
mtx_unlock(sc->sc_mixer_lock); |
2867 |
|
2868 |
error = sysctl_handle_int(oidp, &temp, 0, req); |
2869 |
if (error != 0 || req->newptr == NULL) |
2870 |
return (error); |
2871 |
|
2872 |
/* update mixer value */ |
2873 |
|
2874 |
mtx_lock(sc->sc_mixer_lock); |
2875 |
if (pmc != NULL && |
2876 |
temp >= pmc->minval && |
2877 |
temp <= pmc->maxval) { |
2878 |
|
2879 |
pmc->wData[chan] = temp; |
2880 |
pmc->update[(chan / 8)] |= (1 << (chan % 8)); |
2881 |
|
2882 |
/* start the transfer, if not already started */ |
2883 |
usbd_transfer_start(sc->sc_mixer_xfer[0]); |
2884 |
} |
2885 |
mtx_unlock(sc->sc_mixer_lock); |
2886 |
|
2887 |
return (0); |
2888 |
} |
2889 |
|
2890 |
static void |
2891 |
uaudio_mixer_ctl_free(struct uaudio_softc *sc) |
2892 |
{ |
2893 |
struct uaudio_mixer_node *p_mc; |
2894 |
|
2895 |
while ((p_mc = sc->sc_mixer_root) != NULL) { |
2896 |
sc->sc_mixer_root = p_mc->next; |
2897 |
free(p_mc, M_USBDEV); |
2898 |
} |
2899 |
} |
2900 |
|
2901 |
static void |
2902 |
uaudio_mixer_register_sysctl(struct uaudio_softc *sc, device_t dev) |
2903 |
{ |
2904 |
struct uaudio_mixer_node *pmc; |
2905 |
struct sysctl_oid *mixer_tree; |
2906 |
struct sysctl_oid *control_tree; |
2907 |
char buf[32]; |
2908 |
int chan; |
2909 |
int n; |
2910 |
|
2911 |
mixer_tree = SYSCTL_ADD_NODE(device_get_sysctl_ctx(dev), |
2912 |
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "mixer", |
2913 |
CTLFLAG_RD, NULL, ""); |
2914 |
|
2915 |
if (mixer_tree == NULL) |
2916 |
return; |
2917 |
|
2918 |
for (n = 0, pmc = sc->sc_mixer_root; pmc != NULL; |
2919 |
pmc = pmc->next, n++) { |
2920 |
|
2921 |
for (chan = 0; chan < pmc->nchan; chan++) { |
2922 |
|
2923 |
if (pmc->nchan > 1) { |
2924 |
snprintf(buf, sizeof(buf), "%s_%d_%d", |
2925 |
pmc->name, n, chan); |
2926 |
} else { |
2927 |
snprintf(buf, sizeof(buf), "%s_%d", |
2928 |
pmc->name, n); |
2929 |
} |
2930 |
|
2931 |
control_tree = SYSCTL_ADD_NODE(device_get_sysctl_ctx(dev), |
2932 |
SYSCTL_CHILDREN(mixer_tree), OID_AUTO, buf, |
2933 |
CTLFLAG_RD, NULL, "Mixer control nodes"); |
2934 |
|
2935 |
if (control_tree == NULL) |
2936 |
continue; |
2937 |
|
2938 |
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), |
2939 |
SYSCTL_CHILDREN(control_tree), |
2940 |
OID_AUTO, "val", CTLTYPE_INT | CTLFLAG_RW, sc, |
2941 |
pmc->wValue[chan], |
2942 |
uaudio_mixer_sysctl_handler, "I", "Current value"); |
2943 |
|
2944 |
SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), |
2945 |
SYSCTL_CHILDREN(control_tree), |
2946 |
OID_AUTO, "min", CTLFLAG_RD, 0, pmc->minval, |
2947 |
"Minimum value"); |
2948 |
|
2949 |
SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), |
2950 |
SYSCTL_CHILDREN(control_tree), |
2951 |
OID_AUTO, "max", CTLFLAG_RD, 0, pmc->maxval, |
2952 |
"Maximum value"); |
2953 |
|
2954 |
SYSCTL_ADD_STRING(device_get_sysctl_ctx(dev), |
2955 |
SYSCTL_CHILDREN(control_tree), |
2956 |
OID_AUTO, "desc", CTLFLAG_RD, pmc->desc, 0, |
2957 |
"Description"); |
2958 |
} |
2959 |
} |
2960 |
} |
2961 |
|
2962 |
/* M-Audio FastTrack Ultra Mixer Description */ |
2963 |
/* Origin: Linux USB Audio driver */ |
2964 |
static void |
2965 |
uaudio_mixer_controls_create_ftu(struct uaudio_softc *sc) |
2966 |
{ |
2967 |
int chx; |
2968 |
int chy; |
2969 |
|
2970 |
memset(&MIX(sc), 0, sizeof(MIX(sc))); |
2971 |
MIX(sc).wIndex = MAKE_WORD(6, sc->sc_mixer_iface_no); |
2972 |
MIX(sc).wValue[0] = MAKE_WORD(8, 0); |
2973 |
MIX(sc).class = UAC_OUTPUT; |
2974 |
MIX(sc).type = MIX_UNSIGNED_16; |
2975 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; |
2976 |
MIX(sc).name = "effect"; |
2977 |
MIX(sc).minval = 0; |
2978 |
MIX(sc).maxval = 7; |
2979 |
MIX(sc).mul = 7; |
2980 |
MIX(sc).nchan = 1; |
2981 |
MIX(sc).update[0] = 1; |
2982 |
strlcpy(MIX(sc).desc, "Room1,2,3,Hall1,2,Plate,Delay,Echo", sizeof(MIX(sc).desc)); |
2983 |
uaudio_mixer_add_ctl_sub(sc, &MIX(sc)); |
2984 |
|
2985 |
memset(&MIX(sc), 0, sizeof(MIX(sc))); |
2986 |
MIX(sc).wIndex = MAKE_WORD(5, sc->sc_mixer_iface_no); |
2987 |
|
2988 |
for (chx = 0; chx != 8; chx++) { |
2989 |
for (chy = 0; chy != 8; chy++) { |
2990 |
|
2991 |
MIX(sc).wValue[0] = MAKE_WORD(chx + 1, chy + 1); |
2992 |
MIX(sc).type = MIX_SIGNED_16; |
2993 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; |
2994 |
MIX(sc).name = "mix_rec"; |
2995 |
MIX(sc).nchan = 1; |
2996 |
MIX(sc).update[0] = 1; |
2997 |
MIX(sc).val_default = 0; |
2998 |
snprintf(MIX(sc).desc, sizeof(MIX(sc).desc), |
2999 |
"AIn%d - Out%d Record Volume", chy + 1, chx + 1); |
3000 |
|
3001 |
uaudio_mixer_add_ctl(sc, &MIX(sc)); |
3002 |
|
3003 |
MIX(sc).wValue[0] = MAKE_WORD(chx + 1, chy + 1 + 8); |
3004 |
MIX(sc).type = MIX_SIGNED_16; |
3005 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; |
3006 |
MIX(sc).name = "mix_play"; |
3007 |
MIX(sc).nchan = 1; |
3008 |
MIX(sc).update[0] = 1; |
3009 |
MIX(sc).val_default = (chx == chy) ? 2 : 0; |
3010 |
snprintf(MIX(sc).desc, sizeof(MIX(sc).desc), |
3011 |
"DIn%d - Out%d Playback Volume", chy + 1, chx + 1); |
3012 |
|
3013 |
uaudio_mixer_add_ctl(sc, &MIX(sc)); |
3014 |
} |
3015 |
} |
3016 |
|
3017 |
memset(&MIX(sc), 0, sizeof(MIX(sc))); |
3018 |
MIX(sc).wIndex = MAKE_WORD(6, sc->sc_mixer_iface_no); |
3019 |
MIX(sc).wValue[0] = MAKE_WORD(2, 0); |
3020 |
MIX(sc).class = UAC_OUTPUT; |
3021 |
MIX(sc).type = MIX_SIGNED_8; |
3022 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; |
3023 |
MIX(sc).name = "effect_vol"; |
3024 |
MIX(sc).nchan = 1; |
3025 |
MIX(sc).update[0] = 1; |
3026 |
MIX(sc).minval = 0; |
3027 |
MIX(sc).maxval = 0x7f; |
3028 |
MIX(sc).mul = 0x7f; |
3029 |
MIX(sc).nchan = 1; |
3030 |
MIX(sc).update[0] = 1; |
3031 |
strlcpy(MIX(sc).desc, "Effect Volume", sizeof(MIX(sc).desc)); |
3032 |
uaudio_mixer_add_ctl_sub(sc, &MIX(sc)); |
3033 |
|
3034 |
memset(&MIX(sc), 0, sizeof(MIX(sc))); |
3035 |
MIX(sc).wIndex = MAKE_WORD(6, sc->sc_mixer_iface_no); |
3036 |
MIX(sc).wValue[0] = MAKE_WORD(3, 0); |
3037 |
MIX(sc).class = UAC_OUTPUT; |
3038 |
MIX(sc).type = MIX_SIGNED_16; |
3039 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; |
3040 |
MIX(sc).name = "effect_dur"; |
3041 |
MIX(sc).nchan = 1; |
3042 |
MIX(sc).update[0] = 1; |
3043 |
MIX(sc).minval = 0; |
3044 |
MIX(sc).maxval = 0x7f00; |
3045 |
MIX(sc).mul = 0x7f00; |
3046 |
MIX(sc).nchan = 1; |
3047 |
MIX(sc).update[0] = 1; |
3048 |
strlcpy(MIX(sc).desc, "Effect Duration", sizeof(MIX(sc).desc)); |
3049 |
uaudio_mixer_add_ctl_sub(sc, &MIX(sc)); |
3050 |
|
3051 |
memset(&MIX(sc), 0, sizeof(MIX(sc))); |
3052 |
MIX(sc).wIndex = MAKE_WORD(6, sc->sc_mixer_iface_no); |
3053 |
MIX(sc).wValue[0] = MAKE_WORD(4, 0); |
3054 |
MIX(sc).class = UAC_OUTPUT; |
3055 |
MIX(sc).type = MIX_SIGNED_8; |
3056 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; |
3057 |
MIX(sc).name = "effect_fb"; |
3058 |
MIX(sc).nchan = 1; |
3059 |
MIX(sc).update[0] = 1; |
3060 |
MIX(sc).minval = 0; |
3061 |
MIX(sc).maxval = 0x7f; |
3062 |
MIX(sc).mul = 0x7f; |
3063 |
MIX(sc).nchan = 1; |
3064 |
MIX(sc).update[0] = 1; |
3065 |
strlcpy(MIX(sc).desc, "Effect Feedback Volume", sizeof(MIX(sc).desc)); |
3066 |
uaudio_mixer_add_ctl_sub(sc, &MIX(sc)); |
3067 |
|
3068 |
memset(&MIX(sc), 0, sizeof(MIX(sc))); |
3069 |
MIX(sc).wIndex = MAKE_WORD(7, sc->sc_mixer_iface_no); |
3070 |
for (chy = 0; chy != 4; chy++) { |
3071 |
|
3072 |
MIX(sc).wValue[0] = MAKE_WORD(7, chy + 1); |
3073 |
MIX(sc).type = MIX_SIGNED_16; |
3074 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; |
3075 |
MIX(sc).name = "effect_ret"; |
3076 |
MIX(sc).nchan = 1; |
3077 |
MIX(sc).update[0] = 1; |
3078 |
snprintf(MIX(sc).desc, sizeof(MIX(sc).desc), |
3079 |
"Effect Return %d Volume", chy + 1); |
3080 |
|
3081 |
uaudio_mixer_add_ctl(sc, &MIX(sc)); |
3082 |
} |
3083 |
|
3084 |
memset(&MIX(sc), 0, sizeof(MIX(sc))); |
3085 |
MIX(sc).wIndex = MAKE_WORD(5, sc->sc_mixer_iface_no); |
3086 |
|
3087 |
for (chy = 0; chy != 8; chy++) { |
3088 |
MIX(sc).wValue[0] = MAKE_WORD(9, chy + 1); |
3089 |
MIX(sc).type = MIX_SIGNED_16; |
3090 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; |
3091 |
MIX(sc).name = "effect_send"; |
3092 |
MIX(sc).nchan = 1; |
3093 |
MIX(sc).update[0] = 1; |
3094 |
snprintf(MIX(sc).desc, sizeof(MIX(sc).desc), |
3095 |
"Effect Send AIn%d Volume", chy + 1); |
3096 |
|
3097 |
uaudio_mixer_add_ctl(sc, &MIX(sc)); |
3098 |
|
3099 |
MIX(sc).wValue[0] = MAKE_WORD(9, chy + 1 + 8); |
3100 |
MIX(sc).type = MIX_SIGNED_16; |
3101 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; |
3102 |
MIX(sc).name = "effect_send"; |
3103 |
MIX(sc).nchan = 1; |
3104 |
MIX(sc).update[0] = 1; |
3105 |
snprintf(MIX(sc).desc, sizeof(MIX(sc).desc), |
3106 |
"Effect Send DIn%d Volume", chy + 1); |
3107 |
|
3108 |
uaudio_mixer_add_ctl(sc, &MIX(sc)); |
3109 |
} |
3110 |
} |
3111 |
|
3112 |
static void |
3113 |
uaudio_mixer_reload_all(struct uaudio_softc *sc) |
3114 |
{ |
3115 |
struct uaudio_mixer_node *pmc; |
3116 |
int chan; |
3117 |
|
3118 |
if (sc->sc_mixer_lock == NULL) |
3119 |
return; |
3120 |
|
3121 |
mtx_lock(sc->sc_mixer_lock); |
3122 |
for (pmc = sc->sc_mixer_root; pmc != NULL; pmc = pmc->next) { |
3123 |
/* use reset defaults for non-oss controlled settings */ |
3124 |
if (pmc->ctl == SOUND_MIXER_NRDEVICES) |
3125 |
continue; |
3126 |
for (chan = 0; chan < pmc->nchan; chan++) |
3127 |
pmc->update[chan / 8] |= (1 << (chan % 8)); |
3128 |
} |
3129 |
usbd_transfer_start(sc->sc_mixer_xfer[0]); |
3130 |
|
3131 |
/* start HID volume keys, if any */ |
3132 |
usbd_transfer_start(sc->sc_hid.xfer[0]); |
3133 |
mtx_unlock(sc->sc_mixer_lock); |
3134 |
} |
3135 |
|
3136 |
static void |
3137 |
uaudio_mixer_add_ctl_sub(struct uaudio_softc *sc, struct uaudio_mixer_node *mc) |
3138 |
{ |
3139 |
struct uaudio_mixer_node *p_mc_new = |
3140 |
malloc(sizeof(*p_mc_new), M_USBDEV, M_WAITOK); |
3141 |
int ch; |
3142 |
|
3143 |
if (p_mc_new != NULL) { |
3144 |
memcpy(p_mc_new, mc, sizeof(*p_mc_new)); |
3145 |
p_mc_new->next = sc->sc_mixer_root; |
3146 |
sc->sc_mixer_root = p_mc_new; |
3147 |
sc->sc_mixer_count++; |
3148 |
|
3149 |
/* set default value for all channels */ |
3150 |
for (ch = 0; ch < p_mc_new->nchan; ch++) { |
3151 |
switch (p_mc_new->val_default) { |
3152 |
case 1: |
3153 |
/* 50% */ |
3154 |
p_mc_new->wData[ch] = (p_mc_new->maxval + p_mc_new->minval) / 2; |
3155 |
break; |
3156 |
case 2: |
3157 |
/* 100% */ |
3158 |
p_mc_new->wData[ch] = p_mc_new->maxval; |
3159 |
break; |
3160 |
default: |
3161 |
/* 0% */ |
3162 |
p_mc_new->wData[ch] = p_mc_new->minval; |
3163 |
break; |
3164 |
} |
3165 |
} |
3166 |
} else { |
3167 |
DPRINTF("out of memory\n"); |
3168 |
} |
3169 |
} |
3170 |
|
3171 |
static void |
3172 |
uaudio_mixer_add_ctl(struct uaudio_softc *sc, struct uaudio_mixer_node *mc) |
3173 |
{ |
3174 |
int32_t res; |
3175 |
|
3176 |
if (mc->class < UAC_NCLASSES) { |
3177 |
DPRINTF("adding %s.%d\n", |
3178 |
uac_names[mc->class], mc->ctl); |
3179 |
} else { |
3180 |
DPRINTF("adding %d\n", mc->ctl); |
3181 |
} |
3182 |
|
3183 |
if (mc->type == MIX_ON_OFF) { |
3184 |
mc->minval = 0; |
3185 |
mc->maxval = 1; |
3186 |
} else if (mc->type == MIX_SELECTOR) { |
3187 |
} else { |
3188 |
|
3189 |
/* determine min and max values */ |
3190 |
|
3191 |
mc->minval = uaudio_mixer_get(sc->sc_udev, |
3192 |
sc->sc_audio_rev, GET_MIN, mc); |
3193 |
mc->maxval = uaudio_mixer_get(sc->sc_udev, |
3194 |
sc->sc_audio_rev, GET_MAX, mc); |
3195 |
|
3196 |
/* check if max and min was swapped */ |
3197 |
|
3198 |
if (mc->maxval < mc->minval) { |
3199 |
res = mc->maxval; |
3200 |
mc->maxval = mc->minval; |
3201 |
mc->minval = res; |
3202 |
} |
3203 |
|
3204 |
/* compute value range */ |
3205 |
mc->mul = mc->maxval - mc->minval; |
3206 |
if (mc->mul == 0) |
3207 |
mc->mul = 1; |
3208 |
|
3209 |
/* compute value alignment */ |
3210 |
res = uaudio_mixer_get(sc->sc_udev, |
3211 |
sc->sc_audio_rev, GET_RES, mc); |
3212 |
|
3213 |
DPRINTF("Resolution = %d\n", (int)res); |
3214 |
} |
3215 |
|
3216 |
uaudio_mixer_add_ctl_sub(sc, mc); |
3217 |
|
3218 |
#ifdef USB_DEBUG |
3219 |
if (uaudio_debug > 2) { |
3220 |
uint8_t i; |
3221 |
|
3222 |
for (i = 0; i < mc->nchan; i++) { |
3223 |
DPRINTF("[mix] wValue=%04x\n", mc->wValue[0]); |
3224 |
} |
3225 |
DPRINTF("[mix] wIndex=%04x type=%d ctl='%d' " |
3226 |
"min=%d max=%d\n", |
3227 |
mc->wIndex, mc->type, mc->ctl, |
3228 |
mc->minval, mc->maxval); |
3229 |
} |
3230 |
#endif |
3231 |
} |
3232 |
|
3233 |
static void |
3234 |
uaudio_mixer_add_mixer(struct uaudio_softc *sc, |
3235 |
const struct uaudio_terminal_node *iot, int id) |
3236 |
{ |
3237 |
const struct usb_audio_mixer_unit_0 *d0 = iot[id].u.mu_v1; |
3238 |
const struct usb_audio_mixer_unit_1 *d1; |
3239 |
|
3240 |
uint32_t bno; /* bit number */ |
3241 |
uint32_t p; /* bit number accumulator */ |
3242 |
uint32_t mo; /* matching outputs */ |
3243 |
uint32_t mc; /* matching channels */ |
3244 |
uint32_t ichs; /* input channels */ |
3245 |
uint32_t ochs; /* output channels */ |
3246 |
uint32_t c; |
3247 |
uint32_t chs; /* channels */ |
3248 |
uint32_t i; |
3249 |
uint32_t o; |
3250 |
|
3251 |
DPRINTFN(3, "bUnitId=%d bNrInPins=%d\n", |
3252 |
d0->bUnitId, d0->bNrInPins); |
3253 |
|
3254 |
/* compute the number of input channels */ |
3255 |
|
3256 |
ichs = 0; |
3257 |
for (i = 0; i < d0->bNrInPins; i++) { |
3258 |
ichs += uaudio_mixer_get_cluster( |
3259 |
d0->baSourceId[i], iot).bNrChannels; |
3260 |
} |
3261 |
|
3262 |
d1 = (const void *)(d0->baSourceId + d0->bNrInPins); |
3263 |
|
3264 |
/* and the number of output channels */ |
3265 |
|
3266 |
ochs = d1->bNrChannels; |
3267 |
|
3268 |
DPRINTFN(3, "ichs=%d ochs=%d\n", ichs, ochs); |
3269 |
|
3270 |
memset(&MIX(sc), 0, sizeof(MIX(sc))); |
3271 |
|
3272 |
MIX(sc).wIndex = MAKE_WORD(d0->bUnitId, sc->sc_mixer_iface_no); |
3273 |
uaudio_mixer_determine_class(&iot[id], &MIX(sc)); |
3274 |
MIX(sc).type = MIX_SIGNED_16; |
3275 |
|
3276 |
if (uaudio_mixer_verify_desc(d0, ((ichs * ochs) + 7) / 8) == NULL) |
3277 |
return; |
3278 |
|
3279 |
for (p = i = 0; i < d0->bNrInPins; i++) { |
3280 |
chs = uaudio_mixer_get_cluster( |
3281 |
d0->baSourceId[i], iot).bNrChannels; |
3282 |
mc = 0; |
3283 |
for (c = 0; c < chs; c++) { |
3284 |
mo = 0; |
3285 |
for (o = 0; o < ochs; o++) { |
3286 |
bno = ((p + c) * ochs) + o; |
3287 |
if (BIT_TEST(d1->bmControls, bno)) |
3288 |
mo++; |
3289 |
} |
3290 |
if (mo == 1) |
3291 |
mc++; |
3292 |
} |
3293 |
if ((mc == chs) && (chs <= MIX_MAX_CHAN)) { |
3294 |
|
3295 |
/* repeat bit-scan */ |
3296 |
|
3297 |
mc = 0; |
3298 |
for (c = 0; c < chs; c++) { |
3299 |
for (o = 0; o < ochs; o++) { |
3300 |
bno = ((p + c) * ochs) + o; |
3301 |
if (BIT_TEST(d1->bmControls, bno)) |
3302 |
MIX(sc).wValue[mc++] = MAKE_WORD(p + c + 1, o + 1); |
3303 |
} |
3304 |
} |
3305 |
MIX(sc).nchan = chs; |
3306 |
uaudio_mixer_add_ctl(sc, &MIX(sc)); |
3307 |
} |
3308 |
p += chs; |
3309 |
} |
3310 |
} |
3311 |
|
3312 |
static void |
3313 |
uaudio20_mixer_add_mixer(struct uaudio_softc *sc, |
3314 |
const struct uaudio_terminal_node *iot, int id) |
3315 |
{ |
3316 |
const struct usb_audio20_mixer_unit_0 *d0 = iot[id].u.mu_v2; |
3317 |
const struct usb_audio20_mixer_unit_1 *d1; |
3318 |
|
3319 |
uint32_t bno; /* bit number */ |
3320 |
uint32_t p; /* bit number accumulator */ |
3321 |
uint32_t mo; /* matching outputs */ |
3322 |
uint32_t mc; /* matching channels */ |
3323 |
uint32_t ichs; /* input channels */ |
3324 |
uint32_t ochs; /* output channels */ |
3325 |
uint32_t c; |
3326 |
uint32_t chs; /* channels */ |
3327 |
uint32_t i; |
3328 |
uint32_t o; |
3329 |
|
3330 |
DPRINTFN(3, "bUnitId=%d bNrInPins=%d\n", |
3331 |
d0->bUnitId, d0->bNrInPins); |
3332 |
|
3333 |
/* compute the number of input channels */ |
3334 |
|
3335 |
ichs = 0; |
3336 |
for (i = 0; i < d0->bNrInPins; i++) { |
3337 |
ichs += uaudio20_mixer_get_cluster( |
3338 |
d0->baSourceId[i], iot).bNrChannels; |
3339 |
} |
3340 |
|
3341 |
d1 = (const void *)(d0->baSourceId + d0->bNrInPins); |
3342 |
|
3343 |
/* and the number of output channels */ |
3344 |
|
3345 |
ochs = d1->bNrChannels; |
3346 |
|
3347 |
DPRINTFN(3, "ichs=%d ochs=%d\n", ichs, ochs); |
3348 |
|
3349 |
memset(&MIX(sc), 0, sizeof(MIX(sc))); |
3350 |
|
3351 |
MIX(sc).wIndex = MAKE_WORD(d0->bUnitId, sc->sc_mixer_iface_no); |
3352 |
uaudio20_mixer_determine_class(&iot[id], &MIX(sc)); |
3353 |
MIX(sc).type = MIX_SIGNED_16; |
3354 |
|
3355 |
if (uaudio20_mixer_verify_desc(d0, ((ichs * ochs) + 7) / 8) == NULL) |
3356 |
return; |
3357 |
|
3358 |
for (p = i = 0; i < d0->bNrInPins; i++) { |
3359 |
chs = uaudio20_mixer_get_cluster( |
3360 |
d0->baSourceId[i], iot).bNrChannels; |
3361 |
mc = 0; |
3362 |
for (c = 0; c < chs; c++) { |
3363 |
mo = 0; |
3364 |
for (o = 0; o < ochs; o++) { |
3365 |
bno = ((p + c) * ochs) + o; |
3366 |
if (BIT_TEST(d1->bmControls, bno)) |
3367 |
mo++; |
3368 |
} |
3369 |
if (mo == 1) |
3370 |
mc++; |
3371 |
} |
3372 |
if ((mc == chs) && (chs <= MIX_MAX_CHAN)) { |
3373 |
|
3374 |
/* repeat bit-scan */ |
3375 |
|
3376 |
mc = 0; |
3377 |
for (c = 0; c < chs; c++) { |
3378 |
for (o = 0; o < ochs; o++) { |
3379 |
bno = ((p + c) * ochs) + o; |
3380 |
if (BIT_TEST(d1->bmControls, bno)) |
3381 |
MIX(sc).wValue[mc++] = MAKE_WORD(p + c + 1, o + 1); |
3382 |
} |
3383 |
} |
3384 |
MIX(sc).nchan = chs; |
3385 |
uaudio_mixer_add_ctl(sc, &MIX(sc)); |
3386 |
} |
3387 |
p += chs; |
3388 |
} |
3389 |
} |
3390 |
|
3391 |
static void |
3392 |
uaudio_mixer_add_selector(struct uaudio_softc *sc, |
3393 |
const struct uaudio_terminal_node *iot, int id) |
3394 |
{ |
3395 |
const struct usb_audio_selector_unit *d = iot[id].u.su_v1; |
3396 |
uint16_t i; |
3397 |
|
3398 |
DPRINTFN(3, "bUnitId=%d bNrInPins=%d\n", |
3399 |
d->bUnitId, d->bNrInPins); |
3400 |
|
3401 |
if (d->bNrInPins == 0) |
3402 |
return; |
3403 |
|
3404 |
memset(&MIX(sc), 0, sizeof(MIX(sc))); |
3405 |
|
3406 |
MIX(sc).wIndex = MAKE_WORD(d->bUnitId, sc->sc_mixer_iface_no); |
3407 |
MIX(sc).wValue[0] = MAKE_WORD(0, 0); |
3408 |
uaudio_mixer_determine_class(&iot[id], &MIX(sc)); |
3409 |
MIX(sc).nchan = 1; |
3410 |
MIX(sc).type = MIX_SELECTOR; |
3411 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; |
3412 |
MIX(sc).minval = 1; |
3413 |
MIX(sc).maxval = d->bNrInPins; |
3414 |
MIX(sc).name = "selector"; |
3415 |
|
3416 |
i = d->baSourceId[d->bNrInPins]; |
3417 |
if (i == 0 || |
3418 |
usbd_req_get_string_any(sc->sc_udev, NULL, |
3419 |
MIX(sc).desc, sizeof(MIX(sc).desc), i) != 0) { |
3420 |
MIX(sc).desc[0] = 0; |
3421 |
} |
3422 |
|
3423 |
if (MIX(sc).maxval > MAX_SELECTOR_INPUT_PIN) { |
3424 |
MIX(sc).maxval = MAX_SELECTOR_INPUT_PIN; |
3425 |
} |
3426 |
MIX(sc).mul = (MIX(sc).maxval - MIX(sc).minval); |
3427 |
for (i = 0; i < MAX_SELECTOR_INPUT_PIN; i++) { |
3428 |
MIX(sc).slctrtype[i] = SOUND_MIXER_NRDEVICES; |
3429 |
} |
3430 |
|
3431 |
for (i = 0; i < MIX(sc).maxval; i++) { |
3432 |
MIX(sc).slctrtype[i] = uaudio_mixer_feature_name( |
3433 |
&iot[d->baSourceId[i]], &MIX(sc)); |
3434 |
} |
3435 |
|
3436 |
MIX(sc).class = 0; /* not used */ |
3437 |
|
3438 |
uaudio_mixer_add_ctl(sc, &MIX(sc)); |
3439 |
} |
3440 |
|
3441 |
static void |
3442 |
uaudio20_mixer_add_selector(struct uaudio_softc *sc, |
3443 |
const struct uaudio_terminal_node *iot, int id) |
3444 |
{ |
3445 |
const struct usb_audio20_selector_unit *d = iot[id].u.su_v2; |
3446 |
uint16_t i; |
3447 |
|
3448 |
DPRINTFN(3, "bUnitId=%d bNrInPins=%d\n", |
3449 |
d->bUnitId, d->bNrInPins); |
3450 |
|
3451 |
if (d->bNrInPins == 0) |
3452 |
return; |
3453 |
|
3454 |
memset(&MIX(sc), 0, sizeof(MIX(sc))); |
3455 |
|
3456 |
MIX(sc).wIndex = MAKE_WORD(d->bUnitId, sc->sc_mixer_iface_no); |
3457 |
MIX(sc).wValue[0] = MAKE_WORD(0, 0); |
3458 |
uaudio20_mixer_determine_class(&iot[id], &MIX(sc)); |
3459 |
MIX(sc).nchan = 1; |
3460 |
MIX(sc).type = MIX_SELECTOR; |
3461 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; |
3462 |
MIX(sc).minval = 1; |
3463 |
MIX(sc).maxval = d->bNrInPins; |
3464 |
MIX(sc).name = "selector"; |
3465 |
|
3466 |
i = d->baSourceId[d->bNrInPins]; |
3467 |
if (i == 0 || |
3468 |
usbd_req_get_string_any(sc->sc_udev, NULL, |
3469 |
MIX(sc).desc, sizeof(MIX(sc).desc), i) != 0) { |
3470 |
MIX(sc).desc[0] = 0; |
3471 |
} |
3472 |
|
3473 |
if (MIX(sc).maxval > MAX_SELECTOR_INPUT_PIN) |
3474 |
MIX(sc).maxval = MAX_SELECTOR_INPUT_PIN; |
3475 |
|
3476 |
MIX(sc).mul = (MIX(sc).maxval - MIX(sc).minval); |
3477 |
for (i = 0; i < MAX_SELECTOR_INPUT_PIN; i++) |
3478 |
MIX(sc).slctrtype[i] = SOUND_MIXER_NRDEVICES; |
3479 |
|
3480 |
for (i = 0; i < MIX(sc).maxval; i++) { |
3481 |
MIX(sc).slctrtype[i] = uaudio20_mixer_feature_name( |
3482 |
&iot[d->baSourceId[i]], &MIX(sc)); |
3483 |
} |
3484 |
|
3485 |
MIX(sc).class = 0; /* not used */ |
3486 |
|
3487 |
uaudio_mixer_add_ctl(sc, &MIX(sc)); |
3488 |
} |
3489 |
|
3490 |
static uint32_t |
3491 |
uaudio_mixer_feature_get_bmaControls(const struct usb_audio_feature_unit *d, |
3492 |
uint8_t i) |
3493 |
{ |
3494 |
uint32_t temp = 0; |
3495 |
uint32_t offset = (i * d->bControlSize); |
3496 |
|
3497 |
if (d->bControlSize > 0) { |
3498 |
temp |= d->bmaControls[offset]; |
3499 |
if (d->bControlSize > 1) { |
3500 |
temp |= d->bmaControls[offset + 1] << 8; |
3501 |
if (d->bControlSize > 2) { |
3502 |
temp |= d->bmaControls[offset + 2] << 16; |
3503 |
if (d->bControlSize > 3) { |
3504 |
temp |= d->bmaControls[offset + 3] << 24; |
3505 |
} |
3506 |
} |
3507 |
} |
3508 |
} |
3509 |
return (temp); |
3510 |
} |
3511 |
|
3512 |
static void |
3513 |
uaudio_mixer_add_feature(struct uaudio_softc *sc, |
3514 |
const struct uaudio_terminal_node *iot, int id) |
3515 |
{ |
3516 |
const struct usb_audio_feature_unit *d = iot[id].u.fu_v1; |
3517 |
uint32_t fumask; |
3518 |
uint32_t mmask; |
3519 |
uint32_t cmask; |
3520 |
uint16_t mixernumber; |
3521 |
uint8_t nchan; |
3522 |
uint8_t chan; |
3523 |
uint8_t ctl; |
3524 |
uint8_t i; |
3525 |
|
3526 |
if (d->bControlSize == 0) |
3527 |
return; |
3528 |
|
3529 |
memset(&MIX(sc), 0, sizeof(MIX(sc))); |
3530 |
|
3531 |
nchan = (d->bLength - 7) / d->bControlSize; |
3532 |
mmask = uaudio_mixer_feature_get_bmaControls(d, 0); |
3533 |
cmask = 0; |
3534 |
|
3535 |
if (nchan == 0) |
3536 |
return; |
3537 |
|
3538 |
/* figure out what we can control */ |
3539 |
|
3540 |
for (chan = 1; chan < nchan; chan++) { |
3541 |
DPRINTFN(10, "chan=%d mask=%x\n", |
3542 |
chan, uaudio_mixer_feature_get_bmaControls(d, chan)); |
3543 |
|
3544 |
cmask |= uaudio_mixer_feature_get_bmaControls(d, chan); |
3545 |
} |
3546 |
|
3547 |
if (nchan > MIX_MAX_CHAN) { |
3548 |
nchan = MIX_MAX_CHAN; |
3549 |
} |
3550 |
MIX(sc).wIndex = MAKE_WORD(d->bUnitId, sc->sc_mixer_iface_no); |
3551 |
|
3552 |
i = d->bmaControls[d->bControlSize]; |
3553 |
if (i == 0 || |
3554 |
usbd_req_get_string_any(sc->sc_udev, NULL, |
3555 |
MIX(sc).desc, sizeof(MIX(sc).desc), i) != 0) { |
3556 |
MIX(sc).desc[0] = 0; |
3557 |
} |
3558 |
|
3559 |
for (ctl = 1; ctl <= LOUDNESS_CONTROL; ctl++) { |
3560 |
|
3561 |
fumask = FU_MASK(ctl); |
3562 |
|
3563 |
DPRINTFN(5, "ctl=%d fumask=0x%04x\n", |
3564 |
ctl, fumask); |
3565 |
|
3566 |
if (mmask & fumask) { |
3567 |
MIX(sc).nchan = 1; |
3568 |
MIX(sc).wValue[0] = MAKE_WORD(ctl, 0); |
3569 |
} else if (cmask & fumask) { |
3570 |
MIX(sc).nchan = nchan - 1; |
3571 |
for (i = 1; i < nchan; i++) { |
3572 |
if (uaudio_mixer_feature_get_bmaControls(d, i) & fumask) |
3573 |
MIX(sc).wValue[i - 1] = MAKE_WORD(ctl, i); |
3574 |
else |
3575 |
MIX(sc).wValue[i - 1] = -1; |
3576 |
} |
3577 |
} else { |
3578 |
continue; |
3579 |
} |
3580 |
|
3581 |
mixernumber = uaudio_mixer_feature_name(&iot[id], &MIX(sc)); |
3582 |
|
3583 |
switch (ctl) { |
3584 |
case MUTE_CONTROL: |
3585 |
MIX(sc).type = MIX_ON_OFF; |
3586 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; |
3587 |
MIX(sc).name = "mute"; |
3588 |
break; |
3589 |
|
3590 |
case VOLUME_CONTROL: |
3591 |
MIX(sc).type = MIX_SIGNED_16; |
3592 |
MIX(sc).ctl = mixernumber; |
3593 |
MIX(sc).name = "vol"; |
3594 |
break; |
3595 |
|
3596 |
case BASS_CONTROL: |
3597 |
MIX(sc).type = MIX_SIGNED_8; |
3598 |
MIX(sc).ctl = SOUND_MIXER_BASS; |
3599 |
MIX(sc).name = "bass"; |
3600 |
break; |
3601 |
|
3602 |
case MID_CONTROL: |
3603 |
MIX(sc).type = MIX_SIGNED_8; |
3604 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */ |
3605 |
MIX(sc).name = "mid"; |
3606 |
break; |
3607 |
|
3608 |
case TREBLE_CONTROL: |
3609 |
MIX(sc).type = MIX_SIGNED_8; |
3610 |
MIX(sc).ctl = SOUND_MIXER_TREBLE; |
3611 |
MIX(sc).name = "treble"; |
3612 |
break; |
3613 |
|
3614 |
case GRAPHIC_EQUALIZER_CONTROL: |
3615 |
continue; /* XXX don't add anything */ |
3616 |
|
3617 |
case AGC_CONTROL: |
3618 |
MIX(sc).type = MIX_ON_OFF; |
3619 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */ |
3620 |
MIX(sc).name = "agc"; |
3621 |
break; |
3622 |
|
3623 |
case DELAY_CONTROL: |
3624 |
MIX(sc).type = MIX_UNSIGNED_16; |
3625 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */ |
3626 |
MIX(sc).name = "delay"; |
3627 |
break; |
3628 |
|
3629 |
case BASS_BOOST_CONTROL: |
3630 |
MIX(sc).type = MIX_ON_OFF; |
3631 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */ |
3632 |
MIX(sc).name = "boost"; |
3633 |
break; |
3634 |
|
3635 |
case LOUDNESS_CONTROL: |
3636 |
MIX(sc).type = MIX_ON_OFF; |
3637 |
MIX(sc).ctl = SOUND_MIXER_LOUD; /* Is this correct ? */ |
3638 |
MIX(sc).name = "loudness"; |
3639 |
break; |
3640 |
|
3641 |
default: |
3642 |
MIX(sc).type = MIX_UNKNOWN; |
3643 |
break; |
3644 |
} |
3645 |
|
3646 |
if (MIX(sc).type != MIX_UNKNOWN) |
3647 |
uaudio_mixer_add_ctl(sc, &MIX(sc)); |
3648 |
} |
3649 |
} |
3650 |
|
3651 |
static void |
3652 |
uaudio20_mixer_add_feature(struct uaudio_softc *sc, |
3653 |
const struct uaudio_terminal_node *iot, int id) |
3654 |
{ |
3655 |
const struct usb_audio20_feature_unit *d = iot[id].u.fu_v2; |
3656 |
uint32_t ctl; |
3657 |
uint32_t mmask; |
3658 |
uint32_t cmask; |
3659 |
uint16_t mixernumber; |
3660 |
uint8_t nchan; |
3661 |
uint8_t chan; |
3662 |
uint8_t i; |
3663 |
uint8_t what; |
3664 |
|
3665 |
if (UGETDW(d->bmaControls[0]) == 0) |
3666 |
return; |
3667 |
|
3668 |
memset(&MIX(sc), 0, sizeof(MIX(sc))); |
3669 |
|
3670 |
nchan = (d->bLength - 6) / 4; |
3671 |
mmask = UGETDW(d->bmaControls[0]); |
3672 |
cmask = 0; |
3673 |
|
3674 |
if (nchan == 0) |
3675 |
return; |
3676 |
|
3677 |
/* figure out what we can control */ |
3678 |
|
3679 |
for (chan = 1; chan < nchan; chan++) |
3680 |
cmask |= UGETDW(d->bmaControls[chan]); |
3681 |
|
3682 |
if (nchan > MIX_MAX_CHAN) |
3683 |
nchan = MIX_MAX_CHAN; |
3684 |
|
3685 |
MIX(sc).wIndex = MAKE_WORD(d->bUnitId, sc->sc_mixer_iface_no); |
3686 |
|
3687 |
i = d->bmaControls[nchan][0]; |
3688 |
if (i == 0 || |
3689 |
usbd_req_get_string_any(sc->sc_udev, NULL, |
3690 |
MIX(sc).desc, sizeof(MIX(sc).desc), i) != 0) { |
3691 |
MIX(sc).desc[0] = 0; |
3692 |
} |
3693 |
|
3694 |
for (ctl = 3; ctl != 0; ctl <<= 2) { |
3695 |
|
3696 |
mixernumber = uaudio20_mixer_feature_name(&iot[id], &MIX(sc)); |
3697 |
|
3698 |
switch (ctl) { |
3699 |
case (3 << 0): |
3700 |
MIX(sc).type = MIX_ON_OFF; |
3701 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; |
3702 |
MIX(sc).name = "mute"; |
3703 |
what = MUTE_CONTROL; |
3704 |
break; |
3705 |
case (3 << 2): |
3706 |
MIX(sc).type = MIX_SIGNED_16; |
3707 |
MIX(sc).ctl = mixernumber; |
3708 |
MIX(sc).name = "vol"; |
3709 |
what = VOLUME_CONTROL; |
3710 |
break; |
3711 |
case (3 << 4): |
3712 |
MIX(sc).type = MIX_SIGNED_8; |
3713 |
MIX(sc).ctl = SOUND_MIXER_BASS; |
3714 |
MIX(sc).name = "bass"; |
3715 |
what = BASS_CONTROL; |
3716 |
break; |
3717 |
case (3 << 6): |
3718 |
MIX(sc).type = MIX_SIGNED_8; |
3719 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */ |
3720 |
MIX(sc).name = "mid"; |
3721 |
what = MID_CONTROL; |
3722 |
break; |
3723 |
case (3 << 8): |
3724 |
MIX(sc).type = MIX_SIGNED_8; |
3725 |
MIX(sc).ctl = SOUND_MIXER_TREBLE; |
3726 |
MIX(sc).name = "treble"; |
3727 |
what = TREBLE_CONTROL; |
3728 |
break; |
3729 |
case (3 << 12): |
3730 |
MIX(sc).type = MIX_ON_OFF; |
3731 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */ |
3732 |
MIX(sc).name = "agc"; |
3733 |
what = AGC_CONTROL; |
3734 |
break; |
3735 |
case (3 << 14): |
3736 |
MIX(sc).type = MIX_UNSIGNED_16; |
3737 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */ |
3738 |
MIX(sc).name = "delay"; |
3739 |
what = DELAY_CONTROL; |
3740 |
break; |
3741 |
case (3 << 16): |
3742 |
MIX(sc).type = MIX_ON_OFF; |
3743 |
MIX(sc).ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */ |
3744 |
MIX(sc).name = "boost"; |
3745 |
what = BASS_BOOST_CONTROL; |
3746 |
break; |
3747 |
case (3 << 18): |
3748 |
MIX(sc).type = MIX_ON_OFF; |
3749 |
MIX(sc).ctl = SOUND_MIXER_LOUD; /* Is this correct ? */ |
3750 |
MIX(sc).name = "loudness"; |
3751 |
what = LOUDNESS_CONTROL; |
3752 |
break; |
3753 |
case (3 << 20): |
3754 |
MIX(sc).type = MIX_SIGNED_16; |
3755 |
MIX(sc).ctl = mixernumber; |
3756 |
MIX(sc).name = "igain"; |
3757 |
what = INPUT_GAIN_CONTROL; |
3758 |
break; |
3759 |
case (3 << 22): |
3760 |
MIX(sc).type = MIX_SIGNED_16; |
3761 |
MIX(sc).ctl = mixernumber; |
3762 |
MIX(sc).name = "igainpad"; |
3763 |
what = INPUT_GAIN_PAD_CONTROL; |
3764 |
break; |
3765 |
default: |
3766 |
continue; |
3767 |
} |
3768 |
|
3769 |
if ((mmask & ctl) == ctl) { |
3770 |
MIX(sc).nchan = 1; |
3771 |
MIX(sc).wValue[0] = MAKE_WORD(what, 0); |
3772 |
} else if ((cmask & ctl) == ctl) { |
3773 |
MIX(sc).nchan = nchan - 1; |
3774 |
for (i = 1; i < nchan; i++) { |
3775 |
if ((UGETDW(d->bmaControls[i]) & ctl) == ctl) |
3776 |
MIX(sc).wValue[i - 1] = MAKE_WORD(what, i); |
3777 |
else |
3778 |
MIX(sc).wValue[i - 1] = -1; |
3779 |
} |
3780 |
} else { |
3781 |
continue; |
3782 |
} |
3783 |
|
3784 |
if (MIX(sc).type != MIX_UNKNOWN) |
3785 |
uaudio_mixer_add_ctl(sc, &MIX(sc)); |
3786 |
} |
3787 |
} |
3788 |
|
3789 |
static void |
3790 |
uaudio_mixer_add_processing_updown(struct uaudio_softc *sc, |
3791 |
const struct uaudio_terminal_node *iot, int id) |
3792 |
{ |
3793 |
const struct usb_audio_processing_unit_0 *d0 = iot[id].u.pu_v1; |
3794 |
const struct usb_audio_processing_unit_1 *d1 = |
3795 |
(const void *)(d0->baSourceId + d0->bNrInPins); |
3796 |
const struct usb_audio_processing_unit_updown *ud = |
3797 |
(const void *)(d1->bmControls + d1->bControlSize); |
3798 |
uint8_t i; |
3799 |
|
3800 |
if (uaudio_mixer_verify_desc(d0, sizeof(*ud)) == NULL) { |
3801 |
return; |
3802 |
} |
3803 |
if (uaudio_mixer_verify_desc(d0, sizeof(*ud) + (2 * ud->bNrModes)) |
3804 |
== NULL) { |
3805 |
return; |
3806 |
} |
3807 |
DPRINTFN(3, "bUnitId=%d bNrModes=%d\n", |
3808 |
d0->bUnitId, ud->bNrModes); |
3809 |
|
3810 |
if (!(d1->bmControls[0] & UA_PROC_MASK(UD_MODE_SELECT_CONTROL))) { |
3811 |
DPRINTF("no mode select\n"); |
3812 |
return; |
3813 |
} |
3814 |
memset(&MIX(sc), 0, sizeof(MIX(sc))); |
3815 |
|
3816 |
MIX(sc).wIndex = MAKE_WORD(d0->bUnitId, sc->sc_mixer_iface_no); |
3817 |
MIX(sc).nchan = 1; |
3818 |
MIX(sc).wValue[0] = MAKE_WORD(UD_MODE_SELECT_CONTROL, 0); |
3819 |
uaudio_mixer_determine_class(&iot[id], &MIX(sc)); |
3820 |
MIX(sc).type = MIX_ON_OFF; /* XXX */ |
3821 |
|
3822 |
for (i = 0; i < ud->bNrModes; i++) { |
3823 |
DPRINTFN(3, "i=%d bm=0x%x\n", i, UGETW(ud->waModes[i])); |
3824 |
/* XXX */ |
3825 |
} |
3826 |
|
3827 |
uaudio_mixer_add_ctl(sc, &MIX(sc)); |
3828 |
} |
3829 |
|
3830 |
static void |
3831 |
uaudio_mixer_add_processing(struct uaudio_softc *sc, |
3832 |
const struct uaudio_terminal_node *iot, int id) |
3833 |
{ |
3834 |
const struct usb_audio_processing_unit_0 *d0 = iot[id].u.pu_v1; |
3835 |
const struct usb_audio_processing_unit_1 *d1 = |
3836 |
(const void *)(d0->baSourceId + d0->bNrInPins); |
3837 |
uint16_t ptype; |
3838 |
|
3839 |
memset(&MIX(sc), 0, sizeof(MIX(sc))); |
3840 |
|
3841 |
ptype = UGETW(d0->wProcessType); |
3842 |
|
3843 |
DPRINTFN(3, "wProcessType=%d bUnitId=%d " |
3844 |
"bNrInPins=%d\n", ptype, d0->bUnitId, d0->bNrInPins); |
3845 |
|
3846 |
if (d1->bControlSize == 0) { |
3847 |
return; |
3848 |
} |
3849 |
if (d1->bmControls[0] & UA_PROC_ENABLE_MASK) { |
3850 |
MIX(sc).wIndex = MAKE_WORD(d0->bUnitId, sc->sc_mixer_iface_no); |
3851 |
MIX(sc).nchan = 1; |
3852 |
MIX(sc).wValue[0] = MAKE_WORD(XX_ENABLE_CONTROL, 0); |
3853 |
uaudio_mixer_determine_class(&iot[id], &MIX(sc)); |
3854 |
MIX(sc).type = MIX_ON_OFF; |
3855 |
uaudio_mixer_add_ctl(sc, &MIX(sc)); |
3856 |
} |
3857 |
switch (ptype) { |
3858 |
case UPDOWNMIX_PROCESS: |
3859 |
uaudio_mixer_add_processing_updown(sc, iot, id); |
3860 |
break; |
3861 |
|
3862 |
case DOLBY_PROLOGIC_PROCESS: |
3863 |
case P3D_STEREO_EXTENDER_PROCESS: |
3864 |
case REVERBATION_PROCESS: |
3865 |
case CHORUS_PROCESS: |
3866 |
case DYN_RANGE_COMP_PROCESS: |
3867 |
default: |
3868 |
DPRINTF("unit %d, type=%d is not implemented\n", |
3869 |
d0->bUnitId, ptype); |
3870 |
break; |
3871 |
} |
3872 |
} |
3873 |
|
3874 |
static void |
3875 |
uaudio_mixer_add_extension(struct uaudio_softc *sc, |
3876 |
const struct uaudio_terminal_node *iot, int id) |
3877 |
{ |
3878 |
const struct usb_audio_extension_unit_0 *d0 = iot[id].u.eu_v1; |
3879 |
const struct usb_audio_extension_unit_1 *d1 = |
3880 |
(const void *)(d0->baSourceId + d0->bNrInPins); |
3881 |
|
3882 |
DPRINTFN(3, "bUnitId=%d bNrInPins=%d\n", |
3883 |
d0->bUnitId, d0->bNrInPins); |
3884 |
|
3885 |
if (sc->sc_uq_au_no_xu) { |
3886 |
return; |
3887 |
} |
3888 |
if (d1->bControlSize == 0) { |
3889 |
return; |
3890 |
} |
3891 |
if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) { |
3892 |
|
3893 |
memset(&MIX(sc), 0, sizeof(MIX(sc))); |
3894 |
|
3895 |
MIX(sc).wIndex = MAKE_WORD(d0->bUnitId, sc->sc_mixer_iface_no); |
3896 |
MIX(sc).nchan = 1; |
3897 |
MIX(sc).wValue[0] = MAKE_WORD(UA_EXT_ENABLE, 0); |
3898 |
uaudio_mixer_determine_class(&iot[id], &MIX(sc)); |
3899 |
MIX(sc).type = MIX_ON_OFF; |
3900 |
|
3901 |
uaudio_mixer_add_ctl(sc, &MIX(sc)); |
3902 |
} |
3903 |
} |
3904 |
|
3905 |
static const void * |
3906 |
uaudio_mixer_verify_desc(const void *arg, uint32_t len) |
3907 |
{ |
3908 |
const struct usb_audio_mixer_unit_1 *d1; |
3909 |
const struct usb_audio_extension_unit_1 *e1; |
3910 |
const struct usb_audio_processing_unit_1 *u1; |
3911 |
|
3912 |
union { |
3913 |
const struct usb_descriptor *desc; |
3914 |
const struct usb_audio_input_terminal *it; |
3915 |
const struct usb_audio_output_terminal *ot; |
3916 |
const struct usb_audio_mixer_unit_0 *mu; |
3917 |
const struct usb_audio_selector_unit *su; |
3918 |
const struct usb_audio_feature_unit *fu; |
3919 |
const struct usb_audio_processing_unit_0 *pu; |
3920 |
const struct usb_audio_extension_unit_0 *eu; |
3921 |
} u; |
3922 |
|
3923 |
u.desc = arg; |
3924 |
|
3925 |
if (u.desc == NULL) { |
3926 |
goto error; |
3927 |
} |
3928 |
if (u.desc->bDescriptorType != UDESC_CS_INTERFACE) { |
3929 |
goto error; |
3930 |
} |
3931 |
switch (u.desc->bDescriptorSubtype) { |
3932 |
case UDESCSUB_AC_INPUT: |
3933 |
len += sizeof(*u.it); |
3934 |
break; |
3935 |
|
3936 |
case UDESCSUB_AC_OUTPUT: |
3937 |
len += sizeof(*u.ot); |
3938 |
break; |
3939 |
|
3940 |
case UDESCSUB_AC_MIXER: |
3941 |
len += sizeof(*u.mu); |
3942 |
|
3943 |
if (u.desc->bLength < len) { |
3944 |
goto error; |
3945 |
} |
3946 |
len += u.mu->bNrInPins; |
3947 |
|
3948 |
if (u.desc->bLength < len) { |
3949 |
goto error; |
3950 |
} |
3951 |
d1 = (const void *)(u.mu->baSourceId + u.mu->bNrInPins); |
3952 |
|
3953 |
len += sizeof(*d1); |
3954 |
break; |
3955 |
|
3956 |
case UDESCSUB_AC_SELECTOR: |
3957 |
len += sizeof(*u.su); |
3958 |
|
3959 |
if (u.desc->bLength < len) { |
3960 |
goto error; |
3961 |
} |
3962 |
len += u.su->bNrInPins + 1; |
3963 |
break; |
3964 |
|
3965 |
case UDESCSUB_AC_FEATURE: |
3966 |
len += sizeof(*u.fu) + 1; |
3967 |
|
3968 |
if (u.desc->bLength < len) |
3969 |
goto error; |
3970 |
|
3971 |
len += u.fu->bControlSize; |
3972 |
break; |
3973 |
|
3974 |
case UDESCSUB_AC_PROCESSING: |
3975 |
len += sizeof(*u.pu); |
3976 |
|
3977 |
if (u.desc->bLength < len) { |
3978 |
goto error; |
3979 |
} |
3980 |
len += u.pu->bNrInPins; |
3981 |
|
3982 |
if (u.desc->bLength < len) { |
3983 |
goto error; |
3984 |
} |
3985 |
u1 = (const void *)(u.pu->baSourceId + u.pu->bNrInPins); |
3986 |
|
3987 |
len += sizeof(*u1); |
3988 |
|
3989 |
if (u.desc->bLength < len) { |
3990 |
goto error; |
3991 |
} |
3992 |
len += u1->bControlSize; |
3993 |
|
3994 |
break; |
3995 |
|
3996 |
case UDESCSUB_AC_EXTENSION: |
3997 |
len += sizeof(*u.eu); |
3998 |
|
3999 |
if (u.desc->bLength < len) { |
4000 |
goto error; |
4001 |
} |
4002 |
len += u.eu->bNrInPins; |
4003 |
|
4004 |
if (u.desc->bLength < len) { |
4005 |
goto error; |
4006 |
} |
4007 |
e1 = (const void *)(u.eu->baSourceId + u.eu->bNrInPins); |
4008 |
|
4009 |
len += sizeof(*e1); |
4010 |
|
4011 |
if (u.desc->bLength < len) { |
4012 |
goto error; |
4013 |
} |
4014 |
len += e1->bControlSize; |
4015 |
break; |
4016 |
|
4017 |
default: |
4018 |
goto error; |
4019 |
} |
4020 |
|
4021 |
if (u.desc->bLength < len) { |
4022 |
goto error; |
4023 |
} |
4024 |
return (u.desc); |
4025 |
|
4026 |
error: |
4027 |
if (u.desc) { |
4028 |
DPRINTF("invalid descriptor, type=%d, " |
4029 |
"sub_type=%d, len=%d of %d bytes\n", |
4030 |
u.desc->bDescriptorType, |
4031 |
u.desc->bDescriptorSubtype, |
4032 |
u.desc->bLength, len); |
4033 |
} |
4034 |
return (NULL); |
4035 |
} |
4036 |
|
4037 |
static const void * |
4038 |
uaudio20_mixer_verify_desc(const void *arg, uint32_t len) |
4039 |
{ |
4040 |
const struct usb_audio20_mixer_unit_1 *d1; |
4041 |
const struct usb_audio20_extension_unit_1 *e1; |
4042 |
const struct usb_audio20_processing_unit_1 *u1; |
4043 |
const struct usb_audio20_clock_selector_unit_1 *c1; |
4044 |
|
4045 |
union { |
4046 |
const struct usb_descriptor *desc; |
4047 |
const struct usb_audio20_clock_source_unit *csrc; |
4048 |
const struct usb_audio20_clock_selector_unit_0 *csel; |
4049 |
const struct usb_audio20_clock_multiplier_unit *cmul; |
4050 |
const struct usb_audio20_input_terminal *it; |
4051 |
const struct usb_audio20_output_terminal *ot; |
4052 |
const struct usb_audio20_mixer_unit_0 *mu; |
4053 |
const struct usb_audio20_selector_unit *su; |
4054 |
const struct usb_audio20_feature_unit *fu; |
4055 |
const struct usb_audio20_sample_rate_unit *ru; |
4056 |
const struct usb_audio20_processing_unit_0 *pu; |
4057 |
const struct usb_audio20_extension_unit_0 *eu; |
4058 |
const struct usb_audio20_effect_unit *ef; |
4059 |
} u; |
4060 |
|
4061 |
u.desc = arg; |
4062 |
|
4063 |
if (u.desc == NULL) |
4064 |
goto error; |
4065 |
|
4066 |
if (u.desc->bDescriptorType != UDESC_CS_INTERFACE) |
4067 |
goto error; |
4068 |
|
4069 |
switch (u.desc->bDescriptorSubtype) { |
4070 |
case UDESCSUB_AC_INPUT: |
4071 |
len += sizeof(*u.it); |
4072 |
break; |
4073 |
|
4074 |
case UDESCSUB_AC_OUTPUT: |
4075 |
len += sizeof(*u.ot); |
4076 |
break; |
4077 |
|
4078 |
case UDESCSUB_AC_MIXER: |
4079 |
len += sizeof(*u.mu); |
4080 |
|
4081 |
if (u.desc->bLength < len) |
4082 |
goto error; |
4083 |
len += u.mu->bNrInPins; |
4084 |
|
4085 |
if (u.desc->bLength < len) |
4086 |
goto error; |
4087 |
|
4088 |
d1 = (const void *)(u.mu->baSourceId + u.mu->bNrInPins); |
4089 |
|
4090 |
len += sizeof(*d1) + d1->bNrChannels; |
4091 |
break; |
4092 |
|
4093 |
case UDESCSUB_AC_SELECTOR: |
4094 |
len += sizeof(*u.su); |
4095 |
|
4096 |
if (u.desc->bLength < len) |
4097 |
goto error; |
4098 |
|
4099 |
len += u.su->bNrInPins + 1; |
4100 |
break; |
4101 |
|
4102 |
case UDESCSUB_AC_FEATURE: |
4103 |
len += sizeof(*u.fu) + 1; |
4104 |
break; |
4105 |
|
4106 |
case UDESCSUB_AC_EFFECT: |
4107 |
len += sizeof(*u.ef) + 4; |
4108 |
break; |
4109 |
|
4110 |
case UDESCSUB_AC_PROCESSING_V2: |
4111 |
len += sizeof(*u.pu); |
4112 |
|
4113 |
if (u.desc->bLength < len) |
4114 |
goto error; |
4115 |
|
4116 |
len += u.pu->bNrInPins; |
4117 |
|
4118 |
if (u.desc->bLength < len) |
4119 |
goto error; |
4120 |
|
4121 |
u1 = (const void *)(u.pu->baSourceId + u.pu->bNrInPins); |
4122 |
|
4123 |
len += sizeof(*u1); |
4124 |
break; |
4125 |
|
4126 |
case UDESCSUB_AC_EXTENSION_V2: |
4127 |
len += sizeof(*u.eu); |
4128 |
|
4129 |
if (u.desc->bLength < len) |
4130 |
goto error; |
4131 |
|
4132 |
len += u.eu->bNrInPins; |
4133 |
|
4134 |
if (u.desc->bLength < len) |
4135 |
goto error; |
4136 |
|
4137 |
e1 = (const void *)(u.eu->baSourceId + u.eu->bNrInPins); |
4138 |
|
4139 |
len += sizeof(*e1); |
4140 |
break; |
4141 |
|
4142 |
case UDESCSUB_AC_CLOCK_SRC: |
4143 |
len += sizeof(*u.csrc); |
4144 |
break; |
4145 |
|
4146 |
case UDESCSUB_AC_CLOCK_SEL: |
4147 |
len += sizeof(*u.csel); |
4148 |
|
4149 |
if (u.desc->bLength < len) |
4150 |
goto error; |
4151 |
|
4152 |
len += u.csel->bNrInPins; |
4153 |
|
4154 |
if (u.desc->bLength < len) |
4155 |
goto error; |
4156 |
|
4157 |
c1 = (const void *)(u.csel->baCSourceId + u.csel->bNrInPins); |
4158 |
|
4159 |
len += sizeof(*c1); |
4160 |
break; |
4161 |
|
4162 |
case UDESCSUB_AC_CLOCK_MUL: |
4163 |
len += sizeof(*u.cmul); |
4164 |
break; |
4165 |
|
4166 |
case UDESCSUB_AC_SAMPLE_RT: |
4167 |
len += sizeof(*u.ru); |
4168 |
break; |
4169 |
|
4170 |
default: |
4171 |
goto error; |
4172 |
} |
4173 |
|
4174 |
if (u.desc->bLength < len) |
4175 |
goto error; |
4176 |
|
4177 |
return (u.desc); |
4178 |
|
4179 |
error: |
4180 |
if (u.desc) { |
4181 |
DPRINTF("invalid descriptor, type=%d, " |
4182 |
"sub_type=%d, len=%d of %d bytes\n", |
4183 |
u.desc->bDescriptorType, |
4184 |
u.desc->bDescriptorSubtype, |
4185 |
u.desc->bLength, len); |
4186 |
} |
4187 |
return (NULL); |
4188 |
} |
4189 |
|
4190 |
static struct usb_audio_cluster |
4191 |
uaudio_mixer_get_cluster(uint8_t id, const struct uaudio_terminal_node *iot) |
4192 |
{ |
4193 |
struct usb_audio_cluster r; |
4194 |
const struct usb_descriptor *dp; |
4195 |
uint8_t i; |
4196 |
|
4197 |
for (i = 0; i < UAUDIO_RECURSE_LIMIT; i++) { /* avoid infinite loops */ |
4198 |
dp = iot[id].u.desc; |
4199 |
if (dp == NULL) { |
4200 |
goto error; |
4201 |
} |
4202 |
switch (dp->bDescriptorSubtype) { |
4203 |
case UDESCSUB_AC_INPUT: |
4204 |
r.bNrChannels = iot[id].u.it_v1->bNrChannels; |
4205 |
r.wChannelConfig[0] = iot[id].u.it_v1->wChannelConfig[0]; |
4206 |
r.wChannelConfig[1] = iot[id].u.it_v1->wChannelConfig[1]; |
4207 |
r.iChannelNames = iot[id].u.it_v1->iChannelNames; |
4208 |
goto done; |
4209 |
|
4210 |
case UDESCSUB_AC_OUTPUT: |
4211 |
id = iot[id].u.ot_v1->bSourceId; |
4212 |
break; |
4213 |
|
4214 |
case UDESCSUB_AC_MIXER: |
4215 |
r = *(const struct usb_audio_cluster *) |
4216 |
&iot[id].u.mu_v1->baSourceId[ |
4217 |
iot[id].u.mu_v1->bNrInPins]; |
4218 |
goto done; |
4219 |
|
4220 |
case UDESCSUB_AC_SELECTOR: |
4221 |
if (iot[id].u.su_v1->bNrInPins > 0) { |
4222 |
/* XXX This is not really right */ |
4223 |
id = iot[id].u.su_v1->baSourceId[0]; |
4224 |
} |
4225 |
break; |
4226 |
|
4227 |
case UDESCSUB_AC_FEATURE: |
4228 |
id = iot[id].u.fu_v1->bSourceId; |
4229 |
break; |
4230 |
|
4231 |
case UDESCSUB_AC_PROCESSING: |
4232 |
r = *((const struct usb_audio_cluster *) |
4233 |
&iot[id].u.pu_v1->baSourceId[ |
4234 |
iot[id].u.pu_v1->bNrInPins]); |
4235 |
goto done; |
4236 |
|
4237 |
case UDESCSUB_AC_EXTENSION: |
4238 |
r = *((const struct usb_audio_cluster *) |
4239 |
&iot[id].u.eu_v1->baSourceId[ |
4240 |
iot[id].u.eu_v1->bNrInPins]); |
4241 |
goto done; |
4242 |
|
4243 |
default: |
4244 |
goto error; |
4245 |
} |
4246 |
} |
4247 |
error: |
4248 |
DPRINTF("bad data\n"); |
4249 |
memset(&r, 0, sizeof(r)); |
4250 |
done: |
4251 |
return (r); |
4252 |
} |
4253 |
|
4254 |
static struct usb_audio20_cluster |
4255 |
uaudio20_mixer_get_cluster(uint8_t id, const struct uaudio_terminal_node *iot) |
4256 |
{ |
4257 |
struct usb_audio20_cluster r; |
4258 |
const struct usb_descriptor *dp; |
4259 |
uint8_t i; |
4260 |
|
4261 |
for (i = 0; i < UAUDIO_RECURSE_LIMIT; i++) { /* avoid infinite loops */ |
4262 |
dp = iot[id].u.desc; |
4263 |
if (dp == NULL) |
4264 |
goto error; |
4265 |
|
4266 |
switch (dp->bDescriptorSubtype) { |
4267 |
case UDESCSUB_AC_INPUT: |
4268 |
r.bNrChannels = iot[id].u.it_v2->bNrChannels; |
4269 |
r.bmChannelConfig[0] = iot[id].u.it_v2->bmChannelConfig[0]; |
4270 |
r.bmChannelConfig[1] = iot[id].u.it_v2->bmChannelConfig[1]; |
4271 |
r.bmChannelConfig[2] = iot[id].u.it_v2->bmChannelConfig[2]; |
4272 |
r.bmChannelConfig[3] = iot[id].u.it_v2->bmChannelConfig[3]; |
4273 |
r.iChannelNames = iot[id].u.it_v2->iTerminal; |
4274 |
goto done; |
4275 |
|
4276 |
case UDESCSUB_AC_OUTPUT: |
4277 |
id = iot[id].u.ot_v2->bSourceId; |
4278 |
break; |
4279 |
|
4280 |
case UDESCSUB_AC_MIXER: |
4281 |
r = *(const struct usb_audio20_cluster *) |
4282 |
&iot[id].u.mu_v2->baSourceId[ |
4283 |
iot[id].u.mu_v2->bNrInPins]; |
4284 |
goto done; |
4285 |
|
4286 |
case UDESCSUB_AC_SELECTOR: |
4287 |
if (iot[id].u.su_v2->bNrInPins > 0) { |
4288 |
/* XXX This is not really right */ |
4289 |
id = iot[id].u.su_v2->baSourceId[0]; |
4290 |
} |
4291 |
break; |
4292 |
|
4293 |
case UDESCSUB_AC_SAMPLE_RT: |
4294 |
id = iot[id].u.ru_v2->bSourceId; |
4295 |
break; |
4296 |
|
4297 |
case UDESCSUB_AC_EFFECT: |
4298 |
id = iot[id].u.ef_v2->bSourceId; |
4299 |
break; |
4300 |
|
4301 |
case UDESCSUB_AC_FEATURE: |
4302 |
id = iot[id].u.fu_v2->bSourceId; |
4303 |
break; |
4304 |
|
4305 |
case UDESCSUB_AC_PROCESSING_V2: |
4306 |
r = *((const struct usb_audio20_cluster *) |
4307 |
&iot[id].u.pu_v2->baSourceId[ |
4308 |
iot[id].u.pu_v2->bNrInPins]); |
4309 |
goto done; |
4310 |
|
4311 |
case UDESCSUB_AC_EXTENSION_V2: |
4312 |
r = *((const struct usb_audio20_cluster *) |
4313 |
&iot[id].u.eu_v2->baSourceId[ |
4314 |
iot[id].u.eu_v2->bNrInPins]); |
4315 |
goto done; |
4316 |
|
4317 |
default: |
4318 |
goto error; |
4319 |
} |
4320 |
} |
4321 |
error: |
4322 |
DPRINTF("Bad data!\n"); |
4323 |
memset(&r, 0, sizeof(r)); |
4324 |
done: |
4325 |
return (r); |
4326 |
} |
4327 |
|
4328 |
static uint16_t |
4329 |
uaudio_mixer_determine_class(const struct uaudio_terminal_node *iot, |
4330 |
struct uaudio_mixer_node *mix) |
4331 |
{ |
4332 |
uint16_t terminal_type = 0x0000; |
4333 |
const struct uaudio_terminal_node *input[2]; |
4334 |
const struct uaudio_terminal_node *output[2]; |
4335 |
|
4336 |
input[0] = uaudio_mixer_get_input(iot, 0); |
4337 |
input[1] = uaudio_mixer_get_input(iot, 1); |
4338 |
|
4339 |
output[0] = uaudio_mixer_get_output(iot, 0); |
4340 |
output[1] = uaudio_mixer_get_output(iot, 1); |
4341 |
|
4342 |
/* |
4343 |
* check if there is only |
4344 |
* one output terminal: |
4345 |
*/ |
4346 |
if (output[0] && (!output[1])) { |
4347 |
terminal_type = |
4348 |
UGETW(output[0]->u.ot_v1->wTerminalType); |
4349 |
} |
4350 |
/* |
4351 |
* If the only output terminal is USB, |
4352 |
* the class is UAC_RECORD. |
4353 |
*/ |
4354 |
if ((terminal_type & 0xff00) == (UAT_UNDEFINED & 0xff00)) { |
4355 |
|
4356 |
mix->class = UAC_RECORD; |
4357 |
if (input[0] && (!input[1])) { |
4358 |
terminal_type = |
4359 |
UGETW(input[0]->u.it_v1->wTerminalType); |
4360 |
} else { |
4361 |
terminal_type = 0; |
4362 |
} |
4363 |
goto done; |
4364 |
} |
4365 |
/* |
4366 |
* if the unit is connected to just |
4367 |
* one input terminal, the |
4368 |
* class is UAC_INPUT: |
4369 |
*/ |
4370 |
if (input[0] && (!input[1])) { |
4371 |
mix->class = UAC_INPUT; |
4372 |
terminal_type = |
4373 |
UGETW(input[0]->u.it_v1->wTerminalType); |
4374 |
goto done; |
4375 |
} |
4376 |
/* |
4377 |
* Otherwise, the class is UAC_OUTPUT. |
4378 |
*/ |
4379 |
mix->class = UAC_OUTPUT; |
4380 |
done: |
4381 |
return (terminal_type); |
4382 |
} |
4383 |
|
4384 |
static uint16_t |
4385 |
uaudio20_mixer_determine_class(const struct uaudio_terminal_node *iot, |
4386 |
struct uaudio_mixer_node *mix) |
4387 |
{ |
4388 |
uint16_t terminal_type = 0x0000; |
4389 |
const struct uaudio_terminal_node *input[2]; |
4390 |
const struct uaudio_terminal_node *output[2]; |
4391 |
|
4392 |
input[0] = uaudio_mixer_get_input(iot, 0); |
4393 |
input[1] = uaudio_mixer_get_input(iot, 1); |
4394 |
|
4395 |
output[0] = uaudio_mixer_get_output(iot, 0); |
4396 |
output[1] = uaudio_mixer_get_output(iot, 1); |
4397 |
|
4398 |
/* |
4399 |
* check if there is only |
4400 |
* one output terminal: |
4401 |
*/ |
4402 |
if (output[0] && (!output[1])) |
4403 |
terminal_type = UGETW(output[0]->u.ot_v2->wTerminalType); |
4404 |
/* |
4405 |
* If the only output terminal is USB, |
4406 |
* the class is UAC_RECORD. |
4407 |
*/ |
4408 |
if ((terminal_type & 0xff00) == (UAT_UNDEFINED & 0xff00)) { |
4409 |
|
4410 |
mix->class = UAC_RECORD; |
4411 |
if (input[0] && (!input[1])) { |
4412 |
terminal_type = |
4413 |
UGETW(input[0]->u.it_v2->wTerminalType); |
4414 |
} else { |
4415 |
terminal_type = 0; |
4416 |
} |
4417 |
goto done; |
4418 |
} |
4419 |
/* |
4420 |
* if the unit is connected to just |
4421 |
* one input terminal, the |
4422 |
* class is UAC_INPUT: |
4423 |
*/ |
4424 |
if (input[0] && (!input[1])) { |
4425 |
mix->class = UAC_INPUT; |
4426 |
terminal_type = |
4427 |
UGETW(input[0]->u.it_v2->wTerminalType); |
4428 |
goto done; |
4429 |
} |
4430 |
/* |
4431 |
* Otherwise, the class is UAC_OUTPUT. |
4432 |
*/ |
4433 |
mix->class = UAC_OUTPUT; |
4434 |
done: |
4435 |
return (terminal_type); |
4436 |
} |
4437 |
|
4438 |
struct uaudio_tt_to_feature { |
4439 |
uint16_t terminal_type; |
4440 |
uint16_t feature; |
4441 |
}; |
4442 |
|
4443 |
static const struct uaudio_tt_to_feature uaudio_tt_to_feature[] = { |
4444 |
|
4445 |
{UAT_STREAM, SOUND_MIXER_PCM}, |
4446 |
|
4447 |
{UATI_MICROPHONE, SOUND_MIXER_MIC}, |
4448 |
{UATI_DESKMICROPHONE, SOUND_MIXER_MIC}, |
4449 |
{UATI_PERSONALMICROPHONE, SOUND_MIXER_MIC}, |
4450 |
{UATI_OMNIMICROPHONE, SOUND_MIXER_MIC}, |
4451 |
{UATI_MICROPHONEARRAY, SOUND_MIXER_MIC}, |
4452 |
{UATI_PROCMICROPHONEARR, SOUND_MIXER_MIC}, |
4453 |
|
4454 |
{UATO_SPEAKER, SOUND_MIXER_SPEAKER}, |
4455 |
{UATO_DESKTOPSPEAKER, SOUND_MIXER_SPEAKER}, |
4456 |
{UATO_ROOMSPEAKER, SOUND_MIXER_SPEAKER}, |
4457 |
{UATO_COMMSPEAKER, SOUND_MIXER_SPEAKER}, |
4458 |
|
4459 |
{UATE_ANALOGCONN, SOUND_MIXER_LINE}, |
4460 |
{UATE_LINECONN, SOUND_MIXER_LINE}, |
4461 |
{UATE_LEGACYCONN, SOUND_MIXER_LINE}, |
4462 |
|
4463 |
{UATE_DIGITALAUIFC, SOUND_MIXER_ALTPCM}, |
4464 |
{UATE_SPDIF, SOUND_MIXER_ALTPCM}, |
4465 |
{UATE_1394DA, SOUND_MIXER_ALTPCM}, |
4466 |
{UATE_1394DV, SOUND_MIXER_ALTPCM}, |
4467 |
|
4468 |
{UATF_CDPLAYER, SOUND_MIXER_CD}, |
4469 |
|
4470 |
{UATF_SYNTHESIZER, SOUND_MIXER_SYNTH}, |
4471 |
|
4472 |
{UATF_VIDEODISCAUDIO, SOUND_MIXER_VIDEO}, |
4473 |
{UATF_DVDAUDIO, SOUND_MIXER_VIDEO}, |
4474 |
{UATF_TVTUNERAUDIO, SOUND_MIXER_VIDEO}, |
4475 |
|
4476 |
/* telephony terminal types */ |
4477 |
{UATT_UNDEFINED, SOUND_MIXER_PHONEIN}, /* SOUND_MIXER_PHONEOUT */ |
4478 |
{UATT_PHONELINE, SOUND_MIXER_PHONEIN}, /* SOUND_MIXER_PHONEOUT */ |
4479 |
{UATT_TELEPHONE, SOUND_MIXER_PHONEIN}, /* SOUND_MIXER_PHONEOUT */ |
4480 |
{UATT_DOWNLINEPHONE, SOUND_MIXER_PHONEIN}, /* SOUND_MIXER_PHONEOUT */ |
4481 |
|
4482 |
{UATF_RADIORECV, SOUND_MIXER_RADIO}, |
4483 |
{UATF_RADIOXMIT, SOUND_MIXER_RADIO}, |
4484 |
|
4485 |
{UAT_UNDEFINED, SOUND_MIXER_VOLUME}, |
4486 |
{UAT_VENDOR, SOUND_MIXER_VOLUME}, |
4487 |
{UATI_UNDEFINED, SOUND_MIXER_VOLUME}, |
4488 |
|
4489 |
/* output terminal types */ |
4490 |
{UATO_UNDEFINED, SOUND_MIXER_VOLUME}, |
4491 |
{UATO_DISPLAYAUDIO, SOUND_MIXER_VOLUME}, |
4492 |
{UATO_SUBWOOFER, SOUND_MIXER_VOLUME}, |
4493 |
{UATO_HEADPHONES, SOUND_MIXER_VOLUME}, |
4494 |
|
4495 |
/* bidir terminal types */ |
4496 |
{UATB_UNDEFINED, SOUND_MIXER_VOLUME}, |
4497 |
{UATB_HANDSET, SOUND_MIXER_VOLUME}, |
4498 |
{UATB_HEADSET, SOUND_MIXER_VOLUME}, |
4499 |
{UATB_SPEAKERPHONE, SOUND_MIXER_VOLUME}, |
4500 |
{UATB_SPEAKERPHONEESUP, SOUND_MIXER_VOLUME}, |
4501 |
{UATB_SPEAKERPHONEECANC, SOUND_MIXER_VOLUME}, |
4502 |
|
4503 |
/* external terminal types */ |
4504 |
{UATE_UNDEFINED, SOUND_MIXER_VOLUME}, |
4505 |
|
4506 |
/* embedded function terminal types */ |
4507 |
{UATF_UNDEFINED, SOUND_MIXER_VOLUME}, |
4508 |
{UATF_CALIBNOISE, SOUND_MIXER_VOLUME}, |
4509 |
{UATF_EQUNOISE, SOUND_MIXER_VOLUME}, |
4510 |
{UATF_DAT, SOUND_MIXER_VOLUME}, |
4511 |
{UATF_DCC, SOUND_MIXER_VOLUME}, |
4512 |
{UATF_MINIDISK, SOUND_MIXER_VOLUME}, |
4513 |
{UATF_ANALOGTAPE, SOUND_MIXER_VOLUME}, |
4514 |
{UATF_PHONOGRAPH, SOUND_MIXER_VOLUME}, |
4515 |
{UATF_VCRAUDIO, SOUND_MIXER_VOLUME}, |
4516 |
{UATF_SATELLITE, SOUND_MIXER_VOLUME}, |
4517 |
{UATF_CABLETUNER, SOUND_MIXER_VOLUME}, |
4518 |
{UATF_DSS, SOUND_MIXER_VOLUME}, |
4519 |
{UATF_MULTITRACK, SOUND_MIXER_VOLUME}, |
4520 |
{0xffff, SOUND_MIXER_VOLUME}, |
4521 |
|
4522 |
/* default */ |
4523 |
{0x0000, SOUND_MIXER_VOLUME}, |
4524 |
}; |
4525 |
|
4526 |
static uint16_t |
4527 |
uaudio_mixer_feature_name(const struct uaudio_terminal_node *iot, |
4528 |
struct uaudio_mixer_node *mix) |
4529 |
{ |
4530 |
const struct uaudio_tt_to_feature *uat = uaudio_tt_to_feature; |
4531 |
uint16_t terminal_type = uaudio_mixer_determine_class(iot, mix); |
4532 |
|
4533 |
if ((mix->class == UAC_RECORD) && (terminal_type == 0)) { |
4534 |
return (SOUND_MIXER_IMIX); |
4535 |
} |
4536 |
while (uat->terminal_type) { |
4537 |
if (uat->terminal_type == terminal_type) { |
4538 |
break; |
4539 |
} |
4540 |
uat++; |
4541 |
} |
4542 |
|
4543 |
DPRINTF("terminal_type=0x%04x -> %d\n", |
4544 |
terminal_type, uat->feature); |
4545 |
|
4546 |
return (uat->feature); |
4547 |
} |
4548 |
|
4549 |
static uint16_t |
4550 |
uaudio20_mixer_feature_name(const struct uaudio_terminal_node *iot, |
4551 |
struct uaudio_mixer_node *mix) |
4552 |
{ |
4553 |
const struct uaudio_tt_to_feature *uat; |
4554 |
uint16_t terminal_type = uaudio20_mixer_determine_class(iot, mix); |
4555 |
|
4556 |
if ((mix->class == UAC_RECORD) && (terminal_type == 0)) |
4557 |
return (SOUND_MIXER_IMIX); |
4558 |
|
4559 |
for (uat = uaudio_tt_to_feature; uat->terminal_type != 0; uat++) { |
4560 |
if (uat->terminal_type == terminal_type) |
4561 |
break; |
4562 |
} |
4563 |
|
4564 |
DPRINTF("terminal_type=0x%04x -> %d\n", |
4565 |
terminal_type, uat->feature); |
4566 |
|
4567 |
return (uat->feature); |
4568 |
} |
4569 |
|
4570 |
static const struct uaudio_terminal_node * |
4571 |
uaudio_mixer_get_input(const struct uaudio_terminal_node *iot, uint8_t i) |
4572 |
{ |
4573 |
struct uaudio_terminal_node *root = iot->root; |
4574 |
uint8_t n; |
4575 |
|
4576 |
n = iot->usr.id_max; |
4577 |
do { |
4578 |
if (iot->usr.bit_input[n / 8] & (1 << (n % 8))) { |
4579 |
if (!i--) |
4580 |
return (root + n); |
4581 |
} |
4582 |
} while (n--); |
4583 |
|
4584 |
return (NULL); |
4585 |
} |
4586 |
|
4587 |
static const struct uaudio_terminal_node * |
4588 |
uaudio_mixer_get_output(const struct uaudio_terminal_node *iot, uint8_t i) |
4589 |
{ |
4590 |
struct uaudio_terminal_node *root = iot->root; |
4591 |
uint8_t n; |
4592 |
|
4593 |
n = iot->usr.id_max; |
4594 |
do { |
4595 |
if (iot->usr.bit_output[n / 8] & (1 << (n % 8))) { |
4596 |
if (!i--) |
4597 |
return (root + n); |
4598 |
} |
4599 |
} while (n--); |
4600 |
|
4601 |
return (NULL); |
4602 |
} |
4603 |
|
4604 |
static void |
4605 |
uaudio_mixer_find_inputs_sub(struct uaudio_terminal_node *root, |
4606 |
const uint8_t *p_id, uint8_t n_id, |
4607 |
struct uaudio_search_result *info) |
4608 |
{ |
4609 |
struct uaudio_terminal_node *iot; |
4610 |
uint8_t n; |
4611 |
uint8_t i; |
4612 |
uint8_t is_last; |
4613 |
|
4614 |
top: |
4615 |
for (n = 0; n < n_id; n++) { |
4616 |
|
4617 |
i = p_id[n]; |
4618 |
|
4619 |
if (info->recurse_level == UAUDIO_RECURSE_LIMIT) { |
4620 |
DPRINTF("avoided going into a circle at id=%d!\n", i); |
4621 |
return; |
4622 |
} |
4623 |
|
4624 |
info->recurse_level++; |
4625 |
|
4626 |
iot = (root + i); |
4627 |
|
4628 |
if (iot->u.desc == NULL) |
4629 |
continue; |
4630 |
|
4631 |
is_last = ((n + 1) == n_id); |
4632 |
|
4633 |
switch (iot->u.desc->bDescriptorSubtype) { |
4634 |
case UDESCSUB_AC_INPUT: |
4635 |
info->bit_input[i / 8] |= (1 << (i % 8)); |
4636 |
break; |
4637 |
|
4638 |
case UDESCSUB_AC_FEATURE: |
4639 |
if (is_last) { |
4640 |
p_id = &iot->u.fu_v1->bSourceId; |
4641 |
n_id = 1; |
4642 |
goto top; |
4643 |
} |
4644 |
uaudio_mixer_find_inputs_sub( |
4645 |
root, &iot->u.fu_v1->bSourceId, 1, info); |
4646 |
break; |
4647 |
|
4648 |
case UDESCSUB_AC_OUTPUT: |
4649 |
if (is_last) { |
4650 |
p_id = &iot->u.ot_v1->bSourceId; |
4651 |
n_id = 1; |
4652 |
goto top; |
4653 |
} |
4654 |
uaudio_mixer_find_inputs_sub( |
4655 |
root, &iot->u.ot_v1->bSourceId, 1, info); |
4656 |
break; |
4657 |
|
4658 |
case UDESCSUB_AC_MIXER: |
4659 |
if (is_last) { |
4660 |
p_id = iot->u.mu_v1->baSourceId; |
4661 |
n_id = iot->u.mu_v1->bNrInPins; |
4662 |
goto top; |
4663 |
} |
4664 |
uaudio_mixer_find_inputs_sub( |
4665 |
root, iot->u.mu_v1->baSourceId, |
4666 |
iot->u.mu_v1->bNrInPins, info); |
4667 |
break; |
4668 |
|
4669 |
case UDESCSUB_AC_SELECTOR: |
4670 |
if (is_last) { |
4671 |
p_id = iot->u.su_v1->baSourceId; |
4672 |
n_id = iot->u.su_v1->bNrInPins; |
4673 |
goto top; |
4674 |
} |
4675 |
uaudio_mixer_find_inputs_sub( |
4676 |
root, iot->u.su_v1->baSourceId, |
4677 |
iot->u.su_v1->bNrInPins, info); |
4678 |
break; |
4679 |
|
4680 |
case UDESCSUB_AC_PROCESSING: |
4681 |
if (is_last) { |
4682 |
p_id = iot->u.pu_v1->baSourceId; |
4683 |
n_id = iot->u.pu_v1->bNrInPins; |
4684 |
goto top; |
4685 |
} |
4686 |
uaudio_mixer_find_inputs_sub( |
4687 |
root, iot->u.pu_v1->baSourceId, |
4688 |
iot->u.pu_v1->bNrInPins, info); |
4689 |
break; |
4690 |
|
4691 |
case UDESCSUB_AC_EXTENSION: |
4692 |
if (is_last) { |
4693 |
p_id = iot->u.eu_v1->baSourceId; |
4694 |
n_id = iot->u.eu_v1->bNrInPins; |
4695 |
goto top; |
4696 |
} |
4697 |
uaudio_mixer_find_inputs_sub( |
4698 |
root, iot->u.eu_v1->baSourceId, |
4699 |
iot->u.eu_v1->bNrInPins, info); |
4700 |
break; |
4701 |
|
4702 |
default: |
4703 |
break; |
4704 |
} |
4705 |
} |
4706 |
} |
4707 |
|
4708 |
static void |
4709 |
uaudio20_mixer_find_inputs_sub(struct uaudio_terminal_node *root, |
4710 |
const uint8_t *p_id, uint8_t n_id, |
4711 |
struct uaudio_search_result *info) |
4712 |
{ |
4713 |
struct uaudio_terminal_node *iot; |
4714 |
uint8_t n; |
4715 |
uint8_t i; |
4716 |
uint8_t is_last; |
4717 |
|
4718 |
top: |
4719 |
for (n = 0; n < n_id; n++) { |
4720 |
|
4721 |
i = p_id[n]; |
4722 |
|
4723 |
if (info->recurse_level == UAUDIO_RECURSE_LIMIT) { |
4724 |
DPRINTF("avoided going into a circle at id=%d!\n", i); |
4725 |
return; |
4726 |
} |
4727 |
|
4728 |
info->recurse_level++; |
4729 |
|
4730 |
iot = (root + i); |
4731 |
|
4732 |
if (iot->u.desc == NULL) |
4733 |
continue; |
4734 |
|
4735 |
is_last = ((n + 1) == n_id); |
4736 |
|
4737 |
switch (iot->u.desc->bDescriptorSubtype) { |
4738 |
case UDESCSUB_AC_INPUT: |
4739 |
info->bit_input[i / 8] |= (1 << (i % 8)); |
4740 |
break; |
4741 |
|
4742 |
case UDESCSUB_AC_OUTPUT: |
4743 |
if (is_last) { |
4744 |
p_id = &iot->u.ot_v2->bSourceId; |
4745 |
n_id = 1; |
4746 |
goto top; |
4747 |
} |
4748 |
uaudio20_mixer_find_inputs_sub( |
4749 |
root, &iot->u.ot_v2->bSourceId, 1, info); |
4750 |
break; |
4751 |
|
4752 |
case UDESCSUB_AC_MIXER: |
4753 |
if (is_last) { |
4754 |
p_id = iot->u.mu_v2->baSourceId; |
4755 |
n_id = iot->u.mu_v2->bNrInPins; |
4756 |
goto top; |
4757 |
} |
4758 |
uaudio20_mixer_find_inputs_sub( |
4759 |
root, iot->u.mu_v2->baSourceId, |
4760 |
iot->u.mu_v2->bNrInPins, info); |
4761 |
break; |
4762 |
|
4763 |
case UDESCSUB_AC_SELECTOR: |
4764 |
if (is_last) { |
4765 |
p_id = iot->u.su_v2->baSourceId; |
4766 |
n_id = iot->u.su_v2->bNrInPins; |
4767 |
goto top; |
4768 |
} |
4769 |
uaudio20_mixer_find_inputs_sub( |
4770 |
root, iot->u.su_v2->baSourceId, |
4771 |
iot->u.su_v2->bNrInPins, info); |
4772 |
break; |
4773 |
|
4774 |
case UDESCSUB_AC_SAMPLE_RT: |
4775 |
if (is_last) { |
4776 |
p_id = &iot->u.ru_v2->bSourceId; |
4777 |
n_id = 1; |
4778 |
goto top; |
4779 |
} |
4780 |
uaudio20_mixer_find_inputs_sub( |
4781 |
root, &iot->u.ru_v2->bSourceId, |
4782 |
1, info); |
4783 |
break; |
4784 |
|
4785 |
case UDESCSUB_AC_EFFECT: |
4786 |
if (is_last) { |
4787 |
p_id = &iot->u.ef_v2->bSourceId; |
4788 |
n_id = 1; |
4789 |
goto top; |
4790 |
} |
4791 |
uaudio20_mixer_find_inputs_sub( |
4792 |
root, &iot->u.ef_v2->bSourceId, |
4793 |
1, info); |
4794 |
break; |
4795 |
|
4796 |
case UDESCSUB_AC_FEATURE: |
4797 |
if (is_last) { |
4798 |
p_id = &iot->u.fu_v2->bSourceId; |
4799 |
n_id = 1; |
4800 |
goto top; |
4801 |
} |
4802 |
uaudio20_mixer_find_inputs_sub( |
4803 |
root, &iot->u.fu_v2->bSourceId, 1, info); |
4804 |
break; |
4805 |
|
4806 |
case UDESCSUB_AC_PROCESSING_V2: |
4807 |
if (is_last) { |
4808 |
p_id = iot->u.pu_v2->baSourceId; |
4809 |
n_id = iot->u.pu_v2->bNrInPins; |
4810 |
goto top; |
4811 |
} |
4812 |
uaudio20_mixer_find_inputs_sub( |
4813 |
root, iot->u.pu_v2->baSourceId, |
4814 |
iot->u.pu_v2->bNrInPins, info); |
4815 |
break; |
4816 |
|
4817 |
case UDESCSUB_AC_EXTENSION_V2: |
4818 |
if (is_last) { |
4819 |
p_id = iot->u.eu_v2->baSourceId; |
4820 |
n_id = iot->u.eu_v2->bNrInPins; |
4821 |
goto top; |
4822 |
} |
4823 |
uaudio20_mixer_find_inputs_sub( |
4824 |
root, iot->u.eu_v2->baSourceId, |
4825 |
iot->u.eu_v2->bNrInPins, info); |
4826 |
break; |
4827 |
default: |
4828 |
break; |
4829 |
} |
4830 |
} |
4831 |
} |
4832 |
|
4833 |
static void |
4834 |
uaudio20_mixer_find_clocks_sub(struct uaudio_terminal_node *root, |
4835 |
const uint8_t *p_id, uint8_t n_id, |
4836 |
struct uaudio_search_result *info) |
4837 |
{ |
4838 |
struct uaudio_terminal_node *iot; |
4839 |
uint8_t n; |
4840 |
uint8_t i; |
4841 |
uint8_t is_last; |
4842 |
uint8_t id; |
4843 |
|
4844 |
top: |
4845 |
for (n = 0; n < n_id; n++) { |
4846 |
|
4847 |
i = p_id[n]; |
4848 |
|
4849 |
if (info->recurse_level == UAUDIO_RECURSE_LIMIT) { |
4850 |
DPRINTF("avoided going into a circle at id=%d!\n", i); |
4851 |
return; |
4852 |
} |
4853 |
|
4854 |
info->recurse_level++; |
4855 |
|
4856 |
iot = (root + i); |
4857 |
|
4858 |
if (iot->u.desc == NULL) |
4859 |
continue; |
4860 |
|
4861 |
is_last = ((n + 1) == n_id); |
4862 |
|
4863 |
switch (iot->u.desc->bDescriptorSubtype) { |
4864 |
case UDESCSUB_AC_INPUT: |
4865 |
info->is_input = 1; |
4866 |
if (is_last) { |
4867 |
p_id = &iot->u.it_v2->bCSourceId; |
4868 |
n_id = 1; |
4869 |
goto top; |
4870 |
} |
4871 |
uaudio20_mixer_find_clocks_sub(root, |
4872 |
&iot->u.it_v2->bCSourceId, 1, info); |
4873 |
break; |
4874 |
|
4875 |
case UDESCSUB_AC_OUTPUT: |
4876 |
info->is_input = 0; |
4877 |
if (is_last) { |
4878 |
p_id = &iot->u.ot_v2->bCSourceId; |
4879 |
n_id = 1; |
4880 |
goto top; |
4881 |
} |
4882 |
uaudio20_mixer_find_clocks_sub(root, |
4883 |
&iot->u.ot_v2->bCSourceId, 1, info); |
4884 |
break; |
4885 |
|
4886 |
case UDESCSUB_AC_CLOCK_SEL: |
4887 |
if (is_last) { |
4888 |
p_id = iot->u.csel_v2->baCSourceId; |
4889 |
n_id = iot->u.csel_v2->bNrInPins; |
4890 |
goto top; |
4891 |
} |
4892 |
uaudio20_mixer_find_clocks_sub(root, |
4893 |
iot->u.csel_v2->baCSourceId, |
4894 |
iot->u.csel_v2->bNrInPins, info); |
4895 |
break; |
4896 |
|
4897 |
case UDESCSUB_AC_CLOCK_MUL: |
4898 |
if (is_last) { |
4899 |
p_id = &iot->u.cmul_v2->bCSourceId; |
4900 |
n_id = 1; |
4901 |
goto top; |
4902 |
} |
4903 |
uaudio20_mixer_find_clocks_sub(root, |
4904 |
&iot->u.cmul_v2->bCSourceId, |
4905 |
1, info); |
4906 |
break; |
4907 |
|
4908 |
case UDESCSUB_AC_CLOCK_SRC: |
4909 |
|
4910 |
id = iot->u.csrc_v2->bClockId; |
4911 |
|
4912 |
switch (info->is_input) { |
4913 |
case 0: |
4914 |
info->bit_output[id / 8] |= (1 << (id % 8)); |
4915 |
break; |
4916 |
case 1: |
4917 |
info->bit_input[id / 8] |= (1 << (id % 8)); |
4918 |
break; |
4919 |
default: |
4920 |
break; |
4921 |
} |
4922 |
break; |
4923 |
|
4924 |
default: |
4925 |
break; |
4926 |
} |
4927 |
} |
4928 |
} |
4929 |
|
4930 |
static void |
4931 |
uaudio_mixer_find_outputs_sub(struct uaudio_terminal_node *root, uint8_t id, |
4932 |
uint8_t n_id, struct uaudio_search_result *info) |
4933 |
{ |
4934 |
struct uaudio_terminal_node *iot = (root + id); |
4935 |
uint8_t j; |
4936 |
|
4937 |
j = n_id; |
4938 |
do { |
4939 |
if ((j != id) && ((root + j)->u.desc) && |
4940 |
((root + j)->u.desc->bDescriptorSubtype == UDESCSUB_AC_OUTPUT)) { |
4941 |
|
4942 |
/* |
4943 |
* "j" (output) <--- virtual wire <--- "id" (input) |
4944 |
* |
4945 |
* if "j" has "id" on the input, then "id" have "j" on |
4946 |
* the output, because they are connected: |
4947 |
*/ |
4948 |
if ((root + j)->usr.bit_input[id / 8] & (1 << (id % 8))) { |
4949 |
iot->usr.bit_output[j / 8] |= (1 << (j % 8)); |
4950 |
} |
4951 |
} |
4952 |
} while (j--); |
4953 |
} |
4954 |
|
4955 |
static void |
4956 |
uaudio_mixer_fill_info(struct uaudio_softc *sc, |
4957 |
struct usb_device *udev, void *desc) |
4958 |
{ |
4959 |
const struct usb_audio_control_descriptor *acdp; |
4960 |
struct usb_config_descriptor *cd = usbd_get_config_descriptor(udev); |
4961 |
const struct usb_descriptor *dp; |
4962 |
const struct usb_audio_unit *au; |
4963 |
struct uaudio_terminal_node *iot = NULL; |
4964 |
uint16_t wTotalLen; |
4965 |
uint8_t ID_max = 0; /* inclusive */ |
4966 |
uint8_t i; |
4967 |
|
4968 |
desc = usb_desc_foreach(cd, desc); |
4969 |
|
4970 |
if (desc == NULL) { |
4971 |
DPRINTF("no Audio Control header\n"); |
4972 |
goto done; |
4973 |
} |
4974 |
acdp = desc; |
4975 |
|
4976 |
if ((acdp->bLength < sizeof(*acdp)) || |
4977 |
(acdp->bDescriptorType != UDESC_CS_INTERFACE) || |
4978 |
(acdp->bDescriptorSubtype != UDESCSUB_AC_HEADER)) { |
4979 |
DPRINTF("invalid Audio Control header\n"); |
4980 |
goto done; |
4981 |
} |
4982 |
/* "wTotalLen" is allowed to be corrupt */ |
4983 |
wTotalLen = UGETW(acdp->wTotalLength) - acdp->bLength; |
4984 |
|
4985 |
/* get USB audio revision */ |
4986 |
sc->sc_audio_rev = UGETW(acdp->bcdADC); |
4987 |
|
4988 |
DPRINTFN(3, "found AC header, vers=%03x, len=%d\n", |
4989 |
sc->sc_audio_rev, wTotalLen); |
4990 |
|
4991 |
iot = malloc(sizeof(struct uaudio_terminal_node) * 256, M_TEMP, |
4992 |
M_WAITOK | M_ZERO); |
4993 |
|
4994 |
if (iot == NULL) { |
4995 |
DPRINTF("no memory!\n"); |
4996 |
goto done; |
4997 |
} |
4998 |
while ((desc = usb_desc_foreach(cd, desc))) { |
4999 |
|
5000 |
dp = desc; |
5001 |
|
5002 |
if (dp->bLength > wTotalLen) { |
5003 |
break; |
5004 |
} else { |
5005 |
wTotalLen -= dp->bLength; |
5006 |
} |
5007 |
|
5008 |
if (sc->sc_audio_rev >= UAUDIO_VERSION_30) |
5009 |
au = NULL; |
5010 |
else if (sc->sc_audio_rev >= UAUDIO_VERSION_20) |
5011 |
au = uaudio20_mixer_verify_desc(dp, 0); |
5012 |
else |
5013 |
au = uaudio_mixer_verify_desc(dp, 0); |
5014 |
|
5015 |
if (au) { |
5016 |
iot[au->bUnitId].u.desc = (const void *)au; |
5017 |
if (au->bUnitId > ID_max) |
5018 |
ID_max = au->bUnitId; |
5019 |
} |
5020 |
} |
5021 |
|
5022 |
DPRINTF("Maximum ID=%d\n", ID_max); |
5023 |
|
5024 |
/* |
5025 |
* determine sourcing inputs for |
5026 |
* all nodes in the tree: |
5027 |
*/ |
5028 |
i = ID_max; |
5029 |
do { |
5030 |
if (sc->sc_audio_rev >= UAUDIO_VERSION_30) { |
5031 |
/* FALLTHROUGH */ |
5032 |
} else if (sc->sc_audio_rev >= UAUDIO_VERSION_20) { |
5033 |
uaudio20_mixer_find_inputs_sub(iot, |
5034 |
&i, 1, &((iot + i)->usr)); |
5035 |
|
5036 |
sc->sc_mixer_clocks.is_input = 255; |
5037 |
sc->sc_mixer_clocks.recurse_level = 0; |
5038 |
|
5039 |
uaudio20_mixer_find_clocks_sub(iot, |
5040 |
&i, 1, &sc->sc_mixer_clocks); |
5041 |
} else { |
5042 |
uaudio_mixer_find_inputs_sub(iot, |
5043 |
&i, 1, &((iot + i)->usr)); |
5044 |
} |
5045 |
} while (i--); |
5046 |
|
5047 |
/* |
5048 |
* determine outputs for |
5049 |
* all nodes in the tree: |
5050 |
*/ |
5051 |
i = ID_max; |
5052 |
do { |
5053 |
uaudio_mixer_find_outputs_sub(iot, |
5054 |
i, ID_max, &((iot + i)->usr)); |
5055 |
} while (i--); |
5056 |
|
5057 |
/* set "id_max" and "root" */ |
5058 |
|
5059 |
i = ID_max; |
5060 |
do { |
5061 |
(iot + i)->usr.id_max = ID_max; |
5062 |
(iot + i)->root = iot; |
5063 |
} while (i--); |
5064 |
|
5065 |
/* |
5066 |
* Scan the config to create a linked list of "mixer" nodes: |
5067 |
*/ |
5068 |
|
5069 |
i = ID_max; |
5070 |
do { |
5071 |
dp = iot[i].u.desc; |
5072 |
|
5073 |
if (dp == NULL) |
5074 |
continue; |
5075 |
|
5076 |
DPRINTFN(11, "id=%d subtype=%d\n", |
5077 |
i, dp->bDescriptorSubtype); |
5078 |
|
5079 |
if (sc->sc_audio_rev >= UAUDIO_VERSION_30) { |
5080 |
continue; |
5081 |
} else if (sc->sc_audio_rev >= UAUDIO_VERSION_20) { |
5082 |
|
5083 |
switch (dp->bDescriptorSubtype) { |
5084 |
case UDESCSUB_AC_HEADER: |
5085 |
DPRINTF("unexpected AC header\n"); |
5086 |
break; |
5087 |
|
5088 |
case UDESCSUB_AC_INPUT: |
5089 |
case UDESCSUB_AC_OUTPUT: |
5090 |
case UDESCSUB_AC_PROCESSING_V2: |
5091 |
case UDESCSUB_AC_EXTENSION_V2: |
5092 |
case UDESCSUB_AC_EFFECT: |
5093 |
case UDESCSUB_AC_CLOCK_SRC: |
5094 |
case UDESCSUB_AC_CLOCK_SEL: |
5095 |
case UDESCSUB_AC_CLOCK_MUL: |
5096 |
case UDESCSUB_AC_SAMPLE_RT: |
5097 |
break; |
5098 |
|
5099 |
case UDESCSUB_AC_MIXER: |
5100 |
uaudio20_mixer_add_mixer(sc, iot, i); |
5101 |
break; |
5102 |
|
5103 |
case UDESCSUB_AC_SELECTOR: |
5104 |
uaudio20_mixer_add_selector(sc, iot, i); |
5105 |
break; |
5106 |
|
5107 |
case UDESCSUB_AC_FEATURE: |
5108 |
uaudio20_mixer_add_feature(sc, iot, i); |
5109 |
break; |
5110 |
|
5111 |
default: |
5112 |
DPRINTF("bad AC desc subtype=0x%02x\n", |
5113 |
dp->bDescriptorSubtype); |
5114 |
break; |
5115 |
} |
5116 |
continue; |
5117 |
} |
5118 |
|
5119 |
switch (dp->bDescriptorSubtype) { |
5120 |
case UDESCSUB_AC_HEADER: |
5121 |
DPRINTF("unexpected AC header\n"); |
5122 |
break; |
5123 |
|
5124 |
case UDESCSUB_AC_INPUT: |
5125 |
case UDESCSUB_AC_OUTPUT: |
5126 |
break; |
5127 |
|
5128 |
case UDESCSUB_AC_MIXER: |
5129 |
uaudio_mixer_add_mixer(sc, iot, i); |
5130 |
break; |
5131 |
|
5132 |
case UDESCSUB_AC_SELECTOR: |
5133 |
uaudio_mixer_add_selector(sc, iot, i); |
5134 |
break; |
5135 |
|
5136 |
case UDESCSUB_AC_FEATURE: |
5137 |
uaudio_mixer_add_feature(sc, iot, i); |
5138 |
break; |
5139 |
|
5140 |
case UDESCSUB_AC_PROCESSING: |
5141 |
uaudio_mixer_add_processing(sc, iot, i); |
5142 |
break; |
5143 |
|
5144 |
case UDESCSUB_AC_EXTENSION: |
5145 |
uaudio_mixer_add_extension(sc, iot, i); |
5146 |
break; |
5147 |
|
5148 |
default: |
5149 |
DPRINTF("bad AC desc subtype=0x%02x\n", |
5150 |
dp->bDescriptorSubtype); |
5151 |
break; |
5152 |
} |
5153 |
|
5154 |
} while (i--); |
5155 |
|
5156 |
done: |
5157 |
free(iot, M_TEMP); |
5158 |
} |
5159 |
|
5160 |
static int |
5161 |
uaudio_mixer_get(struct usb_device *udev, uint16_t audio_rev, |
5162 |
uint8_t what, struct uaudio_mixer_node *mc) |
5163 |
{ |
5164 |
struct usb_device_request req; |
5165 |
int val; |
5166 |
uint8_t data[2 + (2 * 3)]; |
5167 |
usb_error_t err; |
5168 |
|
5169 |
if (mc->wValue[0] == -1) |
5170 |
return (0); |
5171 |
|
5172 |
if (audio_rev >= UAUDIO_VERSION_30) |
5173 |
return (0); |
5174 |
else if (audio_rev >= UAUDIO_VERSION_20) { |
5175 |
if (what == GET_CUR) { |
5176 |
req.bRequest = UA20_CS_CUR; |
5177 |
USETW(req.wLength, 2); |
5178 |
} else { |
5179 |
req.bRequest = UA20_CS_RANGE; |
5180 |
USETW(req.wLength, 8); |
5181 |
} |
5182 |
} else { |
5183 |
uint16_t len = MIX_SIZE(mc->type); |
5184 |
|
5185 |
req.bRequest = what; |
5186 |
USETW(req.wLength, len); |
5187 |
} |
5188 |
|
5189 |
req.bmRequestType = UT_READ_CLASS_INTERFACE; |
5190 |
USETW(req.wValue, mc->wValue[0]); |
5191 |
USETW(req.wIndex, mc->wIndex); |
5192 |
|
5193 |
memset(data, 0, sizeof(data)); |
5194 |
|
5195 |
err = usbd_do_request(udev, NULL, &req, data); |
5196 |
if (err) { |
5197 |
DPRINTF("err=%s\n", usbd_errstr(err)); |
5198 |
return (0); |
5199 |
} |
5200 |
|
5201 |
if (audio_rev >= UAUDIO_VERSION_30) { |
5202 |
val = 0; |
5203 |
} else if (audio_rev >= UAUDIO_VERSION_20) { |
5204 |
switch (what) { |
5205 |
case GET_CUR: |
5206 |
val = (data[0] | (data[1] << 8)); |
5207 |
break; |
5208 |
case GET_MIN: |
5209 |
val = (data[2] | (data[3] << 8)); |
5210 |
break; |
5211 |
case GET_MAX: |
5212 |
val = (data[4] | (data[5] << 8)); |
5213 |
break; |
5214 |
case GET_RES: |
5215 |
val = (data[6] | (data[7] << 8)); |
5216 |
break; |
5217 |
default: |
5218 |
val = 0; |
5219 |
break; |
5220 |
} |
5221 |
} else { |
5222 |
val = (data[0] | (data[1] << 8)); |
5223 |
} |
5224 |
|
5225 |
if (what == GET_CUR || what == GET_MIN || what == GET_MAX) |
5226 |
val = uaudio_mixer_signext(mc->type, val); |
5227 |
|
5228 |
DPRINTFN(3, "val=%d\n", val); |
5229 |
|
5230 |
return (val); |
5231 |
} |
5232 |
|
5233 |
static void |
5234 |
uaudio_mixer_write_cfg_callback(struct usb_xfer *xfer, usb_error_t error) |
5235 |
{ |
5236 |
struct usb_device_request req; |
5237 |
struct uaudio_softc *sc = usbd_xfer_softc(xfer); |
5238 |
struct uaudio_mixer_node *mc = sc->sc_mixer_curr; |
5239 |
struct usb_page_cache *pc; |
5240 |
uint16_t len; |
5241 |
uint8_t repeat = 1; |
5242 |
uint8_t update; |
5243 |
uint8_t chan; |
5244 |
uint8_t buf[2]; |
5245 |
|
5246 |
DPRINTF("\n"); |
5247 |
|
5248 |
switch (USB_GET_STATE(xfer)) { |
5249 |
case USB_ST_TRANSFERRED: |
5250 |
tr_transferred: |
5251 |
case USB_ST_SETUP: |
5252 |
tr_setup: |
5253 |
|
5254 |
if (mc == NULL) { |
5255 |
mc = sc->sc_mixer_root; |
5256 |
sc->sc_mixer_curr = mc; |
5257 |
sc->sc_mixer_chan = 0; |
5258 |
repeat = 0; |
5259 |
} |
5260 |
while (mc) { |
5261 |
while (sc->sc_mixer_chan < mc->nchan) { |
5262 |
|
5263 |
chan = sc->sc_mixer_chan; |
5264 |
|
5265 |
sc->sc_mixer_chan++; |
5266 |
|
5267 |
update = ((mc->update[chan / 8] & (1 << (chan % 8))) && |
5268 |
(mc->wValue[chan] != -1)); |
5269 |
|
5270 |
mc->update[chan / 8] &= ~(1 << (chan % 8)); |
5271 |
|
5272 |
if (update) { |
5273 |
|
5274 |
req.bmRequestType = UT_WRITE_CLASS_INTERFACE; |
5275 |
USETW(req.wValue, mc->wValue[chan]); |
5276 |
USETW(req.wIndex, mc->wIndex); |
5277 |
|
5278 |
if (sc->sc_audio_rev >= UAUDIO_VERSION_30) { |
5279 |
return; |
5280 |
} else if (sc->sc_audio_rev >= UAUDIO_VERSION_20) { |
5281 |
len = 2; |
5282 |
req.bRequest = UA20_CS_CUR; |
5283 |
USETW(req.wLength, len); |
5284 |
} else { |
5285 |
len = MIX_SIZE(mc->type); |
5286 |
req.bRequest = SET_CUR; |
5287 |
USETW(req.wLength, len); |
5288 |
} |
5289 |
|
5290 |
buf[0] = (mc->wData[chan] & 0xFF); |
5291 |
buf[1] = (mc->wData[chan] >> 8) & 0xFF; |
5292 |
|
5293 |
pc = usbd_xfer_get_frame(xfer, 0); |
5294 |
usbd_copy_in(pc, 0, &req, sizeof(req)); |
5295 |
pc = usbd_xfer_get_frame(xfer, 1); |
5296 |
usbd_copy_in(pc, 0, buf, len); |
5297 |
|
5298 |
usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); |
5299 |
usbd_xfer_set_frame_len(xfer, 1, len); |
5300 |
usbd_xfer_set_frames(xfer, len ? 2 : 1); |
5301 |
usbd_transfer_submit(xfer); |
5302 |
return; |
5303 |
} |
5304 |
} |
5305 |
|
5306 |
mc = mc->next; |
5307 |
sc->sc_mixer_curr = mc; |
5308 |
sc->sc_mixer_chan = 0; |
5309 |
} |
5310 |
|
5311 |
if (repeat) { |
5312 |
goto tr_setup; |
5313 |
} |
5314 |
break; |
5315 |
|
5316 |
default: /* Error */ |
5317 |
DPRINTF("error=%s\n", usbd_errstr(error)); |
5318 |
if (error == USB_ERR_CANCELLED) { |
5319 |
/* do nothing - we are detaching */ |
5320 |
break; |
5321 |
} |
5322 |
goto tr_transferred; |
5323 |
} |
5324 |
} |
5325 |
|
5326 |
static usb_error_t |
5327 |
uaudio_set_speed(struct usb_device *udev, uint8_t endpt, uint32_t speed) |
5328 |
{ |
5329 |
struct usb_device_request req; |
5330 |
uint8_t data[3]; |
5331 |
|
5332 |
DPRINTFN(6, "endpt=%d speed=%u\n", endpt, speed); |
5333 |
|
5334 |
req.bmRequestType = UT_WRITE_CLASS_ENDPOINT; |
5335 |
req.bRequest = SET_CUR; |
5336 |
USETW2(req.wValue, SAMPLING_FREQ_CONTROL, 0); |
5337 |
USETW(req.wIndex, endpt); |
5338 |
USETW(req.wLength, 3); |
5339 |
data[0] = speed; |
5340 |
data[1] = speed >> 8; |
5341 |
data[2] = speed >> 16; |
5342 |
|
5343 |
return (usbd_do_request(udev, NULL, &req, data)); |
5344 |
} |
5345 |
|
5346 |
static usb_error_t |
5347 |
uaudio20_set_speed(struct usb_device *udev, uint8_t iface_no, |
5348 |
uint8_t clockid, uint32_t speed) |
5349 |
{ |
5350 |
struct usb_device_request req; |
5351 |
uint8_t data[4]; |
5352 |
|
5353 |
DPRINTFN(6, "ifaceno=%d clockid=%d speed=%u\n", |
5354 |
iface_no, clockid, speed); |
5355 |
|
5356 |
req.bmRequestType = UT_WRITE_CLASS_INTERFACE; |
5357 |
req.bRequest = UA20_CS_CUR; |
5358 |
USETW2(req.wValue, UA20_CS_SAM_FREQ_CONTROL, 0); |
5359 |
USETW2(req.wIndex, clockid, iface_no); |
5360 |
USETW(req.wLength, 4); |
5361 |
data[0] = speed; |
5362 |
data[1] = speed >> 8; |
5363 |
data[2] = speed >> 16; |
5364 |
data[3] = speed >> 24; |
5365 |
|
5366 |
return (usbd_do_request(udev, NULL, &req, data)); |
5367 |
} |
5368 |
|
5369 |
static int |
5370 |
uaudio_mixer_signext(uint8_t type, int val) |
5371 |
{ |
5372 |
if (!MIX_UNSIGNED(type)) { |
5373 |
if (MIX_SIZE(type) == 2) { |
5374 |
val = (int16_t)val; |
5375 |
} else { |
5376 |
val = (int8_t)val; |
5377 |
} |
5378 |
} |
5379 |
return (val); |
5380 |
} |
5381 |
|
5382 |
static int |
5383 |
uaudio_mixer_bsd2value(struct uaudio_mixer_node *mc, int32_t val) |
5384 |
{ |
5385 |
if (mc->type == MIX_ON_OFF) { |
5386 |
val = (val != 0); |
5387 |
} else if (mc->type == MIX_SELECTOR) { |
5388 |
if ((val < mc->minval) || |
5389 |
(val > mc->maxval)) { |
5390 |
val = mc->minval; |
5391 |
} |
5392 |
} else { |
5393 |
|
5394 |
/* compute actual volume */ |
5395 |
val = (val * mc->mul) / 255; |
5396 |
|
5397 |
/* add lower offset */ |
5398 |
val = val + mc->minval; |
5399 |
|
5400 |
/* make sure we don't write a value out of range */ |
5401 |
if (val > mc->maxval) |
5402 |
val = mc->maxval; |
5403 |
else if (val < mc->minval) |
5404 |
val = mc->minval; |
5405 |
} |
5406 |
|
5407 |
DPRINTFN(6, "type=0x%03x val=%d min=%d max=%d val=%d\n", |
5408 |
mc->type, val, mc->minval, mc->maxval, val); |
5409 |
return (val); |
5410 |
} |
5411 |
|
5412 |
static void |
5413 |
uaudio_mixer_ctl_set(struct uaudio_softc *sc, struct uaudio_mixer_node *mc, |
5414 |
uint8_t chan, int32_t val) |
5415 |
{ |
5416 |
val = uaudio_mixer_bsd2value(mc, val); |
5417 |
|
5418 |
mc->update[chan / 8] |= (1 << (chan % 8)); |
5419 |
mc->wData[chan] = val; |
5420 |
|
5421 |
/* start the transfer, if not already started */ |
5422 |
|
5423 |
usbd_transfer_start(sc->sc_mixer_xfer[0]); |
5424 |
} |
5425 |
|
5426 |
static void |
5427 |
uaudio_mixer_init(struct uaudio_softc *sc) |
5428 |
{ |
5429 |
struct uaudio_mixer_node *mc; |
5430 |
int32_t i; |
5431 |
|
5432 |
for (mc = sc->sc_mixer_root; mc; |
5433 |
mc = mc->next) { |
5434 |
|
5435 |
if (mc->ctl != SOUND_MIXER_NRDEVICES) { |
5436 |
/* |
5437 |
* Set device mask bits. See |
5438 |
* /usr/include/machine/soundcard.h |
5439 |
*/ |
5440 |
sc->sc_mix_info |= (1 << mc->ctl); |
5441 |
} |
5442 |
if ((mc->ctl == SOUND_MIXER_NRDEVICES) && |
5443 |
(mc->type == MIX_SELECTOR)) { |
5444 |
|
5445 |
for (i = mc->minval; (i > 0) && (i <= mc->maxval); i++) { |
5446 |
if (mc->slctrtype[i - 1] == SOUND_MIXER_NRDEVICES) { |
5447 |
continue; |
5448 |
} |
5449 |
sc->sc_recsrc_info |= 1 << mc->slctrtype[i - 1]; |
5450 |
} |
5451 |
} |
5452 |
} |
5453 |
} |
5454 |
|
5455 |
int |
5456 |
uaudio_mixer_init_sub(struct uaudio_softc *sc, struct snd_mixer *m) |
5457 |
{ |
5458 |
DPRINTF("\n"); |
5459 |
|
5460 |
sc->sc_mixer_lock = mixer_get_lock(m); |
5461 |
sc->sc_mixer_dev = m; |
5462 |
|
5463 |
if (usbd_transfer_setup(sc->sc_udev, &sc->sc_mixer_iface_index, |
5464 |
sc->sc_mixer_xfer, uaudio_mixer_config, 1, sc, |
5465 |
sc->sc_mixer_lock)) { |
5466 |
DPRINTFN(0, "could not allocate USB " |
5467 |
"transfer for audio mixer!\n"); |
5468 |
return (ENOMEM); |
5469 |
} |
5470 |
if (!(sc->sc_mix_info & SOUND_MASK_VOLUME)) { |
5471 |
mix_setparentchild(m, SOUND_MIXER_VOLUME, SOUND_MASK_PCM); |
5472 |
mix_setrealdev(m, SOUND_MIXER_VOLUME, SOUND_MIXER_NONE); |
5473 |
} |
5474 |
mix_setdevs(m, sc->sc_mix_info); |
5475 |
mix_setrecdevs(m, sc->sc_recsrc_info); |
5476 |
return (0); |
5477 |
} |
5478 |
|
5479 |
int |
5480 |
uaudio_mixer_uninit_sub(struct uaudio_softc *sc) |
5481 |
{ |
5482 |
DPRINTF("\n"); |
5483 |
|
5484 |
usbd_transfer_unsetup(sc->sc_mixer_xfer, 1); |
5485 |
|
5486 |
sc->sc_mixer_lock = NULL; |
5487 |
|
5488 |
return (0); |
5489 |
} |
5490 |
|
5491 |
void |
5492 |
uaudio_mixer_set(struct uaudio_softc *sc, unsigned type, |
5493 |
unsigned left, unsigned right) |
5494 |
{ |
5495 |
struct uaudio_mixer_node *mc; |
5496 |
int chan; |
5497 |
|
5498 |
for (mc = sc->sc_mixer_root; mc != NULL; mc = mc->next) { |
5499 |
|
5500 |
if (mc->ctl == type) { |
5501 |
for (chan = 0; chan < mc->nchan; chan++) { |
5502 |
uaudio_mixer_ctl_set(sc, mc, chan, |
5503 |
(int)((chan == 0 ? left : right) * |
5504 |
255) / 100); |
5505 |
} |
5506 |
} |
5507 |
} |
5508 |
} |
5509 |
|
5510 |
uint32_t |
5511 |
uaudio_mixer_setrecsrc(struct uaudio_softc *sc, uint32_t src) |
5512 |
{ |
5513 |
struct uaudio_mixer_node *mc; |
5514 |
uint32_t mask; |
5515 |
uint32_t temp; |
5516 |
int32_t i; |
5517 |
|
5518 |
for (mc = sc->sc_mixer_root; mc; |
5519 |
mc = mc->next) { |
5520 |
|
5521 |
if ((mc->ctl == SOUND_MIXER_NRDEVICES) && |
5522 |
(mc->type == MIX_SELECTOR)) { |
5523 |
|
5524 |
/* compute selector mask */ |
5525 |
|
5526 |
mask = 0; |
5527 |
for (i = mc->minval; (i > 0) && (i <= mc->maxval); i++) { |
5528 |
mask |= (1 << mc->slctrtype[i - 1]); |
5529 |
} |
5530 |
|
5531 |
temp = mask & src; |
5532 |
if (temp == 0) { |
5533 |
continue; |
5534 |
} |
5535 |
/* find the first set bit */ |
5536 |
temp = (-temp) & temp; |
5537 |
|
5538 |
/* update "src" */ |
5539 |
src &= ~mask; |
5540 |
src |= temp; |
5541 |
|
5542 |
for (i = mc->minval; (i > 0) && (i <= mc->maxval); i++) { |
5543 |
if (temp != (1 << mc->slctrtype[i - 1])) { |
5544 |
continue; |
5545 |
} |
5546 |
uaudio_mixer_ctl_set(sc, mc, 0, i); |
5547 |
break; |
5548 |
} |
5549 |
} |
5550 |
} |
5551 |
return (src); |
5552 |
} |
5553 |
|
5554 |
/*========================================================================* |
5555 |
* MIDI support routines |
5556 |
*========================================================================*/ |
5557 |
|
5558 |
static void |
5559 |
umidi_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) |
5560 |
{ |
5561 |
struct umidi_chan *chan = usbd_xfer_softc(xfer); |
5562 |
struct umidi_sub_chan *sub; |
5563 |
struct usb_page_cache *pc; |
5564 |
uint8_t buf[4]; |
5565 |
uint8_t cmd_len; |
5566 |
uint8_t cn; |
5567 |
uint16_t pos; |
5568 |
int actlen; |
5569 |
|
5570 |
usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); |
5571 |
|
5572 |
switch (USB_GET_STATE(xfer)) { |
5573 |
case USB_ST_TRANSFERRED: |
5574 |
|
5575 |
DPRINTF("actlen=%d bytes\n", actlen); |
5576 |
|
5577 |
pos = 0; |
5578 |
pc = usbd_xfer_get_frame(xfer, 0); |
5579 |
|
5580 |
while (actlen >= 4) { |
5581 |
|
5582 |
/* copy out the MIDI data */ |
5583 |
usbd_copy_out(pc, pos, buf, 4); |
5584 |
/* command length */ |
5585 |
cmd_len = umidi_cmd_to_len[buf[0] & 0xF]; |
5586 |
/* cable number */ |
5587 |
cn = buf[0] >> 4; |
5588 |
/* |
5589 |
* Lookup sub-channel. The index is range |
5590 |
* checked below. |
5591 |
*/ |
5592 |
sub = &chan->sub[cn]; |
5593 |
|
5594 |
if ((cmd_len != 0) && (cn < chan->max_emb_jack) && |
5595 |
(sub->read_open != 0)) { |
5596 |
|
5597 |
/* Send data to the application */ |
5598 |
usb_fifo_put_data_linear( |
5599 |
sub->fifo.fp[USB_FIFO_RX], |
5600 |
buf + 1, cmd_len, 1); |
5601 |
} |
5602 |
actlen -= 4; |
5603 |
pos += 4; |
5604 |
} |
5605 |
|
5606 |
case USB_ST_SETUP: |
5607 |
DPRINTF("start\n"); |
5608 |
tr_setup: |
5609 |
usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); |
5610 |
usbd_transfer_submit(xfer); |
5611 |
break; |
5612 |
|
5613 |
default: |
5614 |
DPRINTF("error=%s\n", usbd_errstr(error)); |
5615 |
|
5616 |
if (error != USB_ERR_CANCELLED) { |
5617 |
/* try to clear stall first */ |
5618 |
usbd_xfer_set_stall(xfer); |
5619 |
goto tr_setup; |
5620 |
} |
5621 |
break; |
5622 |
} |
5623 |
} |
5624 |
|
5625 |
/* |
5626 |
* The following statemachine, that converts MIDI commands to |
5627 |
* USB MIDI packets, derives from Linux's usbmidi.c, which |
5628 |
* was written by "Clemens Ladisch": |
5629 |
* |
5630 |
* Returns: |
5631 |
* 0: No command |
5632 |
* Else: Command is complete |
5633 |
*/ |
5634 |
static uint8_t |
5635 |
umidi_convert_to_usb(struct umidi_sub_chan *sub, uint8_t cn, uint8_t b) |
5636 |
{ |
5637 |
uint8_t p0 = (cn << 4); |
5638 |
|
5639 |
if (b >= 0xf8) { |
5640 |
sub->temp_0[0] = p0 | 0x0f; |
5641 |
sub->temp_0[1] = b; |
5642 |
sub->temp_0[2] = 0; |
5643 |
sub->temp_0[3] = 0; |
5644 |
sub->temp_cmd = sub->temp_0; |
5645 |
return (1); |
5646 |
|
5647 |
} else if (b >= 0xf0) { |
5648 |
switch (b) { |
5649 |
case 0xf0: /* system exclusive begin */ |
5650 |
sub->temp_1[1] = b; |
5651 |
sub->state = UMIDI_ST_SYSEX_1; |
5652 |
break; |
5653 |
case 0xf1: /* MIDI time code */ |
5654 |
case 0xf3: /* song select */ |
5655 |
sub->temp_1[1] = b; |
5656 |
sub->state = UMIDI_ST_1PARAM; |
5657 |
break; |
5658 |
case 0xf2: /* song position pointer */ |
5659 |
sub->temp_1[1] = b; |
5660 |
sub->state = UMIDI_ST_2PARAM_1; |
5661 |
break; |
5662 |
case 0xf4: /* unknown */ |
5663 |
case 0xf5: /* unknown */ |
5664 |
sub->state = UMIDI_ST_UNKNOWN; |
5665 |
break; |
5666 |
case 0xf6: /* tune request */ |
5667 |
sub->temp_1[0] = p0 | 0x05; |
5668 |
sub->temp_1[1] = 0xf6; |
5669 |
sub->temp_1[2] = 0; |
5670 |
sub->temp_1[3] = 0; |
5671 |
sub->temp_cmd = sub->temp_1; |
5672 |
sub->state = UMIDI_ST_UNKNOWN; |
5673 |
return (1); |
5674 |
|
5675 |
case 0xf7: /* system exclusive end */ |
5676 |
switch (sub->state) { |
5677 |
case UMIDI_ST_SYSEX_0: |
5678 |
sub->temp_1[0] = p0 | 0x05; |
5679 |
sub->temp_1[1] = 0xf7; |
5680 |
sub->temp_1[2] = 0; |
5681 |
sub->temp_1[3] = 0; |
5682 |
sub->temp_cmd = sub->temp_1; |
5683 |
sub->state = UMIDI_ST_UNKNOWN; |
5684 |
return (1); |
5685 |
case UMIDI_ST_SYSEX_1: |
5686 |
sub->temp_1[0] = p0 | 0x06; |
5687 |
sub->temp_1[2] = 0xf7; |
5688 |
sub->temp_1[3] = 0; |
5689 |
sub->temp_cmd = sub->temp_1; |
5690 |
sub->state = UMIDI_ST_UNKNOWN; |
5691 |
return (1); |
5692 |
case UMIDI_ST_SYSEX_2: |
5693 |
sub->temp_1[0] = p0 | 0x07; |
5694 |
sub->temp_1[3] = 0xf7; |
5695 |
sub->temp_cmd = sub->temp_1; |
5696 |
sub->state = UMIDI_ST_UNKNOWN; |
5697 |
return (1); |
5698 |
} |
5699 |
sub->state = UMIDI_ST_UNKNOWN; |
5700 |
break; |
5701 |
} |
5702 |
} else if (b >= 0x80) { |
5703 |
sub->temp_1[1] = b; |
5704 |
if ((b >= 0xc0) && (b <= 0xdf)) { |
5705 |
sub->state = UMIDI_ST_1PARAM; |
5706 |
} else { |
5707 |
sub->state = UMIDI_ST_2PARAM_1; |
5708 |
} |
5709 |
} else { /* b < 0x80 */ |
5710 |
switch (sub->state) { |
5711 |
case UMIDI_ST_1PARAM: |
5712 |
if (sub->temp_1[1] < 0xf0) { |
5713 |
p0 |= sub->temp_1[1] >> 4; |
5714 |
} else { |
5715 |
p0 |= 0x02; |
5716 |
sub->state = UMIDI_ST_UNKNOWN; |
5717 |
} |
5718 |
sub->temp_1[0] = p0; |
5719 |
sub->temp_1[2] = b; |
5720 |
sub->temp_1[3] = 0; |
5721 |
sub->temp_cmd = sub->temp_1; |
5722 |
return (1); |
5723 |
case UMIDI_ST_2PARAM_1: |
5724 |
sub->temp_1[2] = b; |
5725 |
sub->state = UMIDI_ST_2PARAM_2; |
5726 |
break; |
5727 |
case UMIDI_ST_2PARAM_2: |
5728 |
if (sub->temp_1[1] < 0xf0) { |
5729 |
p0 |= sub->temp_1[1] >> 4; |
5730 |
sub->state = UMIDI_ST_2PARAM_1; |
5731 |
} else { |
5732 |
p0 |= 0x03; |
5733 |
sub->state = UMIDI_ST_UNKNOWN; |
5734 |
} |
5735 |
sub->temp_1[0] = p0; |
5736 |
sub->temp_1[3] = b; |
5737 |
sub->temp_cmd = sub->temp_1; |
5738 |
return (1); |
5739 |
case UMIDI_ST_SYSEX_0: |
5740 |
sub->temp_1[1] = b; |
5741 |
sub->state = UMIDI_ST_SYSEX_1; |
5742 |
break; |
5743 |
case UMIDI_ST_SYSEX_1: |
5744 |
sub->temp_1[2] = b; |
5745 |
sub->state = UMIDI_ST_SYSEX_2; |
5746 |
break; |
5747 |
case UMIDI_ST_SYSEX_2: |
5748 |
sub->temp_1[0] = p0 | 0x04; |
5749 |
sub->temp_1[3] = b; |
5750 |
sub->temp_cmd = sub->temp_1; |
5751 |
sub->state = UMIDI_ST_SYSEX_0; |
5752 |
return (1); |
5753 |
default: |
5754 |
break; |
5755 |
} |
5756 |
} |
5757 |
return (0); |
5758 |
} |
5759 |
|
5760 |
static void |
5761 |
umidi_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) |
5762 |
{ |
5763 |
struct umidi_chan *chan = usbd_xfer_softc(xfer); |
5764 |
struct umidi_sub_chan *sub; |
5765 |
struct usb_page_cache *pc; |
5766 |
uint32_t actlen; |
5767 |
uint16_t nframes; |
5768 |
uint8_t buf; |
5769 |
uint8_t start_cable; |
5770 |
uint8_t tr_any; |
5771 |
int len; |
5772 |
|
5773 |
usbd_xfer_status(xfer, &len, NULL, NULL, NULL); |
5774 |
|
5775 |
/* |
5776 |
* NOTE: Some MIDI devices only accept 4 bytes of data per |
5777 |
* short terminated USB transfer. |
5778 |
*/ |
5779 |
switch (USB_GET_STATE(xfer)) { |
5780 |
case USB_ST_TRANSFERRED: |
5781 |
DPRINTF("actlen=%d bytes\n", len); |
5782 |
|
5783 |
case USB_ST_SETUP: |
5784 |
tr_setup: |
5785 |
DPRINTF("start\n"); |
5786 |
|
5787 |
nframes = 0; /* reset */ |
5788 |
start_cable = chan->curr_cable; |
5789 |
tr_any = 0; |
5790 |
pc = usbd_xfer_get_frame(xfer, 0); |
5791 |
|
5792 |
while (1) { |
5793 |
|
5794 |
/* round robin de-queueing */ |
5795 |
|
5796 |
sub = &chan->sub[chan->curr_cable]; |
5797 |
|
5798 |
if (sub->write_open) { |
5799 |
usb_fifo_get_data_linear(sub->fifo.fp[USB_FIFO_TX], |
5800 |
&buf, 1, &actlen, 0); |
5801 |
} else { |
5802 |
actlen = 0; |
5803 |
} |
5804 |
|
5805 |
if (actlen) { |
5806 |
|
5807 |
tr_any = 1; |
5808 |
|
5809 |
DPRINTF("byte=0x%02x from FIFO %u\n", buf, |
5810 |
(unsigned int)chan->curr_cable); |
5811 |
|
5812 |
if (umidi_convert_to_usb(sub, chan->curr_cable, buf)) { |
5813 |
|
5814 |
DPRINTF("sub=0x%02x 0x%02x 0x%02x 0x%02x\n", |
5815 |
sub->temp_cmd[0], sub->temp_cmd[1], |
5816 |
sub->temp_cmd[2], sub->temp_cmd[3]); |
5817 |
|
5818 |
usbd_copy_in(pc, nframes * 4, sub->temp_cmd, 4); |
5819 |
|
5820 |
nframes++; |
5821 |
|
5822 |
if ((nframes >= UMIDI_TX_FRAMES) || (chan->single_command != 0)) |
5823 |
break; |
5824 |
} else { |
5825 |
continue; |
5826 |
} |
5827 |
} |
5828 |
|
5829 |
chan->curr_cable++; |
5830 |
if (chan->curr_cable >= chan->max_emb_jack) |
5831 |
chan->curr_cable = 0; |
5832 |
|
5833 |
if (chan->curr_cable == start_cable) { |
5834 |
if (tr_any == 0) |
5835 |
break; |
5836 |
tr_any = 0; |
5837 |
} |
5838 |
} |
5839 |
|
5840 |
if (nframes != 0) { |
5841 |
DPRINTF("Transferring %d frames\n", (int)nframes); |
5842 |
usbd_xfer_set_frame_len(xfer, 0, 4 * nframes); |
5843 |
usbd_transfer_submit(xfer); |
5844 |
} |
5845 |
break; |
5846 |
|
5847 |
default: /* Error */ |
5848 |
|
5849 |
DPRINTF("error=%s\n", usbd_errstr(error)); |
5850 |
|
5851 |
if (error != USB_ERR_CANCELLED) { |
5852 |
/* try to clear stall first */ |
5853 |
usbd_xfer_set_stall(xfer); |
5854 |
goto tr_setup; |
5855 |
} |
5856 |
break; |
5857 |
} |
5858 |
} |
5859 |
|
5860 |
static struct umidi_sub_chan * |
5861 |
umidi_sub_by_fifo(struct usb_fifo *fifo) |
5862 |
{ |
5863 |
struct umidi_chan *chan = usb_fifo_softc(fifo); |
5864 |
struct umidi_sub_chan *sub; |
5865 |
uint32_t n; |
5866 |
|
5867 |
for (n = 0; n < UMIDI_EMB_JACK_MAX; n++) { |
5868 |
sub = &chan->sub[n]; |
5869 |
if ((sub->fifo.fp[USB_FIFO_RX] == fifo) || |
5870 |
(sub->fifo.fp[USB_FIFO_TX] == fifo)) { |
5871 |
return (sub); |
5872 |
} |
5873 |
} |
5874 |
|
5875 |
panic("%s:%d cannot find usb_fifo!\n", |
5876 |
__FILE__, __LINE__); |
5877 |
|
5878 |
return (NULL); |
5879 |
} |
5880 |
|
5881 |
static void |
5882 |
umidi_start_read(struct usb_fifo *fifo) |
5883 |
{ |
5884 |
struct umidi_chan *chan = usb_fifo_softc(fifo); |
5885 |
|
5886 |
usbd_transfer_start(chan->xfer[UMIDI_RX_TRANSFER]); |
5887 |
} |
5888 |
|
5889 |
static void |
5890 |
umidi_stop_read(struct usb_fifo *fifo) |
5891 |
{ |
5892 |
struct umidi_chan *chan = usb_fifo_softc(fifo); |
5893 |
struct umidi_sub_chan *sub = umidi_sub_by_fifo(fifo); |
5894 |
|
5895 |
DPRINTF("\n"); |
5896 |
|
5897 |
sub->read_open = 0; |
5898 |
|
5899 |
if (--(chan->read_open_refcount) == 0) { |
5900 |
/* |
5901 |
* XXX don't stop the read transfer here, hence that causes |
5902 |
* problems with some MIDI adapters |
5903 |
*/ |
5904 |
DPRINTF("(stopping read transfer)\n"); |
5905 |
} |
5906 |
} |
5907 |
|
5908 |
static void |
5909 |
umidi_start_write(struct usb_fifo *fifo) |
5910 |
{ |
5911 |
struct umidi_chan *chan = usb_fifo_softc(fifo); |
5912 |
|
5913 |
if (chan->xfer[UMIDI_TX_TRANSFER] == NULL) { |
5914 |
uint8_t buf[1]; |
5915 |
int actlen; |
5916 |
do { |
5917 |
/* dump data */ |
5918 |
usb_fifo_get_data_linear(fifo, buf, 1, &actlen, 0); |
5919 |
} while (actlen > 0); |
5920 |
} else { |
5921 |
usbd_transfer_start(chan->xfer[UMIDI_TX_TRANSFER]); |
5922 |
} |
5923 |
} |
5924 |
|
5925 |
static void |
5926 |
umidi_stop_write(struct usb_fifo *fifo) |
5927 |
{ |
5928 |
struct umidi_chan *chan = usb_fifo_softc(fifo); |
5929 |
struct umidi_sub_chan *sub = umidi_sub_by_fifo(fifo); |
5930 |
|
5931 |
DPRINTF("\n"); |
5932 |
|
5933 |
sub->write_open = 0; |
5934 |
|
5935 |
if (--(chan->write_open_refcount) == 0) { |
5936 |
DPRINTF("(stopping write transfer)\n"); |
5937 |
usbd_transfer_stop(chan->xfer[UMIDI_TX_TRANSFER]); |
5938 |
} |
5939 |
} |
5940 |
|
5941 |
static int |
5942 |
umidi_open(struct usb_fifo *fifo, int fflags) |
5943 |
{ |
5944 |
struct umidi_chan *chan = usb_fifo_softc(fifo); |
5945 |
struct umidi_sub_chan *sub = umidi_sub_by_fifo(fifo); |
5946 |
|
5947 |
if (fflags & FREAD) { |
5948 |
if (usb_fifo_alloc_buffer(fifo, 4, (1024 / 4))) { |
5949 |
return (ENOMEM); |
5950 |
} |
5951 |
mtx_lock(&chan->mtx); |
5952 |
chan->read_open_refcount++; |
5953 |
sub->read_open = 1; |
5954 |
mtx_unlock(&chan->mtx); |
5955 |
} |
5956 |
if (fflags & FWRITE) { |
5957 |
if (usb_fifo_alloc_buffer(fifo, 32, (1024 / 32))) { |
5958 |
return (ENOMEM); |
5959 |
} |
5960 |
/* clear stall first */ |
5961 |
mtx_lock(&chan->mtx); |
5962 |
chan->write_open_refcount++; |
5963 |
sub->write_open = 1; |
5964 |
|
5965 |
/* reset */ |
5966 |
sub->state = UMIDI_ST_UNKNOWN; |
5967 |
mtx_unlock(&chan->mtx); |
5968 |
} |
5969 |
return (0); /* success */ |
5970 |
} |
5971 |
|
5972 |
static void |
5973 |
umidi_close(struct usb_fifo *fifo, int fflags) |
5974 |
{ |
5975 |
if (fflags & FREAD) { |
5976 |
usb_fifo_free_buffer(fifo); |
5977 |
} |
5978 |
if (fflags & FWRITE) { |
5979 |
usb_fifo_free_buffer(fifo); |
5980 |
} |
5981 |
} |
5982 |
|
5983 |
|
5984 |
static int |
5985 |
umidi_ioctl(struct usb_fifo *fifo, u_long cmd, void *data, |
5986 |
int fflags) |
5987 |
{ |
5988 |
return (ENODEV); |
5989 |
} |
5990 |
|
5991 |
static void |
5992 |
umidi_init(device_t dev) |
5993 |
{ |
5994 |
struct uaudio_softc *sc = device_get_softc(dev); |
5995 |
struct umidi_chan *chan = &sc->sc_midi_chan; |
5996 |
|
5997 |
mtx_init(&chan->mtx, "umidi lock", NULL, MTX_DEF | MTX_RECURSE); |
5998 |
} |
5999 |
|
6000 |
static struct usb_fifo_methods umidi_fifo_methods = { |
6001 |
.f_start_read = &umidi_start_read, |
6002 |
.f_start_write = &umidi_start_write, |
6003 |
.f_stop_read = &umidi_stop_read, |
6004 |
.f_stop_write = &umidi_stop_write, |
6005 |
.f_open = &umidi_open, |
6006 |
.f_close = &umidi_close, |
6007 |
.f_ioctl = &umidi_ioctl, |
6008 |
.basename[0] = "umidi", |
6009 |
}; |
6010 |
|
6011 |
static int |
6012 |
umidi_probe(device_t dev) |
6013 |
{ |
6014 |
struct uaudio_softc *sc = device_get_softc(dev); |
6015 |
struct usb_attach_arg *uaa = device_get_ivars(dev); |
6016 |
struct umidi_chan *chan = &sc->sc_midi_chan; |
6017 |
struct umidi_sub_chan *sub; |
6018 |
int unit = device_get_unit(dev); |
6019 |
int error; |
6020 |
uint32_t n; |
6021 |
|
6022 |
if (usb_test_quirk(uaa, UQ_SINGLE_CMD_MIDI)) |
6023 |
chan->single_command = 1; |
6024 |
|
6025 |
if (usbd_set_alt_interface_index(sc->sc_udev, chan->iface_index, |
6026 |
chan->iface_alt_index)) { |
6027 |
DPRINTF("setting of alternate index failed!\n"); |
6028 |
goto detach; |
6029 |
} |
6030 |
usbd_set_parent_iface(sc->sc_udev, chan->iface_index, |
6031 |
sc->sc_mixer_iface_index); |
6032 |
|
6033 |
error = usbd_transfer_setup(uaa->device, &chan->iface_index, |
6034 |
chan->xfer, umidi_config, UMIDI_N_TRANSFER, |
6035 |
chan, &chan->mtx); |
6036 |
if (error) { |
6037 |
DPRINTF("error=%s\n", usbd_errstr(error)); |
6038 |
goto detach; |
6039 |
} |
6040 |
if (chan->xfer[UMIDI_TX_TRANSFER] == NULL && |
6041 |
chan->xfer[UMIDI_RX_TRANSFER] == NULL) { |
6042 |
DPRINTF("no BULK or INTERRUPT MIDI endpoint(s) found\n"); |
6043 |
goto detach; |
6044 |
} |
6045 |
|
6046 |
/* |
6047 |
* Some USB MIDI device makers couldn't resist using |
6048 |
* wMaxPacketSize = 4 for RX and TX BULK endpoints, although |
6049 |
* that size is an unsupported value for FULL speed BULK |
6050 |
* endpoints. The same applies to some HIGH speed MIDI devices |
6051 |
* which are using a wMaxPacketSize different from 512 bytes. |
6052 |
* |
6053 |
* Refer to section 5.8.3 in USB 2.0 PDF: Cite: "All Host |
6054 |
* Controllers are required to have support for 8-, 16-, 32-, |
6055 |
* and 64-byte maximum packet sizes for full-speed bulk |
6056 |
* endpoints and 512 bytes for high-speed bulk endpoints." |
6057 |
*/ |
6058 |
if (chan->xfer[UMIDI_TX_TRANSFER] != NULL && |
6059 |
usbd_xfer_maxp_was_clamped(chan->xfer[UMIDI_TX_TRANSFER])) |
6060 |
chan->single_command = 1; |
6061 |
|
6062 |
if (chan->single_command != 0) |
6063 |
device_printf(dev, "Single command MIDI quirk enabled\n"); |
6064 |
|
6065 |
if ((chan->max_emb_jack == 0) || |
6066 |
(chan->max_emb_jack > UMIDI_EMB_JACK_MAX)) { |
6067 |
chan->max_emb_jack = UMIDI_EMB_JACK_MAX; |
6068 |
} |
6069 |
|
6070 |
for (n = 0; n < chan->max_emb_jack; n++) { |
6071 |
|
6072 |
sub = &chan->sub[n]; |
6073 |
|
6074 |
error = usb_fifo_attach(sc->sc_udev, chan, &chan->mtx, |
6075 |
&umidi_fifo_methods, &sub->fifo, unit, n, |
6076 |
chan->iface_index, |
6077 |
UID_ROOT, GID_OPERATOR, 0644); |
6078 |
if (error) { |
6079 |
goto detach; |
6080 |
} |
6081 |
} |
6082 |
|
6083 |
mtx_lock(&chan->mtx); |
6084 |
|
6085 |
/* |
6086 |
* NOTE: At least one device will not work properly unless the |
6087 |
* BULK IN pipe is open all the time. This might have to do |
6088 |
* about that the internal queues of the device overflow if we |
6089 |
* don't read them regularly. |
6090 |
*/ |
6091 |
usbd_transfer_start(chan->xfer[UMIDI_RX_TRANSFER]); |
6092 |
|
6093 |
mtx_unlock(&chan->mtx); |
6094 |
|
6095 |
return (0); /* success */ |
6096 |
|
6097 |
detach: |
6098 |
return (ENXIO); /* failure */ |
6099 |
} |
6100 |
|
6101 |
static int |
6102 |
umidi_detach(device_t dev) |
6103 |
{ |
6104 |
struct uaudio_softc *sc = device_get_softc(dev); |
6105 |
struct umidi_chan *chan = &sc->sc_midi_chan; |
6106 |
uint32_t n; |
6107 |
|
6108 |
for (n = 0; n < UMIDI_EMB_JACK_MAX; n++) |
6109 |
usb_fifo_detach(&chan->sub[n].fifo); |
6110 |
|
6111 |
mtx_lock(&chan->mtx); |
6112 |
|
6113 |
usbd_transfer_stop(chan->xfer[UMIDI_RX_TRANSFER]); |
6114 |
|
6115 |
mtx_unlock(&chan->mtx); |
6116 |
|
6117 |
usbd_transfer_unsetup(chan->xfer, UMIDI_N_TRANSFER); |
6118 |
|
6119 |
mtx_destroy(&chan->mtx); |
6120 |
|
6121 |
return (0); |
6122 |
} |
6123 |
|
6124 |
static void |
6125 |
uaudio_hid_rx_callback(struct usb_xfer *xfer, usb_error_t error) |
6126 |
{ |
6127 |
struct uaudio_softc *sc = usbd_xfer_softc(xfer); |
6128 |
const uint8_t *buffer = usbd_xfer_get_frame_buffer(xfer, 0); |
6129 |
struct snd_mixer *m; |
6130 |
uint8_t id; |
6131 |
int actlen; |
6132 |
|
6133 |
usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); |
6134 |
|
6135 |
switch (USB_GET_STATE(xfer)) { |
6136 |
case USB_ST_TRANSFERRED: |
6137 |
DPRINTF("actlen=%d\n", actlen); |
6138 |
|
6139 |
if (actlen != 0 && |
6140 |
(sc->sc_hid.flags & UAUDIO_HID_HAS_ID)) { |
6141 |
id = *buffer; |
6142 |
buffer++; |
6143 |
actlen--; |
6144 |
} else { |
6145 |
id = 0; |
6146 |
} |
6147 |
|
6148 |
m = sc->sc_mixer_dev; |
6149 |
|
6150 |
if ((sc->sc_hid.flags & UAUDIO_HID_HAS_MUTE) && |
6151 |
(sc->sc_hid.mute_id == id) && |
6152 |
hid_get_data(buffer, actlen, |
6153 |
&sc->sc_hid.mute_loc)) { |
6154 |
|
6155 |
DPRINTF("Mute toggle\n"); |
6156 |
|
6157 |
mixer_hwvol_mute_locked(m); |
6158 |
} |
6159 |
|
6160 |
if ((sc->sc_hid.flags & UAUDIO_HID_HAS_VOLUME_UP) && |
6161 |
(sc->sc_hid.volume_up_id == id) && |
6162 |
hid_get_data(buffer, actlen, |
6163 |
&sc->sc_hid.volume_up_loc)) { |
6164 |
|
6165 |
DPRINTF("Volume Up\n"); |
6166 |
|
6167 |
mixer_hwvol_step_locked(m, 1, 1); |
6168 |
} |
6169 |
|
6170 |
if ((sc->sc_hid.flags & UAUDIO_HID_HAS_VOLUME_DOWN) && |
6171 |
(sc->sc_hid.volume_down_id == id) && |
6172 |
hid_get_data(buffer, actlen, |
6173 |
&sc->sc_hid.volume_down_loc)) { |
6174 |
|
6175 |
DPRINTF("Volume Down\n"); |
6176 |
|
6177 |
mixer_hwvol_step_locked(m, -1, -1); |
6178 |
} |
6179 |
|
6180 |
case USB_ST_SETUP: |
6181 |
tr_setup: |
6182 |
/* check if we can put more data into the FIFO */ |
6183 |
usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); |
6184 |
usbd_transfer_submit(xfer); |
6185 |
break; |
6186 |
|
6187 |
default: /* Error */ |
6188 |
|
6189 |
DPRINTF("error=%s\n", usbd_errstr(error)); |
6190 |
|
6191 |
if (error != USB_ERR_CANCELLED) { |
6192 |
/* try to clear stall first */ |
6193 |
usbd_xfer_set_stall(xfer); |
6194 |
goto tr_setup; |
6195 |
} |
6196 |
break; |
6197 |
} |
6198 |
} |
6199 |
|
6200 |
static int |
6201 |
uaudio_hid_probe(struct uaudio_softc *sc, |
6202 |
struct usb_attach_arg *uaa) |
6203 |
{ |
6204 |
void *d_ptr; |
6205 |
uint32_t flags; |
6206 |
uint16_t d_len; |
6207 |
uint8_t id; |
6208 |
int error; |
6209 |
|
6210 |
if (!(sc->sc_hid.flags & UAUDIO_HID_VALID)) |
6211 |
return (-1); |
6212 |
|
6213 |
if (sc->sc_mixer_lock == NULL) |
6214 |
return (-1); |
6215 |
|
6216 |
/* Get HID descriptor */ |
6217 |
error = usbd_req_get_hid_desc(uaa->device, NULL, &d_ptr, |
6218 |
&d_len, M_TEMP, sc->sc_hid.iface_index); |
6219 |
|
6220 |
if (error) { |
6221 |
DPRINTF("error reading report description\n"); |
6222 |
return (-1); |
6223 |
} |
6224 |
|
6225 |
/* check if there is an ID byte */ |
6226 |
hid_report_size(d_ptr, d_len, hid_input, &id); |
6227 |
|
6228 |
if (id != 0) |
6229 |
sc->sc_hid.flags |= UAUDIO_HID_HAS_ID; |
6230 |
|
6231 |
if (hid_locate(d_ptr, d_len, |
6232 |
HID_USAGE2(HUP_CONSUMER, 0xE9 /* Volume Increment */), |
6233 |
hid_input, 0, &sc->sc_hid.volume_up_loc, &flags, |
6234 |
&sc->sc_hid.volume_up_id)) { |
6235 |
if (flags & HIO_VARIABLE) |
6236 |
sc->sc_hid.flags |= UAUDIO_HID_HAS_VOLUME_UP; |
6237 |
DPRINTFN(1, "Found Volume Up key\n"); |
6238 |
} |
6239 |
|
6240 |
if (hid_locate(d_ptr, d_len, |
6241 |
HID_USAGE2(HUP_CONSUMER, 0xEA /* Volume Decrement */), |
6242 |
hid_input, 0, &sc->sc_hid.volume_down_loc, &flags, |
6243 |
&sc->sc_hid.volume_down_id)) { |
6244 |
if (flags & HIO_VARIABLE) |
6245 |
sc->sc_hid.flags |= UAUDIO_HID_HAS_VOLUME_DOWN; |
6246 |
DPRINTFN(1, "Found Volume Down key\n"); |
6247 |
} |
6248 |
|
6249 |
if (hid_locate(d_ptr, d_len, |
6250 |
HID_USAGE2(HUP_CONSUMER, 0xE2 /* Mute */), |
6251 |
hid_input, 0, &sc->sc_hid.mute_loc, &flags, |
6252 |
&sc->sc_hid.mute_id)) { |
6253 |
if (flags & HIO_VARIABLE) |
6254 |
sc->sc_hid.flags |= UAUDIO_HID_HAS_MUTE; |
6255 |
DPRINTFN(1, "Found Mute key\n"); |
6256 |
} |
6257 |
|
6258 |
free(d_ptr, M_TEMP); |
6259 |
|
6260 |
if (!(sc->sc_hid.flags & (UAUDIO_HID_HAS_VOLUME_UP | |
6261 |
UAUDIO_HID_HAS_VOLUME_DOWN | |
6262 |
UAUDIO_HID_HAS_MUTE))) { |
6263 |
DPRINTFN(1, "Did not find any volume related keys\n"); |
6264 |
return (-1); |
6265 |
} |
6266 |
|
6267 |
/* prevent the uhid driver from attaching */ |
6268 |
usbd_set_parent_iface(uaa->device, sc->sc_hid.iface_index, |
6269 |
sc->sc_mixer_iface_index); |
6270 |
|
6271 |
/* allocate USB transfers */ |
6272 |
error = usbd_transfer_setup(uaa->device, &sc->sc_hid.iface_index, |
6273 |
sc->sc_hid.xfer, uaudio_hid_config, UAUDIO_HID_N_TRANSFER, |
6274 |
sc, sc->sc_mixer_lock); |
6275 |
if (error) { |
6276 |
DPRINTF("error=%s\n", usbd_errstr(error)); |
6277 |
return (-1); |
6278 |
} |
6279 |
return (0); |
6280 |
} |
6281 |
|
6282 |
static void |
6283 |
uaudio_hid_detach(struct uaudio_softc *sc) |
6284 |
{ |
6285 |
usbd_transfer_unsetup(sc->sc_hid.xfer, UAUDIO_HID_N_TRANSFER); |
6286 |
} |
6287 |
|
6288 |
DRIVER_MODULE_ORDERED(uaudio, uhub, uaudio_driver, uaudio_devclass, NULL, 0, SI_ORDER_ANY); |
6289 |
MODULE_DEPEND(uaudio, usb, 1, 1, 1); |
6290 |
MODULE_DEPEND(uaudio, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); |
6291 |
MODULE_VERSION(uaudio, 1); |