Commit fb8027eb authored by Takashi Sakamoto's avatar Takashi Sakamoto Committed by Takashi Iwai

ALSA: control: delegate TLV eventing to each driver

In a design of ALSA control core, a set of elements is represented by
'struct snd_kcontrol' to share common attributes. The set of elements
shares TLV (Type-Length-Value) data, too.

On the other hand, in ALSA control interface/protocol for applications,
a TLV operation is committed to an element. Totally, the operation can
have sub-effect to the other elements in the set. For example, TLV_WRITE
operation is expected to change TLV data, which returns to applications.
Applications attempt to change the TLV data per element, but in the above
design, they can effect to elements in the same set.

As a default, ALSA control core has no implementation except for TLV_READ
operation. Thus, the above design looks to have no issue. However, in
kernel APIs of ALSA control component, developers can program a handler
for any request of the TLV operation. Therefore, for elements in a set
which has the handler, applications can commit TLV_WRITE and TLV_COMMAND
requests.

For the above scenario, ALSA control core assist notification. When the
handler returns positive value, the core queueing an event for a requested
element. However, this includes design defects that the event is not
queued for the other element in a set. Actually, developers can program
the handlers to keep per-element TLV data, but it depends on each driver.

As of v4.13-rc6, there's no driver in tree to utilize the notification,
except for user-defined element set. This commit delegates the notification
into each driver to prevent developers from the design defects.
Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 5d3806ee
...@@ -1138,6 +1138,8 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf, ...@@ -1138,6 +1138,8 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
ue->tlv_data = container; ue->tlv_data = container;
ue->tlv_data_size = size; ue->tlv_data_size = size;
snd_ctl_notify(ue->card, SNDRV_CTL_EVENT_MASK_TLV, &kctl->id);
return change; return change;
} }
...@@ -1423,7 +1425,6 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag, ...@@ -1423,7 +1425,6 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag,
}; };
struct snd_kcontrol_volatile *vd = &kctl->vd[snd_ctl_get_ioff(kctl, id)]; struct snd_kcontrol_volatile *vd = &kctl->vd[snd_ctl_get_ioff(kctl, id)];
int i; int i;
int err;
/* Check support of the request for this element. */ /* Check support of the request for this element. */
for (i = 0; i < ARRAY_SIZE(pairs); ++i) { for (i = 0; i < ARRAY_SIZE(pairs); ++i) {
...@@ -1440,14 +1441,7 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag, ...@@ -1440,14 +1441,7 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag,
if (vd->owner != NULL && vd->owner != file) if (vd->owner != NULL && vd->owner != file)
return -EPERM; return -EPERM;
err = kctl->tlv.c(kctl, op_flag, size, buf); return kctl->tlv.c(kctl, op_flag, size, buf);
if (err < 0)
return err;
if (err > 0)
snd_ctl_notify(file->card, SNDRV_CTL_EVENT_MASK_TLV, id);
return 0;
} }
static int read_tlv_buf(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id, static int read_tlv_buf(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment