The info callback is used to get
the detailed information of 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 will be:
Example 6-2. Example of info callback
static int snd_myctl_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 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_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;
}
This callback is used to read the current value of the control and to return to the 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 is depending on
the type of control as well as on 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 is set 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 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 the 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;
}
Like get callback,
when the control has more than one elements,
all elements must be evaluated in this callback, too.
All these three callbacks are basically not atomic.