aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/usbmixer.c
diff options
context:
space:
mode:
authorDaniel Mack <daniel@caiaq.de>2010-02-22 17:49:09 -0500
committerTakashi Iwai <tiwai@suse.de>2010-02-23 02:40:12 -0500
commit28e1b773083d349d5223f586a39fa30f5d0f1c36 (patch)
tree4793eb1d87a094cf3642600ac3b201f81bab7e54 /sound/usb/usbmixer.c
parent40717382e0c1f572553e4fdefb489db4b95a5e7e (diff)
ALSA: usbaudio: parse USB descriptors with structs
In preparation of support for v2.0 audio class, use the structs from linux/usb/audio.h and add some new ones to describe the fields that are actually parsed by the descriptor decoders. Also, factor out code from usb_create_streams(). This makes it easier to adopt the new iteration logic needed for v2.0. Signed-off-by: Daniel Mack <daniel@caiaq.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb/usbmixer.c')
-rw-r--r--sound/usb/usbmixer.c37
1 files changed, 20 insertions, 17 deletions
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index 35b4830fb0c4..11636a6112d5 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -32,6 +32,8 @@
32#include <linux/slab.h> 32#include <linux/slab.h>
33#include <linux/string.h> 33#include <linux/string.h>
34#include <linux/usb.h> 34#include <linux/usb.h>
35#include <linux/usb/audio.h>
36
35#include <sound/core.h> 37#include <sound/core.h>
36#include <sound/control.h> 38#include <sound/control.h>
37#include <sound/hwdep.h> 39#include <sound/hwdep.h>
@@ -1086,29 +1088,30 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc,
1086 * 1088 *
1087 * most of controlls are defined here. 1089 * most of controlls are defined here.
1088 */ 1090 */
1089static int parse_audio_feature_unit(struct mixer_build *state, int unitid, unsigned char *ftr) 1091static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void *_ftr)
1090{ 1092{
1091 int channels, i, j; 1093 int channels, i, j;
1092 struct usb_audio_term iterm; 1094 struct usb_audio_term iterm;
1093 unsigned int master_bits, first_ch_bits; 1095 unsigned int master_bits, first_ch_bits;
1094 int err, csize; 1096 int err, csize;
1097 struct uac_feature_unit_descriptor *ftr = _ftr;
1095 1098
1096 if (ftr[0] < 7 || ! (csize = ftr[5]) || ftr[0] < 7 + csize) { 1099 if (ftr->bLength < 7 || ! (csize = ftr->bControlSize) || ftr->bLength < 7 + csize) {
1097 snd_printk(KERN_ERR "usbaudio: unit %u: invalid FEATURE_UNIT descriptor\n", unitid); 1100 snd_printk(KERN_ERR "usbaudio: unit %u: invalid FEATURE_UNIT descriptor\n", unitid);
1098 return -EINVAL; 1101 return -EINVAL;
1099 } 1102 }
1100 1103
1101 /* parse the source unit */ 1104 /* parse the source unit */
1102 if ((err = parse_audio_unit(state, ftr[4])) < 0) 1105 if ((err = parse_audio_unit(state, ftr->bSourceID)) < 0)
1103 return err; 1106 return err;
1104 1107
1105 /* determine the input source type and name */ 1108 /* determine the input source type and name */
1106 if (check_input_term(state, ftr[4], &iterm) < 0) 1109 if (check_input_term(state, ftr->bSourceID, &iterm) < 0)
1107 return -EINVAL; 1110 return -EINVAL;
1108 1111
1109 channels = (ftr[0] - 7) / csize - 1; 1112 channels = (ftr->bLength - 7) / csize - 1;
1110 1113
1111 master_bits = snd_usb_combine_bytes(ftr + 6, csize); 1114 master_bits = snd_usb_combine_bytes(ftr->controls, csize);
1112 /* master configuration quirks */ 1115 /* master configuration quirks */
1113 switch (state->chip->usb_id) { 1116 switch (state->chip->usb_id) {
1114 case USB_ID(0x08bb, 0x2702): 1117 case USB_ID(0x08bb, 0x2702):
@@ -1119,21 +1122,21 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, unsig
1119 break; 1122 break;
1120 } 1123 }
1121 if (channels > 0) 1124 if (channels > 0)
1122 first_ch_bits = snd_usb_combine_bytes(ftr + 6 + csize, csize); 1125 first_ch_bits = snd_usb_combine_bytes(ftr->controls + csize, csize);
1123 else 1126 else
1124 first_ch_bits = 0; 1127 first_ch_bits = 0;
1125 /* check all control types */ 1128 /* check all control types */
1126 for (i = 0; i < 10; i++) { 1129 for (i = 0; i < 10; i++) {
1127 unsigned int ch_bits = 0; 1130 unsigned int ch_bits = 0;
1128 for (j = 0; j < channels; j++) { 1131 for (j = 0; j < channels; j++) {
1129 unsigned int mask = snd_usb_combine_bytes(ftr + 6 + csize * (j+1), csize); 1132 unsigned int mask = snd_usb_combine_bytes(ftr->controls + csize * (j+1), csize);
1130 if (mask & (1 << i)) 1133 if (mask & (1 << i))
1131 ch_bits |= (1 << j); 1134 ch_bits |= (1 << j);
1132 } 1135 }
1133 if (ch_bits & 1) /* the first channel must be set (for ease of programming) */ 1136 if (ch_bits & 1) /* the first channel must be set (for ease of programming) */
1134 build_feature_ctl(state, ftr, ch_bits, i, &iterm, unitid); 1137 build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid);
1135 if (master_bits & (1 << i)) 1138 if (master_bits & (1 << i))
1136 build_feature_ctl(state, ftr, 0, i, &iterm, unitid); 1139 build_feature_ctl(state, _ftr, 0, i, &iterm, unitid);
1137 } 1140 }
1138 1141
1139 return 0; 1142 return 0;
@@ -1780,7 +1783,7 @@ static int snd_usb_mixer_dev_free(struct snd_device *device)
1780 */ 1783 */
1781static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) 1784static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
1782{ 1785{
1783 unsigned char *desc; 1786 struct uac_output_terminal_descriptor_v1 *desc;
1784 struct mixer_build state; 1787 struct mixer_build state;
1785 int err; 1788 int err;
1786 const struct usbmix_ctl_map *map; 1789 const struct usbmix_ctl_map *map;
@@ -1805,13 +1808,13 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
1805 1808
1806 desc = NULL; 1809 desc = NULL;
1807 while ((desc = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, desc, OUTPUT_TERMINAL)) != NULL) { 1810 while ((desc = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, desc, OUTPUT_TERMINAL)) != NULL) {
1808 if (desc[0] < 9) 1811 if (desc->bLength < 9)
1809 continue; /* invalid descriptor? */ 1812 continue; /* invalid descriptor? */
1810 set_bit(desc[3], state.unitbitmap); /* mark terminal ID as visited */ 1813 set_bit(desc->bTerminalID, state.unitbitmap); /* mark terminal ID as visited */
1811 state.oterm.id = desc[3]; 1814 state.oterm.id = desc->bTerminalID;
1812 state.oterm.type = combine_word(&desc[4]); 1815 state.oterm.type = le16_to_cpu(desc->wTerminalType);
1813 state.oterm.name = desc[8]; 1816 state.oterm.name = desc->iTerminal;
1814 err = parse_audio_unit(&state, desc[7]); 1817 err = parse_audio_unit(&state, desc->bSourceID);
1815 if (err < 0) 1818 if (err < 0)
1816 return err; 1819 return err;
1817 } 1820 }