aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
authorDaniel Mack <daniel@caiaq.de>2010-03-11 15:13:24 -0500
committerTakashi Iwai <tiwai@suse.de>2010-03-12 06:21:12 -0500
commit99fc86450c439039d2ef88d06b222fd51a779176 (patch)
treede18f564ac09bc36f40b4ea4f88ab71c48ce290c /sound/usb
parentf0b5e634ff25e02a64676022ee13284a9c810879 (diff)
ALSA: usb-mixer: parse descriptors with structs
Introduce a number of new structs for mixer, selector, feature and processing units and some static inline helpers to access fields which have dynamic offsets. Use them in mixer.c to parse the descriptors. This is necessary for the upcoming audio v2 parsers. Signed-off-by: Daniel Mack <daniel@caiaq.de> Cc: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/mixer.c87
1 files changed, 47 insertions, 40 deletions
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 4e7c2fd9e3b4..994b0385235c 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -860,13 +860,14 @@ static size_t append_ctl_name(struct snd_kcontrol *kctl, const char *str)
860 return strlcat(kctl->id.name, str, sizeof(kctl->id.name)); 860 return strlcat(kctl->id.name, str, sizeof(kctl->id.name));
861} 861}
862 862
863static void build_feature_ctl(struct mixer_build *state, unsigned char *desc, 863static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
864 unsigned int ctl_mask, int control, 864 unsigned int ctl_mask, int control,
865 struct usb_audio_term *iterm, int unitid) 865 struct usb_audio_term *iterm, int unitid)
866{ 866{
867 struct uac_feature_unit_descriptor *desc = raw_desc;
867 unsigned int len = 0; 868 unsigned int len = 0;
868 int mapped_name = 0; 869 int mapped_name = 0;
869 int nameid = desc[desc[0] - 1]; 870 int nameid = uac_feature_unit_iFeature(desc);
870 struct snd_kcontrol *kctl; 871 struct snd_kcontrol *kctl;
871 struct usb_mixer_elem_info *cval; 872 struct usb_mixer_elem_info *cval;
872 const struct usbmix_name_map *map; 873 const struct usbmix_name_map *map;
@@ -1032,7 +1033,7 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
1032 1033
1033 channels = (ftr->bLength - 7) / csize - 1; 1034 channels = (ftr->bLength - 7) / csize - 1;
1034 1035
1035 master_bits = snd_usb_combine_bytes(ftr->controls, csize); 1036 master_bits = snd_usb_combine_bytes(ftr->bmaControls, csize);
1036 /* master configuration quirks */ 1037 /* master configuration quirks */
1037 switch (state->chip->usb_id) { 1038 switch (state->chip->usb_id) {
1038 case USB_ID(0x08bb, 0x2702): 1039 case USB_ID(0x08bb, 0x2702):
@@ -1043,14 +1044,14 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
1043 break; 1044 break;
1044 } 1045 }
1045 if (channels > 0) 1046 if (channels > 0)
1046 first_ch_bits = snd_usb_combine_bytes(ftr->controls + csize, csize); 1047 first_ch_bits = snd_usb_combine_bytes(ftr->bmaControls + csize, csize);
1047 else 1048 else
1048 first_ch_bits = 0; 1049 first_ch_bits = 0;
1049 /* check all control types */ 1050 /* check all control types */
1050 for (i = 0; i < 10; i++) { 1051 for (i = 0; i < 10; i++) {
1051 unsigned int ch_bits = 0; 1052 unsigned int ch_bits = 0;
1052 for (j = 0; j < channels; j++) { 1053 for (j = 0; j < channels; j++) {
1053 unsigned int mask = snd_usb_combine_bytes(ftr->controls + csize * (j+1), csize); 1054 unsigned int mask = snd_usb_combine_bytes(ftr->bmaControls + csize * (j+1), csize);
1054 if (mask & (1 << i)) 1055 if (mask & (1 << i))
1055 ch_bits |= (1 << j); 1056 ch_bits |= (1 << j);
1056 } 1057 }
@@ -1075,13 +1076,13 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
1075 * input channel number (zero based) is given in control field instead. 1076 * input channel number (zero based) is given in control field instead.
1076 */ 1077 */
1077 1078
1078static void build_mixer_unit_ctl(struct mixer_build *state, unsigned char *desc, 1079static void build_mixer_unit_ctl(struct mixer_build *state,
1080 struct uac_mixer_unit_descriptor *desc,
1079 int in_pin, int in_ch, int unitid, 1081 int in_pin, int in_ch, int unitid,
1080 struct usb_audio_term *iterm) 1082 struct usb_audio_term *iterm)
1081{ 1083{
1082 struct usb_mixer_elem_info *cval; 1084 struct usb_mixer_elem_info *cval;
1083 unsigned int input_pins = desc[4]; 1085 unsigned int num_outs = uac_mixer_unit_bNrChannels(desc);
1084 unsigned int num_outs = desc[5 + input_pins];
1085 unsigned int i, len; 1086 unsigned int i, len;
1086 struct snd_kcontrol *kctl; 1087 struct snd_kcontrol *kctl;
1087 const struct usbmix_name_map *map; 1088 const struct usbmix_name_map *map;
@@ -1099,7 +1100,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, unsigned char *desc,
1099 cval->control = in_ch + 1; /* based on 1 */ 1100 cval->control = in_ch + 1; /* based on 1 */
1100 cval->val_type = USB_MIXER_S16; 1101 cval->val_type = USB_MIXER_S16;
1101 for (i = 0; i < num_outs; i++) { 1102 for (i = 0; i < num_outs; i++) {
1102 if (check_matrix_bitmap(desc + 9 + input_pins, in_ch, i, num_outs)) { 1103 if (check_matrix_bitmap(uac_mixer_unit_bmControls(desc), in_ch, i, num_outs)) {
1103 cval->cmask |= (1 << i); 1104 cval->cmask |= (1 << i);
1104 cval->channels++; 1105 cval->channels++;
1105 } 1106 }
@@ -1132,18 +1133,19 @@ static void build_mixer_unit_ctl(struct mixer_build *state, unsigned char *desc,
1132/* 1133/*
1133 * parse a mixer unit 1134 * parse a mixer unit
1134 */ 1135 */
1135static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, unsigned char *desc) 1136static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, void *raw_desc)
1136{ 1137{
1138 struct uac_mixer_unit_descriptor *desc = raw_desc;
1137 struct usb_audio_term iterm; 1139 struct usb_audio_term iterm;
1138 int input_pins, num_ins, num_outs; 1140 int input_pins, num_ins, num_outs;
1139 int pin, ich, err; 1141 int pin, ich, err;
1140 1142
1141 if (desc[0] < 11 || ! (input_pins = desc[4]) || ! (num_outs = desc[5 + input_pins])) { 1143 if (desc->bLength < 11 || ! (input_pins = desc->bNrInPins) || ! (num_outs = uac_mixer_unit_bNrChannels(desc))) {
1142 snd_printk(KERN_ERR "invalid MIXER UNIT descriptor %d\n", unitid); 1144 snd_printk(KERN_ERR "invalid MIXER UNIT descriptor %d\n", unitid);
1143 return -EINVAL; 1145 return -EINVAL;
1144 } 1146 }
1145 /* no bmControls field (e.g. Maya44) -> ignore */ 1147 /* no bmControls field (e.g. Maya44) -> ignore */
1146 if (desc[0] <= 10 + input_pins) { 1148 if (desc->bLength <= 10 + input_pins) {
1147 snd_printdd(KERN_INFO "MU %d has no bmControls field\n", unitid); 1149 snd_printdd(KERN_INFO "MU %d has no bmControls field\n", unitid);
1148 return 0; 1150 return 0;
1149 } 1151 }
@@ -1151,10 +1153,10 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, unsigne
1151 num_ins = 0; 1153 num_ins = 0;
1152 ich = 0; 1154 ich = 0;
1153 for (pin = 0; pin < input_pins; pin++) { 1155 for (pin = 0; pin < input_pins; pin++) {
1154 err = parse_audio_unit(state, desc[5 + pin]); 1156 err = parse_audio_unit(state, desc->baSourceID[pin]);
1155 if (err < 0) 1157 if (err < 0)
1156 return err; 1158 return err;
1157 err = check_input_term(state, desc[5 + pin], &iterm); 1159 err = check_input_term(state, desc->baSourceID[pin], &iterm);
1158 if (err < 0) 1160 if (err < 0)
1159 return err; 1161 return err;
1160 num_ins += iterm.channels; 1162 num_ins += iterm.channels;
@@ -1162,7 +1164,7 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, unsigne
1162 int och, ich_has_controls = 0; 1164 int och, ich_has_controls = 0;
1163 1165
1164 for (och = 0; och < num_outs; ++och) { 1166 for (och = 0; och < num_outs; ++och) {
1165 if (check_matrix_bitmap(desc + 9 + input_pins, 1167 if (check_matrix_bitmap(uac_mixer_unit_bmControls(desc),
1166 ich, och, num_outs)) { 1168 ich, och, num_outs)) {
1167 ich_has_controls = 1; 1169 ich_has_controls = 1;
1168 break; 1170 break;
@@ -1323,9 +1325,10 @@ static struct procunit_info extunits[] = {
1323/* 1325/*
1324 * build a processing/extension unit 1326 * build a processing/extension unit
1325 */ 1327 */
1326static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned char *dsc, struct procunit_info *list, char *name) 1328static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw_desc, struct procunit_info *list, char *name)
1327{ 1329{
1328 int num_ins = dsc[6]; 1330 struct uac_processing_unit_descriptor *desc = raw_desc;
1331 int num_ins = desc->bNrInPins;
1329 struct usb_mixer_elem_info *cval; 1332 struct usb_mixer_elem_info *cval;
1330 struct snd_kcontrol *kctl; 1333 struct snd_kcontrol *kctl;
1331 int i, err, nameid, type, len; 1334 int i, err, nameid, type, len;
@@ -1340,17 +1343,17 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned
1340 0, NULL, default_value_info 1343 0, NULL, default_value_info
1341 }; 1344 };
1342 1345
1343 if (dsc[0] < 13 || dsc[0] < 13 + num_ins || dsc[0] < num_ins + dsc[11 + num_ins]) { 1346 if (desc->bLength < 13 || desc->bLength < 13 + num_ins || desc->bLength < num_ins + uac_processing_unit_bControlSize(desc)) {
1344 snd_printk(KERN_ERR "invalid %s descriptor (id %d)\n", name, unitid); 1347 snd_printk(KERN_ERR "invalid %s descriptor (id %d)\n", name, unitid);
1345 return -EINVAL; 1348 return -EINVAL;
1346 } 1349 }
1347 1350
1348 for (i = 0; i < num_ins; i++) { 1351 for (i = 0; i < num_ins; i++) {
1349 if ((err = parse_audio_unit(state, dsc[7 + i])) < 0) 1352 if ((err = parse_audio_unit(state, desc->baSourceID[i])) < 0)
1350 return err; 1353 return err;
1351 } 1354 }
1352 1355
1353 type = combine_word(&dsc[4]); 1356 type = le16_to_cpu(desc->wProcessType);
1354 for (info = list; info && info->type; info++) 1357 for (info = list; info && info->type; info++)
1355 if (info->type == type) 1358 if (info->type == type)
1356 break; 1359 break;
@@ -1358,8 +1361,9 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned
1358 info = &default_info; 1361 info = &default_info;
1359 1362
1360 for (valinfo = info->values; valinfo->control; valinfo++) { 1363 for (valinfo = info->values; valinfo->control; valinfo++) {
1361 /* FIXME: bitmap might be longer than 8bit */ 1364 __u8 *controls = uac_processing_unit_bmControls(desc);
1362 if (! (dsc[12 + num_ins] & (1 << (valinfo->control - 1)))) 1365
1366 if (! (controls[valinfo->control / 8] & (1 << ((valinfo->control % 8) - 1))))
1363 continue; 1367 continue;
1364 map = find_map(state, unitid, valinfo->control); 1368 map = find_map(state, unitid, valinfo->control);
1365 if (check_ignored_ctl(map)) 1369 if (check_ignored_ctl(map))
@@ -1377,9 +1381,10 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned
1377 1381
1378 /* get min/max values */ 1382 /* get min/max values */
1379 if (type == USB_PROC_UPDOWN && cval->control == USB_PROC_UPDOWN_MODE_SEL) { 1383 if (type == USB_PROC_UPDOWN && cval->control == USB_PROC_UPDOWN_MODE_SEL) {
1384 __u8 *control_spec = uac_processing_unit_specific(desc);
1380 /* FIXME: hard-coded */ 1385 /* FIXME: hard-coded */
1381 cval->min = 1; 1386 cval->min = 1;
1382 cval->max = dsc[15]; 1387 cval->max = control_spec[0];
1383 cval->res = 1; 1388 cval->res = 1;
1384 cval->initialized = 1; 1389 cval->initialized = 1;
1385 } else { 1390 } else {
@@ -1409,7 +1414,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned
1409 else if (info->name) 1414 else if (info->name)
1410 strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name)); 1415 strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name));
1411 else { 1416 else {
1412 nameid = dsc[12 + num_ins + dsc[11 + num_ins]]; 1417 nameid = uac_processing_unit_iProcessing(desc);
1413 len = 0; 1418 len = 0;
1414 if (nameid) 1419 if (nameid)
1415 len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name)); 1420 len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name));
@@ -1428,14 +1433,16 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned
1428} 1433}
1429 1434
1430 1435
1431static int parse_audio_processing_unit(struct mixer_build *state, int unitid, unsigned char *desc) 1436static int parse_audio_processing_unit(struct mixer_build *state, int unitid, void *raw_desc)
1432{ 1437{
1433 return build_audio_procunit(state, unitid, desc, procunits, "Processing Unit"); 1438 return build_audio_procunit(state, unitid, raw_desc, procunits, "Processing Unit");
1434} 1439}
1435 1440
1436static int parse_audio_extension_unit(struct mixer_build *state, int unitid, unsigned char *desc) 1441static int parse_audio_extension_unit(struct mixer_build *state, int unitid, void *raw_desc)
1437{ 1442{
1438 return build_audio_procunit(state, unitid, desc, extunits, "Extension Unit"); 1443 /* Note that we parse extension units with processing unit descriptors.
1444 * That's ok as the layout is the same */
1445 return build_audio_procunit(state, unitid, raw_desc, extunits, "Extension Unit");
1439} 1446}
1440 1447
1441 1448
@@ -1537,9 +1544,9 @@ static void usb_mixer_selector_elem_free(struct snd_kcontrol *kctl)
1537/* 1544/*
1538 * parse a selector unit 1545 * parse a selector unit
1539 */ 1546 */
1540static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsigned char *desc) 1547static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void *raw_desc)
1541{ 1548{
1542 unsigned int num_ins = desc[4]; 1549 struct uac_selector_unit_descriptor *desc = raw_desc;
1543 unsigned int i, nameid, len; 1550 unsigned int i, nameid, len;
1544 int err; 1551 int err;
1545 struct usb_mixer_elem_info *cval; 1552 struct usb_mixer_elem_info *cval;
@@ -1547,17 +1554,17 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi
1547 const struct usbmix_name_map *map; 1554 const struct usbmix_name_map *map;
1548 char **namelist; 1555 char **namelist;
1549 1556
1550 if (! num_ins || desc[0] < 5 + num_ins) { 1557 if (!desc->bNrInPins || desc->bLength < 5 + desc->bNrInPins) {
1551 snd_printk(KERN_ERR "invalid SELECTOR UNIT descriptor %d\n", unitid); 1558 snd_printk(KERN_ERR "invalid SELECTOR UNIT descriptor %d\n", unitid);
1552 return -EINVAL; 1559 return -EINVAL;
1553 } 1560 }
1554 1561
1555 for (i = 0; i < num_ins; i++) { 1562 for (i = 0; i < desc->bNrInPins; i++) {
1556 if ((err = parse_audio_unit(state, desc[5 + i])) < 0) 1563 if ((err = parse_audio_unit(state, desc->baSourceID[i])) < 0)
1557 return err; 1564 return err;
1558 } 1565 }
1559 1566
1560 if (num_ins == 1) /* only one ? nonsense! */ 1567 if (desc->bNrInPins == 1) /* only one ? nonsense! */
1561 return 0; 1568 return 0;
1562 1569
1563 map = find_map(state, unitid, 0); 1570 map = find_map(state, unitid, 0);
@@ -1574,18 +1581,18 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi
1574 cval->val_type = USB_MIXER_U8; 1581 cval->val_type = USB_MIXER_U8;
1575 cval->channels = 1; 1582 cval->channels = 1;
1576 cval->min = 1; 1583 cval->min = 1;
1577 cval->max = num_ins; 1584 cval->max = desc->bNrInPins;
1578 cval->res = 1; 1585 cval->res = 1;
1579 cval->initialized = 1; 1586 cval->initialized = 1;
1580 1587
1581 namelist = kmalloc(sizeof(char *) * num_ins, GFP_KERNEL); 1588 namelist = kmalloc(sizeof(char *) * desc->bNrInPins, GFP_KERNEL);
1582 if (! namelist) { 1589 if (! namelist) {
1583 snd_printk(KERN_ERR "cannot malloc\n"); 1590 snd_printk(KERN_ERR "cannot malloc\n");
1584 kfree(cval); 1591 kfree(cval);
1585 return -ENOMEM; 1592 return -ENOMEM;
1586 } 1593 }
1587#define MAX_ITEM_NAME_LEN 64 1594#define MAX_ITEM_NAME_LEN 64
1588 for (i = 0; i < num_ins; i++) { 1595 for (i = 0; i < desc->bNrInPins; i++) {
1589 struct usb_audio_term iterm; 1596 struct usb_audio_term iterm;
1590 len = 0; 1597 len = 0;
1591 namelist[i] = kmalloc(MAX_ITEM_NAME_LEN, GFP_KERNEL); 1598 namelist[i] = kmalloc(MAX_ITEM_NAME_LEN, GFP_KERNEL);
@@ -1599,7 +1606,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi
1599 } 1606 }
1600 len = check_mapped_selector_name(state, unitid, i, namelist[i], 1607 len = check_mapped_selector_name(state, unitid, i, namelist[i],
1601 MAX_ITEM_NAME_LEN); 1608 MAX_ITEM_NAME_LEN);
1602 if (! len && check_input_term(state, desc[5 + i], &iterm) >= 0) 1609 if (! len && check_input_term(state, desc->baSourceID[i], &iterm) >= 0)
1603 len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0); 1610 len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0);
1604 if (! len) 1611 if (! len)
1605 sprintf(namelist[i], "Input %d", i); 1612 sprintf(namelist[i], "Input %d", i);
@@ -1615,7 +1622,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi
1615 kctl->private_value = (unsigned long)namelist; 1622 kctl->private_value = (unsigned long)namelist;
1616 kctl->private_free = usb_mixer_selector_elem_free; 1623 kctl->private_free = usb_mixer_selector_elem_free;
1617 1624
1618 nameid = desc[desc[0] - 1]; 1625 nameid = uac_selector_unit_iSelector(desc);
1619 len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); 1626 len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
1620 if (len) 1627 if (len)
1621 ; 1628 ;
@@ -1634,7 +1641,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi
1634 } 1641 }
1635 1642
1636 snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", 1643 snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n",
1637 cval->id, kctl->id.name, num_ins); 1644 cval->id, kctl->id.name, desc->bNrInPins);
1638 if ((err = add_control_to_empty(state, kctl)) < 0) 1645 if ((err = add_control_to_empty(state, kctl)) < 0)
1639 return err; 1646 return err;
1640 1647