[alsa-devel] Regressions on x86(_64) and >128 mixer controls

Mark Hills mark at xwax.org
Fri Mar 24 12:22:18 CET 2017


I have an echo3g (Layla) PCI soundcard on x86_64. alsamixer and alsactl 
fail with the following:

  alsactl: control.c:2976: snd_ctl_elem_value_get_integer: Assertion `idx < ARRAY_SIZE(obj->value.integer.value)' failed.

In question is idx=128, and this "value" array in alsa-lib:

  struct snd_ctl_elem_value {
          struct snd_ctl_elem_id id;    /* W: element ID */
          unsigned int indirect: 1;     /* W: indirect access - obsoleted */
          union {
                  union {
                          long value[128];
                          long *value_ptr;        /* obsoleted */
                  } integer;  

At first it appears just to be hitting the fixed limit of 128.

However, this used to work -- and at the time I was using 32-bit kernel 
and userland on an otherwise similar system (not they are both 64-bit)

Increasing the array size cascades to a new problem which suggests these 
controls don't actually exist:

  ./alsactl/alsactl: get_control:258: Cannot read control '2,0,0,PCM Playback Volume,0': Inappropriate ioctl for device

So I investigated the origin of this 256, which is here in 
linux/sound/pci/echoaudio/echoaudio.c:

  static int snd_echo_mixer_info(struct snd_kcontrol *kcontrol,
                                 struct snd_ctl_elem_info *uinfo)
  {
          struct echoaudio *chip;

          chip = snd_kcontrol_chip(kcontrol);
          uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
          uinfo->value.integer.min = ECHOGAIN_MINOUT;
          uinfo->value.integer.max = ECHOGAIN_MAXOUT;
          uinfo->dimen.d[0] = num_busses_out(chip);              /* = 16 */
          uinfo->dimen.d[1] = num_busses_in(chip);               /* = 16 */
          uinfo->count = uinfo->dimen.d[0] * uinfo->dimen.d[1];  /* = 256 */
          return 0;
  }

These values are derived from constants in the source code for this 
Layla3G device; I can find nothing on this path that would cause variation 
between a 32-bit and 64-bit kernel -- the code suggests like this value 
has always been 256 in the kernel, so I can't come up with a reason that 
it could vary. I don't have enough knowledge of the hardware to know if 
256 /is/ the correct value here.

Something which may be related happened for a period when I was using 
32-bit userland with 64-bit kernel. This broke a number of tools (incl. 
echomixer)

Compare alsa-lib/include/alsa/asound.h:

  struct snd_ctl_elem_info {
          struct snd_ctl_elem_id id;      /* W: element ID */
          snd_ctl_elem_type_t type;       /* R: value type - SNDRV_CTL_ELEM_TYPE_* */
          unsigned int access;            /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */
          unsigned int count;             /* count of values */
          __kernel_pid_t owner;           /* owner's PID of this control */
          union {
                  struct {
                          long min;               /* R: minimum value */
                          long max;               /* R: maximum value */
                          long step;              /* R: step (0 variable) */
                  } integer;

and notice the use of 'long' in this struct. It has a 
shadow/equivalent/identical in linux/uapi/sound/asound.h, copied to 
userland, using:

 	if (ioctl(hw->fd, SNDRV_CTL_IOCTL_ELEM_INFO, info) < 0)
		return -errno;

The kernel and userland can have different interpretations of 'long';
do these really not need to be the 'int' type?

Though maybe I am missing something -- surely I am not the only person to 
have used a 32-bit userland on a 64-bit kernel?

-- 
Mark


More information about the Alsa-devel mailing list