aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/control.c51
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);