Root/
1 | /* |
2 | * This program is free software; you can redistribute it and/or modify |
3 | * it under the terms of the GNU General Public License as published by |
4 | * the Free Software Foundation; either version 2 of the License, or |
5 | * (at your option) any later version. |
6 | * |
7 | * This program is distributed in the hope that it will be useful, |
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | * GNU General Public License for more details. |
11 | * |
12 | * You should have received a copy of the GNU General Public License |
13 | * along with this program; if not, write to the Free Software |
14 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
15 | */ |
16 | |
17 | |
18 | #include <linux/init.h> |
19 | #include <linux/slab.h> |
20 | #include <linux/usb.h> |
21 | #include <linux/usb/audio.h> |
22 | #include <linux/usb/audio-v2.h> |
23 | |
24 | #include <sound/core.h> |
25 | #include <sound/pcm.h> |
26 | #include <sound/control.h> |
27 | #include <sound/tlv.h> |
28 | |
29 | #include "usbaudio.h" |
30 | #include "card.h" |
31 | #include "proc.h" |
32 | #include "quirks.h" |
33 | #include "endpoint.h" |
34 | #include "pcm.h" |
35 | #include "helper.h" |
36 | #include "format.h" |
37 | #include "clock.h" |
38 | #include "stream.h" |
39 | |
40 | /* |
41 | * free a substream |
42 | */ |
43 | static void free_substream(struct snd_usb_substream *subs) |
44 | { |
45 | struct list_head *p, *n; |
46 | |
47 | if (!subs->num_formats) |
48 | return; /* not initialized */ |
49 | list_for_each_safe(p, n, &subs->fmt_list) { |
50 | struct audioformat *fp = list_entry(p, struct audioformat, list); |
51 | kfree(fp->rate_table); |
52 | kfree(fp->chmap); |
53 | kfree(fp); |
54 | } |
55 | kfree(subs->rate_list.list); |
56 | } |
57 | |
58 | |
59 | /* |
60 | * free a usb stream instance |
61 | */ |
62 | static void snd_usb_audio_stream_free(struct snd_usb_stream *stream) |
63 | { |
64 | free_substream(&stream->substream[0]); |
65 | free_substream(&stream->substream[1]); |
66 | list_del(&stream->list); |
67 | kfree(stream); |
68 | } |
69 | |
70 | static void snd_usb_audio_pcm_free(struct snd_pcm *pcm) |
71 | { |
72 | struct snd_usb_stream *stream = pcm->private_data; |
73 | if (stream) { |
74 | stream->pcm = NULL; |
75 | snd_usb_audio_stream_free(stream); |
76 | } |
77 | } |
78 | |
79 | /* |
80 | * initialize the substream instance. |
81 | */ |
82 | |
83 | static void snd_usb_init_substream(struct snd_usb_stream *as, |
84 | int stream, |
85 | struct audioformat *fp) |
86 | { |
87 | struct snd_usb_substream *subs = &as->substream[stream]; |
88 | |
89 | INIT_LIST_HEAD(&subs->fmt_list); |
90 | spin_lock_init(&subs->lock); |
91 | |
92 | subs->stream = as; |
93 | subs->direction = stream; |
94 | subs->dev = as->chip->dev; |
95 | subs->txfr_quirk = as->chip->txfr_quirk; |
96 | subs->speed = snd_usb_get_speed(subs->dev); |
97 | |
98 | snd_usb_set_pcm_ops(as->pcm, stream); |
99 | |
100 | list_add_tail(&fp->list, &subs->fmt_list); |
101 | subs->formats |= fp->formats; |
102 | subs->num_formats++; |
103 | subs->fmt_type = fp->fmt_type; |
104 | subs->ep_num = fp->endpoint; |
105 | if (fp->channels > subs->channels_max) |
106 | subs->channels_max = fp->channels; |
107 | } |
108 | |
109 | /* kctl callbacks for usb-audio channel maps */ |
110 | static int usb_chmap_ctl_info(struct snd_kcontrol *kcontrol, |
111 | struct snd_ctl_elem_info *uinfo) |
112 | { |
113 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); |
114 | struct snd_usb_substream *subs = info->private_data; |
115 | |
116 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
117 | uinfo->count = subs->channels_max; |
118 | uinfo->value.integer.min = 0; |
119 | uinfo->value.integer.max = SNDRV_CHMAP_LAST; |
120 | return 0; |
121 | } |
122 | |
123 | /* check whether a duplicated entry exists in the audiofmt list */ |
124 | static bool have_dup_chmap(struct snd_usb_substream *subs, |
125 | struct audioformat *fp) |
126 | { |
127 | struct list_head *p; |
128 | |
129 | for (p = fp->list.prev; p != &subs->fmt_list; p = p->prev) { |
130 | struct audioformat *prev; |
131 | prev = list_entry(p, struct audioformat, list); |
132 | if (prev->chmap && |
133 | !memcmp(prev->chmap, fp->chmap, sizeof(*fp->chmap))) |
134 | return true; |
135 | } |
136 | return false; |
137 | } |
138 | |
139 | static int usb_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag, |
140 | unsigned int size, unsigned int __user *tlv) |
141 | { |
142 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); |
143 | struct snd_usb_substream *subs = info->private_data; |
144 | struct audioformat *fp; |
145 | unsigned int __user *dst; |
146 | int count = 0; |
147 | |
148 | if (size < 8) |
149 | return -ENOMEM; |
150 | if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv)) |
151 | return -EFAULT; |
152 | size -= 8; |
153 | dst = tlv + 2; |
154 | list_for_each_entry(fp, &subs->fmt_list, list) { |
155 | int i, ch_bytes; |
156 | |
157 | if (!fp->chmap) |
158 | continue; |
159 | if (have_dup_chmap(subs, fp)) |
160 | continue; |
161 | /* copy the entry */ |
162 | ch_bytes = fp->chmap->channels * 4; |
163 | if (size < 8 + ch_bytes) |
164 | return -ENOMEM; |
165 | if (put_user(SNDRV_CTL_TLVT_CHMAP_FIXED, dst) || |
166 | put_user(ch_bytes, dst + 1)) |
167 | return -EFAULT; |
168 | dst += 2; |
169 | for (i = 0; i < fp->chmap->channels; i++, dst++) { |
170 | if (put_user(fp->chmap->map[i], dst)) |
171 | return -EFAULT; |
172 | } |
173 | |
174 | count += 8 + ch_bytes; |
175 | size -= 8 + ch_bytes; |
176 | } |
177 | if (put_user(count, tlv + 1)) |
178 | return -EFAULT; |
179 | return 0; |
180 | } |
181 | |
182 | static int usb_chmap_ctl_get(struct snd_kcontrol *kcontrol, |
183 | struct snd_ctl_elem_value *ucontrol) |
184 | { |
185 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); |
186 | struct snd_usb_substream *subs = info->private_data; |
187 | struct snd_pcm_chmap_elem *chmap = NULL; |
188 | int i; |
189 | |
190 | memset(ucontrol->value.integer.value, 0, |
191 | sizeof(ucontrol->value.integer.value)); |
192 | if (subs->cur_audiofmt) |
193 | chmap = subs->cur_audiofmt->chmap; |
194 | if (chmap) { |
195 | for (i = 0; i < chmap->channels; i++) |
196 | ucontrol->value.integer.value[i] = chmap->map[i]; |
197 | } |
198 | return 0; |
199 | } |
200 | |
201 | /* create a chmap kctl assigned to the given USB substream */ |
202 | static int add_chmap(struct snd_pcm *pcm, int stream, |
203 | struct snd_usb_substream *subs) |
204 | { |
205 | struct audioformat *fp; |
206 | struct snd_pcm_chmap *chmap; |
207 | struct snd_kcontrol *kctl; |
208 | int err; |
209 | |
210 | list_for_each_entry(fp, &subs->fmt_list, list) |
211 | if (fp->chmap) |
212 | goto ok; |
213 | /* no chmap is found */ |
214 | return 0; |
215 | |
216 | ok: |
217 | err = snd_pcm_add_chmap_ctls(pcm, stream, NULL, 0, 0, &chmap); |
218 | if (err < 0) |
219 | return err; |
220 | |
221 | /* override handlers */ |
222 | chmap->private_data = subs; |
223 | kctl = chmap->kctl; |
224 | kctl->info = usb_chmap_ctl_info; |
225 | kctl->get = usb_chmap_ctl_get; |
226 | kctl->tlv.c = usb_chmap_ctl_tlv; |
227 | |
228 | return 0; |
229 | } |
230 | |
231 | /* convert from USB ChannelConfig bits to ALSA chmap element */ |
232 | static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits, |
233 | int protocol) |
234 | { |
235 | static unsigned int uac1_maps[] = { |
236 | SNDRV_CHMAP_FL, /* left front */ |
237 | SNDRV_CHMAP_FR, /* right front */ |
238 | SNDRV_CHMAP_FC, /* center front */ |
239 | SNDRV_CHMAP_LFE, /* LFE */ |
240 | SNDRV_CHMAP_SL, /* left surround */ |
241 | SNDRV_CHMAP_SR, /* right surround */ |
242 | SNDRV_CHMAP_FLC, /* left of center */ |
243 | SNDRV_CHMAP_FRC, /* right of center */ |
244 | SNDRV_CHMAP_RC, /* surround */ |
245 | SNDRV_CHMAP_SL, /* side left */ |
246 | SNDRV_CHMAP_SR, /* side right */ |
247 | SNDRV_CHMAP_TC, /* top */ |
248 | 0 /* terminator */ |
249 | }; |
250 | static unsigned int uac2_maps[] = { |
251 | SNDRV_CHMAP_FL, /* front left */ |
252 | SNDRV_CHMAP_FR, /* front right */ |
253 | SNDRV_CHMAP_FC, /* front center */ |
254 | SNDRV_CHMAP_LFE, /* LFE */ |
255 | SNDRV_CHMAP_RL, /* back left */ |
256 | SNDRV_CHMAP_RR, /* back right */ |
257 | SNDRV_CHMAP_FLC, /* front left of center */ |
258 | SNDRV_CHMAP_FRC, /* front right of center */ |
259 | SNDRV_CHMAP_RC, /* back center */ |
260 | SNDRV_CHMAP_SL, /* side left */ |
261 | SNDRV_CHMAP_SR, /* side right */ |
262 | SNDRV_CHMAP_TC, /* top center */ |
263 | SNDRV_CHMAP_TFL, /* top front left */ |
264 | SNDRV_CHMAP_TFC, /* top front center */ |
265 | SNDRV_CHMAP_TFR, /* top front right */ |
266 | SNDRV_CHMAP_TRL, /* top back left */ |
267 | SNDRV_CHMAP_TRC, /* top back center */ |
268 | SNDRV_CHMAP_TRR, /* top back right */ |
269 | SNDRV_CHMAP_TFLC, /* top front left of center */ |
270 | SNDRV_CHMAP_TFRC, /* top front right of center */ |
271 | SNDRV_CHMAP_LLFE, /* left LFE */ |
272 | SNDRV_CHMAP_RLFE, /* right LFE */ |
273 | SNDRV_CHMAP_TSL, /* top side left */ |
274 | SNDRV_CHMAP_TSR, /* top side right */ |
275 | SNDRV_CHMAP_BC, /* bottom center */ |
276 | SNDRV_CHMAP_BLC, /* bottom left center */ |
277 | SNDRV_CHMAP_BRC, /* bottom right center */ |
278 | 0 /* terminator */ |
279 | }; |
280 | struct snd_pcm_chmap_elem *chmap; |
281 | const unsigned int *maps; |
282 | int c; |
283 | |
284 | if (!bits) |
285 | return NULL; |
286 | if (channels > ARRAY_SIZE(chmap->map)) |
287 | return NULL; |
288 | |
289 | chmap = kzalloc(sizeof(*chmap), GFP_KERNEL); |
290 | if (!chmap) |
291 | return NULL; |
292 | |
293 | maps = protocol == UAC_VERSION_2 ? uac2_maps : uac1_maps; |
294 | chmap->channels = channels; |
295 | c = 0; |
296 | for (; bits && *maps; maps++, bits >>= 1) { |
297 | if (bits & 1) |
298 | chmap->map[c++] = *maps; |
299 | } |
300 | |
301 | for (; c < channels; c++) |
302 | chmap->map[c] = SNDRV_CHMAP_UNKNOWN; |
303 | |
304 | return chmap; |
305 | } |
306 | |
307 | /* |
308 | * add this endpoint to the chip instance. |
309 | * if a stream with the same endpoint already exists, append to it. |
310 | * if not, create a new pcm stream. |
311 | */ |
312 | int snd_usb_add_audio_stream(struct snd_usb_audio *chip, |
313 | int stream, |
314 | struct audioformat *fp) |
315 | { |
316 | struct list_head *p; |
317 | struct snd_usb_stream *as; |
318 | struct snd_usb_substream *subs; |
319 | struct snd_pcm *pcm; |
320 | int err; |
321 | |
322 | list_for_each(p, &chip->pcm_list) { |
323 | as = list_entry(p, struct snd_usb_stream, list); |
324 | if (as->fmt_type != fp->fmt_type) |
325 | continue; |
326 | subs = &as->substream[stream]; |
327 | if (subs->ep_num == fp->endpoint) { |
328 | list_add_tail(&fp->list, &subs->fmt_list); |
329 | subs->num_formats++; |
330 | subs->formats |= fp->formats; |
331 | return 0; |
332 | } |
333 | } |
334 | /* look for an empty stream */ |
335 | list_for_each(p, &chip->pcm_list) { |
336 | as = list_entry(p, struct snd_usb_stream, list); |
337 | if (as->fmt_type != fp->fmt_type) |
338 | continue; |
339 | subs = &as->substream[stream]; |
340 | if (subs->ep_num) |
341 | continue; |
342 | err = snd_pcm_new_stream(as->pcm, stream, 1); |
343 | if (err < 0) |
344 | return err; |
345 | snd_usb_init_substream(as, stream, fp); |
346 | return add_chmap(as->pcm, stream, subs); |
347 | } |
348 | |
349 | /* create a new pcm */ |
350 | as = kzalloc(sizeof(*as), GFP_KERNEL); |
351 | if (!as) |
352 | return -ENOMEM; |
353 | as->pcm_index = chip->pcm_devs; |
354 | as->chip = chip; |
355 | as->fmt_type = fp->fmt_type; |
356 | err = snd_pcm_new(chip->card, "USB Audio", chip->pcm_devs, |
357 | stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0, |
358 | stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1, |
359 | &pcm); |
360 | if (err < 0) { |
361 | kfree(as); |
362 | return err; |
363 | } |
364 | as->pcm = pcm; |
365 | pcm->private_data = as; |
366 | pcm->private_free = snd_usb_audio_pcm_free; |
367 | pcm->info_flags = 0; |
368 | if (chip->pcm_devs > 0) |
369 | sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs); |
370 | else |
371 | strcpy(pcm->name, "USB Audio"); |
372 | |
373 | snd_usb_init_substream(as, stream, fp); |
374 | |
375 | list_add(&as->list, &chip->pcm_list); |
376 | chip->pcm_devs++; |
377 | |
378 | snd_usb_proc_pcm_format_add(as); |
379 | |
380 | return add_chmap(pcm, stream, &as->substream[stream]); |
381 | } |
382 | |
383 | static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, |
384 | struct usb_host_interface *alts, |
385 | int protocol, int iface_no) |
386 | { |
387 | /* parsed with a v1 header here. that's ok as we only look at the |
388 | * header first which is the same for both versions */ |
389 | struct uac_iso_endpoint_descriptor *csep; |
390 | struct usb_interface_descriptor *altsd = get_iface_desc(alts); |
391 | int attributes = 0; |
392 | |
393 | csep = snd_usb_find_desc(alts->endpoint[0].extra, alts->endpoint[0].extralen, NULL, USB_DT_CS_ENDPOINT); |
394 | |
395 | /* Creamware Noah has this descriptor after the 2nd endpoint */ |
396 | if (!csep && altsd->bNumEndpoints >= 2) |
397 | csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT); |
398 | |
399 | if (!csep || csep->bLength < 7 || |
400 | csep->bDescriptorSubtype != UAC_EP_GENERAL) { |
401 | snd_printk(KERN_WARNING "%d:%u:%d : no or invalid" |
402 | " class specific endpoint descriptor\n", |
403 | chip->dev->devnum, iface_no, |
404 | altsd->bAlternateSetting); |
405 | return 0; |
406 | } |
407 | |
408 | if (protocol == UAC_VERSION_1) { |
409 | attributes = csep->bmAttributes; |
410 | } else { |
411 | struct uac2_iso_endpoint_descriptor *csep2 = |
412 | (struct uac2_iso_endpoint_descriptor *) csep; |
413 | |
414 | attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX; |
415 | |
416 | /* emulate the endpoint attributes of a v1 device */ |
417 | if (csep2->bmControls & UAC2_CONTROL_PITCH) |
418 | attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL; |
419 | } |
420 | |
421 | return attributes; |
422 | } |
423 | |
424 | /* find an input terminal descriptor (either UAC1 or UAC2) with the given |
425 | * terminal id |
426 | */ |
427 | static void * |
428 | snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface, |
429 | int terminal_id) |
430 | { |
431 | struct uac2_input_terminal_descriptor *term = NULL; |
432 | |
433 | while ((term = snd_usb_find_csint_desc(ctrl_iface->extra, |
434 | ctrl_iface->extralen, |
435 | term, UAC_INPUT_TERMINAL))) { |
436 | if (term->bTerminalID == terminal_id) |
437 | return term; |
438 | } |
439 | |
440 | return NULL; |
441 | } |
442 | |
443 | static struct uac2_output_terminal_descriptor * |
444 | snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface, |
445 | int terminal_id) |
446 | { |
447 | struct uac2_output_terminal_descriptor *term = NULL; |
448 | |
449 | while ((term = snd_usb_find_csint_desc(ctrl_iface->extra, |
450 | ctrl_iface->extralen, |
451 | term, UAC_OUTPUT_TERMINAL))) { |
452 | if (term->bTerminalID == terminal_id) |
453 | return term; |
454 | } |
455 | |
456 | return NULL; |
457 | } |
458 | |
459 | int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) |
460 | { |
461 | struct usb_device *dev; |
462 | struct usb_interface *iface; |
463 | struct usb_host_interface *alts; |
464 | struct usb_interface_descriptor *altsd; |
465 | int i, altno, err, stream; |
466 | int format = 0, num_channels = 0; |
467 | struct audioformat *fp = NULL; |
468 | int num, protocol, clock = 0; |
469 | struct uac_format_type_i_continuous_descriptor *fmt; |
470 | unsigned int chconfig; |
471 | |
472 | dev = chip->dev; |
473 | |
474 | /* parse the interface's altsettings */ |
475 | iface = usb_ifnum_to_if(dev, iface_no); |
476 | |
477 | num = iface->num_altsetting; |
478 | |
479 | /* |
480 | * Dallas DS4201 workaround: It presents 5 altsettings, but the last |
481 | * one misses syncpipe, and does not produce any sound. |
482 | */ |
483 | if (chip->usb_id == USB_ID(0x04fa, 0x4201)) |
484 | num = 4; |
485 | |
486 | for (i = 0; i < num; i++) { |
487 | alts = &iface->altsetting[i]; |
488 | altsd = get_iface_desc(alts); |
489 | protocol = altsd->bInterfaceProtocol; |
490 | /* skip invalid one */ |
491 | if ((altsd->bInterfaceClass != USB_CLASS_AUDIO && |
492 | altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) || |
493 | (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING && |
494 | altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC) || |
495 | altsd->bNumEndpoints < 1 || |
496 | le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0) |
497 | continue; |
498 | /* must be isochronous */ |
499 | if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != |
500 | USB_ENDPOINT_XFER_ISOC) |
501 | continue; |
502 | /* check direction */ |
503 | stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ? |
504 | SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; |
505 | altno = altsd->bAlternateSetting; |
506 | |
507 | if (snd_usb_apply_interface_quirk(chip, iface_no, altno)) |
508 | continue; |
509 | |
510 | chconfig = 0; |
511 | /* get audio formats */ |
512 | switch (protocol) { |
513 | default: |
514 | snd_printdd(KERN_WARNING "%d:%u:%d: unknown interface protocol %#02x, assuming v1\n", |
515 | dev->devnum, iface_no, altno, protocol); |
516 | protocol = UAC_VERSION_1; |
517 | /* fall through */ |
518 | |
519 | case UAC_VERSION_1: { |
520 | struct uac1_as_header_descriptor *as = |
521 | snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); |
522 | struct uac_input_terminal_descriptor *iterm; |
523 | |
524 | if (!as) { |
525 | snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n", |
526 | dev->devnum, iface_no, altno); |
527 | continue; |
528 | } |
529 | |
530 | if (as->bLength < sizeof(*as)) { |
531 | snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n", |
532 | dev->devnum, iface_no, altno); |
533 | continue; |
534 | } |
535 | |
536 | format = le16_to_cpu(as->wFormatTag); /* remember the format value */ |
537 | |
538 | iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, |
539 | as->bTerminalLink); |
540 | if (iterm) { |
541 | num_channels = iterm->bNrChannels; |
542 | chconfig = le16_to_cpu(iterm->wChannelConfig); |
543 | } |
544 | |
545 | break; |
546 | } |
547 | |
548 | case UAC_VERSION_2: { |
549 | struct uac2_input_terminal_descriptor *input_term; |
550 | struct uac2_output_terminal_descriptor *output_term; |
551 | struct uac2_as_header_descriptor *as = |
552 | snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); |
553 | |
554 | if (!as) { |
555 | snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n", |
556 | dev->devnum, iface_no, altno); |
557 | continue; |
558 | } |
559 | |
560 | if (as->bLength < sizeof(*as)) { |
561 | snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n", |
562 | dev->devnum, iface_no, altno); |
563 | continue; |
564 | } |
565 | |
566 | num_channels = as->bNrChannels; |
567 | format = le32_to_cpu(as->bmFormats); |
568 | |
569 | /* lookup the terminal associated to this interface |
570 | * to extract the clock */ |
571 | input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, |
572 | as->bTerminalLink); |
573 | if (input_term) { |
574 | clock = input_term->bCSourceID; |
575 | chconfig = le32_to_cpu(input_term->bmChannelConfig); |
576 | break; |
577 | } |
578 | |
579 | output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf, |
580 | as->bTerminalLink); |
581 | if (output_term) { |
582 | clock = output_term->bCSourceID; |
583 | break; |
584 | } |
585 | |
586 | snd_printk(KERN_ERR "%d:%u:%d : bogus bTerminalLink %d\n", |
587 | dev->devnum, iface_no, altno, as->bTerminalLink); |
588 | continue; |
589 | } |
590 | } |
591 | |
592 | /* get format type */ |
593 | fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_FORMAT_TYPE); |
594 | if (!fmt) { |
595 | snd_printk(KERN_ERR "%d:%u:%d : no UAC_FORMAT_TYPE desc\n", |
596 | dev->devnum, iface_no, altno); |
597 | continue; |
598 | } |
599 | if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) || |
600 | ((protocol == UAC_VERSION_2) && (fmt->bLength < 6))) { |
601 | snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n", |
602 | dev->devnum, iface_no, altno); |
603 | continue; |
604 | } |
605 | |
606 | /* |
607 | * Blue Microphones workaround: The last altsetting is identical |
608 | * with the previous one, except for a larger packet size, but |
609 | * is actually a mislabeled two-channel setting; ignore it. |
610 | */ |
611 | if (fmt->bNrChannels == 1 && |
612 | fmt->bSubframeSize == 2 && |
613 | altno == 2 && num == 3 && |
614 | fp && fp->altsetting == 1 && fp->channels == 1 && |
615 | fp->formats == SNDRV_PCM_FMTBIT_S16_LE && |
616 | protocol == UAC_VERSION_1 && |
617 | le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == |
618 | fp->maxpacksize * 2) |
619 | continue; |
620 | |
621 | fp = kzalloc(sizeof(*fp), GFP_KERNEL); |
622 | if (! fp) { |
623 | snd_printk(KERN_ERR "cannot malloc\n"); |
624 | return -ENOMEM; |
625 | } |
626 | |
627 | fp->iface = iface_no; |
628 | fp->altsetting = altno; |
629 | fp->altset_idx = i; |
630 | fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; |
631 | fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; |
632 | fp->datainterval = snd_usb_parse_datainterval(chip, alts); |
633 | fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); |
634 | fp->channels = num_channels; |
635 | if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) |
636 | fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) |
637 | * (fp->maxpacksize & 0x7ff); |
638 | fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no); |
639 | fp->clock = clock; |
640 | fp->chmap = convert_chmap(num_channels, chconfig, protocol); |
641 | |
642 | /* some quirks for attributes here */ |
643 | |
644 | switch (chip->usb_id) { |
645 | case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */ |
646 | /* Optoplay sets the sample rate attribute although |
647 | * it seems not supporting it in fact. |
648 | */ |
649 | fp->attributes &= ~UAC_EP_CS_ATTR_SAMPLE_RATE; |
650 | break; |
651 | case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */ |
652 | case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ |
653 | /* doesn't set the sample rate attribute, but supports it */ |
654 | fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE; |
655 | break; |
656 | case USB_ID(0x0763, 0x2001): /* M-Audio Quattro USB */ |
657 | case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro USB */ |
658 | case USB_ID(0x047f, 0x0ca1): /* plantronics headset */ |
659 | case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is |
660 | an older model 77d:223) */ |
661 | /* |
662 | * plantronics headset and Griffin iMic have set adaptive-in |
663 | * although it's really not... |
664 | */ |
665 | fp->ep_attr &= ~USB_ENDPOINT_SYNCTYPE; |
666 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) |
667 | fp->ep_attr |= USB_ENDPOINT_SYNC_ADAPTIVE; |
668 | else |
669 | fp->ep_attr |= USB_ENDPOINT_SYNC_SYNC; |
670 | break; |
671 | } |
672 | |
673 | /* ok, let's parse further... */ |
674 | if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) { |
675 | kfree(fp->rate_table); |
676 | kfree(fp->chmap); |
677 | kfree(fp); |
678 | fp = NULL; |
679 | continue; |
680 | } |
681 | |
682 | snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint); |
683 | err = snd_usb_add_audio_stream(chip, stream, fp); |
684 | if (err < 0) { |
685 | kfree(fp->rate_table); |
686 | kfree(fp->chmap); |
687 | kfree(fp); |
688 | return err; |
689 | } |
690 | /* try to set the interface... */ |
691 | usb_set_interface(chip->dev, iface_no, altno); |
692 | snd_usb_init_pitch(chip, iface_no, alts, fp); |
693 | snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max); |
694 | } |
695 | return 0; |
696 | } |
697 | |
698 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9