[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