Blame view

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