diff options
Diffstat (limited to 'sound/core')
-rw-r--r-- | sound/core/control.c | 51 |
1 files changed, 20 insertions, 31 deletions
diff --git a/sound/core/control.c b/sound/core/control.c index df0774c76f6f..c89ca0d1f3ce 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -232,8 +232,6 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol, | |||
232 | access = ncontrol->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : | 232 | access = ncontrol->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : |
233 | (ncontrol->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| | 233 | (ncontrol->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| |
234 | SNDRV_CTL_ELEM_ACCESS_INACTIVE| | 234 | SNDRV_CTL_ELEM_ACCESS_INACTIVE| |
235 | SNDRV_CTL_ELEM_ACCESS_DINDIRECT| | ||
236 | SNDRV_CTL_ELEM_ACCESS_INDIRECT| | ||
237 | SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE| | 235 | SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE| |
238 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)); | 236 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)); |
239 | kctl.info = ncontrol->info; | 237 | kctl.info = ncontrol->info; |
@@ -692,7 +690,7 @@ int snd_ctl_elem_read(struct snd_card *card, struct snd_ctl_elem_value *control) | |||
692 | struct snd_kcontrol *kctl; | 690 | struct snd_kcontrol *kctl; |
693 | struct snd_kcontrol_volatile *vd; | 691 | struct snd_kcontrol_volatile *vd; |
694 | unsigned int index_offset; | 692 | unsigned int index_offset; |
695 | int result, indirect; | 693 | int result; |
696 | 694 | ||
697 | down_read(&card->controls_rwsem); | 695 | down_read(&card->controls_rwsem); |
698 | kctl = snd_ctl_find_id(card, &control->id); | 696 | kctl = snd_ctl_find_id(card, &control->id); |
@@ -701,17 +699,12 @@ int snd_ctl_elem_read(struct snd_card *card, struct snd_ctl_elem_value *control) | |||
701 | } else { | 699 | } else { |
702 | index_offset = snd_ctl_get_ioff(kctl, &control->id); | 700 | index_offset = snd_ctl_get_ioff(kctl, &control->id); |
703 | vd = &kctl->vd[index_offset]; | 701 | vd = &kctl->vd[index_offset]; |
704 | indirect = vd->access & SNDRV_CTL_ELEM_ACCESS_INDIRECT ? 1 : 0; | 702 | if ((vd->access & SNDRV_CTL_ELEM_ACCESS_READ) && |
705 | if (control->indirect != indirect) { | 703 | kctl->get != NULL) { |
706 | result = -EACCES; | 704 | snd_ctl_build_ioff(&control->id, kctl, index_offset); |
707 | } else { | 705 | result = kctl->get(kctl, control); |
708 | if ((vd->access & SNDRV_CTL_ELEM_ACCESS_READ) && kctl->get != NULL) { | 706 | } else |
709 | snd_ctl_build_ioff(&control->id, kctl, index_offset); | 707 | result = -EPERM; |
710 | result = kctl->get(kctl, control); | ||
711 | } else { | ||
712 | result = -EPERM; | ||
713 | } | ||
714 | } | ||
715 | } | 708 | } |
716 | up_read(&card->controls_rwsem); | 709 | up_read(&card->controls_rwsem); |
717 | return result; | 710 | return result; |
@@ -748,7 +741,7 @@ int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file, | |||
748 | struct snd_kcontrol *kctl; | 741 | struct snd_kcontrol *kctl; |
749 | struct snd_kcontrol_volatile *vd; | 742 | struct snd_kcontrol_volatile *vd; |
750 | unsigned int index_offset; | 743 | unsigned int index_offset; |
751 | int result, indirect; | 744 | int result; |
752 | 745 | ||
753 | down_read(&card->controls_rwsem); | 746 | down_read(&card->controls_rwsem); |
754 | kctl = snd_ctl_find_id(card, &control->id); | 747 | kctl = snd_ctl_find_id(card, &control->id); |
@@ -757,23 +750,19 @@ int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file, | |||
757 | } else { | 750 | } else { |
758 | index_offset = snd_ctl_get_ioff(kctl, &control->id); | 751 | index_offset = snd_ctl_get_ioff(kctl, &control->id); |
759 | vd = &kctl->vd[index_offset]; | 752 | vd = &kctl->vd[index_offset]; |
760 | indirect = vd->access & SNDRV_CTL_ELEM_ACCESS_INDIRECT ? 1 : 0; | 753 | if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_WRITE) || |
761 | if (control->indirect != indirect) { | 754 | kctl->put == NULL || |
762 | result = -EACCES; | 755 | (file && vd->owner && vd->owner != file)) { |
756 | result = -EPERM; | ||
763 | } else { | 757 | } else { |
764 | if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_WRITE) || | 758 | snd_ctl_build_ioff(&control->id, kctl, index_offset); |
765 | kctl->put == NULL || | 759 | result = kctl->put(kctl, control); |
766 | (file && vd->owner != NULL && vd->owner != file)) { | 760 | } |
767 | result = -EPERM; | 761 | if (result > 0) { |
768 | } else { | 762 | up_read(&card->controls_rwsem); |
769 | snd_ctl_build_ioff(&control->id, kctl, index_offset); | 763 | snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, |
770 | result = kctl->put(kctl, control); | 764 | &control->id); |
771 | } | 765 | return 0; |
772 | if (result > 0) { | ||
773 | up_read(&card->controls_rwsem); | ||
774 | snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &control->id); | ||
775 | return 0; | ||
776 | } | ||
777 | } | 766 | } |
778 | } | 767 | } |
779 | up_read(&card->controls_rwsem); | 768 | up_read(&card->controls_rwsem); |