All of lore.kernel.org
 help / color / mirror / Atom feed
From: Clemens Ladisch <clemens@ladisch.de>
To: Daniel Mack <daniel@caiaq.de>, Takashi Iwai <tiwai@suse.de>
Cc: alsa-devel@alsa-project.org
Subject: [PATCH 3/3] ALSA: usb-audio: support multiple formats with audio class v2 devices
Date: Mon, 01 Mar 2010 12:27:54 +0100	[thread overview]
Message-ID: <4B8BA4BA.8040609@ladisch.de> (raw)
In-Reply-To: <1267194883-6854-4-git-send-email-daniel@caiaq.de>

Change the parser to correctly handle v2 descriptors with multiple
format bits set.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>

--- linux/sound/usb/format.c
+++ linux/sound/usb/format.c
@@ -37,19 +37,20 @@
  * @format: the format tag (wFormatTag)
  * @fmt: the format type descriptor
  */
-static int parse_audio_format_i_type(struct snd_usb_audio *chip,
+static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
 				     struct audioformat *fp,
 				     int format, void *_fmt,
 				     int protocol)
 {
-	int pcm_format, i;
 	int sample_width, sample_bytes;
+	u64 pcm_formats;
 
 	switch (protocol) {
 	case UAC_VERSION_1: {
 		struct uac_format_type_i_discrete_descriptor *fmt = _fmt;
 		sample_width = fmt->bBitResolution;
 		sample_bytes = fmt->bSubframeSize;
+		format = 1 << format;
 		break;
 	}
 
@@ -57,24 +58,7 @@ static int parse_audio_format_i_type(str
 		struct uac_format_type_i_ext_descriptor *fmt = _fmt;
 		sample_width = fmt->bBitResolution;
 		sample_bytes = fmt->bSubslotSize;
-
-		/*
-		 * FIXME
-		 * USB audio class v2 devices specify a bitmap of possible
-		 * audio formats rather than one fix value. For now, we just
-		 * pick one of them and report that as the only possible
-		 * value for this setting.
-		 * The bit allocation map is in fact compatible to the
-		 * wFormatTag of the v1 AS streaming descriptors, which is why
-		 * we can simply map the matrix.
-		 */
-
-		for (i = 0; i < 5; i++)
-			if (format & (1UL << i)) {
-				format = i + 1;
-				break;
-			}
-
+		format <<= 1;
 		break;
 	}
 
@@ -82,15 +66,15 @@ static int parse_audio_format_i_type(str
 		return -EINVAL;
 	}
 
-	/* FIXME: correct endianess and sign? */
-	pcm_format = -1;
+	pcm_formats = 0;
 
-	switch (format) {
-	case UAC_FORMAT_TYPE_I_UNDEFINED: /* some devices don't define this correctly... */
+	if (format == 0 || format == (1 << UAC_FORMAT_TYPE_I_UNDEFINED)) {
+		/* some devices don't define this correctly... */
 		snd_printdd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n",
 			    chip->dev->devnum, fp->iface, fp->altsetting);
-		/* fall-through */
-	case UAC_FORMAT_TYPE_I_PCM:
+		format = 1 << UAC_FORMAT_TYPE_I_PCM;
+	}
+	if (format & (1 << UAC_FORMAT_TYPE_I_PCM)) {
 		if (sample_width > sample_bytes * 8) {
 			snd_printk(KERN_INFO "%d:%u:%d : sample bitwidth %d in over sample bytes %d\n",
 				   chip->dev->devnum, fp->iface, fp->altsetting,
@@ -99,22 +83,22 @@ static int parse_audio_format_i_type(str
 		/* check the format byte size */
 		switch (sample_bytes) {
 		case 1:
-			pcm_format = SNDRV_PCM_FORMAT_S8;
+			pcm_formats |= SNDRV_PCM_FMTBIT_S8;
 			break;
 		case 2:
 			if (snd_usb_is_big_endian_format(chip, fp))
-				pcm_format = SNDRV_PCM_FORMAT_S16_BE; /* grrr, big endian!! */
+				pcm_formats |= SNDRV_PCM_FMTBIT_S16_BE; /* grrr, big endian!! */
 			else
-				pcm_format = SNDRV_PCM_FORMAT_S16_LE;
+				pcm_formats |= SNDRV_PCM_FMTBIT_S16_LE;
 			break;
 		case 3:
 			if (snd_usb_is_big_endian_format(chip, fp))
-				pcm_format = SNDRV_PCM_FORMAT_S24_3BE; /* grrr, big endian!! */
+				pcm_formats |= SNDRV_PCM_FMTBIT_S24_3BE; /* grrr, big endian!! */
 			else
-				pcm_format = SNDRV_PCM_FORMAT_S24_3LE;
+				pcm_formats |= SNDRV_PCM_FMTBIT_S24_3LE;
 			break;
 		case 4:
-			pcm_format = SNDRV_PCM_FORMAT_S32_LE;
+			pcm_formats |= SNDRV_PCM_FMTBIT_S32_LE;
 			break;
 		default:
 			snd_printk(KERN_INFO "%d:%u:%d : unsupported sample bitwidth %d in %d bytes\n",
@@ -122,30 +106,29 @@ static int parse_audio_format_i_type(str
 				   sample_width, sample_bytes);
 			break;
 		}
-		break;
-	case UAC_FORMAT_TYPE_I_PCM8:
-		pcm_format = SNDRV_PCM_FORMAT_U8;
-
+	}
+	if (format & (1 << UAC_FORMAT_TYPE_I_PCM8)) {
 		/* Dallas DS4201 workaround: it advertises U8 format, but really
 		   supports S8. */
 		if (chip->usb_id == USB_ID(0x04fa, 0x4201))
-			pcm_format = SNDRV_PCM_FORMAT_S8;
-		break;
-	case UAC_FORMAT_TYPE_I_IEEE_FLOAT:
-		pcm_format = SNDRV_PCM_FORMAT_FLOAT_LE;
-		break;
-	case UAC_FORMAT_TYPE_I_ALAW:
-		pcm_format = SNDRV_PCM_FORMAT_A_LAW;
-		break;
-	case UAC_FORMAT_TYPE_I_MULAW:
-		pcm_format = SNDRV_PCM_FORMAT_MU_LAW;
-		break;
-	default:
-		snd_printk(KERN_INFO "%d:%u:%d : unsupported format type %d\n",
+			pcm_formats |= SNDRV_PCM_FMTBIT_S8;
+		else
+			pcm_formats |= SNDRV_PCM_FMTBIT_U8;
+	}
+	if (format & (1 << UAC_FORMAT_TYPE_I_IEEE_FLOAT)) {
+		pcm_formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
+	}
+	if (format & (1 << UAC_FORMAT_TYPE_I_ALAW)) {
+		pcm_formats |= SNDRV_PCM_FMTBIT_A_LAW;
+	}
+	if (format & (1 << UAC_FORMAT_TYPE_I_MULAW)) {
+		pcm_formats |= SNDRV_PCM_FMTBIT_MU_LAW;
+	}
+	if (format & ~0x3f) {
+		snd_printk(KERN_INFO "%d:%u:%d : unsupported format bits %#x\n",
 			   chip->dev->devnum, fp->iface, fp->altsetting, format);
-		break;
 	}
-	return pcm_format;
+	return pcm_formats;
 }
 
 
@@ -313,14 +296,14 @@ static int parse_audio_format_i(struct s
 		default:
 			pcm_format = SNDRV_PCM_FORMAT_S16_LE;
 		}
+		fp->formats = 1uLL << pcm_format;
 	} else {
-		pcm_format = parse_audio_format_i_type(chip, fp, format, fmt, protocol);
-		if (pcm_format < 0)
+		fp->formats = parse_audio_format_i_type(chip, fp, format,
+							fmt, protocol);
+		if (!fp->formats)
 			return -1;
 	}
 
-	fp->formats = 1uLL << pcm_format;
-
 	/* gather possible sample rates */
 	/* audio class v1 reports possible sample rates as part of the
 	 * proprietary class specific descriptor.

  parent reply	other threads:[~2010-03-01 11:27 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-02-26 14:34 [RFC] Cleanup/refactor the usbaudio driver Daniel Mack
2010-02-26 14:34 ` [PATCH 1/3] ALSA: usb: move ua101 driver Daniel Mack
2010-02-26 14:34   ` [PATCH 2/3] ALSA: usb: header file cleanups Daniel Mack
     [not found]     ` <1267194883-6854-4-git-send-email-daniel@caiaq.de>
2010-03-01 11:27       ` [PATCH 1/3] ALSA: usb-audio: rename substream format field to altset_idx Clemens Ladisch
2010-03-01 11:27       ` [PATCH 2/3] ALSA: usb-audio: use a format bitmask per alternate setting Clemens Ladisch
2010-03-01 11:27       ` Clemens Ladisch [this message]
2010-03-01 14:26         ` [PATCH 3/3] ALSA: usb-audio: support multiple formats with audio class v2 devices Daniel Mack
2010-03-01 15:26           ` Clemens Ladisch
2010-03-01 11:27   ` [PATCH 1/3] ALSA: usb: move ua101 driver Clemens Ladisch
2010-03-01 14:01     ` Daniel Mack
2010-03-01 14:06       ` Takashi Iwai
2010-03-01 14:18         ` Daniel Mack
2010-03-01 14:23           ` Takashi Iwai
2010-03-04 15:16             ` Daniel Mack
2010-03-04 15:31               ` Takashi Iwai
2010-03-04 15:38                 ` Daniel Mack
2010-03-04 15:43                   ` Takashi Iwai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4B8BA4BA.8040609@ladisch.de \
    --to=clemens@ladisch.de \
    --cc=alsa-devel@alsa-project.org \
    --cc=daniel@caiaq.de \
    --cc=tiwai@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.