Skip to content

Commit

Permalink
ALSA: control - introduce snd_ctl_notify_one() helper
Browse files Browse the repository at this point in the history
This helper is required for the following generic LED mute
patch. The helper also simplifies some other functions.

Signed-off-by: Jaroslav Kysela <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Takashi Iwai <[email protected]>
  • Loading branch information
perexg authored and tiwai committed Mar 30, 2021
1 parent a5e13c6 commit 1fa4445
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 25 deletions.
4 changes: 2 additions & 2 deletions include/sound/control.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ typedef int (*snd_kctl_ioctl_func_t) (struct snd_card * card,
unsigned int cmd, unsigned long arg);

void snd_ctl_notify(struct snd_card * card, unsigned int mask, struct snd_ctl_elem_id * id);
void snd_ctl_notify_one(struct snd_card * card, unsigned int mask, struct snd_kcontrol * kctl, unsigned int ioff);

struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new * kcontrolnew, void * private_data);
void snd_ctl_free_one(struct snd_kcontrol * kcontrol);
Expand All @@ -123,8 +124,7 @@ int snd_ctl_remove(struct snd_card * card, struct snd_kcontrol * kcontrol);
int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol, bool add_on_replace);
int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id);
int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id);
int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
int active);
int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id, int active);
struct snd_kcontrol *snd_ctl_find_numid(struct snd_card * card, unsigned int numid);
struct snd_kcontrol *snd_ctl_find_id(struct snd_card * card, struct snd_ctl_elem_id *id);

Expand Down
68 changes: 45 additions & 23 deletions sound/core/control.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,27 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
}
EXPORT_SYMBOL(snd_ctl_notify);

/**
* snd_ctl_notify_one - Send notification to user-space for a control change
* @card: the card to send notification
* @mask: the event mask, SNDRV_CTL_EVENT_*
* @kctl: the pointer with the control instance
* @ioff: the additional offset to the control index
*
* This function calls snd_ctl_notify() and does additional jobs
* like LED state changes.
*/
void snd_ctl_notify_one(struct snd_card *card, unsigned int mask,
struct snd_kcontrol *kctl, unsigned int ioff)
{
struct snd_ctl_elem_id id = kctl->id;

id.index += ioff;
id.numid += ioff;
snd_ctl_notify(card, mask, &id);
}
EXPORT_SYMBOL(snd_ctl_notify_one);

/**
* snd_ctl_new - create a new control instance with some elements
* @kctl: the pointer to store new control instance
Expand Down Expand Up @@ -342,7 +363,6 @@ static int __snd_ctl_add_replace(struct snd_card *card,
{
struct snd_ctl_elem_id id;
unsigned int idx;
unsigned int count;
struct snd_kcontrol *old;
int err;

Expand Down Expand Up @@ -376,10 +396,8 @@ static int __snd_ctl_add_replace(struct snd_card *card,
kcontrol->id.numid = card->last_numid + 1;
card->last_numid += kcontrol->count;

id = kcontrol->id;
count = kcontrol->count;
for (idx = 0; idx < count; idx++, id.index++, id.numid++)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
for (idx = 0; idx < kcontrol->count; idx++)
snd_ctl_notify_one(card, SNDRV_CTL_EVENT_MASK_ADD, kcontrol, idx);

return 0;
}
Expand Down Expand Up @@ -462,16 +480,14 @@ EXPORT_SYMBOL(snd_ctl_replace);
*/
int snd_ctl_remove(struct snd_card *card, struct snd_kcontrol *kcontrol)
{
struct snd_ctl_elem_id id;
unsigned int idx;

if (snd_BUG_ON(!card || !kcontrol))
return -EINVAL;
list_del(&kcontrol->list);
card->controls_count -= kcontrol->count;
id = kcontrol->id;
for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_REMOVE, &id);
for (idx = 0; idx < kcontrol->count; idx++)
snd_ctl_notify_one(card, SNDRV_CTL_EVENT_MASK_REMOVE, kcontrol, idx);
snd_ctl_free_one(kcontrol);
return 0;
}
Expand Down Expand Up @@ -584,11 +600,13 @@ int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
vd->access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
}
snd_ctl_build_ioff(id, kctl, index_offset);
ret = 1;
downgrade_write(&card->controls_rwsem);
snd_ctl_notify_one(card, SNDRV_CTL_EVENT_MASK_INFO, kctl, index_offset);
up_read(&card->controls_rwsem);
return 1;

unlock:
up_write(&card->controls_rwsem);
if (ret > 0)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, id);
return ret;
}
EXPORT_SYMBOL_GPL(snd_ctl_activate_id);
Expand Down Expand Up @@ -1110,25 +1128,34 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
unsigned int index_offset;
int result;

down_write(&card->controls_rwsem);
kctl = snd_ctl_find_id(card, &control->id);
if (kctl == NULL)
if (kctl == NULL) {
up_write(&card->controls_rwsem);
return -ENOENT;
}

index_offset = snd_ctl_get_ioff(kctl, &control->id);
vd = &kctl->vd[index_offset];
if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_WRITE) || kctl->put == NULL ||
(file && vd->owner && vd->owner != file)) {
up_write(&card->controls_rwsem);
return -EPERM;
}

snd_ctl_build_ioff(&control->id, kctl, index_offset);
result = kctl->put(kctl, control);
if (result < 0)
if (result < 0) {
up_write(&card->controls_rwsem);
return result;
}

if (result > 0) {
struct snd_ctl_elem_id id = control->id;
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
downgrade_write(&card->controls_rwsem);
snd_ctl_notify_one(card, SNDRV_CTL_EVENT_MASK_VALUE, kctl, index_offset);
up_read(&card->controls_rwsem);
} else {
up_write(&card->controls_rwsem);
}

return 0;
Expand All @@ -1150,9 +1177,7 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
if (result < 0)
goto error;

down_write(&card->controls_rwsem);
result = snd_ctl_elem_write(card, file, control);
up_write(&card->controls_rwsem);
if (result < 0)
goto error;

Expand Down Expand Up @@ -1301,7 +1326,6 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
{
struct user_element *ue = kctl->private_data;
unsigned int *container;
struct snd_ctl_elem_id id;
unsigned int mask = 0;
int i;
int change;
Expand Down Expand Up @@ -1333,10 +1357,8 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
ue->tlv_data_size = size;

mask |= SNDRV_CTL_EVENT_MASK_TLV;
for (i = 0; i < kctl->count; ++i) {
snd_ctl_build_ioff(&id, kctl, i);
snd_ctl_notify(ue->card, mask, &id);
}
for (i = 0; i < kctl->count; ++i)
snd_ctl_notify_one(ue->card, mask, kctl, i);

return change;
}
Expand Down

0 comments on commit 1fa4445

Please sign in to comment.