blob: 649d3217590ed465c6e13e39bdeb2f9e53a4a2e5 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Routines for driver control interface
Jaroslav Kyselac1017a42007-10-15 09:50:19 +02003 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/threads.h>
23#include <linux/interrupt.h>
Paul Gortmakerda155d52011-07-15 12:38:28 -040024#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/slab.h>
26#include <linux/vmalloc.h>
27#include <linux/time.h>
Al Viro88a89032018-01-07 13:09:15 -050028#include <linux/mm.h>
Ingo Molnar174cd4b2017-02-02 19:15:33 +010029#include <linux/sched/signal.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <sound/core.h>
31#include <sound/minors.h>
32#include <sound/info.h>
33#include <sound/control.h>
34
35/* max number of user-defined controls */
36#define MAX_USER_CONTROLS 32
Dan Rosenberg5591bf02010-09-28 14:18:20 -040037#define MAX_CONTROL_COUNT 1028
Linus Torvalds1da177e2005-04-16 15:20:36 -070038
Takashi Iwai82e9bae2005-11-17 13:53:23 +010039struct snd_kctl_ioctl {
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 struct list_head list; /* list of all ioctls */
41 snd_kctl_ioctl_func_t fioctl;
Takashi Iwai82e9bae2005-11-17 13:53:23 +010042};
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
44static DECLARE_RWSEM(snd_ioctl_rwsem);
45static LIST_HEAD(snd_control_ioctls);
46#ifdef CONFIG_COMPAT
47static LIST_HEAD(snd_control_compat_ioctls);
48#endif
49
50static int snd_ctl_open(struct inode *inode, struct file *file)
51{
Linus Torvalds1da177e2005-04-16 15:20:36 -070052 unsigned long flags;
Takashi Iwai82e9bae2005-11-17 13:53:23 +010053 struct snd_card *card;
54 struct snd_ctl_file *ctl;
Takashi Iwai23c18d42014-02-19 14:30:29 +010055 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
Takashi Iwai02f48652010-04-13 11:49:04 +020057 err = nonseekable_open(inode, file);
58 if (err < 0)
59 return err;
60
Clemens Ladischf87135f2005-11-20 14:06:59 +010061 card = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_CONTROL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070062 if (!card) {
63 err = -ENODEV;
64 goto __error1;
65 }
66 err = snd_card_file_add(card, file);
67 if (err < 0) {
68 err = -ENODEV;
69 goto __error1;
70 }
71 if (!try_module_get(card->module)) {
72 err = -EFAULT;
73 goto __error2;
74 }
Takashi Iwaica2c0962005-09-09 14:20:23 +020075 ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 if (ctl == NULL) {
77 err = -ENOMEM;
78 goto __error;
79 }
80 INIT_LIST_HEAD(&ctl->events);
81 init_waitqueue_head(&ctl->change_sleep);
82 spin_lock_init(&ctl->read_lock);
83 ctl->card = card;
Takashi Iwai23c18d42014-02-19 14:30:29 +010084 for (i = 0; i < SND_CTL_SUBDEV_ITEMS; i++)
85 ctl->preferred_subdevice[i] = -1;
Clemens Ladisch25d27ed2009-11-02 09:35:44 +010086 ctl->pid = get_pid(task_pid(current));
Linus Torvalds1da177e2005-04-16 15:20:36 -070087 file->private_data = ctl;
88 write_lock_irqsave(&card->ctl_files_rwlock, flags);
89 list_add_tail(&ctl->list, &card->ctl_files);
90 write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
Takashi Iwaia0830db2012-10-16 13:05:59 +020091 snd_card_unref(card);
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 return 0;
93
94 __error:
95 module_put(card->module);
96 __error2:
97 snd_card_file_remove(card, file);
98 __error1:
Takashi Iwaia0830db2012-10-16 13:05:59 +020099 if (card)
100 snd_card_unref(card);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101 return err;
102}
103
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100104static void snd_ctl_empty_read_queue(struct snd_ctl_file * ctl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105{
Borislav Petkov7507e8d2007-10-22 17:11:09 +0200106 unsigned long flags;
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100107 struct snd_kctl_event *cread;
Richard Fitzgeralddd5f3132018-02-27 17:29:54 +0000108
Borislav Petkov7507e8d2007-10-22 17:11:09 +0200109 spin_lock_irqsave(&ctl->read_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 while (!list_empty(&ctl->events)) {
111 cread = snd_kctl_event(ctl->events.next);
112 list_del(&cread->list);
113 kfree(cread);
114 }
Borislav Petkov7507e8d2007-10-22 17:11:09 +0200115 spin_unlock_irqrestore(&ctl->read_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116}
117
118static int snd_ctl_release(struct inode *inode, struct file *file)
119{
120 unsigned long flags;
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100121 struct snd_card *card;
122 struct snd_ctl_file *ctl;
123 struct snd_kcontrol *control;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 unsigned int idx;
125
126 ctl = file->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 file->private_data = NULL;
128 card = ctl->card;
129 write_lock_irqsave(&card->ctl_files_rwlock, flags);
130 list_del(&ctl->list);
131 write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
132 down_write(&card->controls_rwsem);
Johannes Berg9244b2c2006-10-05 16:02:22 +0200133 list_for_each_entry(control, &card->controls, list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134 for (idx = 0; idx < control->count; idx++)
135 if (control->vd[idx].owner == ctl)
136 control->vd[idx].owner = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 up_write(&card->controls_rwsem);
138 snd_ctl_empty_read_queue(ctl);
Clemens Ladisch25d27ed2009-11-02 09:35:44 +0100139 put_pid(ctl->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 kfree(ctl);
141 module_put(card->module);
142 snd_card_file_remove(card, file);
143 return 0;
144}
145
Takashi Iwai12cddbd2014-10-30 13:44:34 +0100146/**
147 * snd_ctl_notify - Send notification to user-space for a control change
148 * @card: the card to send notification
149 * @mask: the event mask, SNDRV_CTL_EVENT_*
150 * @id: the ctl element id to send notification
151 *
152 * This function adds an event record with the given id and mask, appends
153 * to the list and wakes up the user-space for notification. This can be
154 * called in the atomic context.
155 */
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100156void snd_ctl_notify(struct snd_card *card, unsigned int mask,
157 struct snd_ctl_elem_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158{
159 unsigned long flags;
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100160 struct snd_ctl_file *ctl;
161 struct snd_kctl_event *ev;
Richard Fitzgeralddd5f3132018-02-27 17:29:54 +0000162
Takashi Iwai7eaa9432008-08-08 17:09:09 +0200163 if (snd_BUG_ON(!card || !id))
164 return;
Takashi Iwaif388cdc2016-07-08 08:05:19 +0200165 if (card->shutdown)
166 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 read_lock(&card->ctl_files_rwlock);
Takashi Iwai8eeaa2f2014-02-10 09:48:47 +0100168#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 card->mixer_oss_change_count++;
170#endif
Johannes Berg9244b2c2006-10-05 16:02:22 +0200171 list_for_each_entry(ctl, &card->ctl_files, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 if (!ctl->subscribed)
173 continue;
174 spin_lock_irqsave(&ctl->read_lock, flags);
Johannes Berg9244b2c2006-10-05 16:02:22 +0200175 list_for_each_entry(ev, &ctl->events, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 if (ev->id.numid == id->numid) {
177 ev->mask |= mask;
178 goto _found;
179 }
180 }
Takashi Iwaica2c0962005-09-09 14:20:23 +0200181 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 if (ev) {
183 ev->id = *id;
184 ev->mask = mask;
185 list_add_tail(&ev->list, &ctl->events);
186 } else {
Takashi Iwaibb009452014-02-04 18:18:16 +0100187 dev_err(card->dev, "No memory available to allocate event\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 }
189 _found:
190 wake_up(&ctl->change_sleep);
191 spin_unlock_irqrestore(&ctl->read_lock, flags);
192 kill_fasync(&ctl->fasync, SIGIO, POLL_IN);
193 }
194 read_unlock(&card->ctl_files_rwlock);
195}
Takashi Iwaic0d3fb32006-04-28 15:13:39 +0200196EXPORT_SYMBOL(snd_ctl_notify);
197
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198/**
Takashi Sakamoto2225e792015-03-10 22:13:31 +0900199 * snd_ctl_new - create a new control instance with some elements
200 * @kctl: the pointer to store new control instance
201 * @count: the number of elements in this control
202 * @access: the default access flags for elements in this control
203 * @file: given when locking these elements
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 *
Takashi Sakamoto2225e792015-03-10 22:13:31 +0900205 * Allocates a memory object for a new control instance. The instance has
206 * elements as many as the given number (@count). Each element has given
207 * access permissions (@access). Each element is locked when @file is given.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 *
Takashi Sakamoto2225e792015-03-10 22:13:31 +0900209 * Return: 0 on success, error code on failure
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 */
Takashi Sakamoto2225e792015-03-10 22:13:31 +0900211static int snd_ctl_new(struct snd_kcontrol **kctl, unsigned int count,
212 unsigned int access, struct snd_ctl_file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213{
Takashi Sakamoto2225e792015-03-10 22:13:31 +0900214 unsigned int size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 unsigned int idx;
Richard Fitzgeralddd5f3132018-02-27 17:29:54 +0000216
Takashi Sakamoto2225e792015-03-10 22:13:31 +0900217 if (count == 0 || count > MAX_CONTROL_COUNT)
218 return -EINVAL;
Dan Rosenberg5591bf02010-09-28 14:18:20 -0400219
Takashi Sakamoto2225e792015-03-10 22:13:31 +0900220 size = sizeof(struct snd_kcontrol);
221 size += sizeof(struct snd_kcontrol_volatile) * count;
Dan Rosenberg5591bf02010-09-28 14:18:20 -0400222
Takashi Sakamoto2225e792015-03-10 22:13:31 +0900223 *kctl = kzalloc(size, GFP_KERNEL);
Takashi Iwaiec0e9932015-03-10 15:42:14 +0100224 if (!*kctl)
Takashi Sakamoto2225e792015-03-10 22:13:31 +0900225 return -ENOMEM;
Takashi Sakamoto2225e792015-03-10 22:13:31 +0900226
227 for (idx = 0; idx < count; idx++) {
228 (*kctl)->vd[idx].access = access;
229 (*kctl)->vd[idx].owner = file;
230 }
231 (*kctl)->count = count;
232
233 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234}
235
236/**
237 * snd_ctl_new1 - create a control instance from the template
238 * @ncontrol: the initialization record
239 * @private_data: the private data to set
240 *
Richard Fitzgeralddd5f3132018-02-27 17:29:54 +0000241 * Allocates a new struct snd_kcontrol instance and initialize from the given
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 * template. When the access field of ncontrol is 0, it's assumed as
243 * READWRITE access. When the count field is 0, it's assumes as one.
244 *
Yacine Belkadieb7c06e2013-03-11 22:05:14 +0100245 * Return: The pointer of the newly generated instance, or %NULL on failure.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 */
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100247struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,
248 void *private_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249{
Takashi Sakamoto2225e792015-03-10 22:13:31 +0900250 struct snd_kcontrol *kctl;
251 unsigned int count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 unsigned int access;
Takashi Sakamoto2225e792015-03-10 22:13:31 +0900253 int err;
Richard Fitzgeralddd5f3132018-02-27 17:29:54 +0000254
Takashi Iwai7eaa9432008-08-08 17:09:09 +0200255 if (snd_BUG_ON(!ncontrol || !ncontrol->info))
256 return NULL;
Takashi Sakamoto2225e792015-03-10 22:13:31 +0900257
258 count = ncontrol->count;
259 if (count == 0)
260 count = 1;
261
262 access = ncontrol->access;
263 if (access == 0)
264 access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
265 access &= (SNDRV_CTL_ELEM_ACCESS_READWRITE |
266 SNDRV_CTL_ELEM_ACCESS_VOLATILE |
267 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
268 SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE |
269 SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND |
270 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK);
271
272 err = snd_ctl_new(&kctl, count, access, NULL);
273 if (err < 0)
274 return NULL;
275
276 /* The 'numid' member is decided when calling snd_ctl_add(). */
277 kctl->id.iface = ncontrol->iface;
278 kctl->id.device = ncontrol->device;
279 kctl->id.subdevice = ncontrol->subdevice;
Mark Brown366840d2008-10-29 14:40:30 +0000280 if (ncontrol->name) {
Takashi Sakamoto2225e792015-03-10 22:13:31 +0900281 strlcpy(kctl->id.name, ncontrol->name, sizeof(kctl->id.name));
282 if (strcmp(ncontrol->name, kctl->id.name) != 0)
Takashi Iwaibb009452014-02-04 18:18:16 +0100283 pr_warn("ALSA: Control name '%s' truncated to '%s'\n",
Takashi Sakamoto2225e792015-03-10 22:13:31 +0900284 ncontrol->name, kctl->id.name);
Mark Brown366840d2008-10-29 14:40:30 +0000285 }
Takashi Sakamoto2225e792015-03-10 22:13:31 +0900286 kctl->id.index = ncontrol->index;
287
288 kctl->info = ncontrol->info;
289 kctl->get = ncontrol->get;
290 kctl->put = ncontrol->put;
291 kctl->tlv.p = ncontrol->tlv.p;
292
293 kctl->private_value = ncontrol->private_value;
294 kctl->private_data = private_data;
295
296 return kctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297}
Takashi Iwaic0d3fb32006-04-28 15:13:39 +0200298EXPORT_SYMBOL(snd_ctl_new1);
299
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300/**
301 * snd_ctl_free_one - release the control instance
302 * @kcontrol: the control instance
303 *
304 * Releases the control instance created via snd_ctl_new()
305 * or snd_ctl_new1().
306 * Don't call this after the control was added to the card.
307 */
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100308void snd_ctl_free_one(struct snd_kcontrol *kcontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309{
310 if (kcontrol) {
311 if (kcontrol->private_free)
312 kcontrol->private_free(kcontrol);
313 kfree(kcontrol);
314 }
315}
Takashi Iwaic0d3fb32006-04-28 15:13:39 +0200316EXPORT_SYMBOL(snd_ctl_free_one);
317
Clemens Ladisch0e82e5f2011-03-07 13:24:30 +0100318static bool snd_ctl_remove_numid_conflict(struct snd_card *card,
319 unsigned int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320{
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100321 struct snd_kcontrol *kctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322
Lars-Peter Clausenac902c12014-06-18 13:32:34 +0200323 /* Make sure that the ids assigned to the control do not wrap around */
324 if (card->last_numid >= UINT_MAX - count)
325 card->last_numid = 0;
326
Johannes Berg9244b2c2006-10-05 16:02:22 +0200327 list_for_each_entry(kctl, &card->controls, list) {
Clemens Ladisch7c733582011-03-07 13:22:50 +0100328 if (kctl->id.numid < card->last_numid + 1 + count &&
Clemens Ladisch0e82e5f2011-03-07 13:24:30 +0100329 kctl->id.numid + kctl->count > card->last_numid + 1) {
330 card->last_numid = kctl->id.numid + kctl->count - 1;
331 return true;
332 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 }
Clemens Ladisch0e82e5f2011-03-07 13:24:30 +0100334 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335}
336
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100337static int snd_ctl_find_hole(struct snd_card *card, unsigned int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338{
Clemens Ladisch0e82e5f2011-03-07 13:24:30 +0100339 unsigned int iter = 100000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340
Clemens Ladisch0e82e5f2011-03-07 13:24:30 +0100341 while (snd_ctl_remove_numid_conflict(card, count)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 if (--iter == 0) {
343 /* this situation is very unlikely */
Takashi Iwaibb009452014-02-04 18:18:16 +0100344 dev_err(card->dev, "unable to allocate new control numid\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 return -ENOMEM;
346 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 }
348 return 0;
349}
350
Takashi Iwaid8a2dca2018-11-22 14:36:17 +0100351/* add a new kcontrol object; call with card->controls_rwsem locked */
352static int __snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
353{
354 struct snd_ctl_elem_id id;
355 unsigned int idx;
356 unsigned int count;
357
358 id = kcontrol->id;
359 if (id.index > UINT_MAX - kcontrol->count)
360 return -EINVAL;
361
362 if (snd_ctl_find_id(card, &id)) {
363 dev_err(card->dev,
364 "control %i:%i:%i:%s:%i is already present\n",
365 id.iface, id.device, id.subdevice, id.name, id.index);
366 return -EBUSY;
367 }
368
369 if (snd_ctl_find_hole(card, kcontrol->count) < 0)
370 return -ENOMEM;
371
372 list_add_tail(&kcontrol->list, &card->controls);
373 card->controls_count += kcontrol->count;
374 kcontrol->id.numid = card->last_numid + 1;
375 card->last_numid += kcontrol->count;
376
377 id = kcontrol->id;
378 count = kcontrol->count;
379 for (idx = 0; idx < count; idx++, id.index++, id.numid++)
380 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
381
382 return 0;
383}
384
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385/**
386 * snd_ctl_add - add the control instance to the card
387 * @card: the card instance
388 * @kcontrol: the control instance to add
389 *
390 * Adds the control instance created via snd_ctl_new() or
391 * snd_ctl_new1() to the given card. Assigns also an unique
392 * numid used for fast search.
393 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 * It frees automatically the control which cannot be added.
Yacine Belkadieb7c06e2013-03-11 22:05:14 +0100395 *
396 * Return: Zero if successful, or a negative error code on failure.
397 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 */
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100399int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400{
Takashi Iwaic6077b32006-03-21 16:07:13 +0100401 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402
Takashi Iwai73e77ba2005-11-17 17:44:01 +0100403 if (! kcontrol)
Takashi Iwaic6077b32006-03-21 16:07:13 +0100404 return err;
Takashi Iwai7eaa9432008-08-08 17:09:09 +0200405 if (snd_BUG_ON(!card || !kcontrol->info))
406 goto error;
Lars-Peter Clausen883a1d42014-06-18 13:32:35 +0200407
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 down_write(&card->controls_rwsem);
Takashi Iwaid8a2dca2018-11-22 14:36:17 +0100409 err = __snd_ctl_add(card, kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 up_write(&card->controls_rwsem);
Takashi Iwaid8a2dca2018-11-22 14:36:17 +0100411 if (err < 0)
412 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 return 0;
Takashi Iwaic6077b32006-03-21 16:07:13 +0100414
415 error:
416 snd_ctl_free_one(kcontrol);
417 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418}
Takashi Iwaic0d3fb32006-04-28 15:13:39 +0200419EXPORT_SYMBOL(snd_ctl_add);
420
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421/**
Dimitris Papastamos66b5b972011-03-16 12:16:39 +0000422 * snd_ctl_replace - replace the control instance of the card
423 * @card: the card instance
424 * @kcontrol: the control instance to replace
425 * @add_on_replace: add the control if not already added
426 *
427 * Replaces the given control. If the given control does not exist
428 * and the add_on_replace flag is set, the control is added. If the
429 * control exists, it is destroyed first.
430 *
Dimitris Papastamos66b5b972011-03-16 12:16:39 +0000431 * It frees automatically the control which cannot be added or replaced.
Yacine Belkadieb7c06e2013-03-11 22:05:14 +0100432 *
433 * Return: Zero if successful, or a negative error code on failure.
Dimitris Papastamos66b5b972011-03-16 12:16:39 +0000434 */
435int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
436 bool add_on_replace)
437{
438 struct snd_ctl_elem_id id;
Lars-Peter Clausenfd9f26e2014-06-18 13:32:33 +0200439 unsigned int count;
Dimitris Papastamos66b5b972011-03-16 12:16:39 +0000440 unsigned int idx;
441 struct snd_kcontrol *old;
442 int ret;
443
444 if (!kcontrol)
445 return -EINVAL;
446 if (snd_BUG_ON(!card || !kcontrol->info)) {
447 ret = -EINVAL;
448 goto error;
449 }
450 id = kcontrol->id;
451 down_write(&card->controls_rwsem);
452 old = snd_ctl_find_id(card, &id);
453 if (!old) {
454 if (add_on_replace)
455 goto add;
456 up_write(&card->controls_rwsem);
457 ret = -EINVAL;
458 goto error;
459 }
460 ret = snd_ctl_remove(card, old);
461 if (ret < 0) {
462 up_write(&card->controls_rwsem);
463 goto error;
464 }
465add:
466 if (snd_ctl_find_hole(card, kcontrol->count) < 0) {
467 up_write(&card->controls_rwsem);
468 ret = -ENOMEM;
469 goto error;
470 }
471 list_add_tail(&kcontrol->list, &card->controls);
472 card->controls_count += kcontrol->count;
473 kcontrol->id.numid = card->last_numid + 1;
474 card->last_numid += kcontrol->count;
Takashi Sakamotoe6ff3842015-02-10 00:01:45 +0900475 id = kcontrol->id;
Lars-Peter Clausenfd9f26e2014-06-18 13:32:33 +0200476 count = kcontrol->count;
Dimitris Papastamos66b5b972011-03-16 12:16:39 +0000477 up_write(&card->controls_rwsem);
Lars-Peter Clausenfd9f26e2014-06-18 13:32:33 +0200478 for (idx = 0; idx < count; idx++, id.index++, id.numid++)
Dimitris Papastamos66b5b972011-03-16 12:16:39 +0000479 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
480 return 0;
481
482error:
483 snd_ctl_free_one(kcontrol);
484 return ret;
485}
486EXPORT_SYMBOL(snd_ctl_replace);
487
488/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 * snd_ctl_remove - remove the control from the card and release it
490 * @card: the card instance
491 * @kcontrol: the control instance to remove
492 *
493 * Removes the control from the card and then releases the instance.
494 * You don't need to call snd_ctl_free_one(). You must be in
495 * the write lock - down_write(&card->controls_rwsem).
Yacine Belkadieb7c06e2013-03-11 22:05:14 +0100496 *
497 * Return: 0 if successful, or a negative error code on failure.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 */
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100499int snd_ctl_remove(struct snd_card *card, struct snd_kcontrol *kcontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500{
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100501 struct snd_ctl_elem_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 unsigned int idx;
503
Takashi Iwai7eaa9432008-08-08 17:09:09 +0200504 if (snd_BUG_ON(!card || !kcontrol))
505 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 list_del(&kcontrol->list);
507 card->controls_count -= kcontrol->count;
508 id = kcontrol->id;
509 for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
510 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_REMOVE, &id);
511 snd_ctl_free_one(kcontrol);
512 return 0;
513}
Takashi Iwaic0d3fb32006-04-28 15:13:39 +0200514EXPORT_SYMBOL(snd_ctl_remove);
515
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516/**
517 * snd_ctl_remove_id - remove the control of the given id and release it
518 * @card: the card instance
519 * @id: the control id to remove
520 *
521 * Finds the control instance with the given id, removes it from the
522 * card list and releases it.
Yacine Belkadieb7c06e2013-03-11 22:05:14 +0100523 *
524 * Return: 0 if successful, or a negative error code on failure.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 */
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100526int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527{
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100528 struct snd_kcontrol *kctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 int ret;
530
531 down_write(&card->controls_rwsem);
532 kctl = snd_ctl_find_id(card, id);
533 if (kctl == NULL) {
534 up_write(&card->controls_rwsem);
535 return -ENOENT;
536 }
537 ret = snd_ctl_remove(card, kctl);
538 up_write(&card->controls_rwsem);
539 return ret;
540}
Takashi Iwaic0d3fb32006-04-28 15:13:39 +0200541EXPORT_SYMBOL(snd_ctl_remove_id);
542
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543/**
Clemens Ladischf217ac52009-08-17 12:27:22 +0200544 * snd_ctl_remove_user_ctl - remove and release the unlocked user control
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 * @file: active control handle
546 * @id: the control id to remove
547 *
548 * Finds the control instance with the given id, removes it from the
549 * card list and releases it.
Yacine Belkadieb7c06e2013-03-11 22:05:14 +0100550 *
551 * Return: 0 if successful, or a negative error code on failure.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 */
Clemens Ladischf217ac52009-08-17 12:27:22 +0200553static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file,
554 struct snd_ctl_elem_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555{
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100556 struct snd_card *card = file->card;
557 struct snd_kcontrol *kctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 int idx, ret;
559
560 down_write(&card->controls_rwsem);
561 kctl = snd_ctl_find_id(card, id);
562 if (kctl == NULL) {
Clemens Ladisch317b8082009-08-17 12:26:34 +0200563 ret = -ENOENT;
564 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 }
Clemens Ladisch18dd0aa2009-08-17 12:28:09 +0200566 if (!(kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_USER)) {
567 ret = -EINVAL;
568 goto error;
569 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 for (idx = 0; idx < kctl->count; idx++)
571 if (kctl->vd[idx].owner != NULL && kctl->vd[idx].owner != file) {
Clemens Ladisch317b8082009-08-17 12:26:34 +0200572 ret = -EBUSY;
573 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 }
575 ret = snd_ctl_remove(card, kctl);
Clemens Ladischf217ac52009-08-17 12:27:22 +0200576 if (ret < 0)
577 goto error;
578 card->user_ctl_count--;
Clemens Ladisch317b8082009-08-17 12:26:34 +0200579error:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 up_write(&card->controls_rwsem);
581 return ret;
582}
583
584/**
Takashi Iwai3cbdd752008-08-29 16:09:01 +0200585 * snd_ctl_activate_id - activate/inactivate the control of the given id
586 * @card: the card instance
587 * @id: the control id to activate/inactivate
588 * @active: non-zero to activate
589 *
590 * Finds the control instance with the given id, and activate or
591 * inactivate the control together with notification, if changed.
Takashi Sakamotoc78497e2015-04-11 17:41:02 +0900592 * The given ID data is filled with full information.
Takashi Iwai3cbdd752008-08-29 16:09:01 +0200593 *
Yacine Belkadieb7c06e2013-03-11 22:05:14 +0100594 * Return: 0 if unchanged, 1 if changed, or a negative error code on failure.
Takashi Iwai3cbdd752008-08-29 16:09:01 +0200595 */
596int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
597 int active)
598{
599 struct snd_kcontrol *kctl;
600 struct snd_kcontrol_volatile *vd;
601 unsigned int index_offset;
602 int ret;
603
604 down_write(&card->controls_rwsem);
605 kctl = snd_ctl_find_id(card, id);
606 if (kctl == NULL) {
607 ret = -ENOENT;
608 goto unlock;
609 }
Lars-Peter Clausen31584ed2014-11-07 14:12:34 +0100610 index_offset = snd_ctl_get_ioff(kctl, id);
Takashi Iwai3cbdd752008-08-29 16:09:01 +0200611 vd = &kctl->vd[index_offset];
612 ret = 0;
613 if (active) {
614 if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE))
615 goto unlock;
616 vd->access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
617 } else {
618 if (vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE)
619 goto unlock;
620 vd->access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
621 }
Takashi Sakamotoc78497e2015-04-11 17:41:02 +0900622 snd_ctl_build_ioff(id, kctl, index_offset);
Takashi Iwai3cbdd752008-08-29 16:09:01 +0200623 ret = 1;
624 unlock:
625 up_write(&card->controls_rwsem);
626 if (ret > 0)
627 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, id);
628 return ret;
629}
630EXPORT_SYMBOL_GPL(snd_ctl_activate_id);
631
632/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 * snd_ctl_rename_id - replace the id of a control on the card
634 * @card: the card instance
635 * @src_id: the old id
636 * @dst_id: the new id
637 *
638 * Finds the control with the old id from the card, and replaces the
639 * id with the new one.
640 *
Yacine Belkadieb7c06e2013-03-11 22:05:14 +0100641 * Return: Zero if successful, or a negative error code on failure.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 */
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100643int snd_ctl_rename_id(struct snd_card *card, struct snd_ctl_elem_id *src_id,
644 struct snd_ctl_elem_id *dst_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645{
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100646 struct snd_kcontrol *kctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647
648 down_write(&card->controls_rwsem);
649 kctl = snd_ctl_find_id(card, src_id);
650 if (kctl == NULL) {
651 up_write(&card->controls_rwsem);
652 return -ENOENT;
653 }
654 kctl->id = *dst_id;
655 kctl->id.numid = card->last_numid + 1;
656 card->last_numid += kctl->count;
657 up_write(&card->controls_rwsem);
658 return 0;
659}
Takashi Iwaic0d3fb32006-04-28 15:13:39 +0200660EXPORT_SYMBOL(snd_ctl_rename_id);
661
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662/**
663 * snd_ctl_find_numid - find the control instance with the given number-id
664 * @card: the card instance
665 * @numid: the number-id to search
666 *
667 * Finds the control instance with the given number-id from the card.
668 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 * The caller must down card->controls_rwsem before calling this function
670 * (if the race condition can happen).
Yacine Belkadieb7c06e2013-03-11 22:05:14 +0100671 *
672 * Return: The pointer of the instance if found, or %NULL if not.
673 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 */
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100675struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676{
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100677 struct snd_kcontrol *kctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678
Takashi Iwai7eaa9432008-08-08 17:09:09 +0200679 if (snd_BUG_ON(!card || !numid))
680 return NULL;
Johannes Berg9244b2c2006-10-05 16:02:22 +0200681 list_for_each_entry(kctl, &card->controls, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 if (kctl->id.numid <= numid && kctl->id.numid + kctl->count > numid)
683 return kctl;
684 }
685 return NULL;
686}
Takashi Iwaic0d3fb32006-04-28 15:13:39 +0200687EXPORT_SYMBOL(snd_ctl_find_numid);
688
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689/**
690 * snd_ctl_find_id - find the control instance with the given id
691 * @card: the card instance
692 * @id: the id to search
693 *
694 * Finds the control instance with the given id from the card.
695 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 * The caller must down card->controls_rwsem before calling this function
697 * (if the race condition can happen).
Yacine Belkadieb7c06e2013-03-11 22:05:14 +0100698 *
699 * Return: The pointer of the instance if found, or %NULL if not.
700 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 */
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100702struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card,
703 struct snd_ctl_elem_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704{
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100705 struct snd_kcontrol *kctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706
Takashi Iwai7eaa9432008-08-08 17:09:09 +0200707 if (snd_BUG_ON(!card || !id))
708 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 if (id->numid != 0)
710 return snd_ctl_find_numid(card, id->numid);
Johannes Berg9244b2c2006-10-05 16:02:22 +0200711 list_for_each_entry(kctl, &card->controls, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 if (kctl->id.iface != id->iface)
713 continue;
714 if (kctl->id.device != id->device)
715 continue;
716 if (kctl->id.subdevice != id->subdevice)
717 continue;
718 if (strncmp(kctl->id.name, id->name, sizeof(kctl->id.name)))
719 continue;
720 if (kctl->id.index > id->index)
721 continue;
722 if (kctl->id.index + kctl->count <= id->index)
723 continue;
724 return kctl;
725 }
726 return NULL;
727}
Takashi Iwaic0d3fb32006-04-28 15:13:39 +0200728EXPORT_SYMBOL(snd_ctl_find_id);
729
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100730static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 unsigned int cmd, void __user *arg)
732{
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100733 struct snd_ctl_card_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734
Takashi Iwaica2c0962005-09-09 14:20:23 +0200735 info = kzalloc(sizeof(*info), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 if (! info)
737 return -ENOMEM;
738 down_read(&snd_ioctl_rwsem);
739 info->card = card->number;
740 strlcpy(info->id, card->id, sizeof(info->id));
741 strlcpy(info->driver, card->driver, sizeof(info->driver));
742 strlcpy(info->name, card->shortname, sizeof(info->name));
743 strlcpy(info->longname, card->longname, sizeof(info->longname));
744 strlcpy(info->mixername, card->mixername, sizeof(info->mixername));
745 strlcpy(info->components, card->components, sizeof(info->components));
746 up_read(&snd_ioctl_rwsem);
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100747 if (copy_to_user(arg, info, sizeof(struct snd_ctl_card_info))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 kfree(info);
749 return -EFAULT;
750 }
751 kfree(info);
752 return 0;
753}
754
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100755static int snd_ctl_elem_list(struct snd_card *card,
756 struct snd_ctl_elem_list __user *_list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757{
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100758 struct snd_ctl_elem_list list;
759 struct snd_kcontrol *kctl;
Takashi Iwai53e7bf42017-05-22 17:43:04 +0200760 struct snd_ctl_elem_id id;
Luca Tettamanti78fa2c42011-05-25 22:43:27 +0200761 unsigned int offset, space, jidx;
Takashi Iwai53e7bf42017-05-22 17:43:04 +0200762 int err = 0;
Richard Fitzgeralddd5f3132018-02-27 17:29:54 +0000763
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 if (copy_from_user(&list, _list, sizeof(list)))
765 return -EFAULT;
766 offset = list.offset;
767 space = list.space;
Takashi Sakamoto4e361d32017-05-24 10:04:30 +0900768
Takashi Iwai53e7bf42017-05-22 17:43:04 +0200769 down_read(&card->controls_rwsem);
770 list.count = card->controls_count;
771 list.used = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 if (space > 0) {
Takashi Iwai53e7bf42017-05-22 17:43:04 +0200773 list_for_each_entry(kctl, &card->controls, list) {
774 if (offset >= kctl->count) {
775 offset -= kctl->count;
776 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 }
Takashi Iwai53e7bf42017-05-22 17:43:04 +0200778 for (jidx = offset; jidx < kctl->count; jidx++) {
779 snd_ctl_build_ioff(&id, kctl, jidx);
780 if (copy_to_user(list.pids + list.used, &id,
781 sizeof(id))) {
782 err = -EFAULT;
783 goto out;
784 }
785 list.used++;
786 if (!--space)
787 goto out;
788 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 offset = 0;
790 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 }
Takashi Iwai53e7bf42017-05-22 17:43:04 +0200792 out:
793 up_read(&card->controls_rwsem);
794 if (!err && copy_to_user(_list, &list, sizeof(list)))
795 err = -EFAULT;
796 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797}
798
Takashi Sakamoto860c1992016-07-07 21:57:10 +0900799static bool validate_element_member_dimension(struct snd_ctl_elem_info *info)
800{
801 unsigned int members;
802 unsigned int i;
803
804 if (info->dimen.d[0] == 0)
805 return true;
806
807 members = 1;
808 for (i = 0; i < ARRAY_SIZE(info->dimen.d); ++i) {
809 if (info->dimen.d[i] == 0)
810 break;
811 members *= info->dimen.d[i];
812
813 /*
814 * info->count should be validated in advance, to guarantee
815 * calculation soundness.
816 */
817 if (members > info->count)
818 return false;
819 }
820
821 for (++i; i < ARRAY_SIZE(info->dimen.d); ++i) {
822 if (info->dimen.d[i] > 0)
823 return false;
824 }
825
826 return members == info->count;
827}
828
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100829static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
830 struct snd_ctl_elem_info *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831{
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100832 struct snd_card *card = ctl->card;
833 struct snd_kcontrol *kctl;
834 struct snd_kcontrol_volatile *vd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 unsigned int index_offset;
836 int result;
Richard Fitzgeralddd5f3132018-02-27 17:29:54 +0000837
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 down_read(&card->controls_rwsem);
839 kctl = snd_ctl_find_id(card, &info->id);
840 if (kctl == NULL) {
841 up_read(&card->controls_rwsem);
842 return -ENOENT;
843 }
844#ifdef CONFIG_SND_DEBUG
845 info->access = 0;
846#endif
847 result = kctl->info(kctl, info);
848 if (result >= 0) {
Takashi Iwai7eaa9432008-08-08 17:09:09 +0200849 snd_BUG_ON(info->access);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 index_offset = snd_ctl_get_ioff(kctl, &info->id);
851 vd = &kctl->vd[index_offset];
852 snd_ctl_build_ioff(&info->id, kctl, index_offset);
853 info->access = vd->access;
854 if (vd->owner) {
855 info->access |= SNDRV_CTL_ELEM_ACCESS_LOCK;
856 if (vd->owner == ctl)
857 info->access |= SNDRV_CTL_ELEM_ACCESS_OWNER;
Clemens Ladisch25d27ed2009-11-02 09:35:44 +0100858 info->owner = pid_vnr(vd->owner->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 } else {
860 info->owner = -1;
861 }
862 }
863 up_read(&card->controls_rwsem);
864 return result;
865}
866
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100867static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl,
868 struct snd_ctl_elem_info __user *_info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869{
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100870 struct snd_ctl_elem_info info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 int result;
872
873 if (copy_from_user(&info, _info, sizeof(info)))
874 return -EFAULT;
Takashi Iwaicbac4b02006-03-27 12:38:07 +0200875 result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
Takashi Iwai7d8e8292017-08-30 16:13:25 +0200876 if (result < 0)
877 return result;
878 result = snd_ctl_elem_info(ctl, &info);
879 if (result < 0)
880 return result;
881 if (copy_to_user(_info, &info, sizeof(info)))
882 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 return result;
884}
885
Takashi Iwaid3bd67c2008-06-12 18:17:26 +0200886static int snd_ctl_elem_read(struct snd_card *card,
887 struct snd_ctl_elem_value *control)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888{
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100889 struct snd_kcontrol *kctl;
890 struct snd_kcontrol_volatile *vd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 unsigned int index_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 kctl = snd_ctl_find_id(card, &control->id);
Takashi Sakamotobecf9e52017-08-20 13:49:07 +0900894 if (kctl == NULL)
895 return -ENOENT;
896
897 index_offset = snd_ctl_get_ioff(kctl, &control->id);
898 vd = &kctl->vd[index_offset];
Richard Fitzgerald5a236992018-02-27 17:01:18 +0000899 if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_READ) || kctl->get == NULL)
Takashi Sakamotobecf9e52017-08-20 13:49:07 +0900900 return -EPERM;
901
902 snd_ctl_build_ioff(&control->id, kctl, index_offset);
903 return kctl->get(kctl, control);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904}
905
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100906static int snd_ctl_elem_read_user(struct snd_card *card,
907 struct snd_ctl_elem_value __user *_control)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908{
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100909 struct snd_ctl_elem_value *control;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 int result;
Li Zefanef44a1e2009-04-10 09:43:08 +0800911
912 control = memdup_user(_control, sizeof(*control));
913 if (IS_ERR(control))
914 return PTR_ERR(control);
915
Takashi Iwaicbac4b02006-03-27 12:38:07 +0200916 result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
Takashi Iwai7d8e8292017-08-30 16:13:25 +0200917 if (result < 0)
918 goto error;
919
920 down_read(&card->controls_rwsem);
921 result = snd_ctl_elem_read(card, control);
922 up_read(&card->controls_rwsem);
923 if (result < 0)
924 goto error;
925
926 if (copy_to_user(_control, control, sizeof(*control)))
927 result = -EFAULT;
928 error:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 kfree(control);
930 return result;
931}
932
Takashi Iwaid3bd67c2008-06-12 18:17:26 +0200933static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
934 struct snd_ctl_elem_value *control)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935{
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100936 struct snd_kcontrol *kctl;
937 struct snd_kcontrol_volatile *vd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 unsigned int index_offset;
Takashi Iwai8ace4f32008-01-08 17:57:26 +0100939 int result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 kctl = snd_ctl_find_id(card, &control->id);
Takashi Sakamotobecf9e52017-08-20 13:49:07 +0900942 if (kctl == NULL)
943 return -ENOENT;
944
945 index_offset = snd_ctl_get_ioff(kctl, &control->id);
946 vd = &kctl->vd[index_offset];
947 if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_WRITE) || kctl->put == NULL ||
948 (file && vd->owner && vd->owner != file)) {
949 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 }
Takashi Sakamotobecf9e52017-08-20 13:49:07 +0900951
952 snd_ctl_build_ioff(&control->id, kctl, index_offset);
953 result = kctl->put(kctl, control);
954 if (result < 0)
955 return result;
956
957 if (result > 0) {
958 struct snd_ctl_elem_id id = control->id;
959 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
960 }
961
962 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963}
964
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100965static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
966 struct snd_ctl_elem_value __user *_control)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967{
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100968 struct snd_ctl_elem_value *control;
Giuliano Pochini64649402006-03-13 14:11:11 +0100969 struct snd_card *card;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 int result;
971
Li Zefanef44a1e2009-04-10 09:43:08 +0800972 control = memdup_user(_control, sizeof(*control));
973 if (IS_ERR(control))
974 return PTR_ERR(control);
975
Giuliano Pochini64649402006-03-13 14:11:11 +0100976 card = file->card;
Takashi Iwaicbac4b02006-03-27 12:38:07 +0200977 result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
Takashi Iwai7d8e8292017-08-30 16:13:25 +0200978 if (result < 0)
979 goto error;
980
981 down_write(&card->controls_rwsem);
982 result = snd_ctl_elem_write(card, file, control);
983 up_write(&card->controls_rwsem);
984 if (result < 0)
985 goto error;
986
987 if (copy_to_user(_control, control, sizeof(*control)))
988 result = -EFAULT;
989 error:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 kfree(control);
991 return result;
992}
993
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100994static int snd_ctl_elem_lock(struct snd_ctl_file *file,
995 struct snd_ctl_elem_id __user *_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996{
Takashi Iwai82e9bae2005-11-17 13:53:23 +0100997 struct snd_card *card = file->card;
998 struct snd_ctl_elem_id id;
999 struct snd_kcontrol *kctl;
1000 struct snd_kcontrol_volatile *vd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 int result;
Richard Fitzgeralddd5f3132018-02-27 17:29:54 +00001002
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 if (copy_from_user(&id, _id, sizeof(id)))
1004 return -EFAULT;
1005 down_write(&card->controls_rwsem);
1006 kctl = snd_ctl_find_id(card, &id);
1007 if (kctl == NULL) {
1008 result = -ENOENT;
1009 } else {
1010 vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)];
1011 if (vd->owner != NULL)
1012 result = -EBUSY;
1013 else {
1014 vd->owner = file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 result = 0;
1016 }
1017 }
1018 up_write(&card->controls_rwsem);
1019 return result;
1020}
1021
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001022static int snd_ctl_elem_unlock(struct snd_ctl_file *file,
1023 struct snd_ctl_elem_id __user *_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024{
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001025 struct snd_card *card = file->card;
1026 struct snd_ctl_elem_id id;
1027 struct snd_kcontrol *kctl;
1028 struct snd_kcontrol_volatile *vd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 int result;
Richard Fitzgeralddd5f3132018-02-27 17:29:54 +00001030
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 if (copy_from_user(&id, _id, sizeof(id)))
1032 return -EFAULT;
1033 down_write(&card->controls_rwsem);
1034 kctl = snd_ctl_find_id(card, &id);
1035 if (kctl == NULL) {
1036 result = -ENOENT;
1037 } else {
1038 vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)];
1039 if (vd->owner == NULL)
1040 result = -EINVAL;
1041 else if (vd->owner != file)
1042 result = -EPERM;
1043 else {
1044 vd->owner = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 result = 0;
1046 }
1047 }
1048 up_write(&card->controls_rwsem);
1049 return result;
1050}
1051
1052struct user_element {
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001053 struct snd_ctl_elem_info info;
Lars-Peter Clausen07f4d9d2014-06-18 13:32:31 +02001054 struct snd_card *card;
Takashi Sakamotoe1c78df2015-04-12 10:12:25 +09001055 char *elem_data; /* element data */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 unsigned long elem_data_size; /* size of element data in bytes */
Jaroslav Kysela8aa9b582006-07-05 17:34:51 +02001057 void *tlv_data; /* TLV data */
1058 unsigned long tlv_data_size; /* TLV data size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 void *priv_data; /* private data (like strings for enumerated type) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060};
1061
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001062static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol,
1063 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064{
1065 struct user_element *ue = kcontrol->private_data;
Takashi Sakamotoc378c3b2015-04-11 17:41:03 +09001066 unsigned int offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067
Takashi Sakamotoc378c3b2015-04-11 17:41:03 +09001068 offset = snd_ctl_get_ioff(kcontrol, &uinfo->id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 *uinfo = ue->info;
Takashi Sakamotoc378c3b2015-04-11 17:41:03 +09001070 snd_ctl_build_ioff(&uinfo->id, kcontrol, offset);
1071
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 return 0;
1073}
1074
Clemens Ladisch8d448162011-10-07 22:38:59 +02001075static int snd_ctl_elem_user_enum_info(struct snd_kcontrol *kcontrol,
1076 struct snd_ctl_elem_info *uinfo)
1077{
1078 struct user_element *ue = kcontrol->private_data;
1079 const char *names;
1080 unsigned int item;
Takashi Sakamotoc378c3b2015-04-11 17:41:03 +09001081 unsigned int offset;
Clemens Ladisch8d448162011-10-07 22:38:59 +02001082
1083 item = uinfo->value.enumerated.item;
1084
Takashi Sakamotoc378c3b2015-04-11 17:41:03 +09001085 offset = snd_ctl_get_ioff(kcontrol, &uinfo->id);
Clemens Ladisch8d448162011-10-07 22:38:59 +02001086 *uinfo = ue->info;
Takashi Sakamotoc378c3b2015-04-11 17:41:03 +09001087 snd_ctl_build_ioff(&uinfo->id, kcontrol, offset);
Clemens Ladisch8d448162011-10-07 22:38:59 +02001088
1089 item = min(item, uinfo->value.enumerated.items - 1);
1090 uinfo->value.enumerated.item = item;
1091
1092 names = ue->priv_data;
1093 for (; item > 0; --item)
1094 names += strlen(names) + 1;
1095 strcpy(uinfo->value.enumerated.name, names);
1096
1097 return 0;
1098}
1099
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001100static int snd_ctl_elem_user_get(struct snd_kcontrol *kcontrol,
1101 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102{
1103 struct user_element *ue = kcontrol->private_data;
Takashi Sakamotoe1c78df2015-04-12 10:12:25 +09001104 unsigned int size = ue->elem_data_size;
1105 char *src = ue->elem_data +
1106 snd_ctl_get_ioff(kcontrol, &ucontrol->id) * size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107
Takashi Sakamotoe1c78df2015-04-12 10:12:25 +09001108 memcpy(&ucontrol->value, src, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 return 0;
1110}
1111
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001112static int snd_ctl_elem_user_put(struct snd_kcontrol *kcontrol,
1113 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114{
1115 int change;
1116 struct user_element *ue = kcontrol->private_data;
Takashi Sakamotoe1c78df2015-04-12 10:12:25 +09001117 unsigned int size = ue->elem_data_size;
1118 char *dst = ue->elem_data +
1119 snd_ctl_get_ioff(kcontrol, &ucontrol->id) * size;
Lars-Peter Clausen07f4d9d2014-06-18 13:32:31 +02001120
Takashi Sakamotoe1c78df2015-04-12 10:12:25 +09001121 change = memcmp(&ucontrol->value, dst, size) != 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 if (change)
Takashi Sakamotoe1c78df2015-04-12 10:12:25 +09001123 memcpy(dst, &ucontrol->value, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 return change;
1125}
1126
Takashi Sakamoto6d4d41f2017-08-03 20:20:44 +09001127static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
1128 unsigned int size)
Jaroslav Kysela8aa9b582006-07-05 17:34:51 +02001129{
Takashi Sakamoto6d4d41f2017-08-03 20:20:44 +09001130 struct user_element *ue = kctl->private_data;
1131 unsigned int *container;
Takashi Sakamotoda428822017-08-24 10:46:15 +09001132 struct snd_ctl_elem_id id;
Takashi Sakamotob8e22042017-08-24 10:46:16 +09001133 unsigned int mask = 0;
Takashi Sakamotoda428822017-08-24 10:46:15 +09001134 int i;
Takashi Sakamoto6d4d41f2017-08-03 20:20:44 +09001135 int change;
Jaroslav Kysela8aa9b582006-07-05 17:34:51 +02001136
Takashi Sakamoto6d4d41f2017-08-03 20:20:44 +09001137 if (size > 1024 * 128) /* sane value */
1138 return -EINVAL;
Takashi Sakamoto30d83402017-08-03 20:20:42 +09001139
Al Viro88a89032018-01-07 13:09:15 -05001140 container = vmemdup_user(buf, size);
Takashi Sakamoto6d4d41f2017-08-03 20:20:44 +09001141 if (IS_ERR(container))
1142 return PTR_ERR(container);
Li Zefanef44a1e2009-04-10 09:43:08 +08001143
Takashi Sakamoto6d4d41f2017-08-03 20:20:44 +09001144 change = ue->tlv_data_size != size;
1145 if (!change)
Takashi Iwai241bc822017-08-22 15:44:45 +02001146 change = memcmp(ue->tlv_data, container, size) != 0;
Takashi Sakamoto6d4d41f2017-08-03 20:20:44 +09001147 if (!change) {
Al Viro88a89032018-01-07 13:09:15 -05001148 kvfree(container);
Takashi Sakamoto30d83402017-08-03 20:20:42 +09001149 return 0;
Jaroslav Kysela8aa9b582006-07-05 17:34:51 +02001150 }
Takashi Sakamoto6d4d41f2017-08-03 20:20:44 +09001151
Takashi Sakamotob8e22042017-08-24 10:46:16 +09001152 if (ue->tlv_data == NULL) {
1153 /* Now TLV data is available. */
1154 for (i = 0; i < kctl->count; ++i)
1155 kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
1156 mask = SNDRV_CTL_EVENT_MASK_INFO;
1157 }
1158
Al Viro88a89032018-01-07 13:09:15 -05001159 kvfree(ue->tlv_data);
Takashi Sakamoto6d4d41f2017-08-03 20:20:44 +09001160 ue->tlv_data = container;
1161 ue->tlv_data_size = size;
1162
Takashi Sakamotob8e22042017-08-24 10:46:16 +09001163 mask |= SNDRV_CTL_EVENT_MASK_TLV;
Takashi Sakamotoda428822017-08-24 10:46:15 +09001164 for (i = 0; i < kctl->count; ++i) {
1165 snd_ctl_build_ioff(&id, kctl, i);
Takashi Sakamotob8e22042017-08-24 10:46:16 +09001166 snd_ctl_notify(ue->card, mask, &id);
Takashi Sakamotoda428822017-08-24 10:46:15 +09001167 }
Takashi Sakamotofb8027e2017-08-24 10:46:14 +09001168
Takashi Sakamoto6d4d41f2017-08-03 20:20:44 +09001169 return change;
1170}
1171
1172static int read_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
1173 unsigned int size)
1174{
1175 struct user_element *ue = kctl->private_data;
1176
1177 if (ue->tlv_data_size == 0 || ue->tlv_data == NULL)
1178 return -ENXIO;
1179
1180 if (size < ue->tlv_data_size)
1181 return -ENOSPC;
1182
1183 if (copy_to_user(buf, ue->tlv_data, ue->tlv_data_size))
1184 return -EFAULT;
1185
1186 return 0;
1187}
1188
1189static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kctl, int op_flag,
1190 unsigned int size, unsigned int __user *buf)
1191{
1192 if (op_flag == SNDRV_CTL_TLV_OP_WRITE)
1193 return replace_user_tlv(kctl, buf, size);
1194 else
1195 return read_user_tlv(kctl, buf, size);
Jaroslav Kysela8aa9b582006-07-05 17:34:51 +02001196}
1197
Clemens Ladisch8d448162011-10-07 22:38:59 +02001198static int snd_ctl_elem_init_enum_names(struct user_element *ue)
1199{
1200 char *names, *p;
1201 size_t buf_len, name_len;
1202 unsigned int i;
Olof Johansson447c6f92011-11-05 22:51:54 +01001203 const uintptr_t user_ptrval = ue->info.value.enumerated.names_ptr;
Clemens Ladisch8d448162011-10-07 22:38:59 +02001204
1205 if (ue->info.value.enumerated.names_length > 64 * 1024)
1206 return -EINVAL;
1207
Al Viro59aeaf32018-01-07 13:11:03 -05001208 names = vmemdup_user((const void __user *)user_ptrval,
Clemens Ladisch8d448162011-10-07 22:38:59 +02001209 ue->info.value.enumerated.names_length);
1210 if (IS_ERR(names))
1211 return PTR_ERR(names);
1212
1213 /* check that there are enough valid names */
1214 buf_len = ue->info.value.enumerated.names_length;
1215 p = names;
1216 for (i = 0; i < ue->info.value.enumerated.items; ++i) {
1217 name_len = strnlen(p, buf_len);
1218 if (name_len == 0 || name_len >= 64 || name_len == buf_len) {
Al Viro59aeaf32018-01-07 13:11:03 -05001219 kvfree(names);
Clemens Ladisch8d448162011-10-07 22:38:59 +02001220 return -EINVAL;
1221 }
1222 p += name_len + 1;
1223 buf_len -= name_len + 1;
1224 }
1225
1226 ue->priv_data = names;
1227 ue->info.value.enumerated.names_ptr = 0;
1228
1229 return 0;
1230}
1231
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001232static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233{
Jaroslav Kysela8aa9b582006-07-05 17:34:51 +02001234 struct user_element *ue = kcontrol->private_data;
Clemens Ladisch8d448162011-10-07 22:38:59 +02001235
Al Viro88a89032018-01-07 13:09:15 -05001236 kvfree(ue->tlv_data);
Al Viro59aeaf32018-01-07 13:11:03 -05001237 kvfree(ue->priv_data);
Jaroslav Kysela8aa9b582006-07-05 17:34:51 +02001238 kfree(ue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239}
1240
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001241static int snd_ctl_elem_add(struct snd_ctl_file *file,
1242 struct snd_ctl_elem_info *info, int replace)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243{
Takashi Sakamoto4ed56662015-03-10 22:13:30 +09001244 /* The capacity of struct snd_ctl_elem_value.value.*/
1245 static const unsigned int value_sizes[] = {
1246 [SNDRV_CTL_ELEM_TYPE_BOOLEAN] = sizeof(long),
1247 [SNDRV_CTL_ELEM_TYPE_INTEGER] = sizeof(long),
1248 [SNDRV_CTL_ELEM_TYPE_ENUMERATED] = sizeof(unsigned int),
1249 [SNDRV_CTL_ELEM_TYPE_BYTES] = sizeof(unsigned char),
1250 [SNDRV_CTL_ELEM_TYPE_IEC958] = sizeof(struct snd_aes_iec958),
1251 [SNDRV_CTL_ELEM_TYPE_INTEGER64] = sizeof(long long),
1252 };
1253 static const unsigned int max_value_counts[] = {
1254 [SNDRV_CTL_ELEM_TYPE_BOOLEAN] = 128,
1255 [SNDRV_CTL_ELEM_TYPE_INTEGER] = 128,
1256 [SNDRV_CTL_ELEM_TYPE_ENUMERATED] = 128,
1257 [SNDRV_CTL_ELEM_TYPE_BYTES] = 512,
1258 [SNDRV_CTL_ELEM_TYPE_IEC958] = 1,
1259 [SNDRV_CTL_ELEM_TYPE_INTEGER64] = 64,
1260 };
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001261 struct snd_card *card = file->card;
Takashi Sakamoto2225e792015-03-10 22:13:31 +09001262 struct snd_kcontrol *kctl;
1263 unsigned int count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 unsigned int access;
1265 long private_size;
1266 struct user_element *ue;
Takashi Sakamotocab2ed72015-04-11 17:41:04 +09001267 unsigned int offset;
Takashi Sakamoto2225e792015-03-10 22:13:31 +09001268 int err;
Lu Guanqun983929c2011-08-24 11:12:34 +08001269
Takashi Iwaibe3bb822015-03-11 18:12:49 +01001270 if (!*info->id.name)
1271 return -EINVAL;
1272 if (strnlen(info->id.name, sizeof(info->id.name)) >= sizeof(info->id.name))
1273 return -EINVAL;
Lars-Peter Clausen82262a462014-06-18 13:32:32 +02001274
Takashi Sakamoto2225e792015-03-10 22:13:31 +09001275 /* Delete a control to replace them if needed. */
Lars-Peter Clausen82262a462014-06-18 13:32:32 +02001276 if (replace) {
Takashi Sakamoto2225e792015-03-10 22:13:31 +09001277 info->id.numid = 0;
Lars-Peter Clausen82262a462014-06-18 13:32:32 +02001278 err = snd_ctl_remove_user_ctl(file, &info->id);
1279 if (err)
1280 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 }
Lars-Peter Clausen82262a462014-06-18 13:32:32 +02001282
Takashi Sakamoto2225e792015-03-10 22:13:31 +09001283 /*
1284 * The number of userspace controls are counted control by control,
1285 * not element by element.
1286 */
1287 if (card->user_ctl_count + 1 > MAX_USER_CONTROLS)
Lars-Peter Clausen82262a462014-06-18 13:32:32 +02001288 return -ENOMEM;
1289
Takashi Sakamoto2225e792015-03-10 22:13:31 +09001290 /* Check the number of elements for this userspace control. */
1291 count = info->owner;
1292 if (count == 0)
1293 count = 1;
Takashi Sakamoto4ed56662015-03-10 22:13:30 +09001294
Takashi Sakamoto2225e792015-03-10 22:13:31 +09001295 /* Arrange access permissions if needed. */
1296 access = info->access;
1297 if (access == 0)
1298 access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
1299 access &= (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1300 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
Takashi Sakamotob8e22042017-08-24 10:46:16 +09001301 SNDRV_CTL_ELEM_ACCESS_TLV_WRITE);
1302
1303 /* In initial state, nothing is available as TLV container. */
1304 if (access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
Takashi Sakamoto2225e792015-03-10 22:13:31 +09001305 access |= SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
1306 access |= SNDRV_CTL_ELEM_ACCESS_USER;
1307
1308 /*
1309 * Check information and calculate the size of data specific to
1310 * this userspace control.
1311 */
Takashi Sakamoto4ed56662015-03-10 22:13:30 +09001312 if (info->type < SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
1313 info->type > SNDRV_CTL_ELEM_TYPE_INTEGER64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 return -EINVAL;
Takashi Sakamoto4ed56662015-03-10 22:13:30 +09001315 if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED &&
1316 info->value.enumerated.items == 0)
1317 return -EINVAL;
1318 if (info->count < 1 ||
1319 info->count > max_value_counts[info->type])
1320 return -EINVAL;
Takashi Sakamoto860c1992016-07-07 21:57:10 +09001321 if (!validate_element_member_dimension(info))
1322 return -EINVAL;
Takashi Sakamoto4ed56662015-03-10 22:13:30 +09001323 private_size = value_sizes[info->type] * info->count;
Takashi Sakamoto2225e792015-03-10 22:13:31 +09001324
1325 /*
1326 * Keep memory object for this userspace control. After passing this
1327 * code block, the instance should be freed by snd_ctl_free_one().
1328 *
1329 * Note that these elements in this control are locked.
1330 */
1331 err = snd_ctl_new(&kctl, count, access, file);
1332 if (err < 0)
1333 return err;
Takashi Iwaie79d74a2015-03-12 16:57:51 +01001334 memcpy(&kctl->id, &info->id, sizeof(kctl->id));
Takashi Sakamotoe1c78df2015-04-12 10:12:25 +09001335 kctl->private_data = kzalloc(sizeof(struct user_element) + private_size * count,
Takashi Sakamoto2225e792015-03-10 22:13:31 +09001336 GFP_KERNEL);
1337 if (kctl->private_data == NULL) {
1338 kfree(kctl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 return -ENOMEM;
Takashi Sakamoto2225e792015-03-10 22:13:31 +09001340 }
1341 kctl->private_free = snd_ctl_elem_user_free;
1342
1343 /* Set private data for this userspace control. */
1344 ue = (struct user_element *)kctl->private_data;
Lars-Peter Clausen07f4d9d2014-06-18 13:32:31 +02001345 ue->card = card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 ue->info = *info;
Takashi Iwai86148e82006-08-24 12:36:36 +02001347 ue->info.access = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 ue->elem_data = (char *)ue + sizeof(*ue);
1349 ue->elem_data_size = private_size;
Clemens Ladisch8d448162011-10-07 22:38:59 +02001350 if (ue->info.type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
1351 err = snd_ctl_elem_init_enum_names(ue);
1352 if (err < 0) {
Takashi Sakamoto2225e792015-03-10 22:13:31 +09001353 snd_ctl_free_one(kctl);
Clemens Ladisch8d448162011-10-07 22:38:59 +02001354 return err;
1355 }
1356 }
Takashi Sakamoto2225e792015-03-10 22:13:31 +09001357
1358 /* Set callback functions. */
1359 if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED)
1360 kctl->info = snd_ctl_elem_user_enum_info;
1361 else
1362 kctl->info = snd_ctl_elem_user_info;
1363 if (access & SNDRV_CTL_ELEM_ACCESS_READ)
1364 kctl->get = snd_ctl_elem_user_get;
1365 if (access & SNDRV_CTL_ELEM_ACCESS_WRITE)
1366 kctl->put = snd_ctl_elem_user_put;
Takashi Sakamotob8e22042017-08-24 10:46:16 +09001367 if (access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
Takashi Sakamoto2225e792015-03-10 22:13:31 +09001368 kctl->tlv.c = snd_ctl_elem_user_tlv;
1369
1370 /* This function manage to free the instance on failure. */
Takashi Iwaid8a2dca2018-11-22 14:36:17 +01001371 down_write(&card->controls_rwsem);
1372 err = __snd_ctl_add(card, kctl);
1373 if (err < 0) {
1374 snd_ctl_free_one(kctl);
1375 goto unlock;
1376 }
Takashi Sakamotocab2ed72015-04-11 17:41:04 +09001377 offset = snd_ctl_get_ioff(kctl, &info->id);
1378 snd_ctl_build_ioff(&info->id, kctl, offset);
1379 /*
1380 * Here we cannot fill any field for the number of elements added by
1381 * this operation because there're no specific fields. The usage of
1382 * 'owner' field for this purpose may cause any bugs to userspace
1383 * applications because the field originally means PID of a process
1384 * which locks the element.
1385 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 card->user_ctl_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388
Takashi Iwaid8a2dca2018-11-22 14:36:17 +01001389 unlock:
1390 up_write(&card->controls_rwsem);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 return 0;
1392}
1393
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001394static int snd_ctl_elem_add_user(struct snd_ctl_file *file,
1395 struct snd_ctl_elem_info __user *_info, int replace)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396{
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001397 struct snd_ctl_elem_info info;
Takashi Sakamotocab2ed72015-04-11 17:41:04 +09001398 int err;
1399
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400 if (copy_from_user(&info, _info, sizeof(info)))
1401 return -EFAULT;
Takashi Sakamotocab2ed72015-04-11 17:41:04 +09001402 err = snd_ctl_elem_add(file, &info, replace);
1403 if (err < 0)
1404 return err;
1405 if (copy_to_user(_info, &info, sizeof(info))) {
1406 snd_ctl_remove_user_ctl(file, &info.id);
1407 return -EFAULT;
1408 }
1409
1410 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411}
1412
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001413static int snd_ctl_elem_remove(struct snd_ctl_file *file,
1414 struct snd_ctl_elem_id __user *_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415{
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001416 struct snd_ctl_elem_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417
1418 if (copy_from_user(&id, _id, sizeof(id)))
1419 return -EFAULT;
Clemens Ladischf217ac52009-08-17 12:27:22 +02001420 return snd_ctl_remove_user_ctl(file, &id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421}
1422
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001423static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424{
1425 int subscribe;
1426 if (get_user(subscribe, ptr))
1427 return -EFAULT;
1428 if (subscribe < 0) {
1429 subscribe = file->subscribed;
1430 if (put_user(subscribe, ptr))
1431 return -EFAULT;
1432 return 0;
1433 }
1434 if (subscribe) {
1435 file->subscribed = 1;
1436 return 0;
1437 } else if (file->subscribed) {
1438 snd_ctl_empty_read_queue(file);
1439 file->subscribed = 0;
1440 }
1441 return 0;
1442}
1443
Takashi Sakamoto450296f2017-08-03 20:20:43 +09001444static int call_tlv_handler(struct snd_ctl_file *file, int op_flag,
1445 struct snd_kcontrol *kctl,
1446 struct snd_ctl_elem_id *id,
1447 unsigned int __user *buf, unsigned int size)
Jaroslav Kysela42750b02006-06-01 18:34:01 +02001448{
Takashi Sakamoto450296f2017-08-03 20:20:43 +09001449 static const struct {
1450 int op;
1451 int perm;
1452 } pairs[] = {
1453 {SNDRV_CTL_TLV_OP_READ, SNDRV_CTL_ELEM_ACCESS_TLV_READ},
1454 {SNDRV_CTL_TLV_OP_WRITE, SNDRV_CTL_ELEM_ACCESS_TLV_WRITE},
1455 {SNDRV_CTL_TLV_OP_CMD, SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND},
1456 };
1457 struct snd_kcontrol_volatile *vd = &kctl->vd[snd_ctl_get_ioff(kctl, id)];
1458 int i;
Takashi Sakamoto450296f2017-08-03 20:20:43 +09001459
1460 /* Check support of the request for this element. */
1461 for (i = 0; i < ARRAY_SIZE(pairs); ++i) {
1462 if (op_flag == pairs[i].op && (vd->access & pairs[i].perm))
1463 break;
1464 }
1465 if (i == ARRAY_SIZE(pairs))
1466 return -ENXIO;
1467
1468 if (kctl->tlv.c == NULL)
1469 return -ENXIO;
1470
1471 /* When locked, this is unavailable. */
1472 if (vd->owner != NULL && vd->owner != file)
1473 return -EPERM;
1474
Takashi Sakamotofb8027e2017-08-24 10:46:14 +09001475 return kctl->tlv.c(kctl, op_flag, size, buf);
Takashi Sakamoto450296f2017-08-03 20:20:43 +09001476}
1477
1478static int read_tlv_buf(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id,
1479 unsigned int __user *buf, unsigned int size)
1480{
1481 struct snd_kcontrol_volatile *vd = &kctl->vd[snd_ctl_get_ioff(kctl, id)];
Jaroslav Kysela42750b02006-06-01 18:34:01 +02001482 unsigned int len;
Jaroslav Kysela42750b02006-06-01 18:34:01 +02001483
Takashi Sakamoto450296f2017-08-03 20:20:43 +09001484 if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ))
1485 return -ENXIO;
Takashi Sakamoto4c8099e2017-08-03 20:20:41 +09001486
1487 if (kctl->tlv.p == NULL)
1488 return -ENXIO;
1489
Takashi Sakamoto450296f2017-08-03 20:20:43 +09001490 len = sizeof(unsigned int) * 2 + kctl->tlv.p[1];
1491 if (size < len)
1492 return -ENOMEM;
Takashi Sakamoto4c8099e2017-08-03 20:20:41 +09001493
Takashi Sakamoto450296f2017-08-03 20:20:43 +09001494 if (copy_to_user(buf, kctl->tlv.p, len))
1495 return -EFAULT;
Takashi Sakamoto4c8099e2017-08-03 20:20:41 +09001496
1497 return 0;
Jaroslav Kysela42750b02006-06-01 18:34:01 +02001498}
1499
Takashi Sakamoto450296f2017-08-03 20:20:43 +09001500static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
1501 struct snd_ctl_tlv __user *buf,
1502 int op_flag)
1503{
1504 struct snd_ctl_tlv header;
Takashi Iwai1ba78622018-04-23 15:01:44 +02001505 unsigned int __user *container;
Takashi Sakamoto450296f2017-08-03 20:20:43 +09001506 unsigned int container_size;
1507 struct snd_kcontrol *kctl;
1508 struct snd_ctl_elem_id id;
1509 struct snd_kcontrol_volatile *vd;
1510
1511 if (copy_from_user(&header, buf, sizeof(header)))
1512 return -EFAULT;
1513
1514 /* In design of control core, numerical ID starts at 1. */
1515 if (header.numid == 0)
1516 return -EINVAL;
1517
1518 /* At least, container should include type and length fields. */
1519 if (header.length < sizeof(unsigned int) * 2)
1520 return -EINVAL;
1521 container_size = header.length;
1522 container = buf->tlv;
1523
1524 kctl = snd_ctl_find_numid(file->card, header.numid);
1525 if (kctl == NULL)
1526 return -ENOENT;
1527
1528 /* Calculate index of the element in this set. */
1529 id = kctl->id;
1530 snd_ctl_build_ioff(&id, kctl, header.numid - id.numid);
1531 vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)];
1532
1533 if (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
1534 return call_tlv_handler(file, op_flag, kctl, &id, container,
1535 container_size);
1536 } else {
1537 if (op_flag == SNDRV_CTL_TLV_OP_READ) {
1538 return read_tlv_buf(kctl, &id, container,
1539 container_size);
1540 }
1541 }
1542
1543 /* Not supported. */
1544 return -ENXIO;
1545}
1546
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1548{
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001549 struct snd_ctl_file *ctl;
1550 struct snd_card *card;
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001551 struct snd_kctl_ioctl *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 void __user *argp = (void __user *)arg;
1553 int __user *ip = argp;
1554 int err;
1555
1556 ctl = file->private_data;
1557 card = ctl->card;
Takashi Iwai7eaa9432008-08-08 17:09:09 +02001558 if (snd_BUG_ON(!card))
1559 return -ENXIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 switch (cmd) {
1561 case SNDRV_CTL_IOCTL_PVERSION:
1562 return put_user(SNDRV_CTL_VERSION, ip) ? -EFAULT : 0;
1563 case SNDRV_CTL_IOCTL_CARD_INFO:
1564 return snd_ctl_card_info(card, ctl, cmd, argp);
1565 case SNDRV_CTL_IOCTL_ELEM_LIST:
Jaroslav Kysela42750b02006-06-01 18:34:01 +02001566 return snd_ctl_elem_list(card, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 case SNDRV_CTL_IOCTL_ELEM_INFO:
1568 return snd_ctl_elem_info_user(ctl, argp);
1569 case SNDRV_CTL_IOCTL_ELEM_READ:
Jaroslav Kysela42750b02006-06-01 18:34:01 +02001570 return snd_ctl_elem_read_user(card, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571 case SNDRV_CTL_IOCTL_ELEM_WRITE:
1572 return snd_ctl_elem_write_user(ctl, argp);
1573 case SNDRV_CTL_IOCTL_ELEM_LOCK:
1574 return snd_ctl_elem_lock(ctl, argp);
1575 case SNDRV_CTL_IOCTL_ELEM_UNLOCK:
1576 return snd_ctl_elem_unlock(ctl, argp);
1577 case SNDRV_CTL_IOCTL_ELEM_ADD:
1578 return snd_ctl_elem_add_user(ctl, argp, 0);
1579 case SNDRV_CTL_IOCTL_ELEM_REPLACE:
1580 return snd_ctl_elem_add_user(ctl, argp, 1);
1581 case SNDRV_CTL_IOCTL_ELEM_REMOVE:
1582 return snd_ctl_elem_remove(ctl, argp);
1583 case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
1584 return snd_ctl_subscribe_events(ctl, ip);
Jaroslav Kysela8aa9b582006-07-05 17:34:51 +02001585 case SNDRV_CTL_IOCTL_TLV_READ:
Takashi Sakamoto4c8099e2017-08-03 20:20:41 +09001586 down_read(&ctl->card->controls_rwsem);
1587 err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_READ);
1588 up_read(&ctl->card->controls_rwsem);
1589 return err;
Jaroslav Kysela8aa9b582006-07-05 17:34:51 +02001590 case SNDRV_CTL_IOCTL_TLV_WRITE:
Takashi Sakamoto4c8099e2017-08-03 20:20:41 +09001591 down_write(&ctl->card->controls_rwsem);
1592 err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_WRITE);
1593 up_write(&ctl->card->controls_rwsem);
1594 return err;
Jaroslav Kysela8aa9b582006-07-05 17:34:51 +02001595 case SNDRV_CTL_IOCTL_TLV_COMMAND:
Takashi Sakamoto4c8099e2017-08-03 20:20:41 +09001596 down_write(&ctl->card->controls_rwsem);
1597 err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_CMD);
1598 up_write(&ctl->card->controls_rwsem);
1599 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 case SNDRV_CTL_IOCTL_POWER:
Takashi Iwaia381a7a2005-11-17 15:55:49 +01001601 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 case SNDRV_CTL_IOCTL_POWER_STATE:
1603#ifdef CONFIG_PM
1604 return put_user(card->power_state, ip) ? -EFAULT : 0;
1605#else
1606 return put_user(SNDRV_CTL_POWER_D0, ip) ? -EFAULT : 0;
1607#endif
1608 }
1609 down_read(&snd_ioctl_rwsem);
Johannes Berg9244b2c2006-10-05 16:02:22 +02001610 list_for_each_entry(p, &snd_control_ioctls, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611 err = p->fioctl(card, ctl, cmd, arg);
1612 if (err != -ENOIOCTLCMD) {
1613 up_read(&snd_ioctl_rwsem);
1614 return err;
1615 }
1616 }
1617 up_read(&snd_ioctl_rwsem);
Takashi Iwaibb009452014-02-04 18:18:16 +01001618 dev_dbg(card->dev, "unknown ioctl = 0x%x\n", cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619 return -ENOTTY;
1620}
1621
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001622static ssize_t snd_ctl_read(struct file *file, char __user *buffer,
1623 size_t count, loff_t * offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624{
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001625 struct snd_ctl_file *ctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 int err = 0;
1627 ssize_t result = 0;
1628
1629 ctl = file->private_data;
Takashi Iwai7eaa9432008-08-08 17:09:09 +02001630 if (snd_BUG_ON(!ctl || !ctl->card))
1631 return -ENXIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 if (!ctl->subscribed)
1633 return -EBADFD;
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001634 if (count < sizeof(struct snd_ctl_event))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 return -EINVAL;
1636 spin_lock_irq(&ctl->read_lock);
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001637 while (count >= sizeof(struct snd_ctl_event)) {
1638 struct snd_ctl_event ev;
1639 struct snd_kctl_event *kev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 while (list_empty(&ctl->events)) {
Ingo Molnarac6424b2017-06-20 12:06:13 +02001641 wait_queue_entry_t wait;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
1643 err = -EAGAIN;
1644 goto __end_lock;
1645 }
1646 init_waitqueue_entry(&wait, current);
1647 add_wait_queue(&ctl->change_sleep, &wait);
1648 set_current_state(TASK_INTERRUPTIBLE);
1649 spin_unlock_irq(&ctl->read_lock);
1650 schedule();
1651 remove_wait_queue(&ctl->change_sleep, &wait);
Takashi Iwai0914f792012-10-16 16:43:39 +02001652 if (ctl->card->shutdown)
1653 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 if (signal_pending(current))
Adrian Bunk0e5d7202006-11-07 13:42:54 +01001655 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656 spin_lock_irq(&ctl->read_lock);
1657 }
1658 kev = snd_kctl_event(ctl->events.next);
1659 ev.type = SNDRV_CTL_EVENT_ELEM;
1660 ev.data.elem.mask = kev->mask;
1661 ev.data.elem.id = kev->id;
1662 list_del(&kev->list);
1663 spin_unlock_irq(&ctl->read_lock);
1664 kfree(kev);
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001665 if (copy_to_user(buffer, &ev, sizeof(struct snd_ctl_event))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 err = -EFAULT;
1667 goto __end;
1668 }
1669 spin_lock_irq(&ctl->read_lock);
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001670 buffer += sizeof(struct snd_ctl_event);
1671 count -= sizeof(struct snd_ctl_event);
1672 result += sizeof(struct snd_ctl_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 }
1674 __end_lock:
1675 spin_unlock_irq(&ctl->read_lock);
1676 __end:
1677 return result > 0 ? result : err;
1678}
1679
Al Viro680ef722017-07-02 23:27:36 -04001680static __poll_t snd_ctl_poll(struct file *file, poll_table * wait)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681{
Al Viro680ef722017-07-02 23:27:36 -04001682 __poll_t mask;
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001683 struct snd_ctl_file *ctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684
1685 ctl = file->private_data;
1686 if (!ctl->subscribed)
1687 return 0;
1688 poll_wait(file, &ctl->change_sleep, wait);
1689
1690 mask = 0;
1691 if (!list_empty(&ctl->events))
Linus Torvaldsa9a08842018-02-11 14:34:03 -08001692 mask |= EPOLLIN | EPOLLRDNORM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693
1694 return mask;
1695}
1696
1697/*
1698 * register the device-specific control-ioctls.
1699 * called from each device manager like pcm.c, hwdep.c, etc.
1700 */
1701static int _snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head *lists)
1702{
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001703 struct snd_kctl_ioctl *pn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001705 pn = kzalloc(sizeof(struct snd_kctl_ioctl), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 if (pn == NULL)
1707 return -ENOMEM;
1708 pn->fioctl = fcn;
1709 down_write(&snd_ioctl_rwsem);
1710 list_add_tail(&pn->list, lists);
1711 up_write(&snd_ioctl_rwsem);
1712 return 0;
1713}
1714
Takashi Iwai12cddbd2014-10-30 13:44:34 +01001715/**
1716 * snd_ctl_register_ioctl - register the device-specific control-ioctls
1717 * @fcn: ioctl callback function
1718 *
1719 * called from each device manager like pcm.c, hwdep.c, etc.
1720 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn)
1722{
1723 return _snd_ctl_register_ioctl(fcn, &snd_control_ioctls);
1724}
Takashi Iwaic0d3fb32006-04-28 15:13:39 +02001725EXPORT_SYMBOL(snd_ctl_register_ioctl);
1726
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727#ifdef CONFIG_COMPAT
Takashi Iwai12cddbd2014-10-30 13:44:34 +01001728/**
1729 * snd_ctl_register_ioctl_compat - register the device-specific 32bit compat
1730 * control-ioctls
1731 * @fcn: ioctl callback function
1732 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn)
1734{
1735 return _snd_ctl_register_ioctl(fcn, &snd_control_compat_ioctls);
1736}
Takashi Iwaic0d3fb32006-04-28 15:13:39 +02001737EXPORT_SYMBOL(snd_ctl_register_ioctl_compat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738#endif
1739
1740/*
1741 * de-register the device-specific control-ioctls.
1742 */
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001743static int _snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn,
1744 struct list_head *lists)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745{
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001746 struct snd_kctl_ioctl *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747
Takashi Iwai7eaa9432008-08-08 17:09:09 +02001748 if (snd_BUG_ON(!fcn))
1749 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 down_write(&snd_ioctl_rwsem);
Johannes Berg9244b2c2006-10-05 16:02:22 +02001751 list_for_each_entry(p, lists, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 if (p->fioctl == fcn) {
1753 list_del(&p->list);
1754 up_write(&snd_ioctl_rwsem);
1755 kfree(p);
1756 return 0;
1757 }
1758 }
1759 up_write(&snd_ioctl_rwsem);
1760 snd_BUG();
1761 return -EINVAL;
1762}
1763
Takashi Iwai12cddbd2014-10-30 13:44:34 +01001764/**
1765 * snd_ctl_unregister_ioctl - de-register the device-specific control-ioctls
1766 * @fcn: ioctl callback function to unregister
1767 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn)
1769{
1770 return _snd_ctl_unregister_ioctl(fcn, &snd_control_ioctls);
1771}
Takashi Iwaic0d3fb32006-04-28 15:13:39 +02001772EXPORT_SYMBOL(snd_ctl_unregister_ioctl);
1773
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774#ifdef CONFIG_COMPAT
Takashi Iwai12cddbd2014-10-30 13:44:34 +01001775/**
1776 * snd_ctl_unregister_ioctl - de-register the device-specific compat 32bit
1777 * control-ioctls
1778 * @fcn: ioctl callback function to unregister
1779 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn)
1781{
1782 return _snd_ctl_unregister_ioctl(fcn, &snd_control_compat_ioctls);
1783}
Takashi Iwaic0d3fb32006-04-28 15:13:39 +02001784EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785#endif
1786
1787static int snd_ctl_fasync(int fd, struct file * file, int on)
1788{
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001789 struct snd_ctl_file *ctl;
Jonathan Corbet60aa4922009-02-01 14:52:56 -07001790
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 ctl = file->private_data;
Jonathan Corbet60aa4922009-02-01 14:52:56 -07001792 return fasync_helper(fd, file, on, &ctl->fasync);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793}
1794
Takashi Iwai23c18d42014-02-19 14:30:29 +01001795/* return the preferred subdevice number if already assigned;
1796 * otherwise return -1
1797 */
1798int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type)
1799{
1800 struct snd_ctl_file *kctl;
1801 int subdevice = -1;
1802
1803 read_lock(&card->ctl_files_rwlock);
1804 list_for_each_entry(kctl, &card->ctl_files, list) {
1805 if (kctl->pid == task_pid(current)) {
1806 subdevice = kctl->preferred_subdevice[type];
1807 if (subdevice != -1)
1808 break;
1809 }
1810 }
1811 read_unlock(&card->ctl_files_rwlock);
1812 return subdevice;
1813}
1814EXPORT_SYMBOL_GPL(snd_ctl_get_preferred_subdevice);
1815
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816/*
1817 * ioctl32 compat
1818 */
1819#ifdef CONFIG_COMPAT
1820#include "control_compat.c"
1821#else
1822#define snd_ctl_ioctl_compat NULL
1823#endif
1824
1825/*
1826 * INIT PART
1827 */
1828
Arjan van de Ven9c2e08c2007-02-12 00:55:37 -08001829static const struct file_operations snd_ctl_f_ops =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830{
1831 .owner = THIS_MODULE,
1832 .read = snd_ctl_read,
1833 .open = snd_ctl_open,
1834 .release = snd_ctl_release,
Takashi Iwai02f48652010-04-13 11:49:04 +02001835 .llseek = no_llseek,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 .poll = snd_ctl_poll,
1837 .unlocked_ioctl = snd_ctl_ioctl,
1838 .compat_ioctl = snd_ctl_ioctl_compat,
1839 .fasync = snd_ctl_fasync,
1840};
1841
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842/*
1843 * registration of the control device
1844 */
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001845static int snd_ctl_dev_register(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846{
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001847 struct snd_card *card = device->device_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848
Takashi Iwai40a4b262015-01-30 08:34:58 +01001849 return snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,
1850 &snd_ctl_f_ops, card, &card->ctl_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851}
1852
1853/*
1854 * disconnection of the control device
1855 */
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001856static int snd_ctl_dev_disconnect(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857{
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001858 struct snd_card *card = device->device_data;
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001859 struct snd_ctl_file *ctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860
Takashi Iwaid8009882008-09-07 12:51:13 +02001861 read_lock(&card->ctl_files_rwlock);
Johannes Berg9244b2c2006-10-05 16:02:22 +02001862 list_for_each_entry(ctl, &card->ctl_files, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863 wake_up(&ctl->change_sleep);
1864 kill_fasync(&ctl->fasync, SIGIO, POLL_ERR);
1865 }
Takashi Iwaid8009882008-09-07 12:51:13 +02001866 read_unlock(&card->ctl_files_rwlock);
Takashi Iwaic4614822006-06-23 14:38:23 +02001867
Takashi Iwai40a4b262015-01-30 08:34:58 +01001868 return snd_unregister_device(&card->ctl_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869}
1870
1871/*
1872 * free all controls
1873 */
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001874static int snd_ctl_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875{
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001876 struct snd_card *card = device->device_data;
1877 struct snd_kcontrol *control;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878
1879 down_write(&card->controls_rwsem);
1880 while (!list_empty(&card->controls)) {
1881 control = snd_kcontrol(card->controls.next);
1882 snd_ctl_remove(card, control);
1883 }
1884 up_write(&card->controls_rwsem);
Takashi Iwai0fcd9f42015-01-29 16:41:27 +01001885 put_device(&card->ctl_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 return 0;
1887}
1888
1889/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 * create control core:
1891 * called from init.c
1892 */
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001893int snd_ctl_create(struct snd_card *card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894{
Takashi Iwai82e9bae2005-11-17 13:53:23 +01001895 static struct snd_device_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 .dev_free = snd_ctl_dev_free,
1897 .dev_register = snd_ctl_dev_register,
1898 .dev_disconnect = snd_ctl_dev_disconnect,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 };
Takashi Iwai0fcd9f42015-01-29 16:41:27 +01001900 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901
Takashi Iwai7eaa9432008-08-08 17:09:09 +02001902 if (snd_BUG_ON(!card))
1903 return -ENXIO;
Takashi Iwai0fcd9f42015-01-29 16:41:27 +01001904 if (snd_BUG_ON(card->number < 0 || card->number >= SNDRV_CARDS))
1905 return -ENXIO;
1906
1907 snd_device_initialize(&card->ctl_dev, card);
1908 dev_set_name(&card->ctl_dev, "controlC%d", card->number);
1909
1910 err = snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops);
1911 if (err < 0)
1912 put_device(&card->ctl_dev);
1913 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914}
Takashi Iwaib9ed4f22007-07-23 15:41:34 +02001915
1916/*
Clemens Ladisch96007322011-01-10 16:25:44 +01001917 * Frequently used control callbacks/helpers
Takashi Iwaib9ed4f22007-07-23 15:41:34 +02001918 */
Takashi Iwai12cddbd2014-10-30 13:44:34 +01001919
1920/**
1921 * snd_ctl_boolean_mono_info - Helper function for a standard boolean info
1922 * callback with a mono channel
1923 * @kcontrol: the kcontrol instance
1924 * @uinfo: info to store
1925 *
1926 * This is a function that can be used as info callback for a standard
1927 * boolean control with a single mono channel.
1928 */
Takashi Iwaib9ed4f22007-07-23 15:41:34 +02001929int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol,
1930 struct snd_ctl_elem_info *uinfo)
1931{
1932 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1933 uinfo->count = 1;
1934 uinfo->value.integer.min = 0;
1935 uinfo->value.integer.max = 1;
1936 return 0;
1937}
Takashi Iwaib9ed4f22007-07-23 15:41:34 +02001938EXPORT_SYMBOL(snd_ctl_boolean_mono_info);
1939
Takashi Iwai12cddbd2014-10-30 13:44:34 +01001940/**
1941 * snd_ctl_boolean_stereo_info - Helper function for a standard boolean info
1942 * callback with stereo two channels
1943 * @kcontrol: the kcontrol instance
1944 * @uinfo: info to store
1945 *
1946 * This is a function that can be used as info callback for a standard
1947 * boolean control with stereo two channels.
1948 */
Takashi Iwaib9ed4f22007-07-23 15:41:34 +02001949int snd_ctl_boolean_stereo_info(struct snd_kcontrol *kcontrol,
1950 struct snd_ctl_elem_info *uinfo)
1951{
1952 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1953 uinfo->count = 2;
1954 uinfo->value.integer.min = 0;
1955 uinfo->value.integer.max = 1;
1956 return 0;
1957}
Takashi Iwaib9ed4f22007-07-23 15:41:34 +02001958EXPORT_SYMBOL(snd_ctl_boolean_stereo_info);
Clemens Ladisch96007322011-01-10 16:25:44 +01001959
1960/**
1961 * snd_ctl_enum_info - fills the info structure for an enumerated control
1962 * @info: the structure to be filled
1963 * @channels: the number of the control's channels; often one
1964 * @items: the number of control values; also the size of @names
1965 * @names: an array containing the names of all control values
1966 *
1967 * Sets all required fields in @info to their appropriate values.
1968 * If the control's accessibility is not the default (readable and writable),
1969 * the caller has to fill @info->access.
Yacine Belkadieb7c06e2013-03-11 22:05:14 +01001970 *
1971 * Return: Zero.
Clemens Ladisch96007322011-01-10 16:25:44 +01001972 */
1973int snd_ctl_enum_info(struct snd_ctl_elem_info *info, unsigned int channels,
1974 unsigned int items, const char *const names[])
1975{
1976 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1977 info->count = channels;
1978 info->value.enumerated.items = items;
Takashi Iwaia7e6fb92014-10-20 18:08:50 +02001979 if (!items)
1980 return 0;
Clemens Ladisch96007322011-01-10 16:25:44 +01001981 if (info->value.enumerated.item >= items)
1982 info->value.enumerated.item = items - 1;
Takashi Iwaidf803e12014-10-20 18:07:21 +02001983 WARN(strlen(names[info->value.enumerated.item]) >= sizeof(info->value.enumerated.name),
1984 "ALSA: too long item name '%s'\n",
1985 names[info->value.enumerated.item]);
Clemens Ladisch96007322011-01-10 16:25:44 +01001986 strlcpy(info->value.enumerated.name,
1987 names[info->value.enumerated.item],
1988 sizeof(info->value.enumerated.name));
1989 return 0;
1990}
1991EXPORT_SYMBOL(snd_ctl_enum_info);