aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/usbmixer.c
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2005-04-29 10:23:13 -0400
committerJaroslav Kysela <perex@suse.cz>2005-05-29 04:05:37 -0400
commit84957a8ab086377a025e0448fa716ed5983f3c3a (patch)
tree7d405711f0fd2e6eb8c305b7bddf0aaeac22f3e4 /sound/usb/usbmixer.c
parent707e60732fc25fe3760f916d083b262a86a666c0 (diff)
[ALSA] usb-audio - move mixer data into separate struct
USB generic driver Move all data related to audio control interfaces into a separate struct local to usbmixer.c. Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Diffstat (limited to 'sound/usb/usbmixer.c')
-rw-r--r--sound/usb/usbmixer.c142
1 files changed, 98 insertions, 44 deletions
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index e601f4ba5f2c..7bbccebd76c6 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -50,6 +50,14 @@ typedef struct usb_audio_term usb_audio_term_t;
50typedef struct usb_mixer_elem_info usb_mixer_elem_info_t; 50typedef struct usb_mixer_elem_info usb_mixer_elem_info_t;
51 51
52 52
53struct usb_mixer_interface {
54 snd_usb_audio_t *chip;
55 unsigned int ctrlif;
56 struct list_head list;
57 unsigned int ignore_ctl_error;
58};
59
60
53struct usb_audio_term { 61struct usb_audio_term {
54 int id; 62 int id;
55 int type; 63 int type;
@@ -62,9 +70,9 @@ struct usbmix_name_map;
62 70
63struct usb_mixer_build { 71struct usb_mixer_build {
64 snd_usb_audio_t *chip; 72 snd_usb_audio_t *chip;
73 struct usb_mixer_interface *mixer;
65 unsigned char *buffer; 74 unsigned char *buffer;
66 unsigned int buflen; 75 unsigned int buflen;
67 unsigned int ctrlif;
68 unsigned short vendor; 76 unsigned short vendor;
69 unsigned short product; 77 unsigned short product;
70 DECLARE_BITMAP(unitbitmap, 256); 78 DECLARE_BITMAP(unitbitmap, 256);
@@ -74,8 +82,7 @@ struct usb_mixer_build {
74}; 82};
75 83
76struct usb_mixer_elem_info { 84struct usb_mixer_elem_info {
77 snd_usb_audio_t *chip; 85 struct usb_mixer_interface *mixer;
78 unsigned int ctrlif;
79 unsigned int id; 86 unsigned int id;
80 unsigned int control; /* CS or ICN (high byte) */ 87 unsigned int control; /* CS or ICN (high byte) */
81 unsigned int cmask; /* channel mask bitmap: 0 = master */ 88 unsigned int cmask; /* channel mask bitmap: 0 = master */
@@ -317,16 +324,18 @@ static int get_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i
317 int timeout = 10; 324 int timeout = 10;
318 325
319 while (timeout-- > 0) { 326 while (timeout-- > 0) {
320 if (snd_usb_ctl_msg(cval->chip->dev, usb_rcvctrlpipe(cval->chip->dev, 0), 327 if (snd_usb_ctl_msg(cval->mixer->chip->dev,
328 usb_rcvctrlpipe(cval->mixer->chip->dev, 0),
321 request, 329 request,
322 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, 330 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
323 validx, cval->ctrlif | (cval->id << 8), 331 validx, cval->mixer->ctrlif | (cval->id << 8),
324 buf, val_len, 100) >= 0) { 332 buf, val_len, 100) >= 0) {
325 *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); 333 *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
326 return 0; 334 return 0;
327 } 335 }
328 } 336 }
329 snd_printdd(KERN_ERR "cannot get ctl value: req = 0x%x, wValue = 0x%x, wIndex = 0x%x, type = %d\n", request, validx, cval->ctrlif | (cval->id << 8), cval->val_type); 337 snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
338 request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type);
330 return -EINVAL; 339 return -EINVAL;
331} 340}
332 341
@@ -355,13 +364,15 @@ static int set_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i
355 buf[0] = value_set & 0xff; 364 buf[0] = value_set & 0xff;
356 buf[1] = (value_set >> 8) & 0xff; 365 buf[1] = (value_set >> 8) & 0xff;
357 while (timeout -- > 0) 366 while (timeout -- > 0)
358 if (snd_usb_ctl_msg(cval->chip->dev, usb_sndctrlpipe(cval->chip->dev, 0), 367 if (snd_usb_ctl_msg(cval->mixer->chip->dev,
368 usb_sndctrlpipe(cval->mixer->chip->dev, 0),
359 request, 369 request,
360 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, 370 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
361 validx, cval->ctrlif | (cval->id << 8), 371 validx, cval->mixer->ctrlif | (cval->id << 8),
362 buf, val_len, 100) >= 0) 372 buf, val_len, 100) >= 0)
363 return 0; 373 return 0;
364 snd_printdd(KERN_ERR "cannot set ctl value: req = 0x%x, wValue = 0x%x, wIndex = 0x%x, type = %d, data = 0x%x/0x%x\n", request, validx, cval->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]); 374 snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
375 request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]);
365 return -EINVAL; 376 return -EINVAL;
366} 377}
367 378
@@ -401,12 +412,13 @@ static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_ou
401 * if failed, give up and free the control instance. 412 * if failed, give up and free the control instance.
402 */ 413 */
403 414
404static int add_control_to_empty(snd_card_t *card, snd_kcontrol_t *kctl) 415static int add_control_to_empty(mixer_build_t *state, snd_kcontrol_t *kctl)
405{ 416{
406 int err; 417 int err;
407 while (snd_ctl_find_id(card, &kctl->id)) 418
419 while (snd_ctl_find_id(state->chip->card, &kctl->id))
408 kctl->id.index++; 420 kctl->id.index++;
409 if ((err = snd_ctl_add(card, kctl)) < 0) { 421 if ((err = snd_ctl_add(state->chip->card, kctl)) < 0) {
410 snd_printd(KERN_ERR "cannot add control (err = %d)\n", err); 422 snd_printd(KERN_ERR "cannot add control (err = %d)\n", err);
411 snd_ctl_free_one(kctl); 423 snd_ctl_free_one(kctl);
412 } 424 }
@@ -624,7 +636,8 @@ static int get_min_max(usb_mixer_elem_info_t *cval, int default_min)
624 } 636 }
625 if (get_ctl_value(cval, GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 || 637 if (get_ctl_value(cval, GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 ||
626 get_ctl_value(cval, GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { 638 get_ctl_value(cval, GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) {
627 snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", cval->id, cval->ctrlif, cval->control, cval->id); 639 snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n",
640 cval->id, cval->mixer->ctrlif, cval->control, cval->id);
628 return -EINVAL; 641 return -EINVAL;
629 } 642 }
630 if (get_ctl_value(cval, GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) { 643 if (get_ctl_value(cval, GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) {
@@ -684,7 +697,7 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
684 if (cval->cmask & (1 << c)) { 697 if (cval->cmask & (1 << c)) {
685 err = get_cur_mix_value(cval, c + 1, &val); 698 err = get_cur_mix_value(cval, c + 1, &val);
686 if (err < 0) { 699 if (err < 0) {
687 if (cval->chip->ignore_ctl_error) { 700 if (cval->mixer->ignore_ctl_error) {
688 ucontrol->value.integer.value[0] = cval->min; 701 ucontrol->value.integer.value[0] = cval->min;
689 return 0; 702 return 0;
690 } 703 }
@@ -700,7 +713,7 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
700 /* master channel */ 713 /* master channel */
701 err = get_cur_mix_value(cval, 0, &val); 714 err = get_cur_mix_value(cval, 0, &val);
702 if (err < 0) { 715 if (err < 0) {
703 if (cval->chip->ignore_ctl_error) { 716 if (cval->mixer->ignore_ctl_error) {
704 ucontrol->value.integer.value[0] = cval->min; 717 ucontrol->value.integer.value[0] = cval->min;
705 return 0; 718 return 0;
706 } 719 }
@@ -726,7 +739,7 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
726 if (cval->cmask & (1 << c)) { 739 if (cval->cmask & (1 << c)) {
727 err = get_cur_mix_value(cval, c + 1, &oval); 740 err = get_cur_mix_value(cval, c + 1, &oval);
728 if (err < 0) { 741 if (err < 0) {
729 if (cval->chip->ignore_ctl_error) 742 if (cval->mixer->ignore_ctl_error)
730 return 0; 743 return 0;
731 return err; 744 return err;
732 } 745 }
@@ -743,7 +756,7 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
743 } else { 756 } else {
744 /* master channel */ 757 /* master channel */
745 err = get_cur_mix_value(cval, 0, &oval); 758 err = get_cur_mix_value(cval, 0, &oval);
746 if (err < 0 && cval->chip->ignore_ctl_error) 759 if (err < 0 && cval->mixer->ignore_ctl_error)
747 return 0; 760 return 0;
748 if (err < 0) 761 if (err < 0)
749 return err; 762 return err;
@@ -795,8 +808,7 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
795 snd_printk(KERN_ERR "cannot malloc kcontrol\n"); 808 snd_printk(KERN_ERR "cannot malloc kcontrol\n");
796 return; 809 return;
797 } 810 }
798 cval->chip = state->chip; 811 cval->mixer = state->mixer;
799 cval->ctrlif = state->ctrlif;
800 cval->id = unitid; 812 cval->id = unitid;
801 cval->control = control; 813 cval->control = control;
802 cval->cmask = ctl_mask; 814 cval->cmask = ctl_mask;
@@ -880,7 +892,7 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
880 892
881 snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", 893 snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
882 cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); 894 cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res);
883 add_control_to_empty(state->chip->card, kctl); 895 add_control_to_empty(state, kctl);
884} 896}
885 897
886 898
@@ -963,8 +975,7 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc,
963 if (! cval) 975 if (! cval)
964 return; 976 return;
965 977
966 cval->chip = state->chip; 978 cval->mixer = state->mixer;
967 cval->ctrlif = state->ctrlif;
968 cval->id = unitid; 979 cval->id = unitid;
969 cval->control = in_ch + 1; /* based on 1 */ 980 cval->control = in_ch + 1; /* based on 1 */
970 cval->val_type = USB_MIXER_S16; 981 cval->val_type = USB_MIXER_S16;
@@ -995,7 +1006,7 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc,
995 1006
996 snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", 1007 snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n",
997 cval->id, kctl->id.name, cval->channels, cval->min, cval->max); 1008 cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
998 add_control_to_empty(state->chip->card, kctl); 1009 add_control_to_empty(state, kctl);
999} 1010}
1000 1011
1001 1012
@@ -1058,7 +1069,7 @@ static int mixer_ctl_procunit_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
1058 int err, val; 1069 int err, val;
1059 1070
1060 err = get_cur_ctl_value(cval, cval->control << 8, &val); 1071 err = get_cur_ctl_value(cval, cval->control << 8, &val);
1061 if (err < 0 && cval->chip->ignore_ctl_error) { 1072 if (err < 0 && cval->mixer->ignore_ctl_error) {
1062 ucontrol->value.integer.value[0] = cval->min; 1073 ucontrol->value.integer.value[0] = cval->min;
1063 return 0; 1074 return 0;
1064 } 1075 }
@@ -1077,7 +1088,7 @@ static int mixer_ctl_procunit_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
1077 1088
1078 err = get_cur_ctl_value(cval, cval->control << 8, &oval); 1089 err = get_cur_ctl_value(cval, cval->control << 8, &oval);
1079 if (err < 0) { 1090 if (err < 0) {
1080 if (cval->chip->ignore_ctl_error) 1091 if (cval->mixer->ignore_ctl_error)
1081 return 0; 1092 return 0;
1082 return err; 1093 return err;
1083 } 1094 }
@@ -1215,8 +1226,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char
1215 snd_printk(KERN_ERR "cannot malloc kcontrol\n"); 1226 snd_printk(KERN_ERR "cannot malloc kcontrol\n");
1216 return -ENOMEM; 1227 return -ENOMEM;
1217 } 1228 }
1218 cval->chip = state->chip; 1229 cval->mixer = state->mixer;
1219 cval->ctrlif = state->ctrlif;
1220 cval->id = unitid; 1230 cval->id = unitid;
1221 cval->control = valinfo->control; 1231 cval->control = valinfo->control;
1222 cval->val_type = valinfo->val_type; 1232 cval->val_type = valinfo->val_type;
@@ -1257,7 +1267,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char
1257 1267
1258 snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n", 1268 snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n",
1259 cval->id, kctl->id.name, cval->channels, cval->min, cval->max); 1269 cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
1260 if ((err = add_control_to_empty(state->chip->card, kctl)) < 0) 1270 if ((err = add_control_to_empty(state, kctl)) < 0)
1261 return err; 1271 return err;
1262 } 1272 }
1263 return 0; 1273 return 0;
@@ -1305,7 +1315,7 @@ static int mixer_ctl_selector_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
1305 1315
1306 err = get_cur_ctl_value(cval, 0, &val); 1316 err = get_cur_ctl_value(cval, 0, &val);
1307 if (err < 0) { 1317 if (err < 0) {
1308 if (cval->chip->ignore_ctl_error) { 1318 if (cval->mixer->ignore_ctl_error) {
1309 ucontrol->value.enumerated.item[0] = 0; 1319 ucontrol->value.enumerated.item[0] = 0;
1310 return 0; 1320 return 0;
1311 } 1321 }
@@ -1324,7 +1334,7 @@ static int mixer_ctl_selector_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
1324 1334
1325 err = get_cur_ctl_value(cval, 0, &oval); 1335 err = get_cur_ctl_value(cval, 0, &oval);
1326 if (err < 0) { 1336 if (err < 0) {
1327 if (cval->chip->ignore_ctl_error) 1337 if (cval->mixer->ignore_ctl_error)
1328 return 0; 1338 return 0;
1329 return err; 1339 return err;
1330 } 1340 }
@@ -1402,8 +1412,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
1402 snd_printk(KERN_ERR "cannot malloc kcontrol\n"); 1412 snd_printk(KERN_ERR "cannot malloc kcontrol\n");
1403 return -ENOMEM; 1413 return -ENOMEM;
1404 } 1414 }
1405 cval->chip = state->chip; 1415 cval->mixer = state->mixer;
1406 cval->ctrlif = state->ctrlif;
1407 cval->id = unitid; 1416 cval->id = unitid;
1408 cval->val_type = USB_MIXER_U8; 1417 cval->val_type = USB_MIXER_U8;
1409 cval->channels = 1; 1418 cval->channels = 1;
@@ -1468,7 +1477,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
1468 1477
1469 snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", 1478 snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n",
1470 cval->id, kctl->id.name, num_ins); 1479 cval->id, kctl->id.name, num_ins);
1471 if ((err = add_control_to_empty(state->chip->card, kctl)) < 0) 1480 if ((err = add_control_to_empty(state, kctl)) < 0)
1472 return err; 1481 return err;
1473 1482
1474 return 0; 1483 return 0;
@@ -1511,27 +1520,38 @@ static int parse_audio_unit(mixer_build_t *state, int unitid)
1511 } 1520 }
1512} 1521}
1513 1522
1523static void snd_usb_mixer_free(struct usb_mixer_interface *mixer)
1524{
1525 kfree(mixer);
1526}
1527
1528static int snd_usb_mixer_dev_free(snd_device_t *device)
1529{
1530 struct usb_mixer_interface *mixer = device->device_data;
1531 snd_usb_mixer_free(mixer);
1532 return 0;
1533}
1534
1514/* 1535/*
1515 * create mixer controls 1536 * create mixer controls
1516 * 1537 *
1517 * walk through all OUTPUT_TERMINAL descriptors to search for mixers 1538 * walk through all OUTPUT_TERMINAL descriptors to search for mixers
1518 */ 1539 */
1519int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif) 1540static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
1520{ 1541{
1521 unsigned char *desc; 1542 unsigned char *desc;
1522 mixer_build_t state; 1543 mixer_build_t state;
1523 int err; 1544 int err;
1524 const struct usbmix_ctl_map *map; 1545 const struct usbmix_ctl_map *map;
1525 struct usb_device_descriptor *dev = &chip->dev->descriptor; 1546 struct usb_device_descriptor *dev = &mixer->chip->dev->descriptor;
1526 struct usb_host_interface *hostif = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0]; 1547 struct usb_host_interface *hostif;
1527
1528 strcpy(chip->card->mixername, "USB Mixer");
1529 1548
1549 hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0];
1530 memset(&state, 0, sizeof(state)); 1550 memset(&state, 0, sizeof(state));
1531 state.chip = chip; 1551 state.chip = mixer->chip;
1552 state.mixer = mixer;
1532 state.buffer = hostif->extra; 1553 state.buffer = hostif->extra;
1533 state.buflen = hostif->extralen; 1554 state.buflen = hostif->extralen;
1534 state.ctrlif = ctrlif;
1535 state.vendor = le16_to_cpu(dev->idVendor); 1555 state.vendor = le16_to_cpu(dev->idVendor);
1536 state.product = le16_to_cpu(dev->idProduct); 1556 state.product = le16_to_cpu(dev->idProduct);
1537 1557
@@ -1540,13 +1560,10 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif)
1540 if (map->vendor == state.vendor && map->product == state.product) { 1560 if (map->vendor == state.vendor && map->product == state.product) {
1541 state.map = map->map; 1561 state.map = map->map;
1542 state.selector_map = map->selector_map; 1562 state.selector_map = map->selector_map;
1543 chip->ignore_ctl_error = map->ignore_ctl_error; 1563 mixer->ignore_ctl_error = map->ignore_ctl_error;
1544 break; 1564 break;
1545 } 1565 }
1546 } 1566 }
1547#ifdef IGNORE_CTL_ERROR
1548 chip->ignore_ctl_error = 1;
1549#endif
1550 1567
1551 desc = NULL; 1568 desc = NULL;
1552 while ((desc = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, desc, OUTPUT_TERMINAL)) != NULL) { 1569 while ((desc = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, desc, OUTPUT_TERMINAL)) != NULL) {
@@ -1562,3 +1579,40 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif)
1562 } 1579 }
1563 return 0; 1580 return 0;
1564} 1581}
1582
1583int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif)
1584{
1585 static snd_device_ops_t dev_ops = {
1586 .dev_free = snd_usb_mixer_dev_free
1587 };
1588 struct usb_mixer_interface *mixer;
1589 int err;
1590
1591 strcpy(chip->card->mixername, "USB Mixer");
1592
1593 mixer = kcalloc(1, sizeof(*mixer), GFP_KERNEL);
1594 if (!mixer)
1595 return -ENOMEM;
1596 mixer->chip = chip;
1597 mixer->ctrlif = ctrlif;
1598#ifdef IGNORE_CTL_ERROR
1599 mixer->ignore_ctl_error = 1;
1600#endif
1601
1602 if ((err = snd_usb_mixer_controls(mixer)) < 0) {
1603 snd_usb_mixer_free(mixer);
1604 return err;
1605 }
1606
1607 err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops);
1608 if (err < 0) {
1609 snd_usb_mixer_free(mixer);
1610 return err;
1611 }
1612 list_add(&mixer->list, &chip->mixer_list);
1613 return 0;
1614}
1615
1616void snd_usb_mixer_disconnect(struct list_head *p)
1617{
1618}