aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/stream.c
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/usb/stream.c
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/usb/stream.c')
-rw-r--r--sound/usb/stream.c453
1 files changed, 453 insertions, 0 deletions
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