* usb-audio code refactoring, more v2 support [resend]
@ 2010-03-05 7:41 Daniel Mack
2010-03-05 7:41 ` [PATCH 1/8] ALSA: usb-audio: move ua101 driver Daniel Mack
2010-03-05 7:52 ` usb-audio code refactoring, more v2 support [resend] Daniel Mack
0 siblings, 2 replies; 9+ messages in thread
From: Daniel Mack @ 2010-03-05 7:41 UTC (permalink / raw)
To: alsa-devel; +Cc: tiwai, clemens
This is a rebased version of the usb-audio cleanup patch set.
On top of what's already been posted, there is one more fix to support
sample rate configuration, and one bugfix.
Commit 864c11080 was also ported over. And Clemens' latest patches
are also included.
With these patches applied, I can stream audio on a class v2 device.
At least for awhile, then I get CRC errors in DATA0 packets. But
that's a different issue.
What's not yet done is all the feature unit parsing, mixers etc.
Daniel
[PATCH 1/8] ALSA: usb-audio: move ua101 driver
[PATCH 2/8] ALSA: usb-audio: header file cleanups
[PATCH 3/8] ALSA: usb-audio: refactor code
[PATCH 4/8] ALSA: usb-audio: rename substream format field to altset_idx
[PATCH 5/8] ALSA: usb-audio: use a format bitmask per alternate setting
[PATCH 6/8] ALSA: usb-audio: support multiple formats with audio class v2 devices
[PATCH 7/8] ALSA: usb-audio: add support for samplerate setting on v2 devices
[PATCH 8/8] usb/audio.h: Fix field order
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/8] ALSA: usb-audio: move ua101 driver
2010-03-05 7:41 usb-audio code refactoring, more v2 support [resend] Daniel Mack
@ 2010-03-05 7:41 ` Daniel Mack
2010-03-05 7:41 ` [PATCH 2/8] ALSA: usb-audio: header file cleanups Daniel Mack
2010-03-05 7:52 ` usb-audio code refactoring, more v2 support [resend] Daniel Mack
1 sibling, 1 reply; 9+ messages in thread
From: Daniel Mack @ 2010-03-05 7:41 UTC (permalink / raw)
To: alsa-devel; +Cc: tiwai, clemens
As part of the USB audio code cleanup, move the non-standard ua101
driver out of the way.
Signed-off-by: Daniel Mack <daniel@caiaq.de>
Cc: Clemens Ladisch <clemens@ladisch.de>
Cc: Takashi Iwai <tiwai@suse.de>
---
sound/usb/Makefile | 5 ++---
sound/usb/misc/Makefile | 2 ++
sound/usb/{ => misc}/ua101.c | 2 +-
3 files changed, 5 insertions(+), 4 deletions(-)
create mode 100644 sound/usb/misc/Makefile
rename sound/usb/{ => misc}/ua101.c (99%)
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index 5bf64ae..b0e5597 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -4,12 +4,11 @@
snd-usb-audio-objs := usbaudio.o usbmixer.o
snd-usb-lib-objs := usbmidi.o
-snd-ua101-objs := ua101.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_USB_AUDIO) += snd-usb-audio.o snd-usb-lib.o
-obj-$(CONFIG_SND_USB_UA101) += snd-ua101.o snd-usb-lib.o
+obj-$(CONFIG_SND_USB_UA101) += snd-usb-lib.o
obj-$(CONFIG_SND_USB_USX2Y) += snd-usb-lib.o
obj-$(CONFIG_SND_USB_US122L) += snd-usb-lib.o
-obj-$(CONFIG_SND) += usx2y/ caiaq/
+obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/
diff --git a/sound/usb/misc/Makefile b/sound/usb/misc/Makefile
new file mode 100644
index 0000000..ccefd81
--- /dev/null
+++ b/sound/usb/misc/Makefile
@@ -0,0 +1,2 @@
+snd-ua101-objs := ua101.o
+obj-$(CONFIG_SND_USB_UA101) += snd-ua101.o
diff --git a/sound/usb/ua101.c b/sound/usb/misc/ua101.c
similarity index 99%
rename from sound/usb/ua101.c
rename to sound/usb/misc/ua101.c
index 3d458d3..e9b0ae5 100644
--- a/sound/usb/ua101.c
+++ b/sound/usb/misc/ua101.c
@@ -23,7 +23,7 @@
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
-#include "usbaudio.h"
+#include "../usbaudio.h"
MODULE_DESCRIPTION("Edirol UA-101/1000 driver");
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
--
1.6.6.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/8] ALSA: usb-audio: header file cleanups
2010-03-05 7:41 ` [PATCH 1/8] ALSA: usb-audio: move ua101 driver Daniel Mack
@ 2010-03-05 7:41 ` Daniel Mack
[not found] ` <1267774885-16266-4-git-send-email-daniel@caiaq.de>
0 siblings, 1 reply; 9+ messages in thread
From: Daniel Mack @ 2010-03-05 7:41 UTC (permalink / raw)
To: alsa-devel; +Cc: tiwai, clemens
Rename snd-usb-lib to snd-usbmidi-lib as MIDI functions are the only
thing it actually contains. Introduce a new header file to only declare
these functions.
Introduced usbmixer.h for all functions exported by usbmixer.c.
Signed-off-by: Daniel Mack <daniel@caiaq.de>
Cc: Clemens Ladisch <clemens@ladisch.de>
Cc: Takashi Iwai <tiwai@suse.de>
---
sound/usb/Makefile | 11 +++++----
sound/usb/misc/ua101.c | 1 +
sound/usb/usbaudio.c | 3 +-
sound/usb/usbaudio.h | 51 --------------------------------------------
sound/usb/usbmidi.c | 1 +
sound/usb/usbmidi.h | 48 +++++++++++++++++++++++++++++++++++++++++
sound/usb/usbmixer.c | 1 +
sound/usb/usbmixer.h | 11 +++++++++
sound/usb/usx2y/us122l.c | 1 +
sound/usb/usx2y/usbusx2y.h | 1 +
10 files changed, 72 insertions(+), 57 deletions(-)
create mode 100644 sound/usb/usbmidi.h
create mode 100644 sound/usb/usbmixer.h
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index b0e5597..423d829 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -3,12 +3,13 @@
#
snd-usb-audio-objs := usbaudio.o usbmixer.o
-snd-usb-lib-objs := usbmidi.o
+snd-usbmidi-lib-objs := usbmidi.o
# Toplevel Module Dependency
-obj-$(CONFIG_SND_USB_AUDIO) += snd-usb-audio.o snd-usb-lib.o
-obj-$(CONFIG_SND_USB_UA101) += snd-usb-lib.o
-obj-$(CONFIG_SND_USB_USX2Y) += snd-usb-lib.o
-obj-$(CONFIG_SND_USB_US122L) += snd-usb-lib.o
+obj-$(CONFIG_SND_USB_AUDIO) += snd-usb-audio.o snd-usbmidi-lib.o
+
+obj-$(CONFIG_SND_USB_UA101) += snd-usbmidi-lib.o
+obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o
+obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o
obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/
diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c
index e9b0ae5..b4a4cb4 100644
--- a/sound/usb/misc/ua101.c
+++ b/sound/usb/misc/ua101.c
@@ -24,6 +24,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include "../usbaudio.h"
+#include "../usbmidi.h"
MODULE_DESCRIPTION("Edirol UA-101/1000 driver");
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 11b0826..5b91aa0 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -56,7 +56,8 @@
#include <sound/initval.h>
#include "usbaudio.h"
-
+#include "usbmidi.h"
+#include "usbmixer.h"
MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
MODULE_DESCRIPTION("USB Audio");
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 42c299c..49a691a 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -21,9 +21,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/* maximum number of endpoints per interface */
-#define MIDI_MAX_ENDPOINTS 2
-
/* handling of USB vendor/product ID pairs as 32-bit numbers */
#define USB_ID(vendor, product) (((vendor) << 16) | (product))
#define USB_ID_VENDOR(id) ((id) >> 16)
@@ -89,39 +86,6 @@ struct snd_usb_audio_quirk {
const void *data;
};
-/* data for QUIRK_MIDI_FIXED_ENDPOINT */
-struct snd_usb_midi_endpoint_info {
- int8_t out_ep; /* ep number, 0 autodetect */
- uint8_t out_interval; /* interval for interrupt endpoints */
- int8_t in_ep;
- uint8_t in_interval;
- uint16_t out_cables; /* bitmask */
- uint16_t in_cables; /* bitmask */
-};
-
-/* for QUIRK_MIDI_YAMAHA, data is NULL */
-
-/* for QUIRK_MIDI_MIDIMAN, data points to a snd_usb_midi_endpoint_info
- * structure (out_cables and in_cables only) */
-
-/* for QUIRK_COMPOSITE, data points to an array of snd_usb_audio_quirk
- * structures, terminated with .ifnum = -1 */
-
-/* for QUIRK_AUDIO_FIXED_ENDPOINT, data points to an audioformat structure */
-
-/* for QUIRK_AUDIO/MIDI_STANDARD_INTERFACE, data is NULL */
-
-/* for QUIRK_AUDIO_EDIROL_UAXX, data is NULL */
-
-/* for QUIRK_IGNORE_INTERFACE, data is NULL */
-
-/* for QUIRK_MIDI_NOVATION and _RAW, data is NULL */
-
-/* for QUIRK_MIDI_EMAGIC, data points to a snd_usb_midi_endpoint_info
- * structure (out_cables and in_cables only) */
-
-/* for QUIRK_MIDI_CME, data is NULL */
-
/*
*/
@@ -148,21 +112,6 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe,
__u8 request, __u8 requesttype, __u16 value, __u16 index,
void *data, __u16 size, int timeout);
-int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
- int ignore_error);
-void snd_usb_mixer_disconnect(struct list_head *p);
-
-int snd_usbmidi_create(struct snd_card *card,
- struct usb_interface *iface,
- struct list_head *midi_list,
- const struct snd_usb_audio_quirk *quirk);
-void snd_usbmidi_input_stop(struct list_head* p);
-void snd_usbmidi_input_start(struct list_head* p);
-void snd_usbmidi_disconnect(struct list_head *p);
-
-void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
- unsigned char samplerate_id);
-
/*
* retrieve usb_interface descriptor from the host interface
* (conditional for compatibility with the older API)
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 2c59afd..5915a04 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -53,6 +53,7 @@
#include <sound/rawmidi.h>
#include <sound/asequencer.h>
#include "usbaudio.h"
+#include "usbmidi.h"
/*
diff --git a/sound/usb/usbmidi.h b/sound/usb/usbmidi.h
new file mode 100644
index 0000000..2089ec9
--- /dev/null
+++ b/sound/usb/usbmidi.h
@@ -0,0 +1,48 @@
+#ifndef __USBMIDI_H
+#define __USBMIDI_H
+
+/* maximum number of endpoints per interface */
+#define MIDI_MAX_ENDPOINTS 2
+
+/* data for QUIRK_MIDI_FIXED_ENDPOINT */
+struct snd_usb_midi_endpoint_info {
+ int8_t out_ep; /* ep number, 0 autodetect */
+ uint8_t out_interval; /* interval for interrupt endpoints */
+ int8_t in_ep;
+ uint8_t in_interval;
+ uint16_t out_cables; /* bitmask */
+ uint16_t in_cables; /* bitmask */
+};
+
+/* for QUIRK_MIDI_YAMAHA, data is NULL */
+
+/* for QUIRK_MIDI_MIDIMAN, data points to a snd_usb_midi_endpoint_info
+ * structure (out_cables and in_cables only) */
+
+/* for QUIRK_COMPOSITE, data points to an array of snd_usb_audio_quirk
+ * structures, terminated with .ifnum = -1 */
+
+/* for QUIRK_AUDIO_FIXED_ENDPOINT, data points to an audioformat structure */
+
+/* for QUIRK_AUDIO/MIDI_STANDARD_INTERFACE, data is NULL */
+
+/* for QUIRK_AUDIO_EDIROL_UA700_UA25/UA1000, data is NULL */
+
+/* for QUIRK_IGNORE_INTERFACE, data is NULL */
+
+/* for QUIRK_MIDI_NOVATION and _RAW, data is NULL */
+
+/* for QUIRK_MIDI_EMAGIC, data points to a snd_usb_midi_endpoint_info
+ * structure (out_cables and in_cables only) */
+
+/* for QUIRK_MIDI_CME, data is NULL */
+
+int snd_usbmidi_create(struct snd_card *card,
+ struct usb_interface *iface,
+ struct list_head *midi_list,
+ const struct snd_usb_audio_quirk *quirk);
+void snd_usbmidi_input_stop(struct list_head* p);
+void snd_usbmidi_input_start(struct list_head* p);
+void snd_usbmidi_disconnect(struct list_head *p);
+
+#endif /* __USBMIDI_H */
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index 8e8f871..43d53a3 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -41,6 +41,7 @@
#include <sound/tlv.h>
#include "usbaudio.h"
+#include "usbmixer.h"
/*
*/
diff --git a/sound/usb/usbmixer.h b/sound/usb/usbmixer.h
new file mode 100644
index 0000000..e199e4b
--- /dev/null
+++ b/sound/usb/usbmixer.h
@@ -0,0 +1,11 @@
+#ifndef __USBMIXER_H
+#define __USBMIXER_H
+
+int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
+ int ignore_error);
+void snd_usb_mixer_disconnect(struct list_head *p);
+
+void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
+ unsigned char samplerate_id);
+
+#endif /* __USBMIXER_H */
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c
index 44deb21..4f6518c 100644
--- a/sound/usb/usx2y/us122l.c
+++ b/sound/usb/usx2y/us122l.c
@@ -25,6 +25,7 @@
#define MODNAME "US122L"
#include "usb_stream.c"
#include "../usbaudio.h"
+#include "../usbmidi.h"
#include "us122l.h"
MODULE_AUTHOR("Karsten Wiese <fzu@wemgehoertderstaat.de>");
diff --git a/sound/usb/usx2y/usbusx2y.h b/sound/usb/usx2y/usbusx2y.h
index 1d174ce..9ab97b4 100644
--- a/sound/usb/usx2y/usbusx2y.h
+++ b/sound/usb/usx2y/usbusx2y.h
@@ -1,6 +1,7 @@
#ifndef USBUSX2Y_H
#define USBUSX2Y_H
#include "../usbaudio.h"
+#include "../usbmidi.h"
#include "usbus428ctldefs.h"
#define NRURBS 2
--
1.6.6.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/8] ALSA: usb-audio: rename substream format field to altset_idx
[not found] ` <1267774885-16266-4-git-send-email-daniel@caiaq.de>
@ 2010-03-05 7:41 ` Daniel Mack
2010-03-05 7:41 ` [PATCH 5/8] ALSA: usb-audio: use a format bitmask per alternate setting Daniel Mack
0 siblings, 1 reply; 9+ messages in thread
From: Daniel Mack @ 2010-03-05 7:41 UTC (permalink / raw)
To: alsa-devel; +Cc: tiwai, clemens
From: Clemens Ladisch <clemens@ladisch.de>
The snd_usb_substream::format field actually contains the index of the
current alternate setting, so rename it to altset_idx to avoid
confusion.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
---
sound/usb/card.h | 2 +-
sound/usb/pcm.c | 8 ++++----
sound/usb/proc.c | 2 +-
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 71f03c1..856d71b 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -54,7 +54,7 @@ struct snd_usb_substream {
struct audioformat *cur_audiofmt; /* current audioformat pointer (for hw_params callback) */
unsigned int cur_rate; /* current rate (for hw_params callback) */
unsigned int period_bytes; /* current period bytes (for hw_params callback) */
- unsigned int format; /* USB data format */
+ unsigned int altset_idx; /* USB data format: index of alternate setting */
unsigned int datapipe; /* the data i/o pipe */
unsigned int syncpipe; /* 1 - async out or adaptive in */
unsigned int datainterval; /* log_2 of data packet interval */
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 87863cc..c3d5a97 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -202,11 +202,11 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
return -EIO;
}
subs->interface = -1;
- subs->format = 0;
+ subs->altset_idx = 0;
}
/* set interface */
- if (subs->interface != fmt->iface || subs->format != fmt->altset_idx) {
+ if (subs->interface != fmt->iface || subs->altset_idx != fmt->altset_idx) {
if (usb_set_interface(dev, fmt->iface, fmt->altsetting) < 0) {
snd_printk(KERN_ERR "%d:%d:%d: usb_set_interface failed\n",
dev->devnum, fmt->iface, fmt->altsetting);
@@ -214,7 +214,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
}
snd_printdd(KERN_INFO "setting usb interface %d:%d\n", fmt->iface, fmt->altsetting);
subs->interface = fmt->iface;
- subs->format = fmt->altset_idx;
+ subs->altset_idx = fmt->altset_idx;
}
/* create a data pipe */
@@ -771,7 +771,7 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
struct snd_usb_substream *subs = &as->substream[direction];
subs->interface = -1;
- subs->format = 0;
+ subs->altset_idx = 0;
runtime->hw = snd_usb_hardware;
runtime->private_data = subs;
subs->pcm_substream = substream;
diff --git a/sound/usb/proc.c b/sound/usb/proc.c
index be3065e..78fc3ba 100644
--- a/sound/usb/proc.c
+++ b/sound/usb/proc.c
@@ -116,7 +116,7 @@ static void proc_dump_substream_status(struct snd_usb_substream *subs, struct sn
unsigned int i;
snd_iprintf(buffer, " Status: Running\n");
snd_iprintf(buffer, " Interface = %d\n", subs->interface);
- snd_iprintf(buffer, " Altset = %d\n", subs->format);
+ snd_iprintf(buffer, " Altset = %d\n", subs->altset_idx);
snd_iprintf(buffer, " URBs = %d [ ", subs->nurbs);
for (i = 0; i < subs->nurbs; i++)
snd_iprintf(buffer, "%d ", subs->dataurb[i].packets);
--
1.6.6.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 5/8] ALSA: usb-audio: use a format bitmask per alternate setting
2010-03-05 7:41 ` [PATCH 4/8] ALSA: usb-audio: rename substream format field to altset_idx Daniel Mack
@ 2010-03-05 7:41 ` Daniel Mack
2010-03-05 7:41 ` [PATCH 6/8] ALSA: usb-audio: support multiple formats with audio class v2 devices Daniel Mack
0 siblings, 1 reply; 9+ messages in thread
From: Daniel Mack @ 2010-03-05 7:41 UTC (permalink / raw)
To: alsa-devel; +Cc: tiwai, clemens
From: Clemens Ladisch <clemens@ladisch.de>
In preparation for USB audio 2.0 support, change the audioformat
structure so that it uses a bitmask to specify possible formats.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
---
sound/usb/card.h | 2 +-
sound/usb/endpoint.c | 4 ++--
sound/usb/format.c | 10 +++++-----
sound/usb/pcm.c | 13 ++++++++++---
sound/usb/proc.c | 9 +++++++--
sound/usb/quirks-table.h | 12 ++++++------
sound/usb/quirks.c | 2 +-
sound/usb/urb.c | 4 ++--
8 files changed, 34 insertions(+), 22 deletions(-)
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 856d71b..ed92420 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -9,7 +9,7 @@
struct audioformat {
struct list_head list;
- snd_pcm_format_t format; /* format type */
+ u64 formats; /* ALSA format bits */
unsigned int channels; /* # channels */
unsigned int fmt_type; /* USB audio format type (1-3) */
unsigned int frame_size; /* samples per frame for non-audio */
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 3f53dee..d65235c 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -94,7 +94,7 @@ int snd_usb_add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct au
if (subs->endpoint == fp->endpoint) {
list_add_tail(&fp->list, &subs->fmt_list);
subs->num_formats++;
- subs->formats |= 1ULL << fp->format;
+ subs->formats |= fp->formats;
return 0;
}
}
@@ -268,7 +268,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
*/
if (fmt[4] == 1 && fmt[5] == 2 && altno == 2 && num == 3 &&
fp && fp->altsetting == 1 && fp->channels == 1 &&
- fp->format == SNDRV_PCM_FORMAT_S16_LE &&
+ fp->formats == SNDRV_PCM_FMTBIT_S16_LE &&
protocol == UAC_VERSION_1 &&
le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) ==
fp->maxpacksize * 2)
diff --git a/sound/usb/format.c b/sound/usb/format.c
index cbfe0c2..87f07f0 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -323,7 +323,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
return -1;
}
- fp->format = pcm_format;
+ fp->formats = 1uLL << pcm_format;
/* gather possible sample rates */
/* audio class v1 reports possible sample rates as part of the
@@ -365,16 +365,16 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,
switch (format) {
case UAC_FORMAT_TYPE_II_AC3:
/* FIXME: there is no AC3 format defined yet */
- // fp->format = SNDRV_PCM_FORMAT_AC3;
- fp->format = SNDRV_PCM_FORMAT_U8; /* temporarily hack to receive byte streams */
+ // fp->formats = SNDRV_PCM_FMTBIT_AC3;
+ fp->formats = SNDRV_PCM_FMTBIT_U8; /* temporary hack to receive byte streams */
break;
case UAC_FORMAT_TYPE_II_MPEG:
- fp->format = SNDRV_PCM_FORMAT_MPEG;
+ fp->formats = SNDRV_PCM_FMTBIT_MPEG;
break;
default:
snd_printd(KERN_INFO "%d:%u:%d : unknown format tag %#x is detected. processed as MPEG.\n",
chip->dev->devnum, fp->iface, fp->altsetting, format);
- fp->format = SNDRV_PCM_FORMAT_MPEG;
+ fp->formats = SNDRV_PCM_FMTBIT_MPEG;
break;
}
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index c3d5a97..bd0f84f 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -58,7 +58,9 @@ static struct audioformat *find_format(struct snd_usb_substream *subs, unsigned
list_for_each(p, &subs->fmt_list) {
struct audioformat *fp;
fp = list_entry(p, struct audioformat, list);
- if (fp->format != format || fp->channels != channels)
+ if (!(fp->formats & (1uLL << format)))
+ continue;
+ if (fp->channels != channels)
continue;
if (rate < fp->rate_min || rate > fp->rate_max)
continue;
@@ -428,10 +430,15 @@ static int hw_check_valid_format(struct snd_usb_substream *subs,
struct snd_interval *ct = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
struct snd_mask *fmts = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
struct snd_interval *pt = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME);
+ struct snd_mask check_fmts;
unsigned int ptime;
/* check the format */
- if (!snd_mask_test(fmts, fp->format)) {
+ snd_mask_none(&check_fmts);
+ check_fmts.bits[0] = (u32)fp->formats;
+ check_fmts.bits[1] = (u32)(fp->formats >> 32);
+ snd_mask_intersect(&check_fmts, fmts);
+ if (snd_mask_empty(&check_fmts)) {
hwc_debug(" > check: no supported format %d\n", fp->format);
return 0;
}
@@ -584,7 +591,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
fp = list_entry(p, struct audioformat, list);
if (!hw_check_valid_format(subs, params, fp))
continue;
- fbits |= (1ULL << fp->format);
+ fbits |= fp->formats;
}
oldbits[0] = fmt->bits[0];
diff --git a/sound/usb/proc.c b/sound/usb/proc.c
index 78fc3ba..f5e3f35 100644
--- a/sound/usb/proc.c
+++ b/sound/usb/proc.c
@@ -79,11 +79,16 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
list_for_each(p, &subs->fmt_list) {
struct audioformat *fp;
+ snd_pcm_format_t fmt;
fp = list_entry(p, struct audioformat, list);
snd_iprintf(buffer, " Interface %d\n", fp->iface);
snd_iprintf(buffer, " Altset %d\n", fp->altsetting);
- snd_iprintf(buffer, " Format: %s\n",
- snd_pcm_format_name(fp->format));
+ snd_iprintf(buffer, " Format:");
+ for (fmt = 0; fmt <= SNDRV_PCM_FORMAT_LAST; ++fmt)
+ if (fp->formats & (1uLL << fmt))
+ snd_iprintf(buffer, " %s",
+ snd_pcm_format_name(fmt));
+ snd_iprintf(buffer, "\n");
snd_iprintf(buffer, " Channels: %d\n", fp->channels);
snd_iprintf(buffer, " Endpoint: %d %s (%s)\n",
fp->endpoint & USB_ENDPOINT_NUMBER_MASK,
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 2b426c1..6e8651d 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -279,7 +279,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.ifnum = 0,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = & (const struct audioformat) {
- .format = SNDRV_PCM_FORMAT_S16_LE,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels = 4,
.iface = 0,
.altsetting = 1,
@@ -296,7 +296,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.ifnum = 1,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = & (const struct audioformat) {
- .format = SNDRV_PCM_FORMAT_S16_LE,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels = 2,
.iface = 1,
.altsetting = 1,
@@ -580,7 +580,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.ifnum = 0,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = & (const struct audioformat) {
- .format = SNDRV_PCM_FORMAT_S24_3LE,
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 2,
.iface = 0,
.altsetting = 1,
@@ -597,7 +597,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.ifnum = 1,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = & (const struct audioformat) {
- .format = SNDRV_PCM_FORMAT_S24_3LE,
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 2,
.iface = 1,
.altsetting = 1,
@@ -793,7 +793,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.ifnum = 1,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = & (const struct audioformat) {
- .format = SNDRV_PCM_FORMAT_S24_3LE,
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 2,
.iface = 1,
.altsetting = 1,
@@ -810,7 +810,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.ifnum = 2,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = & (const struct audioformat) {
- .format = SNDRV_PCM_FORMAT_S24_3LE,
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 2,
.iface = 2,
.altsetting = 1,
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 4c16920..99a19ba 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -174,7 +174,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
const struct snd_usb_audio_quirk *quirk)
{
static const struct audioformat ua_format = {
- .format = SNDRV_PCM_FORMAT_S24_3LE,
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 2,
.fmt_type = UAC_FORMAT_TYPE_I,
.altsetting = 1,
diff --git a/sound/usb/urb.c b/sound/usb/urb.c
index e9c339f..ad50d43 100644
--- a/sound/usb/urb.c
+++ b/sound/usb/urb.c
@@ -662,7 +662,7 @@ static int prepare_nodata_playback_urb(struct snd_usb_substream *subs,
urb->number_of_packets = ctx->packets;
urb->transfer_buffer_length = offs * stride;
memset(urb->transfer_buffer,
- subs->cur_audiofmt->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0,
+ runtime->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0,
offs * stride);
return 0;
}
@@ -924,7 +924,7 @@ void snd_usb_init_substream(struct snd_usb_stream *as,
snd_usb_set_pcm_ops(as->pcm, stream);
list_add_tail(&fp->list, &subs->fmt_list);
- subs->formats |= 1ULL << fp->format;
+ subs->formats |= fp->formats;
subs->endpoint = fp->endpoint;
subs->num_formats++;
subs->fmt_type = fp->fmt_type;
--
1.6.6.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 6/8] ALSA: usb-audio: support multiple formats with audio class v2 devices
2010-03-05 7:41 ` [PATCH 5/8] ALSA: usb-audio: use a format bitmask per alternate setting Daniel Mack
@ 2010-03-05 7:41 ` Daniel Mack
2010-03-05 7:41 ` [PATCH 7/8] ALSA: usb-audio: add support for samplerate setting on " Daniel Mack
0 siblings, 1 reply; 9+ messages in thread
From: Daniel Mack @ 2010-03-05 7:41 UTC (permalink / raw)
To: alsa-devel; +Cc: tiwai, clemens
From: Clemens Ladisch <clemens@ladisch.de>
Change the parser to correctly handle v2 descriptors with multiple
format bits set.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
---
sound/usb/format.c | 93 +++++++++++++++++++---------------------------
sound/usb/quirks-table.h | 2 +-
2 files changed, 39 insertions(+), 56 deletions(-)
diff --git a/sound/usb/format.c b/sound/usb/format.c
index 87f07f0..b613e0a 100644
--- a/sound/usb/format.c
+++ b/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(struct snd_usb_audio *chip,
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(struct snd_usb_audio *chip,
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(struct snd_usb_audio *chip,
/* 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(struct snd_usb_audio *chip,
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;
}
@@ -317,14 +300,14 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
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.
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 6e8651d..81c5f8a 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2203,7 +2203,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.ifnum = 1,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = &(const struct audioformat) {
- .format = SNDRV_PCM_FORMAT_S24_3BE,
+ .formats = SNDRV_PCM_FMTBIT_S24_3BE,
.channels = 2,
.iface = 1,
.altsetting = 1,
--
1.6.6.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 7/8] ALSA: usb-audio: add support for samplerate setting on v2 devices
2010-03-05 7:41 ` [PATCH 6/8] ALSA: usb-audio: support multiple formats with audio class v2 devices Daniel Mack
@ 2010-03-05 7:41 ` Daniel Mack
2010-03-05 7:41 ` [PATCH 8/8] usb/audio.h: Fix field order Daniel Mack
0 siblings, 1 reply; 9+ messages in thread
From: Daniel Mack @ 2010-03-05 7:41 UTC (permalink / raw)
To: alsa-devel; +Cc: tiwai, clemens
Sample rate setting is done with a 4-byte long class request that
addresses the interface.
Signed-off-by: Daniel Mack <daniel@caiaq.de>
Cc: Clemens Ladisch <clemens@ladisch.de>
Cc: Takashi Iwai <tiwai@suse.de>
---
sound/usb/endpoint.c | 4 +-
sound/usb/pcm.c | 173 ++++++++++++++++++++++++++++++++++++-------------
sound/usb/pcm.h | 4 +-
sound/usb/quirks.c | 4 +-
4 files changed, 133 insertions(+), 52 deletions(-)
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index d65235c..91850f8 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -350,8 +350,8 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
}
/* try to set the interface... */
usb_set_interface(chip->dev, iface_no, altno);
- snd_usb_init_pitch(chip->dev, iface_no, alts, fp);
- snd_usb_init_sample_rate(chip->dev, iface_no, alts, fp, fp->rate_max);
+ snd_usb_init_pitch(chip, iface_no, alts, fp);
+ snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max);
}
return 0;
}
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index bd0f84f..e0f3f87 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -107,69 +107,150 @@ static struct audioformat *find_format(struct snd_usb_substream *subs, unsigned
return found;
}
+static int init_pitch_v1(struct snd_usb_audio *chip, int iface,
+ struct usb_host_interface *alts,
+ struct audioformat *fmt)
+{
+ struct usb_device *dev = chip->dev;
+ unsigned int ep;
+ unsigned char data[1];
+ int err;
+
+ ep = get_endpoint(alts, 0)->bEndpointAddress;
+
+ /* if endpoint doesn't have pitch control, bail out */
+ if (!(fmt->attributes & UAC_EP_CS_ATTR_PITCH_CONTROL))
+ return 0;
+
+ data[0] = 1;
+ if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
+ USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
+ UAC_EP_CS_ATTR_PITCH_CONTROL << 8, ep,
+ data, sizeof(data), 1000)) < 0) {
+ snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH\n",
+ dev->devnum, iface, ep);
+ return err;
+ }
+
+ return 0;
+}
/*
* initialize the picth control and sample rate
*/
-int snd_usb_init_pitch(struct usb_device *dev, int iface,
+int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
struct usb_host_interface *alts,
struct audioformat *fmt)
{
+ struct usb_interface_descriptor *altsd = get_iface_desc(alts);
+
+ switch (altsd->bInterfaceProtocol) {
+ case UAC_VERSION_1:
+ return init_pitch_v1(chip, iface, alts, fmt);
+
+ case UAC_VERSION_2:
+ /* not implemented yet */
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
+ struct usb_host_interface *alts,
+ struct audioformat *fmt, int rate)
+{
+ struct usb_device *dev = chip->dev;
unsigned int ep;
- unsigned char data[1];
- int err;
+ unsigned char data[3];
+ int err, crate;
ep = get_endpoint(alts, 0)->bEndpointAddress;
- /* if endpoint has pitch control, enable it */
- if (fmt->attributes & UAC_EP_CS_ATTR_PITCH_CONTROL) {
- data[0] = 1;
- if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
- USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
- UAC_EP_CS_ATTR_PITCH_CONTROL << 8, ep, data, 1, 1000)) < 0) {
- snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH\n",
- dev->devnum, iface, ep);
- return err;
- }
+ /* if endpoint doesn't have sampling rate control, bail out */
+ if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE)) {
+ snd_printk(KERN_WARNING "%d:%d:%d: endpoint lacks sample rate attribute bit, cannot set.\n",
+ dev->devnum, iface, fmt->altsetting);
+ return 0;
+ }
+
+ data[0] = rate;
+ data[1] = rate >> 8;
+ data[2] = rate >> 16;
+ if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
+ USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
+ UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
+ data, sizeof(data), 1000)) < 0) {
+ snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n",
+ dev->devnum, iface, fmt->altsetting, rate, ep);
+ return err;
}
+ if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
+ USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
+ UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
+ data, sizeof(data), 1000)) < 0) {
+ snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n",
+ dev->devnum, iface, fmt->altsetting, ep);
+ return 0; /* some devices don't support reading */
+ }
+ crate = data[0] | (data[1] << 8) | (data[2] << 16);
+ if (crate != rate) {
+ snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
+ // runtime->rate = crate;
+ }
+
return 0;
}
-int snd_usb_init_sample_rate(struct usb_device *dev, int iface,
+static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
+ struct usb_host_interface *alts,
+ struct audioformat *fmt, int rate)
+{
+ struct usb_device *dev = chip->dev;
+ unsigned char data[4];
+ int err, crate;
+
+ data[0] = rate;
+ data[1] = rate >> 8;
+ data[2] = rate >> 16;
+ data[3] = rate >> 24;
+ if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ 0x0100, chip->clock_id << 8,
+ data, sizeof(data), 1000)) < 0) {
+ snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2)\n",
+ dev->devnum, iface, fmt->altsetting, rate);
+ return err;
+ }
+ if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+ 0x0100, chip->clock_id << 8,
+ data, sizeof(data), 1000)) < 0) {
+ snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n",
+ dev->devnum, iface, fmt->altsetting);
+ return err;
+ }
+ crate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
+ if (crate != rate)
+ snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
+
+ return 0;
+}
+
+int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
struct usb_host_interface *alts,
struct audioformat *fmt, int rate)
{
- unsigned int ep;
- unsigned char data[3];
- int err;
+ struct usb_interface_descriptor *altsd = get_iface_desc(alts);
- ep = get_endpoint(alts, 0)->bEndpointAddress;
- /* if endpoint has sampling rate control, set it */
- if (fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE) {
- int crate;
- data[0] = rate;
- data[1] = rate >> 8;
- data[2] = rate >> 16;
- if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
- USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
- UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, data, 3, 1000)) < 0) {
- snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n",
- dev->devnum, iface, fmt->altsetting, rate, ep);
- return err;
- }
- if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
- USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
- UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, data, 3, 1000)) < 0) {
- snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n",
- dev->devnum, iface, fmt->altsetting, ep);
- return 0; /* some devices don't support reading */
- }
- crate = data[0] | (data[1] << 8) | (data[2] << 16);
- if (crate != rate) {
- snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
- // runtime->rate = crate;
- }
+ switch (altsd->bInterfaceProtocol) {
+ case UAC_VERSION_1:
+ return set_sample_rate_v1(chip, iface, alts, fmt, rate);
+
+ case UAC_VERSION_2:
+ return set_sample_rate_v2(chip, iface, alts, fmt, rate);
}
- return 0;
+
+ return -EINVAL;
}
/*
@@ -280,7 +361,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
if (fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX)
subs->fill_max = 1;
- if ((err = snd_usb_init_pitch(dev, subs->interface, alts, fmt)) < 0)
+ if ((err = snd_usb_init_pitch(subs->stream->chip, subs->interface, alts, fmt)) < 0)
return err;
subs->cur_audiofmt = fmt;
@@ -343,7 +424,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
struct usb_interface *iface;
iface = usb_ifnum_to_if(subs->dev, fmt->iface);
alts = &iface->altsetting[fmt->altset_idx];
- ret = snd_usb_init_sample_rate(subs->dev, subs->interface, alts, fmt, rate);
+ ret = snd_usb_init_sample_rate(subs->stream->chip, subs->interface, alts, fmt, rate);
if (ret < 0)
return ret;
subs->cur_rate = rate;
diff --git a/sound/usb/pcm.h b/sound/usb/pcm.h
index 8585601..1c931b6 100644
--- a/sound/usb/pcm.h
+++ b/sound/usb/pcm.h
@@ -3,11 +3,11 @@
void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream);
-int snd_usb_init_pitch(struct usb_device *dev, int iface,
+int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
struct usb_host_interface *alts,
struct audioformat *fmt);
-int snd_usb_init_sample_rate(struct usb_device *dev, int iface,
+int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
struct usb_host_interface *alts,
struct audioformat *fmt, int rate);
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 99a19ba..0c0b23b 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -159,8 +159,8 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
fp->datainterval = snd_usb_parse_datainterval(chip, alts);
fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
usb_set_interface(chip->dev, fp->iface, 0);
- snd_usb_init_pitch(chip->dev, fp->iface, alts, fp);
- snd_usb_init_sample_rate(chip->dev, fp->iface, alts, fp, fp->rate_max);
+ snd_usb_init_pitch(chip, fp->iface, alts, fp);
+ snd_usb_init_sample_rate(chip, fp->iface, alts, fp, fp->rate_max);
return 0;
}
--
1.6.6.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 8/8] usb/audio.h: Fix field order
2010-03-05 7:41 ` [PATCH 7/8] ALSA: usb-audio: add support for samplerate setting on " Daniel Mack
@ 2010-03-05 7:41 ` Daniel Mack
0 siblings, 0 replies; 9+ messages in thread
From: Daniel Mack @ 2010-03-05 7:41 UTC (permalink / raw)
To: alsa-devel; +Cc: tiwai, clemens
Signed-off-by: Daniel Mack <daniel@caiaq.de>
Cc: Clemens Ladisch <clemens@ladisch.de>
Cc: Takashi Iwai <tiwai@suse.de>
---
include/linux/usb/audio.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/include/linux/usb/audio.h b/include/linux/usb/audio.h
index 6bb2936..4d3e450 100644
--- a/include/linux/usb/audio.h
+++ b/include/linux/usb/audio.h
@@ -269,8 +269,8 @@ struct uac_format_type_i_ext_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubtype;
- __u8 bSubslotSize;
__u8 bFormatType;
+ __u8 bSubslotSize;
__u8 bBitResolution;
__u8 bHeaderLength;
__u8 bControlSize;
--
1.6.6.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: usb-audio code refactoring, more v2 support [resend]
2010-03-05 7:41 usb-audio code refactoring, more v2 support [resend] Daniel Mack
2010-03-05 7:41 ` [PATCH 1/8] ALSA: usb-audio: move ua101 driver Daniel Mack
@ 2010-03-05 7:52 ` Daniel Mack
1 sibling, 0 replies; 9+ messages in thread
From: Daniel Mack @ 2010-03-05 7:52 UTC (permalink / raw)
To: alsa-devel; +Cc: tiwai, clemens
On Fri, Mar 05, 2010 at 08:41:17AM +0100, Daniel Mack wrote:
> This is a rebased version of the usb-audio cleanup patch set.
> On top of what's already been posted, there is one more fix to support
> sample rate configuration, and one bugfix.
>
> Commit 864c11080 was also ported over. And Clemens' latest patches
> are also included.
>
> With these patches applied, I can stream audio on a class v2 device.
> At least for awhile, then I get CRC errors in DATA0 packets. But
> that's a different issue.
>
> What's not yet done is all the feature unit parsing, mixers etc.
>
> Daniel
>
> [PATCH 1/8] ALSA: usb-audio: move ua101 driver
> [PATCH 2/8] ALSA: usb-audio: header file cleanups
> [PATCH 3/8] ALSA: usb-audio: refactor code
> [PATCH 4/8] ALSA: usb-audio: rename substream format field to altset_idx
> [PATCH 5/8] ALSA: usb-audio: use a format bitmask per alternate setting
> [PATCH 6/8] ALSA: usb-audio: support multiple formats with audio class v2 devices
> [PATCH 7/8] ALSA: usb-audio: add support for samplerate setting on v2 devices
> [PATCH 8/8] usb/audio.h: Fix field order
Takashi applied all these now to a new branch. Even though the changes
made to the driver should only affect devices compliant to v2 of the USB
audio standard, I could have introduced bugs when refactoring the code.
So - if anyone with a common USB audio device could try this branch and
report any regressions, that would help a lot, and make the branch merge
smoother eventually.
git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git topic/usb
Thanks,
Daniel
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2010-03-05 7:52 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-03-05 7:41 usb-audio code refactoring, more v2 support [resend] Daniel Mack
2010-03-05 7:41 ` [PATCH 1/8] ALSA: usb-audio: move ua101 driver Daniel Mack
2010-03-05 7:41 ` [PATCH 2/8] ALSA: usb-audio: header file cleanups Daniel Mack
[not found] ` <1267774885-16266-4-git-send-email-daniel@caiaq.de>
2010-03-05 7:41 ` [PATCH 4/8] ALSA: usb-audio: rename substream format field to altset_idx Daniel Mack
2010-03-05 7:41 ` [PATCH 5/8] ALSA: usb-audio: use a format bitmask per alternate setting Daniel Mack
2010-03-05 7:41 ` [PATCH 6/8] ALSA: usb-audio: support multiple formats with audio class v2 devices Daniel Mack
2010-03-05 7:41 ` [PATCH 7/8] ALSA: usb-audio: add support for samplerate setting on " Daniel Mack
2010-03-05 7:41 ` [PATCH 8/8] usb/audio.h: Fix field order Daniel Mack
2010-03-05 7:52 ` usb-audio code refactoring, more v2 support [resend] Daniel Mack
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).