Commit ebfdeea3 authored by Jaroslav Kysela's avatar Jaroslav Kysela

ALSA: usbmixer - introduce /proc/asound/card#/usbmixer file

The usbmixer proc file contains mapping between ALSA control API and
USB mixer control units. The purpose of this file is for debugging
and a problem diagnostics.
Signed-off-by: default avatarJaroslav Kysela <perex@perex.cz>
parent b8f1f598
...@@ -69,13 +69,16 @@ static const struct rc_config { ...@@ -69,13 +69,16 @@ static const struct rc_config {
{ USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */ { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */
}; };
#define MAX_ID_ELEMS 256
struct usb_mixer_interface { struct usb_mixer_interface {
struct snd_usb_audio *chip; struct snd_usb_audio *chip;
unsigned int ctrlif; unsigned int ctrlif;
struct list_head list; struct list_head list;
unsigned int ignore_ctl_error; unsigned int ignore_ctl_error;
struct urb *urb; struct urb *urb;
struct usb_mixer_elem_info **id_elems; /* array[256], indexed by unit id */ /* array[MAX_ID_ELEMS], indexed by unit id */
struct usb_mixer_elem_info **id_elems;
/* Sound Blaster remote control stuff */ /* Sound Blaster remote control stuff */
const struct rc_config *rc_cfg; const struct rc_config *rc_cfg;
...@@ -1825,6 +1828,45 @@ static void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, ...@@ -1825,6 +1828,45 @@ static void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer,
info->elem_id); info->elem_id);
} }
static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer,
int unitid,
struct usb_mixer_elem_info *cval)
{
static char *val_types[] = {"BOOLEAN", "INV_BOOLEAN",
"S8", "U8", "S16", "U16"};
snd_iprintf(buffer, " Unit: %i\n", unitid);
if (cval->elem_id)
snd_iprintf(buffer, " Control: name=\"%s\", index=%i\n",
cval->elem_id->name, cval->elem_id->index);
snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, "
"channels=%i, type=\"%s\"\n", cval->id,
cval->control, cval->cmask, cval->channels,
val_types[cval->val_type]);
snd_iprintf(buffer, " Volume: min=%i, max=%i, dBmin=%i, dBmax=%i\n",
cval->min, cval->max, cval->dBmin, cval->dBmax);
}
static void snd_usb_mixer_proc_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_usb_audio *chip = entry->private_data;
struct usb_mixer_interface *mixer;
struct usb_mixer_elem_info *cval;
int unitid;
list_for_each_entry(mixer, &chip->mixer_list, list) {
snd_iprintf(buffer,
"USB Mixer: ctrlif=%i, ctlerr=%i\n",
mixer->ctrlif, mixer->ignore_ctl_error);
snd_iprintf(buffer, "Card: %s\n", chip->card->longname);
for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) {
for (cval = mixer->id_elems[unitid]; cval;
cval = cval->next_id_elem)
snd_usb_mixer_dump_cval(buffer, unitid, cval);
}
}
}
static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer, static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer,
int unitid) int unitid)
{ {
...@@ -2187,20 +2229,21 @@ static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer) ...@@ -2187,20 +2229,21 @@ static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer)
} }
void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
unsigned char samplerate_id) unsigned char samplerate_id)
{ {
struct usb_mixer_interface *mixer; struct usb_mixer_interface *mixer;
struct usb_mixer_elem_info *cval; struct usb_mixer_elem_info *cval;
int unitid = 12; /* SamleRate ExtensionUnit ID */ int unitid = 12; /* SamleRate ExtensionUnit ID */
list_for_each_entry(mixer, &chip->mixer_list, list) { list_for_each_entry(mixer, &chip->mixer_list, list) {
cval = mixer->id_elems[unitid]; cval = mixer->id_elems[unitid];
if (cval) { if (cval) {
set_cur_ctl_value(cval, cval->control << 8, samplerate_id); set_cur_ctl_value(cval, cval->control << 8,
samplerate_id);
snd_usb_mixer_notify_id(mixer, unitid); snd_usb_mixer_notify_id(mixer, unitid);
} }
break; break;
} }
} }
int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
...@@ -2210,6 +2253,7 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, ...@@ -2210,6 +2253,7 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
.dev_free = snd_usb_mixer_dev_free .dev_free = snd_usb_mixer_dev_free
}; };
struct usb_mixer_interface *mixer; struct usb_mixer_interface *mixer;
struct snd_info_entry *entry;
int err; int err;
strcpy(chip->card->mixername, "USB Mixer"); strcpy(chip->card->mixername, "USB Mixer");
...@@ -2236,8 +2280,6 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, ...@@ -2236,8 +2280,6 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) || if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) ||
mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) { mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) {
struct snd_info_entry *entry;
if ((err = snd_audigy2nx_controls_create(mixer)) < 0) if ((err = snd_audigy2nx_controls_create(mixer)) < 0)
goto _error; goto _error;
if (!snd_card_proc_new(chip->card, "audigy2nx", &entry)) if (!snd_card_proc_new(chip->card, "audigy2nx", &entry))
...@@ -2255,6 +2297,11 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, ...@@ -2255,6 +2297,11 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops); err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops);
if (err < 0) if (err < 0)
goto _error; goto _error;
if (list_empty(&chip->mixer_list) &&
!snd_card_proc_new(chip->card, "usbmixer", &entry))
snd_info_set_text_ops(entry, chip, snd_usb_mixer_proc_read);
list_add(&mixer->list, &chip->mixer_list); list_add(&mixer->list, &chip->mixer_list);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment