diff options
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/mixer.c | 87 |
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 | ||
863 | static void build_feature_ctl(struct mixer_build *state, unsigned char *desc, | 863 | static 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 | ||
1078 | static void build_mixer_unit_ctl(struct mixer_build *state, unsigned char *desc, | 1079 | static 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 | */ |
1135 | static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, unsigned char *desc) | 1136 | static 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 | */ |
1326 | static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned char *dsc, struct procunit_info *list, char *name) | 1328 | static 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 | ||
1431 | static int parse_audio_processing_unit(struct mixer_build *state, int unitid, unsigned char *desc) | 1436 | static 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 | ||
1436 | static int parse_audio_extension_unit(struct mixer_build *state, int unitid, unsigned char *desc) | 1441 | static 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 | */ |
1540 | static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsigned char *desc) | 1547 | static 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 | ||