diff options
-rw-r--r-- | include/sound/asound.h | 17 | ||||
-rw-r--r-- | sound/core/control.c | 51 |
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 | ||
701 | struct snd_ctl_card_info { | 701 | struct 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 | ||
808 | struct snd_ctl_elem_value { | 807 | struct 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); |