The info
callback is used to get
detailed information on this control. This must store the
values of the given struct snd_ctl_elem_info
object. For example, for a boolean control with a single
element:
Example 6.2. Example of info callback
static int snd_myctl_mono_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = 1; return 0; }
The type
field specifies the type
of the control. There are BOOLEAN
,
INTEGER
, ENUMERATED
,
BYTES
, IEC958
and
INTEGER64
. The
count
field specifies the
number of elements in this control. For example, a stereo
volume would have count = 2. The
value
field is a union, and
the values stored are depending on the type. The boolean and
integer types are identical.
The enumerated type is a bit different from others. You'll need to set the string for the currently given item index.
static int snd_myctl_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[4] = { "First", "Second", "Third", "Fourth" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 4; if (uinfo->value.enumerated.item > 3) uinfo->value.enumerated.item = 3; strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); return 0; }
The above callback can be simplified with a helper function,
snd_ctl_enum_info
. The final code
looks like below.
(You can pass ARRAY_SIZE(texts) instead of 4 in the third
argument; it's a matter of taste.)
static int snd_myctl_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[4] = { "First", "Second", "Third", "Fourth" }; return snd_ctl_enum_info(uinfo, 1, 4, texts); }
Some common info callbacks are available for your convenience:
snd_ctl_boolean_mono_info()
and
snd_ctl_boolean_stereo_info()
.
Obviously, the former is an info callback for a mono channel
boolean item, just like snd_myctl_mono_info
above, and the latter is for a stereo channel boolean item.
This callback is used to read the current value of the control and to return to user-space.
For example,
Example 6.3. Example of get callback
static int snd_myctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct mychip *chip = snd_kcontrol_chip(kcontrol); ucontrol->value.integer.value[0] = get_some_value(chip); return 0; }
The value
field depends on
the type of control as well as on the info callback. For example,
the sb driver uses this field to store the register offset,
the bit-shift and the bit-mask. The
private_value
field is set as follows:
.private_value = reg | (shift << 16) | (mask << 24)
and is retrieved in callbacks like
static int snd_sbmixer_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 16) & 0xff; int mask = (kcontrol->private_value >> 24) & 0xff; .... }
In the get
callback,
you have to fill all the elements if the
control has more than one elements,
i.e. count
> 1.
In the example above, we filled only one element
(value.integer.value[0]
) since it's
assumed as count
= 1.
This callback is used to write a value from user-space.
For example,
Example 6.4. Example of put callback
static int snd_myctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct mychip *chip = snd_kcontrol_chip(kcontrol); int changed = 0; if (chip->current_value != ucontrol->value.integer.value[0]) { change_current_value(chip, ucontrol->value.integer.value[0]); changed = 1; } return changed; }
As seen above, you have to return 1 if the value is
changed. If the value is not changed, return 0 instead.
If any fatal error happens, return a negative error code as
usual.
As in the get
callback,
when the control has more than one elements,
all elements must be evaluated in this callback, too.