aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/asound.h17
-rw-r--r--sound/core/control.c51
2 files changed, 28 insertions, 40 deletions
diff --git a/include/sound/asound.h b/include/sound/asound.h
index eda5c63ea547..ee753d782e2d 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -696,7 +696,7 @@ struct snd_timer_tread {
696 * * 696 * *
697 ****************************************************************************/ 697 ****************************************************************************/
698 698
699#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 4) 699#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 5)
700 700
701struct snd_ctl_card_info { 701struct snd_ctl_card_info {
702 int card; /* card number */ 702 int card; /* card number */
@@ -745,8 +745,7 @@ typedef int __bitwise snd_ctl_elem_iface_t;
745#define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10) /* write lock owner */ 745#define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10) /* write lock owner */
746#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28) /* kernel use a TLV callback */ 746#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28) /* kernel use a TLV callback */
747#define SNDRV_CTL_ELEM_ACCESS_USER (1<<29) /* user space element */ 747#define SNDRV_CTL_ELEM_ACCESS_USER (1<<29) /* user space element */
748#define SNDRV_CTL_ELEM_ACCESS_DINDIRECT (1<<30) /* indirect access for matrix dimensions in the info structure */ 748/* bits 30 and 31 are obsoleted (for indirect access) */
749#define SNDRV_CTL_ELEM_ACCESS_INDIRECT (1<<31) /* indirect access for element value in the value structure */
750 749
751/* for further details see the ACPI and PCI power management specification */ 750/* for further details see the ACPI and PCI power management specification */
752#define SNDRV_CTL_POWER_D0 0x0000 /* full On */ 751#define SNDRV_CTL_POWER_D0 0x0000 /* full On */
@@ -800,30 +799,30 @@ struct snd_ctl_elem_info {
800 } value; 799 } value;
801 union { 800 union {
802 unsigned short d[4]; /* dimensions */ 801 unsigned short d[4]; /* dimensions */
803 unsigned short *d_ptr; /* indirect */ 802 unsigned short *d_ptr; /* indirect - obsoleted */
804 } dimen; 803 } dimen;
805 unsigned char reserved[64-4*sizeof(unsigned short)]; 804 unsigned char reserved[64-4*sizeof(unsigned short)];
806}; 805};
807 806
808struct snd_ctl_elem_value { 807struct snd_ctl_elem_value {
809 struct snd_ctl_elem_id id; /* W: element ID */ 808 struct snd_ctl_elem_id id; /* W: element ID */
810 unsigned int indirect: 1; /* W: use indirect pointer (xxx_ptr member) */ 809 unsigned int indirect: 1; /* W: indirect access - obsoleted */
811 union { 810 union {
812 union { 811 union {
813 long value[128]; 812 long value[128];
814 long *value_ptr; 813 long *value_ptr; /* obsoleted */
815 } integer; 814 } integer;
816 union { 815 union {
817 long long value[64]; 816 long long value[64];
818 long long *value_ptr; 817 long long *value_ptr; /* obsoleted */
819 } integer64; 818 } integer64;
820 union { 819 union {
821 unsigned int item[128]; 820 unsigned int item[128];
822 unsigned int *item_ptr; 821 unsigned int *item_ptr; /* obsoleted */
823 } enumerated; 822 } enumerated;
824 union { 823 union {
825 unsigned char data[512]; 824 unsigned char data[512];
826 unsigned char *data_ptr; 825 unsigned char *data_ptr; /* obsoleted */
827 } bytes; 826 } bytes;
828 struct snd_aes_iec958 iec958; 827 struct snd_aes_iec958 iec958;
829 } value; /* RO */ 828 } value; /* RO */
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);