aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2011-09-12 12:54:12 -0400
committerTakashi Iwai <tiwai@suse.de>2011-09-14 11:07:02 -0400
commite8e8babf561c9560f37b9bd80407ebaf90ad2ca4 (patch)
treebcb7899519e35b094ab1f89d3c929ae4f8935c00 /sound
parent358e2bd4a97780f5522e1666c8188a3a60a0d03c (diff)
ALSA: snd-usb: re-order code
Move code from endpoint.c into a new file called stream.c and rename functions so that their names actually reflect what they're doing. This way, endpoint.c will be available to functions that hold all the endpoint logic. Signed-off-by: Daniel Mack <zonque@gmail.com> Acked-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/usb/Makefile1
-rw-r--r--sound/usb/card.c3
-rw-r--r--sound/usb/endpoint.c433
-rw-r--r--sound/usb/endpoint.h7
-rw-r--r--sound/usb/quirks.c7
-rw-r--r--sound/usb/stream.c453
-rw-r--r--sound/usb/stream.h12
7 files changed, 472 insertions, 444 deletions
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index 083501e78f34..5390db00e098 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -12,6 +12,7 @@ snd-usb-audio-objs := card.o \
12 pcm.o \ 12 pcm.o \
13 proc.o \ 13 proc.o \
14 quirks.o \ 14 quirks.o \
15 stream.o \
15 urb.o 16 urb.o
16 17
17snd-usbmidi-lib-objs := midi.o 18snd-usbmidi-lib-objs := midi.o
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 781d9e61adfb..a3136afb2198 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -68,6 +68,7 @@
68#include "urb.h" 68#include "urb.h"
69#include "format.h" 69#include "format.h"
70#include "power.h" 70#include "power.h"
71#include "stream.h"
71 72
72MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); 73MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
73MODULE_DESCRIPTION("USB Audio"); 74MODULE_DESCRIPTION("USB Audio");
@@ -185,7 +186,7 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int
185 return -EINVAL; 186 return -EINVAL;
186 } 187 }
187 188
188 if (! snd_usb_parse_audio_endpoints(chip, interface)) { 189 if (! snd_usb_parse_audio_interface(chip, interface)) {
189 usb_set_interface(dev, interface, 0); /* reset the current interface */ 190 usb_set_interface(dev, interface, 0); /* reset the current interface */
190 usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L); 191 usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L);
191 return -EINVAL; 192 return -EINVAL;
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 7d46e482375d..b3ee7cf243df 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -15,436 +15,3 @@
15 * 15 *
16 */ 16 */
17 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
27#include "usbaudio.h"
28#include "card.h"
29#include "proc.h"
30#include "quirks.h"
31#include "endpoint.h"
32#include "urb.h"
33#include "pcm.h"
34#include "helper.h"
35#include "format.h"
36#include "clock.h"
37
38/*
39 * free a substream
40 */
41static void free_substream(struct snd_usb_substream *subs)
42{
43 struct list_head *p, *n;
44
45 if (!subs->num_formats)
46 return; /* not initialized */
47 list_for_each_safe(p, n, &subs->fmt_list) {
48 struct audioformat *fp = list_entry(p, struct audioformat, list);
49 kfree(fp->rate_table);
50 kfree(fp);
51 }
52 kfree(subs->rate_list.list);
53}
54
55
56/*
57 * free a usb stream instance
58 */
59static void snd_usb_audio_stream_free(struct snd_usb_stream *stream)
60{
61 free_substream(&stream->substream[0]);
62 free_substream(&stream->substream[1]);
63 list_del(&stream->list);
64 kfree(stream);
65}
66
67static void snd_usb_audio_pcm_free(struct snd_pcm *pcm)
68{
69 struct snd_usb_stream *stream = pcm->private_data;
70 if (stream) {
71 stream->pcm = NULL;
72 snd_usb_audio_stream_free(stream);
73 }
74}
75
76
77/*
78 * add this endpoint to the chip instance.
79 * if a stream with the same endpoint already exists, append to it.
80 * if not, create a new pcm stream.
81 */
82int snd_usb_add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct audioformat *fp)
83{
84 struct list_head *p;
85 struct snd_usb_stream *as;
86 struct snd_usb_substream *subs;
87 struct snd_pcm *pcm;
88 int err;
89
90 list_for_each(p, &chip->pcm_list) {
91 as = list_entry(p, struct snd_usb_stream, list);
92 if (as->fmt_type != fp->fmt_type)
93 continue;
94 subs = &as->substream[stream];
95 if (!subs->endpoint)
96 continue;
97 if (subs->endpoint == fp->endpoint) {
98 list_add_tail(&fp->list, &subs->fmt_list);
99 subs->num_formats++;
100 subs->formats |= fp->formats;
101 return 0;
102 }
103 }
104 /* look for an empty stream */
105 list_for_each(p, &chip->pcm_list) {
106 as = list_entry(p, struct snd_usb_stream, list);
107 if (as->fmt_type != fp->fmt_type)
108 continue;
109 subs = &as->substream[stream];
110 if (subs->endpoint)
111 continue;
112 err = snd_pcm_new_stream(as->pcm, stream, 1);
113 if (err < 0)
114 return err;
115 snd_usb_init_substream(as, stream, fp);
116 return 0;
117 }
118
119 /* create a new pcm */
120 as = kzalloc(sizeof(*as), GFP_KERNEL);
121 if (!as)
122 return -ENOMEM;
123 as->pcm_index = chip->pcm_devs;
124 as->chip = chip;
125 as->fmt_type = fp->fmt_type;
126 err = snd_pcm_new(chip->card, "USB Audio", chip->pcm_devs,
127 stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0,
128 stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1,
129 &pcm);
130 if (err < 0) {
131 kfree(as);
132 return err;
133 }
134 as->pcm = pcm;
135 pcm->private_data = as;
136 pcm->private_free = snd_usb_audio_pcm_free;
137 pcm->info_flags = 0;
138 if (chip->pcm_devs > 0)
139 sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs);
140 else
141 strcpy(pcm->name, "USB Audio");
142
143 snd_usb_init_substream(as, stream, fp);
144
145 list_add(&as->list, &chip->pcm_list);
146 chip->pcm_devs++;
147
148 snd_usb_proc_pcm_format_add(as);
149
150 return 0;
151}
152
153static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
154 struct usb_host_interface *alts,
155 int protocol, int iface_no)
156{
157 /* parsed with a v1 header here. that's ok as we only look at the
158 * header first which is the same for both versions */
159 struct uac_iso_endpoint_descriptor *csep;
160 struct usb_interface_descriptor *altsd = get_iface_desc(alts);
161 int attributes = 0;
162
163 csep = snd_usb_find_desc(alts->endpoint[0].extra, alts->endpoint[0].extralen, NULL, USB_DT_CS_ENDPOINT);
164
165 /* Creamware Noah has this descriptor after the 2nd endpoint */
166 if (!csep && altsd->bNumEndpoints >= 2)
167 csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
168
169 if (!csep || csep->bLength < 7 ||
170 csep->bDescriptorSubtype != UAC_EP_GENERAL) {
171 snd_printk(KERN_WARNING "%d:%u:%d : no or invalid"
172 " class specific endpoint descriptor\n",
173 chip->dev->devnum, iface_no,
174 altsd->bAlternateSetting);
175 return 0;
176 }
177
178 if (protocol == UAC_VERSION_1) {
179 attributes = csep->bmAttributes;
180 } else {
181 struct uac2_iso_endpoint_descriptor *csep2 =
182 (struct uac2_iso_endpoint_descriptor *) csep;
183
184 attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX;
185
186 /* emulate the endpoint attributes of a v1 device */
187 if (csep2->bmControls & UAC2_CONTROL_PITCH)
188 attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
189 }
190
191 return attributes;
192}
193
194static struct uac2_input_terminal_descriptor *
195 snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
196 int terminal_id)
197{
198 struct uac2_input_terminal_descriptor *term = NULL;
199
200 while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
201 ctrl_iface->extralen,
202 term, UAC_INPUT_TERMINAL))) {
203 if (term->bTerminalID == terminal_id)
204 return term;
205 }
206
207 return NULL;
208}
209
210static struct uac2_output_terminal_descriptor *
211 snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface,
212 int terminal_id)
213{
214 struct uac2_output_terminal_descriptor *term = NULL;
215
216 while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
217 ctrl_iface->extralen,
218 term, UAC_OUTPUT_TERMINAL))) {
219 if (term->bTerminalID == terminal_id)
220 return term;
221 }
222
223 return NULL;
224}
225
226int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
227{
228 struct usb_device *dev;
229 struct usb_interface *iface;
230 struct usb_host_interface *alts;
231 struct usb_interface_descriptor *altsd;
232 int i, altno, err, stream;
233 int format = 0, num_channels = 0;
234 struct audioformat *fp = NULL;
235 int num, protocol, clock = 0;
236 struct uac_format_type_i_continuous_descriptor *fmt;
237
238 dev = chip->dev;
239
240 /* parse the interface's altsettings */
241 iface = usb_ifnum_to_if(dev, iface_no);
242
243 num = iface->num_altsetting;
244
245 /*
246 * Dallas DS4201 workaround: It presents 5 altsettings, but the last
247 * one misses syncpipe, and does not produce any sound.
248 */
249 if (chip->usb_id == USB_ID(0x04fa, 0x4201))
250 num = 4;
251
252 for (i = 0; i < num; i++) {
253 alts = &iface->altsetting[i];
254 altsd = get_iface_desc(alts);
255 protocol = altsd->bInterfaceProtocol;
256 /* skip invalid one */
257 if ((altsd->bInterfaceClass != USB_CLASS_AUDIO &&
258 altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
259 (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING &&
260 altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC) ||
261 altsd->bNumEndpoints < 1 ||
262 le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0)
263 continue;
264 /* must be isochronous */
265 if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
266 USB_ENDPOINT_XFER_ISOC)
267 continue;
268 /* check direction */
269 stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ?
270 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
271 altno = altsd->bAlternateSetting;
272
273 if (snd_usb_apply_interface_quirk(chip, iface_no, altno))
274 continue;
275
276 /* get audio formats */
277 switch (protocol) {
278 default:
279 snd_printdd(KERN_WARNING "%d:%u:%d: unknown interface protocol %#02x, assuming v1\n",
280 dev->devnum, iface_no, altno, protocol);
281 protocol = UAC_VERSION_1;
282 /* fall through */
283
284 case UAC_VERSION_1: {
285 struct uac1_as_header_descriptor *as =
286 snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
287
288 if (!as) {
289 snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
290 dev->devnum, iface_no, altno);
291 continue;
292 }
293
294 if (as->bLength < sizeof(*as)) {
295 snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n",
296 dev->devnum, iface_no, altno);
297 continue;
298 }
299
300 format = le16_to_cpu(as->wFormatTag); /* remember the format value */
301 break;
302 }
303
304 case UAC_VERSION_2: {
305 struct uac2_input_terminal_descriptor *input_term;
306 struct uac2_output_terminal_descriptor *output_term;
307 struct uac2_as_header_descriptor *as =
308 snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
309
310 if (!as) {
311 snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
312 dev->devnum, iface_no, altno);
313 continue;
314 }
315
316 if (as->bLength < sizeof(*as)) {
317 snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n",
318 dev->devnum, iface_no, altno);
319 continue;
320 }
321
322 num_channels = as->bNrChannels;
323 format = le32_to_cpu(as->bmFormats);
324
325 /* lookup the terminal associated to this interface
326 * to extract the clock */
327 input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
328 as->bTerminalLink);
329 if (input_term) {
330 clock = input_term->bCSourceID;
331 break;
332 }
333
334 output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
335 as->bTerminalLink);
336 if (output_term) {
337 clock = output_term->bCSourceID;
338 break;
339 }
340
341 snd_printk(KERN_ERR "%d:%u:%d : bogus bTerminalLink %d\n",
342 dev->devnum, iface_no, altno, as->bTerminalLink);
343 continue;
344 }
345 }
346
347 /* get format type */
348 fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_FORMAT_TYPE);
349 if (!fmt) {
350 snd_printk(KERN_ERR "%d:%u:%d : no UAC_FORMAT_TYPE desc\n",
351 dev->devnum, iface_no, altno);
352 continue;
353 }
354 if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) ||
355 ((protocol == UAC_VERSION_2) && (fmt->bLength < 6))) {
356 snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n",
357 dev->devnum, iface_no, altno);
358 continue;
359 }
360
361 /*
362 * Blue Microphones workaround: The last altsetting is identical
363 * with the previous one, except for a larger packet size, but
364 * is actually a mislabeled two-channel setting; ignore it.
365 */
366 if (fmt->bNrChannels == 1 &&
367 fmt->bSubframeSize == 2 &&
368 altno == 2 && num == 3 &&
369 fp && fp->altsetting == 1 && fp->channels == 1 &&
370 fp->formats == SNDRV_PCM_FMTBIT_S16_LE &&
371 protocol == UAC_VERSION_1 &&
372 le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) ==
373 fp->maxpacksize * 2)
374 continue;
375
376 fp = kzalloc(sizeof(*fp), GFP_KERNEL);
377 if (! fp) {
378 snd_printk(KERN_ERR "cannot malloc\n");
379 return -ENOMEM;
380 }
381
382 fp->iface = iface_no;
383 fp->altsetting = altno;
384 fp->altset_idx = i;
385 fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
386 fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
387 fp->datainterval = snd_usb_parse_datainterval(chip, alts);
388 fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
389 /* num_channels is only set for v2 interfaces */
390 fp->channels = num_channels;
391 if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
392 fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
393 * (fp->maxpacksize & 0x7ff);
394 fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
395 fp->clock = clock;
396
397 /* some quirks for attributes here */
398
399 switch (chip->usb_id) {
400 case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */
401 /* Optoplay sets the sample rate attribute although
402 * it seems not supporting it in fact.
403 */
404 fp->attributes &= ~UAC_EP_CS_ATTR_SAMPLE_RATE;
405 break;
406 case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */
407 case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
408 /* doesn't set the sample rate attribute, but supports it */
409 fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE;
410 break;
411 case USB_ID(0x0763, 0x2001): /* M-Audio Quattro USB */
412 case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro USB */
413 case USB_ID(0x047f, 0x0ca1): /* plantronics headset */
414 case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is
415 an older model 77d:223) */
416 /*
417 * plantronics headset and Griffin iMic have set adaptive-in
418 * although it's really not...
419 */
420 fp->ep_attr &= ~USB_ENDPOINT_SYNCTYPE;
421 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
422 fp->ep_attr |= USB_ENDPOINT_SYNC_ADAPTIVE;
423 else
424 fp->ep_attr |= USB_ENDPOINT_SYNC_SYNC;
425 break;
426 }
427
428 /* ok, let's parse further... */
429 if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) {
430 kfree(fp->rate_table);
431 kfree(fp);
432 fp = NULL;
433 continue;
434 }
435
436 snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint);
437 err = snd_usb_add_audio_endpoint(chip, stream, fp);
438 if (err < 0) {
439 kfree(fp->rate_table);
440 kfree(fp);
441 return err;
442 }
443 /* try to set the interface... */
444 usb_set_interface(chip->dev, iface_no, altno);
445 snd_usb_init_pitch(chip, iface_no, alts, fp);
446 snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max);
447 }
448 return 0;
449}
450
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index 64dd0db023b2..e5d8a6adf38f 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -1,11 +1,4 @@
1#ifndef __USBAUDIO_ENDPOINT_H 1#ifndef __USBAUDIO_ENDPOINT_H
2#define __USBAUDIO_ENDPOINT_H 2#define __USBAUDIO_ENDPOINT_H
3 3
4int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip,
5 int iface_no);
6
7int snd_usb_add_audio_endpoint(struct snd_usb_audio *chip,
8 int stream,
9 struct audioformat *fp);
10
11#endif /* __USBAUDIO_ENDPOINT_H */ 4#endif /* __USBAUDIO_ENDPOINT_H */
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index cf61b0340026..556edea28b90 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -34,6 +34,7 @@
34#include "endpoint.h" 34#include "endpoint.h"
35#include "pcm.h" 35#include "pcm.h"
36#include "clock.h" 36#include "clock.h"
37#include "stream.h"
37 38
38/* 39/*
39 * handle the quirks for the contained interfaces 40 * handle the quirks for the contained interfaces
@@ -106,7 +107,7 @@ static int create_standard_audio_quirk(struct snd_usb_audio *chip,
106 107
107 alts = &iface->altsetting[0]; 108 alts = &iface->altsetting[0];
108 altsd = get_iface_desc(alts); 109 altsd = get_iface_desc(alts);
109 err = snd_usb_parse_audio_endpoints(chip, altsd->bInterfaceNumber); 110 err = snd_usb_parse_audio_interface(chip, altsd->bInterfaceNumber);
110 if (err < 0) { 111 if (err < 0) {
111 snd_printk(KERN_ERR "cannot setup if %d: error %d\n", 112 snd_printk(KERN_ERR "cannot setup if %d: error %d\n",
112 altsd->bInterfaceNumber, err); 113 altsd->bInterfaceNumber, err);
@@ -147,7 +148,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
147 148
148 stream = (fp->endpoint & USB_DIR_IN) 149 stream = (fp->endpoint & USB_DIR_IN)
149 ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; 150 ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
150 err = snd_usb_add_audio_endpoint(chip, stream, fp); 151 err = snd_usb_add_audio_stream(chip, stream, fp);
151 if (err < 0) { 152 if (err < 0) {
152 kfree(fp); 153 kfree(fp);
153 kfree(rate_table); 154 kfree(rate_table);
@@ -254,7 +255,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
254 255
255 stream = (fp->endpoint & USB_DIR_IN) 256 stream = (fp->endpoint & USB_DIR_IN)
256 ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; 257 ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
257 err = snd_usb_add_audio_endpoint(chip, stream, fp); 258 err = snd_usb_add_audio_stream(chip, stream, fp);
258 if (err < 0) { 259 if (err < 0) {
259 kfree(fp); 260 kfree(fp);
260 return err; 261 return err;
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
new file mode 100644
index 000000000000..4688d4c6208b
--- /dev/null
+++ b/sound/usb/stream.c
@@ -0,0 +1,453 @@
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
27#include "usbaudio.h"
28#include "card.h"
29#include "proc.h"
30#include "quirks.h"
31#include "endpoint.h"
32#include "urb.h"
33#include "pcm.h"
34#include "helper.h"
35#include "format.h"
36#include "clock.h"
37#include "stream.h"
38
39/*
40 * free a substream
41 */
42static void free_substream(struct snd_usb_substream *subs)
43{
44 struct list_head *p, *n;
45
46 if (!subs->num_formats)
47 return; /* not initialized */
48 list_for_each_safe(p, n, &subs->fmt_list) {
49 struct audioformat *fp = list_entry(p, struct audioformat, list);
50 kfree(fp->rate_table);
51 kfree(fp);
52 }
53 kfree(subs->rate_list.list);
54}
55
56
57/*
58 * free a usb stream instance
59 */
60static void snd_usb_audio_stream_free(struct snd_usb_stream *stream)
61{
62 free_substream(&stream->substream[0]);
63 free_substream(&stream->substream[1]);
64 list_del(&stream->list);
65 kfree(stream);
66}
67
68static void snd_usb_audio_pcm_free(struct snd_pcm *pcm)
69{
70 struct snd_usb_stream *stream = pcm->private_data;
71 if (stream) {
72 stream->pcm = NULL;
73 snd_usb_audio_stream_free(stream);
74 }
75}
76
77
78/*
79 * add this endpoint to the chip instance.
80 * if a stream with the same endpoint already exists, append to it.
81 * if not, create a new pcm stream.
82 */
83int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
84 int stream,
85 struct audioformat *fp)
86{
87 struct list_head *p;
88 struct snd_usb_stream *as;
89 struct snd_usb_substream *subs;
90 struct snd_pcm *pcm;
91 int err;
92
93 list_for_each(p, &chip->pcm_list) {
94 as = list_entry(p, struct snd_usb_stream, list);
95 if (as->fmt_type != fp->fmt_type)
96 continue;
97 subs = &as->substream[stream];
98 if (!subs->endpoint)
99 continue;
100 if (subs->endpoint == fp->endpoint) {
101 list_add_tail(&fp->list, &subs->fmt_list);
102 subs->num_formats++;
103 subs->formats |= fp->formats;
104 return 0;
105 }
106 }
107 /* look for an empty stream */
108 list_for_each(p, &chip->pcm_list) {
109 as = list_entry(p, struct snd_usb_stream, list);
110 if (as->fmt_type != fp->fmt_type)
111 continue;
112 subs = &as->substream[stream];
113 if (subs->endpoint)
114 continue;
115 err = snd_pcm_new_stream(as->pcm, stream, 1);
116 if (err < 0)
117 return err;
118 snd_usb_init_substream(as, stream, fp);
119 return 0;
120 }
121
122 /* create a new pcm */
123 as = kzalloc(sizeof(*as), GFP_KERNEL);
124 if (!as)
125 return -ENOMEM;
126 as->pcm_index = chip->pcm_devs;
127 as->chip = chip;
128 as->fmt_type = fp->fmt_type;
129 err = snd_pcm_new(chip->card, "USB Audio", chip->pcm_devs,
130 stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0,
131 stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1,
132 &pcm);
133 if (err < 0) {
134 kfree(as);
135 return err;
136 }
137 as->pcm = pcm;
138 pcm->private_data = as;
139 pcm->private_free = snd_usb_audio_pcm_free;
140 pcm->info_flags = 0;
141 if (chip->pcm_devs > 0)
142 sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs);
143 else
144 strcpy(pcm->name, "USB Audio");
145
146 snd_usb_init_substream(as, stream, fp);
147
148 list_add(&as->list, &chip->pcm_list);
149 chip->pcm_devs++;
150
151 snd_usb_proc_pcm_format_add(as);
152
153 return 0;
154}
155
156static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
157 struct usb_host_interface *alts,
158 int protocol, int iface_no)
159{
160 /* parsed with a v1 header here. that's ok as we only look at the
161 * header first which is the same for both versions */
162 struct uac_iso_endpoint_descriptor *csep;
163 struct usb_interface_descriptor *altsd = get_iface_desc(alts);
164 int attributes = 0;
165
166 csep = snd_usb_find_desc(alts->endpoint[0].extra, alts->endpoint[0].extralen, NULL, USB_DT_CS_ENDPOINT);
167
168 /* Creamware Noah has this descriptor after the 2nd endpoint */
169 if (!csep && altsd->bNumEndpoints >= 2)
170 csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
171
172 if (!csep || csep->bLength < 7 ||
173 csep->bDescriptorSubtype != UAC_EP_GENERAL) {
174 snd_printk(KERN_WARNING "%d:%u:%d : no or invalid"
175 " class specific endpoint descriptor\n",
176 chip->dev->devnum, iface_no,
177 altsd->bAlternateSetting);
178 return 0;
179 }
180
181 if (protocol == UAC_VERSION_1) {
182 attributes = csep->bmAttributes;
183 } else {
184 struct uac2_iso_endpoint_descriptor *csep2 =
185 (struct uac2_iso_endpoint_descriptor *) csep;
186
187 attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX;
188
189 /* emulate the endpoint attributes of a v1 device */
190 if (csep2->bmControls & UAC2_CONTROL_PITCH)
191 attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
192 }
193
194 return attributes;
195}
196
197static struct uac2_input_terminal_descriptor *
198 snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
199 int terminal_id)
200{
201 struct uac2_input_terminal_descriptor *term = NULL;
202
203 while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
204 ctrl_iface->extralen,
205 term, UAC_INPUT_TERMINAL))) {
206 if (term->bTerminalID == terminal_id)
207 return term;
208 }
209
210 return NULL;
211}
212
213static struct uac2_output_terminal_descriptor *
214 snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface,
215 int terminal_id)
216{
217 struct uac2_output_terminal_descriptor *term = NULL;
218
219 while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
220 ctrl_iface->extralen,
221 term, UAC_OUTPUT_TERMINAL))) {
222 if (term->bTerminalID == terminal_id)
223 return term;
224 }
225
226 return NULL;
227}
228
229int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
230{
231 struct usb_device *dev;
232 struct usb_interface *iface;
233 struct usb_host_interface *alts;
234 struct usb_interface_descriptor *altsd;
235 int i, altno, err, stream;
236 int format = 0, num_channels = 0;
237 struct audioformat *fp = NULL;
238 int num, protocol, clock = 0;
239 struct uac_format_type_i_continuous_descriptor *fmt;
240
241 dev = chip->dev;
242
243 /* parse the interface's altsettings */
244 iface = usb_ifnum_to_if(dev, iface_no);
245
246 num = iface->num_altsetting;
247
248 /*
249 * Dallas DS4201 workaround: It presents 5 altsettings, but the last
250 * one misses syncpipe, and does not produce any sound.
251 */
252 if (chip->usb_id == USB_ID(0x04fa, 0x4201))
253 num = 4;
254
255 for (i = 0; i < num; i++) {
256 alts = &iface->altsetting[i];
257 altsd = get_iface_desc(alts);
258 protocol = altsd->bInterfaceProtocol;
259 /* skip invalid one */
260 if ((altsd->bInterfaceClass != USB_CLASS_AUDIO &&
261 altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
262 (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING &&
263 altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC) ||
264 altsd->bNumEndpoints < 1 ||
265 le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0)
266 continue;
267 /* must be isochronous */
268 if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
269 USB_ENDPOINT_XFER_ISOC)
270 continue;
271 /* check direction */
272 stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ?
273 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
274 altno = altsd->bAlternateSetting;
275
276 if (snd_usb_apply_interface_quirk(chip, iface_no, altno))
277 continue;
278
279 /* get audio formats */
280 switch (protocol) {
281 default:
282 snd_printdd(KERN_WARNING "%d:%u:%d: unknown interface protocol %#02x, assuming v1\n",
283 dev->devnum, iface_no, altno, protocol);
284 protocol = UAC_VERSION_1;
285 /* fall through */
286
287 case UAC_VERSION_1: {
288 struct uac1_as_header_descriptor *as =
289 snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
290
291 if (!as) {
292 snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
293 dev->devnum, iface_no, altno);
294 continue;
295 }
296
297 if (as->bLength < sizeof(*as)) {
298 snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n",
299 dev->devnum, iface_no, altno);
300 continue;
301 }
302
303 format = le16_to_cpu(as->wFormatTag); /* remember the format value */
304 break;
305 }
306
307 case UAC_VERSION_2: {
308 struct uac2_input_terminal_descriptor *input_term;
309 struct uac2_output_terminal_descriptor *output_term;
310 struct uac2_as_header_descriptor *as =
311 snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
312
313 if (!as) {
314 snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
315 dev->devnum, iface_no, altno);
316 continue;
317 }
318
319 if (as->bLength < sizeof(*as)) {
320 snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n",
321 dev->devnum, iface_no, altno);
322 continue;
323 }
324
325 num_channels = as->bNrChannels;
326 format = le32_to_cpu(as->bmFormats);
327
328 /* lookup the terminal associated to this interface
329 * to extract the clock */
330 input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
331 as->bTerminalLink);
332 if (input_term) {
333 clock = input_term->bCSourceID;
334 break;
335 }
336
337 output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
338 as->bTerminalLink);
339 if (output_term) {
340 clock = output_term->bCSourceID;
341 break;
342 }
343
344 snd_printk(KERN_ERR "%d:%u:%d : bogus bTerminalLink %d\n",
345 dev->devnum, iface_no, altno, as->bTerminalLink);
346 continue;
347 }
348 }
349
350 /* get format type */
351 fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_FORMAT_TYPE);
352 if (!fmt) {
353 snd_printk(KERN_ERR "%d:%u:%d : no UAC_FORMAT_TYPE desc\n",
354 dev->devnum, iface_no, altno);
355 continue;
356 }
357 if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) ||
358 ((protocol == UAC_VERSION_2) && (fmt->bLength < 6))) {
359 snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n",
360 dev->devnum, iface_no, altno);
361 continue;
362 }
363
364 /*
365 * Blue Microphones workaround: The last altsetting is identical
366 * with the previous one, except for a larger packet size, but
367 * is actually a mislabeled two-channel setting; ignore it.
368 */
369 if (fmt->bNrChannels == 1 &&
370 fmt->bSubframeSize == 2 &&
371 altno == 2 && num == 3 &&
372 fp && fp->altsetting == 1 && fp->channels == 1 &&
373 fp->formats == SNDRV_PCM_FMTBIT_S16_LE &&
374 protocol == UAC_VERSION_1 &&
375 le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) ==
376 fp->maxpacksize * 2)
377 continue;
378
379 fp = kzalloc(sizeof(*fp), GFP_KERNEL);
380 if (! fp) {
381 snd_printk(KERN_ERR "cannot malloc\n");
382 return -ENOMEM;
383 }
384
385 fp->iface = iface_no;
386 fp->altsetting = altno;
387 fp->altset_idx = i;
388 fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
389 fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
390 fp->datainterval = snd_usb_parse_datainterval(chip, alts);
391 fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
392 /* num_channels is only set for v2 interfaces */
393 fp->channels = num_channels;
394 if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
395 fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
396 * (fp->maxpacksize & 0x7ff);
397 fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
398 fp->clock = clock;
399
400 /* some quirks for attributes here */
401
402 switch (chip->usb_id) {
403 case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */
404 /* Optoplay sets the sample rate attribute although
405 * it seems not supporting it in fact.
406 */
407 fp->attributes &= ~UAC_EP_CS_ATTR_SAMPLE_RATE;
408 break;
409 case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */
410 case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
411 /* doesn't set the sample rate attribute, but supports it */
412 fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE;
413 break;
414 case USB_ID(0x0763, 0x2001): /* M-Audio Quattro USB */
415 case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro USB */
416 case USB_ID(0x047f, 0x0ca1): /* plantronics headset */
417 case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is
418 an older model 77d:223) */
419 /*
420 * plantronics headset and Griffin iMic have set adaptive-in
421 * although it's really not...
422 */
423 fp->ep_attr &= ~USB_ENDPOINT_SYNCTYPE;
424 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
425 fp->ep_attr |= USB_ENDPOINT_SYNC_ADAPTIVE;
426 else
427 fp->ep_attr |= USB_ENDPOINT_SYNC_SYNC;
428 break;
429 }
430
431 /* ok, let's parse further... */
432 if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) {
433 kfree(fp->rate_table);
434 kfree(fp);
435 fp = NULL;
436 continue;
437 }
438
439 snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint);
440 err = snd_usb_add_audio_stream(chip, stream, fp);
441 if (err < 0) {
442 kfree(fp->rate_table);
443 kfree(fp);
444 return err;
445 }
446 /* try to set the interface... */
447 usb_set_interface(chip->dev, iface_no, altno);
448 snd_usb_init_pitch(chip, iface_no, alts, fp);
449 snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max);
450 }
451 return 0;
452}
453
diff --git a/sound/usb/stream.h b/sound/usb/stream.h
new file mode 100644
index 000000000000..c97f679fc84f
--- /dev/null
+++ b/sound/usb/stream.h
@@ -0,0 +1,12 @@
1#ifndef __USBAUDIO_STREAM_H
2#define __USBAUDIO_STREAM_H
3
4int snd_usb_parse_audio_interface(struct snd_usb_audio *chip,
5 int iface_no);
6
7int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
8 int stream,
9 struct audioformat *fp);
10
11#endif /* __USBAUDIO_STREAM_H */
12