Callbacks
Prev | Chapter 6. Control Interface | Next

## Callbacks

### info callback

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;
      }

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.

### get callback

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.

### put callback

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.

### Callbacks are not atomic

All these three callbacks are basically not atomic.

Prev | Up | Next
Access Flags | Home | Constructor