diff options
Diffstat (limited to 'sound/core')
-rw-r--r-- | sound/core/control.c | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/sound/core/control.c b/sound/core/control.c index bb397eaa7187..e9c8854d2f7b 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -241,6 +241,7 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol, | |||
241 | kctl.info = ncontrol->info; | 241 | kctl.info = ncontrol->info; |
242 | kctl.get = ncontrol->get; | 242 | kctl.get = ncontrol->get; |
243 | kctl.put = ncontrol->put; | 243 | kctl.put = ncontrol->put; |
244 | kctl.tlv = ncontrol->tlv; | ||
244 | kctl.private_value = ncontrol->private_value; | 245 | kctl.private_value = ncontrol->private_value; |
245 | kctl.private_data = private_data; | 246 | kctl.private_data = private_data; |
246 | return snd_ctl_new(&kctl, access); | 247 | return snd_ctl_new(&kctl, access); |
@@ -1067,6 +1068,40 @@ static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr) | |||
1067 | return 0; | 1068 | return 0; |
1068 | } | 1069 | } |
1069 | 1070 | ||
1071 | static int snd_ctl_tlv_read(struct snd_card *card, | ||
1072 | struct snd_ctl_tlv __user *_tlv) | ||
1073 | { | ||
1074 | struct snd_ctl_tlv tlv; | ||
1075 | struct snd_kcontrol *kctl; | ||
1076 | unsigned int len; | ||
1077 | int err = 0; | ||
1078 | |||
1079 | if (copy_from_user(&tlv, _tlv, sizeof(tlv))) | ||
1080 | return -EFAULT; | ||
1081 | if (tlv.length < sizeof(unsigned int) * 3) | ||
1082 | return -EINVAL; | ||
1083 | down_read(&card->controls_rwsem); | ||
1084 | kctl = snd_ctl_find_numid(card, tlv.numid); | ||
1085 | if (kctl == NULL) { | ||
1086 | err = -ENOENT; | ||
1087 | goto __kctl_end; | ||
1088 | } | ||
1089 | if (kctl->tlv == NULL) { | ||
1090 | err = -ENXIO; | ||
1091 | goto __kctl_end; | ||
1092 | } | ||
1093 | len = kctl->tlv[1] + 2 * sizeof(unsigned int); | ||
1094 | if (tlv.length < len) { | ||
1095 | err = -ENOMEM; | ||
1096 | goto __kctl_end; | ||
1097 | } | ||
1098 | if (copy_to_user(_tlv->tlv, kctl->tlv, len)) | ||
1099 | err = -EFAULT; | ||
1100 | __kctl_end: | ||
1101 | up_read(&card->controls_rwsem); | ||
1102 | return err; | ||
1103 | } | ||
1104 | |||
1070 | static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 1105 | static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
1071 | { | 1106 | { |
1072 | struct snd_ctl_file *ctl; | 1107 | struct snd_ctl_file *ctl; |
@@ -1086,11 +1121,11 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg | |||
1086 | case SNDRV_CTL_IOCTL_CARD_INFO: | 1121 | case SNDRV_CTL_IOCTL_CARD_INFO: |
1087 | return snd_ctl_card_info(card, ctl, cmd, argp); | 1122 | return snd_ctl_card_info(card, ctl, cmd, argp); |
1088 | case SNDRV_CTL_IOCTL_ELEM_LIST: | 1123 | case SNDRV_CTL_IOCTL_ELEM_LIST: |
1089 | return snd_ctl_elem_list(ctl->card, argp); | 1124 | return snd_ctl_elem_list(card, argp); |
1090 | case SNDRV_CTL_IOCTL_ELEM_INFO: | 1125 | case SNDRV_CTL_IOCTL_ELEM_INFO: |
1091 | return snd_ctl_elem_info_user(ctl, argp); | 1126 | return snd_ctl_elem_info_user(ctl, argp); |
1092 | case SNDRV_CTL_IOCTL_ELEM_READ: | 1127 | case SNDRV_CTL_IOCTL_ELEM_READ: |
1093 | return snd_ctl_elem_read_user(ctl->card, argp); | 1128 | return snd_ctl_elem_read_user(card, argp); |
1094 | case SNDRV_CTL_IOCTL_ELEM_WRITE: | 1129 | case SNDRV_CTL_IOCTL_ELEM_WRITE: |
1095 | return snd_ctl_elem_write_user(ctl, argp); | 1130 | return snd_ctl_elem_write_user(ctl, argp); |
1096 | case SNDRV_CTL_IOCTL_ELEM_LOCK: | 1131 | case SNDRV_CTL_IOCTL_ELEM_LOCK: |
@@ -1105,6 +1140,8 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg | |||
1105 | return snd_ctl_elem_remove(ctl, argp); | 1140 | return snd_ctl_elem_remove(ctl, argp); |
1106 | case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS: | 1141 | case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS: |
1107 | return snd_ctl_subscribe_events(ctl, ip); | 1142 | return snd_ctl_subscribe_events(ctl, ip); |
1143 | case SNDRV_CTL_IOCTL_TLV_READ: | ||
1144 | return snd_ctl_tlv_read(card, argp); | ||
1108 | case SNDRV_CTL_IOCTL_POWER: | 1145 | case SNDRV_CTL_IOCTL_POWER: |
1109 | return -ENOPROTOOPT; | 1146 | return -ENOPROTOOPT; |
1110 | case SNDRV_CTL_IOCTL_POWER_STATE: | 1147 | case SNDRV_CTL_IOCTL_POWER_STATE: |