upgrade to linux 2.6.10-1.12_FC2
[linux-2.6.git] / sound / core / control.c
1 /*
2  *  Routines for driver control interface
3  *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4  *
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
22 #include <sound/driver.h>
23 #include <linux/threads.h>
24 #include <linux/interrupt.h>
25 #include <linux/smp_lock.h>
26 #include <linux/slab.h>
27 #include <linux/vmalloc.h>
28 #include <linux/time.h>
29 #include <sound/core.h>
30 #include <sound/minors.h>
31 #include <sound/info.h>
32 #include <sound/control.h>
33
34 typedef struct _snd_kctl_ioctl {
35         struct list_head list;          /* list of all ioctls */
36         snd_kctl_ioctl_func_t fioctl;
37 } snd_kctl_ioctl_t;
38
39 #define snd_kctl_ioctl(n) list_entry(n, snd_kctl_ioctl_t, list)
40
41 static DECLARE_RWSEM(snd_ioctl_rwsem);
42 static LIST_HEAD(snd_control_ioctls);
43
44 static int snd_ctl_open(struct inode *inode, struct file *file)
45 {
46         int cardnum = SNDRV_MINOR_CARD(iminor(inode));
47         unsigned long flags;
48         snd_card_t *card;
49         snd_ctl_file_t *ctl;
50         int err;
51
52         card = snd_cards[cardnum];
53         if (!card) {
54                 err = -ENODEV;
55                 goto __error1;
56         }
57         err = snd_card_file_add(card, file);
58         if (err < 0) {
59                 err = -ENODEV;
60                 goto __error1;
61         }
62         if (!try_module_get(card->module)) {
63                 err = -EFAULT;
64                 goto __error2;
65         }
66         ctl = kcalloc(1, sizeof(*ctl), GFP_KERNEL);
67         if (ctl == NULL) {
68                 err = -ENOMEM;
69                 goto __error;
70         }
71         INIT_LIST_HEAD(&ctl->events);
72         init_waitqueue_head(&ctl->change_sleep);
73         spin_lock_init(&ctl->read_lock);
74         ctl->card = card;
75         ctl->pid = current->pid;
76         file->private_data = ctl;
77         write_lock_irqsave(&card->ctl_files_rwlock, flags);
78         list_add_tail(&ctl->list, &card->ctl_files);
79         write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
80         return 0;
81
82       __error:
83         module_put(card->module);
84       __error2:
85         snd_card_file_remove(card, file);
86       __error1:
87         return err;
88 }
89
90 static void snd_ctl_empty_read_queue(snd_ctl_file_t * ctl)
91 {
92         snd_kctl_event_t *cread;
93         
94         spin_lock(&ctl->read_lock);
95         while (!list_empty(&ctl->events)) {
96                 cread = snd_kctl_event(ctl->events.next);
97                 list_del(&cread->list);
98                 kfree(cread);
99         }
100         spin_unlock(&ctl->read_lock);
101 }
102
103 static int snd_ctl_release(struct inode *inode, struct file *file)
104 {
105         unsigned long flags;
106         struct list_head *list;
107         snd_card_t *card;
108         snd_ctl_file_t *ctl;
109         snd_kcontrol_t *control;
110         unsigned int idx;
111
112         ctl = file->private_data;
113         fasync_helper(-1, file, 0, &ctl->fasync);
114         file->private_data = NULL;
115         card = ctl->card;
116         write_lock_irqsave(&card->ctl_files_rwlock, flags);
117         list_del(&ctl->list);
118         write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
119         down_write(&card->controls_rwsem);
120         list_for_each(list, &card->controls) {
121                 control = snd_kcontrol(list);
122                 for (idx = 0; idx < control->count; idx++)
123                         if (control->vd[idx].owner == ctl)
124                                 control->vd[idx].owner = NULL;
125         }
126         up_write(&card->controls_rwsem);
127         snd_ctl_empty_read_queue(ctl);
128         kfree(ctl);
129         module_put(card->module);
130         snd_card_file_remove(card, file);
131         return 0;
132 }
133
134 void snd_ctl_notify(snd_card_t *card, unsigned int mask, snd_ctl_elem_id_t *id)
135 {
136         unsigned long flags;
137         struct list_head *flist;
138         snd_ctl_file_t *ctl;
139         snd_kctl_event_t *ev;
140         
141         snd_runtime_check(card != NULL && id != NULL, return);
142         read_lock(&card->ctl_files_rwlock);
143 #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
144         card->mixer_oss_change_count++;
145 #endif
146         list_for_each(flist, &card->ctl_files) {
147                 struct list_head *elist;
148                 ctl = snd_ctl_file(flist);
149                 if (!ctl->subscribed)
150                         continue;
151                 spin_lock_irqsave(&ctl->read_lock, flags);
152                 list_for_each(elist, &ctl->events) {
153                         ev = snd_kctl_event(elist);
154                         if (ev->id.numid == id->numid) {
155                                 ev->mask |= mask;
156                                 goto _found;
157                         }
158                 }
159                 ev = kcalloc(1, sizeof(*ev), GFP_ATOMIC);
160                 if (ev) {
161                         ev->id = *id;
162                         ev->mask = mask;
163                         list_add_tail(&ev->list, &ctl->events);
164                 } else {
165                         snd_printk(KERN_ERR "No memory available to allocate event\n");
166                 }
167         _found:
168                 wake_up(&ctl->change_sleep);
169                 spin_unlock_irqrestore(&ctl->read_lock, flags);
170                 kill_fasync(&ctl->fasync, SIGIO, POLL_IN);
171         }
172         read_unlock(&card->ctl_files_rwlock);
173 }
174
175 /**
176  * snd_ctl_new - create a control instance from the template
177  * @control: the control template
178  * @access: the default control access
179  *
180  * Allocates a new snd_kcontrol_t instance and copies the given template 
181  * to the new instance. It does not copy volatile data (access).
182  *
183  * Returns the pointer of the new instance, or NULL on failure.
184  */
185 snd_kcontrol_t *snd_ctl_new(snd_kcontrol_t * control, unsigned int access)
186 {
187         snd_kcontrol_t *kctl;
188         unsigned int idx;
189         
190         snd_runtime_check(control != NULL, return NULL);
191         snd_runtime_check(control->count > 0, return NULL);
192         kctl = kcalloc(1, sizeof(*kctl) + sizeof(snd_kcontrol_volatile_t) * control->count, GFP_KERNEL);
193         if (kctl == NULL)
194                 return NULL;
195         *kctl = *control;
196         for (idx = 0; idx < kctl->count; idx++)
197                 kctl->vd[idx].access = access;
198         return kctl;
199 }
200
201 /**
202  * snd_ctl_new1 - create a control instance from the template
203  * @ncontrol: the initialization record
204  * @private_data: the private data to set
205  *
206  * Allocates a new snd_kcontrol_t instance and initialize from the given 
207  * template.  When the access field of ncontrol is 0, it's assumed as
208  * READWRITE access. When the count field is 0, it's assumes as one.
209  *
210  * Returns the pointer of the newly generated instance, or NULL on failure.
211  */
212 snd_kcontrol_t *snd_ctl_new1(snd_kcontrol_new_t * ncontrol, void *private_data)
213 {
214         snd_kcontrol_t kctl;
215         unsigned int access;
216         
217         snd_runtime_check(ncontrol != NULL, return NULL);
218         snd_assert(ncontrol->info != NULL, return NULL);
219         memset(&kctl, 0, sizeof(kctl));
220         kctl.id.iface = ncontrol->iface;
221         kctl.id.device = ncontrol->device;
222         kctl.id.subdevice = ncontrol->subdevice;
223         if (ncontrol->name)
224                 strlcpy(kctl.id.name, ncontrol->name, sizeof(kctl.id.name));
225         kctl.id.index = ncontrol->index;
226         kctl.count = ncontrol->count ? ncontrol->count : 1;
227         access = ncontrol->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
228                  (ncontrol->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|SNDRV_CTL_ELEM_ACCESS_INACTIVE|
229                                       SNDRV_CTL_ELEM_ACCESS_DINDIRECT|SNDRV_CTL_ELEM_ACCESS_INDIRECT));
230         kctl.info = ncontrol->info;
231         kctl.get = ncontrol->get;
232         kctl.put = ncontrol->put;
233         kctl.private_value = ncontrol->private_value;
234         kctl.private_data = private_data;
235         return snd_ctl_new(&kctl, access);
236 }
237
238 /**
239  * snd_ctl_free_one - release the control instance
240  * @kcontrol: the control instance
241  *
242  * Releases the control instance created via snd_ctl_new()
243  * or snd_ctl_new1().
244  * Don't call this after the control was added to the card.
245  */
246 void snd_ctl_free_one(snd_kcontrol_t * kcontrol)
247 {
248         if (kcontrol) {
249                 if (kcontrol->private_free)
250                         kcontrol->private_free(kcontrol);
251                 kfree(kcontrol);
252         }
253 }
254
255 static unsigned int snd_ctl_hole_check(snd_card_t * card,
256                                        unsigned int count)
257 {
258         struct list_head *list;
259         snd_kcontrol_t *kctl;
260
261         list_for_each(list, &card->controls) {
262                 kctl = snd_kcontrol(list);
263                 if ((kctl->id.numid <= card->last_numid &&
264                      kctl->id.numid + kctl->count > card->last_numid) ||
265                     (kctl->id.numid <= card->last_numid + count - 1 &&
266                      kctl->id.numid + kctl->count > card->last_numid + count - 1))
267                         return card->last_numid = kctl->id.numid + kctl->count - 1;
268         }
269         return card->last_numid;
270 }
271
272 static int snd_ctl_find_hole(snd_card_t * card, unsigned int count)
273 {
274         unsigned int last_numid, iter = 100000;
275
276         last_numid = card->last_numid;
277         while (last_numid != snd_ctl_hole_check(card, count)) {
278                 if (--iter == 0) {
279                         /* this situation is very unlikely */
280                         snd_printk(KERN_ERR "unable to allocate new control numid\n");
281                         return -ENOMEM;
282                 }
283                 last_numid = card->last_numid;
284         }
285         return 0;
286 }
287
288 /**
289  * snd_ctl_add - add the control instance to the card
290  * @card: the card instance
291  * @kcontrol: the control instance to add
292  *
293  * Adds the control instance created via snd_ctl_new() or
294  * snd_ctl_new1() to the given card. Assigns also an unique
295  * numid used for fast search.
296  *
297  * Returns zero if successful, or a negative error code on failure.
298  *
299  * It frees automatically the control which cannot be added.
300  */
301 int snd_ctl_add(snd_card_t * card, snd_kcontrol_t * kcontrol)
302 {
303         snd_ctl_elem_id_t id;
304         unsigned int idx;
305
306         snd_runtime_check(card != NULL && kcontrol != NULL, return -EINVAL);
307         snd_assert(kcontrol->info != NULL, return -EINVAL);
308         id = kcontrol->id;
309         down_write(&card->controls_rwsem);
310         if (snd_ctl_find_id(card, &id)) {
311                 up_write(&card->controls_rwsem);
312                 snd_ctl_free_one(kcontrol);
313                 snd_printd(KERN_ERR "control %i:%i:%i:%s:%i is already present\n",
314                                         id.iface,
315                                         id.device,
316                                         id.subdevice,
317                                         id.name,
318                                         id.index);
319                 return -EBUSY;
320         }
321         if (snd_ctl_find_hole(card, kcontrol->count) < 0) {
322                 up_write(&card->controls_rwsem);
323                 snd_ctl_free_one(kcontrol);
324                 return -ENOMEM;
325         }
326         list_add_tail(&kcontrol->list, &card->controls);
327         card->controls_count += kcontrol->count;
328         kcontrol->id.numid = card->last_numid + 1;
329         card->last_numid += kcontrol->count;
330         up_write(&card->controls_rwsem);
331         for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
332                 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
333         return 0;
334 }
335
336 /**
337  * snd_ctl_remove - remove the control from the card and release it
338  * @card: the card instance
339  * @kcontrol: the control instance to remove
340  *
341  * Removes the control from the card and then releases the instance.
342  * You don't need to call snd_ctl_free_one(). You must be in
343  * the write lock - down_write(&card->controls_rwsem).
344  * 
345  * Returns 0 if successful, or a negative error code on failure.
346  */
347 int snd_ctl_remove(snd_card_t * card, snd_kcontrol_t * kcontrol)
348 {
349         snd_ctl_elem_id_t id;
350         unsigned int idx;
351
352         snd_runtime_check(card != NULL && kcontrol != NULL, return -EINVAL);
353         list_del(&kcontrol->list);
354         card->controls_count -= kcontrol->count;
355         id = kcontrol->id;
356         for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
357                 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_REMOVE, &id);
358         snd_ctl_free_one(kcontrol);
359         return 0;
360 }
361
362 /**
363  * snd_ctl_remove_id - remove the control of the given id and release it
364  * @card: the card instance
365  * @id: the control id to remove
366  *
367  * Finds the control instance with the given id, removes it from the
368  * card list and releases it.
369  * 
370  * Returns 0 if successful, or a negative error code on failure.
371  */
372 int snd_ctl_remove_id(snd_card_t * card, snd_ctl_elem_id_t *id)
373 {
374         snd_kcontrol_t *kctl;
375         int ret;
376
377         down_write(&card->controls_rwsem);
378         kctl = snd_ctl_find_id(card, id);
379         if (kctl == NULL) {
380                 up_write(&card->controls_rwsem);
381                 return -ENOENT;
382         }
383         ret = snd_ctl_remove(card, kctl);
384         up_write(&card->controls_rwsem);
385         return ret;
386 }
387
388 /**
389  * snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it
390  * @file: active control handle
391  * @id: the control id to remove
392  *
393  * Finds the control instance with the given id, removes it from the
394  * card list and releases it.
395  * 
396  * Returns 0 if successful, or a negative error code on failure.
397  */
398 static int snd_ctl_remove_unlocked_id(snd_ctl_file_t * file, snd_ctl_elem_id_t *id)
399 {
400         snd_card_t *card = file->card;
401         snd_kcontrol_t *kctl;
402         int idx, ret;
403
404         down_write(&card->controls_rwsem);
405         kctl = snd_ctl_find_id(card, id);
406         if (kctl == NULL) {
407                 up_write(&card->controls_rwsem);
408                 return -ENOENT;
409         }
410         for (idx = 0; idx < kctl->count; idx++)
411                 if (kctl->vd[idx].owner != NULL && kctl->vd[idx].owner != file) {
412                         up_write(&card->controls_rwsem);
413                         return -EBUSY;
414                 }
415         ret = snd_ctl_remove(card, kctl);
416         up_write(&card->controls_rwsem);
417         return ret;
418 }
419
420 /**
421  * snd_ctl_rename_id - replace the id of a control on the card
422  * @card: the card instance
423  * @src_id: the old id
424  * @dst_id: the new id
425  *
426  * Finds the control with the old id from the card, and replaces the
427  * id with the new one.
428  *
429  * Returns zero if successful, or a negative error code on failure.
430  */
431 int snd_ctl_rename_id(snd_card_t * card, snd_ctl_elem_id_t *src_id, snd_ctl_elem_id_t *dst_id)
432 {
433         snd_kcontrol_t *kctl;
434
435         down_write(&card->controls_rwsem);
436         kctl = snd_ctl_find_id(card, src_id);
437         if (kctl == NULL) {
438                 up_write(&card->controls_rwsem);
439                 return -ENOENT;
440         }
441         kctl->id = *dst_id;
442         kctl->id.numid = card->last_numid + 1;
443         card->last_numid += kctl->count;
444         up_write(&card->controls_rwsem);
445         return 0;
446 }
447
448 /**
449  * snd_ctl_find_numid - find the control instance with the given number-id
450  * @card: the card instance
451  * @numid: the number-id to search
452  *
453  * Finds the control instance with the given number-id from the card.
454  *
455  * Returns the pointer of the instance if found, or NULL if not.
456  *
457  * The caller must down card->controls_rwsem before calling this function
458  * (if the race condition can happen).
459  */
460 snd_kcontrol_t *snd_ctl_find_numid(snd_card_t * card, unsigned int numid)
461 {
462         struct list_head *list;
463         snd_kcontrol_t *kctl;
464
465         snd_runtime_check(card != NULL && numid != 0, return NULL);
466         list_for_each(list, &card->controls) {
467                 kctl = snd_kcontrol(list);
468                 if (kctl->id.numid <= numid && kctl->id.numid + kctl->count > numid)
469                         return kctl;
470         }
471         return NULL;
472 }
473
474 /**
475  * snd_ctl_find_id - find the control instance with the given id
476  * @card: the card instance
477  * @id: the id to search
478  *
479  * Finds the control instance with the given id from the card.
480  *
481  * Returns the pointer of the instance if found, or NULL if not.
482  *
483  * The caller must down card->controls_rwsem before calling this function
484  * (if the race condition can happen).
485  */
486 snd_kcontrol_t *snd_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id)
487 {
488         struct list_head *list;
489         snd_kcontrol_t *kctl;
490
491         snd_runtime_check(card != NULL && id != NULL, return NULL);
492         if (id->numid != 0)
493                 return snd_ctl_find_numid(card, id->numid);
494         list_for_each(list, &card->controls) {
495                 kctl = snd_kcontrol(list);
496                 if (kctl->id.iface != id->iface)
497                         continue;
498                 if (kctl->id.device != id->device)
499                         continue;
500                 if (kctl->id.subdevice != id->subdevice)
501                         continue;
502                 if (strncmp(kctl->id.name, id->name, sizeof(kctl->id.name)))
503                         continue;
504                 if (kctl->id.index > id->index)
505                         continue;
506                 if (kctl->id.index + kctl->count <= id->index)
507                         continue;
508                 return kctl;
509         }
510         return NULL;
511 }
512
513 static int snd_ctl_card_info(snd_card_t * card, snd_ctl_file_t * ctl,
514                              unsigned int cmd, void __user *arg)
515 {
516         snd_ctl_card_info_t info;
517
518         memset(&info, 0, sizeof(info));
519         down_read(&snd_ioctl_rwsem);
520         info.card = card->number;
521         strlcpy(info.id, card->id, sizeof(info.id));
522         strlcpy(info.driver, card->driver, sizeof(info.driver));
523         strlcpy(info.name, card->shortname, sizeof(info.name));
524         strlcpy(info.longname, card->longname, sizeof(info.longname));
525         strlcpy(info.mixername, card->mixername, sizeof(info.mixername));
526         strlcpy(info.components, card->components, sizeof(info.components));
527         up_read(&snd_ioctl_rwsem);
528         if (copy_to_user(arg, &info, sizeof(snd_ctl_card_info_t)))
529                 return -EFAULT;
530         return 0;
531 }
532
533 static int snd_ctl_elem_list(snd_card_t *card, snd_ctl_elem_list_t __user *_list)
534 {
535         struct list_head *plist;
536         snd_ctl_elem_list_t list;
537         snd_kcontrol_t *kctl;
538         snd_ctl_elem_id_t *dst, *id;
539         unsigned int offset, space, first, jidx;
540         
541         if (copy_from_user(&list, _list, sizeof(list)))
542                 return -EFAULT;
543         offset = list.offset;
544         space = list.space;
545         first = 0;
546         /* try limit maximum space */
547         if (space > 16384)
548                 return -ENOMEM;
549         if (space > 0) {
550                 /* allocate temporary buffer for atomic operation */
551                 dst = vmalloc(space * sizeof(snd_ctl_elem_id_t));
552                 if (dst == NULL)
553                         return -ENOMEM;
554                 down_read(&card->controls_rwsem);
555                 list.count = card->controls_count;
556                 plist = card->controls.next;
557                 while (plist != &card->controls) {
558                         if (offset == 0)
559                                 break;
560                         kctl = snd_kcontrol(plist);
561                         if (offset < kctl->count)
562                                 break;
563                         offset -= kctl->count;
564                         plist = plist->next;
565                 }
566                 list.used = 0;
567                 id = dst;
568                 while (space > 0 && plist != &card->controls) {
569                         kctl = snd_kcontrol(plist);
570                         for (jidx = offset; space > 0 && jidx < kctl->count; jidx++) {
571                                 snd_ctl_build_ioff(id, kctl, jidx);
572                                 id++;
573                                 space--;
574                                 list.used++;
575                         }
576                         plist = plist->next;
577                         offset = 0;
578                 }
579                 up_read(&card->controls_rwsem);
580                 if (list.used > 0 && copy_to_user(list.pids, dst, list.used * sizeof(snd_ctl_elem_id_t))) {
581                         vfree(dst);
582                         return -EFAULT;
583                 }
584                 vfree(dst);
585         } else {
586                 down_read(&card->controls_rwsem);
587                 list.count = card->controls_count;
588                 up_read(&card->controls_rwsem);
589         }
590         if (copy_to_user(_list, &list, sizeof(list)))
591                 return -EFAULT;
592         return 0;
593 }
594
595 static int snd_ctl_elem_info(snd_ctl_file_t *ctl, snd_ctl_elem_info_t __user *_info)
596 {
597         snd_card_t *card = ctl->card;
598         snd_ctl_elem_info_t info;
599         snd_kcontrol_t *kctl;
600         snd_kcontrol_volatile_t *vd;
601         unsigned int index_offset;
602         int result;
603         
604         if (copy_from_user(&info, _info, sizeof(info)))
605                 return -EFAULT;
606         down_read(&card->controls_rwsem);
607         kctl = snd_ctl_find_id(card, &info.id);
608         if (kctl == NULL) {
609                 up_read(&card->controls_rwsem);
610                 return -ENOENT;
611         }
612 #ifdef CONFIG_SND_DEBUG
613         info.access = 0;
614 #endif
615         result = kctl->info(kctl, &info);
616         if (result >= 0) {
617                 snd_assert(info.access == 0, );
618                 index_offset = snd_ctl_get_ioff(kctl, &info.id);
619                 vd = &kctl->vd[index_offset];
620                 snd_ctl_build_ioff(&info.id, kctl, index_offset);
621                 info.access = vd->access;
622                 if (vd->owner) {
623                         info.access |= SNDRV_CTL_ELEM_ACCESS_LOCK;
624                         if (vd->owner == ctl)
625                                 info.access |= SNDRV_CTL_ELEM_ACCESS_OWNER;
626                         info.owner = vd->owner_pid;
627                 } else {
628                         info.owner = -1;
629                 }
630         }
631         up_read(&card->controls_rwsem);
632         if (result >= 0)
633                 if (copy_to_user(_info, &info, sizeof(info)))
634                         return -EFAULT;
635         return result;
636 }
637
638 int snd_ctl_elem_read(snd_card_t *card, snd_ctl_elem_value_t *control)
639 {
640         snd_kcontrol_t *kctl;
641         snd_kcontrol_volatile_t *vd;
642         unsigned int index_offset;
643         int result, indirect;
644
645         down_read(&card->controls_rwsem);
646         kctl = snd_ctl_find_id(card, &control->id);
647         if (kctl == NULL) {
648                 result = -ENOENT;
649         } else {
650                 index_offset = snd_ctl_get_ioff(kctl, &control->id);
651                 vd = &kctl->vd[index_offset];
652                 indirect = vd->access & SNDRV_CTL_ELEM_ACCESS_INDIRECT ? 1 : 0;
653                 if (control->indirect != indirect) {
654                         result = -EACCES;
655                 } else {
656                         if ((vd->access & SNDRV_CTL_ELEM_ACCESS_READ) && kctl->get != NULL) {
657                                 snd_ctl_build_ioff(&control->id, kctl, index_offset);
658                                 result = kctl->get(kctl, control);
659                         } else {
660                                 result = -EPERM;
661                         }
662                 }
663         }
664         up_read(&card->controls_rwsem);
665         return result;
666 }
667
668 static int snd_ctl_elem_read_user(snd_card_t *card, snd_ctl_elem_value_t __user *_control)
669 {
670         snd_ctl_elem_value_t *control;
671         int result;
672         
673         control = kmalloc(sizeof(*control), GFP_KERNEL);
674         if (control == NULL)
675                 return -ENOMEM; 
676         if (copy_from_user(control, _control, sizeof(*control))) {
677                 kfree(control);
678                 return -EFAULT;
679         }
680         result = snd_ctl_elem_read(card, control);
681         if (result >= 0)
682                 if (copy_to_user(_control, control, sizeof(*control)))
683                         result = -EFAULT;
684         kfree(control);
685         return result;
686 }
687
688 int snd_ctl_elem_write(snd_ctl_file_t *file, snd_ctl_elem_value_t *control)
689 {
690         snd_card_t *card = file->card;
691         snd_kcontrol_t *kctl;
692         snd_kcontrol_volatile_t *vd;
693         unsigned int index_offset;
694         int result, indirect;
695
696         down_read(&card->controls_rwsem);
697         kctl = snd_ctl_find_id(card, &control->id);
698         if (kctl == NULL) {
699                 result = -ENOENT;
700         } else {
701                 index_offset = snd_ctl_get_ioff(kctl, &control->id);
702                 vd = &kctl->vd[index_offset];
703                 indirect = vd->access & SNDRV_CTL_ELEM_ACCESS_INDIRECT ? 1 : 0;
704                 if (control->indirect != indirect) {
705                         result = -EACCES;
706                 } else {
707                         if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_WRITE) ||
708                             kctl->put == NULL ||
709                             (vd->owner != NULL && vd->owner != file)) {
710                                 result = -EPERM;
711                         } else {
712                                 snd_ctl_build_ioff(&control->id, kctl, index_offset);
713                                 result = kctl->put(kctl, control);
714                         }
715                         if (result > 0) {
716                                 up_read(&card->controls_rwsem);
717                                 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &control->id);
718                                 return 0;
719                         }
720                 }
721         }
722         up_read(&card->controls_rwsem);
723         return result;
724 }
725
726 static int snd_ctl_elem_write_user(snd_ctl_file_t *file, snd_ctl_elem_value_t __user *_control)
727 {
728         snd_ctl_elem_value_t *control;
729         int result;
730
731         control = kmalloc(sizeof(*control), GFP_KERNEL);
732         if (control == NULL)
733                 return -ENOMEM; 
734         if (copy_from_user(control, _control, sizeof(*control))) {
735                 kfree(control);
736                 return -EFAULT;
737         }
738         result = snd_ctl_elem_write(file, control);
739         if (result >= 0)
740                 if (copy_to_user(_control, control, sizeof(*control)))
741                         result = -EFAULT;
742         kfree(control);
743         return result;
744 }
745
746 static int snd_ctl_elem_lock(snd_ctl_file_t *file, snd_ctl_elem_id_t __user *_id)
747 {
748         snd_card_t *card = file->card;
749         snd_ctl_elem_id_t id;
750         snd_kcontrol_t *kctl;
751         snd_kcontrol_volatile_t *vd;
752         int result;
753         
754         if (copy_from_user(&id, _id, sizeof(id)))
755                 return -EFAULT;
756         down_write(&card->controls_rwsem);
757         kctl = snd_ctl_find_id(card, &id);
758         if (kctl == NULL) {
759                 result = -ENOENT;
760         } else {
761                 vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)];
762                 if (vd->owner != NULL)
763                         result = -EBUSY;
764                 else {
765                         vd->owner = file;
766                         vd->owner_pid = current->pid;
767                         result = 0;
768                 }
769         }
770         up_write(&card->controls_rwsem);
771         return result;
772 }
773
774 static int snd_ctl_elem_unlock(snd_ctl_file_t *file, snd_ctl_elem_id_t __user *_id)
775 {
776         snd_card_t *card = file->card;
777         snd_ctl_elem_id_t id;
778         snd_kcontrol_t *kctl;
779         snd_kcontrol_volatile_t *vd;
780         int result;
781         
782         if (copy_from_user(&id, _id, sizeof(id)))
783                 return -EFAULT;
784         down_write(&card->controls_rwsem);
785         kctl = snd_ctl_find_id(card, &id);
786         if (kctl == NULL) {
787                 result = -ENOENT;
788         } else {
789                 vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)];
790                 if (vd->owner == NULL)
791                         result = -EINVAL;
792                 else if (vd->owner != file)
793                         result = -EPERM;
794                 else {
795                         vd->owner = NULL;
796                         vd->owner_pid = 0;
797                         result = 0;
798                 }
799         }
800         up_write(&card->controls_rwsem);
801         return result;
802 }
803
804 struct user_element {
805         enum sndrv_ctl_elem_type type;  /* element type */
806         unsigned int elem_count;        /* count of elements */
807         union {
808                 struct {
809                         unsigned int items;
810                 } enumerated;
811         } u;
812         void *elem_data;                /* element data */
813         unsigned long elem_data_size;   /* size of element data in bytes */
814         void *priv_data;                /* private data (like strings for enumerated type) */
815         unsigned long priv_data_size;   /* size of private data in bytes */
816         unsigned short dimen_count;     /* count of dimensions */
817         unsigned short dimen[0];        /* array of dimensions */
818 };
819
820 static int snd_ctl_elem_user_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
821 {
822         struct user_element *ue = kcontrol->private_data;
823
824         uinfo->type = ue->type;
825         uinfo->count = ue->elem_count;
826         if (ue->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
827                 uinfo->value.enumerated.items = ue->u.enumerated.items;
828                 if (uinfo->value.enumerated.item >= ue->u.enumerated.items)
829                         uinfo->value.enumerated.item = 0;
830                 strlcpy(uinfo->value.enumerated.name,
831                         (char *)ue->priv_data + uinfo->value.enumerated.item * 64,
832                         64);
833         }
834         return 0;
835 }
836
837 static int snd_ctl_elem_user_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
838 {
839         struct user_element *ue = kcontrol->private_data;
840
841         memcpy(&ucontrol->value, ue->elem_data, ue->elem_data_size);
842         return 0;
843 }
844
845 static int snd_ctl_elem_user_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
846 {
847         int change;
848         struct user_element *ue = kcontrol->private_data;
849         
850         change = memcmp(&ucontrol->value, ue->elem_data, ue->elem_data_size);
851         memcpy(ue->elem_data, &ucontrol->value, ue->elem_data_size);
852         return !!change;
853 }
854
855 static void snd_ctl_elem_user_free(snd_kcontrol_t * kcontrol)
856 {
857         kfree(kcontrol->private_data);
858 }
859
860 static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t __user *_info, int replace)
861 {
862         snd_card_t *card = file->card;
863         snd_ctl_elem_info_t info;
864         snd_kcontrol_t kctl, *_kctl;
865         unsigned int access;
866         long private_size, dimen_size, extra_size;
867         struct user_element *ue;
868         int idx, err;
869         
870         if (copy_from_user(&info, _info, sizeof(info)))
871                 return -EFAULT;
872         if (info.count > 1024)
873                 return -EINVAL;
874         access = info.access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
875                  (info.access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|SNDRV_CTL_ELEM_ACCESS_INACTIVE|
876                                  SNDRV_CTL_ELEM_ACCESS_DINDIRECT|SNDRV_CTL_ELEM_ACCESS_INDIRECT));
877         if (access & (SNDRV_CTL_ELEM_ACCESS_DINDIRECT | SNDRV_CTL_ELEM_ACCESS_INDIRECT))
878                 return -EINVAL;
879         info.id.numid = 0;
880         memset(&kctl, 0, sizeof(kctl));
881         down_write(&card->controls_rwsem);
882         if (!!((_kctl = snd_ctl_find_id(card, &info.id)) != NULL) ^ replace) {
883                 up_write(&card->controls_rwsem);
884                 return !replace ? -EBUSY : -ENOENT;
885         }
886         if (replace) {
887                 err = snd_ctl_remove(card, _kctl);
888                 if (err < 0) {
889                         up_write(&card->controls_rwsem);
890                         return err;
891                 }
892         }
893         up_write(&card->controls_rwsem);
894         memcpy(&kctl.id, &info.id, sizeof(info.id));
895         kctl.count = info.owner ? info.owner : 1;
896         access |= SNDRV_CTL_ELEM_ACCESS_USER;
897         kctl.info = snd_ctl_elem_user_info;
898         if (access & SNDRV_CTL_ELEM_ACCESS_READ)
899                 kctl.get = snd_ctl_elem_user_get;
900         if (access & SNDRV_CTL_ELEM_ACCESS_WRITE)
901                 kctl.put = snd_ctl_elem_user_put;
902         extra_size = 0;
903         switch (info.type) {
904         case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
905                 private_size = sizeof(char);
906                 if (info.count > 128)
907                         return -EINVAL;
908                 break;
909         case SNDRV_CTL_ELEM_TYPE_INTEGER:
910                 private_size = sizeof(long);
911                 if (info.count > 128)
912                         return -EINVAL;
913                 break;
914         case SNDRV_CTL_ELEM_TYPE_INTEGER64:
915                 private_size = sizeof(long long);
916                 if (info.count > 64)
917                         return -EINVAL;
918                 break;
919         case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
920                 private_size = sizeof(unsigned int);
921                 if (info.count > 128)
922                         return -EINVAL;
923                 if (info.value.enumerated.items > 1024)
924                         return -EINVAL;
925                 extra_size = info.value.enumerated.items * 64;
926                 break;
927         case SNDRV_CTL_ELEM_TYPE_BYTES:
928                 private_size = sizeof(unsigned char);
929                 if (info.count > 512)
930                         return -EINVAL;
931                 break;
932         case SNDRV_CTL_ELEM_TYPE_IEC958:
933                 private_size = sizeof(struct sndrv_aes_iec958);
934                 if (info.count != 1)
935                         return -EINVAL;
936                 break;
937         default:
938                 return -EINVAL;
939         }
940         private_size *= info.count;
941         if (private_size > 1024 * 1024)
942                 return -EINVAL;
943         dimen_size = 0;
944         if (!(info.access & SNDRV_CTL_ELEM_ACCESS_DINDIRECT))
945                 for (idx = 0; idx < 4 && info.dimen.d[idx]; idx++)
946                         dimen_size += sizeof(unsigned short);
947         ue = kcalloc(1, sizeof(struct user_element) + dimen_size + private_size + extra_size, GFP_KERNEL);
948         if (ue == NULL)
949                 return -ENOMEM;
950         ue->type = info.type;
951         ue->elem_count = info.count;
952         if (!(info.access & SNDRV_CTL_ELEM_ACCESS_DINDIRECT)) {
953                 for (idx = 0; idx < 4 && info.dimen.d[idx]; idx++)
954                         ue->dimen[idx] = info.dimen.d[idx];
955                 ue->dimen_count = dimen_size / sizeof(unsigned short);
956         }
957         ue->elem_data = (char *)ue + sizeof(ue) + dimen_size;
958         ue->elem_data_size = private_size;
959         if (extra_size) {
960                 ue->priv_data = (char *)ue + sizeof(ue) + dimen_size + private_size;
961                 ue->priv_data_size = extra_size;
962                 if (ue->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
963                         if (copy_from_user(ue->priv_data, *(char **)info.value.enumerated.name, extra_size))
964                                 return -EFAULT;
965                         ue->u.enumerated.items = info.value.enumerated.items;
966                 }
967         }
968         kctl.private_free = snd_ctl_elem_user_free;
969         _kctl = snd_ctl_new(&kctl, access);
970         if (_kctl == NULL) {
971                 kfree(_kctl->private_data);
972                 return -ENOMEM;
973         }
974         _kctl->private_data = ue;
975         for (idx = 0; idx < _kctl->count; idx++)
976                 _kctl->vd[idx].owner = file;
977         err = snd_ctl_add(card, _kctl);
978         if (err < 0) {
979                 snd_ctl_free_one(_kctl);
980                 return err;
981         }
982         return 0;
983 }
984
985 static int snd_ctl_elem_remove(snd_ctl_file_t *file, snd_ctl_elem_id_t __user *_id)
986 {
987         snd_ctl_elem_id_t id;
988
989         if (copy_from_user(&id, _id, sizeof(id)))
990                 return -EFAULT;
991         return snd_ctl_remove_unlocked_id(file, &id);
992 }
993
994 static int snd_ctl_subscribe_events(snd_ctl_file_t *file, int __user *ptr)
995 {
996         int subscribe;
997         if (get_user(subscribe, ptr))
998                 return -EFAULT;
999         if (subscribe < 0) {
1000                 subscribe = file->subscribed;
1001                 if (put_user(subscribe, ptr))
1002                         return -EFAULT;
1003                 return 0;
1004         }
1005         if (subscribe) {
1006                 file->subscribed = 1;
1007                 return 0;
1008         } else if (file->subscribed) {
1009                 snd_ctl_empty_read_queue(file);
1010                 file->subscribed = 0;
1011         }
1012         return 0;
1013 }
1014
1015 #ifdef CONFIG_PM
1016 /*
1017  * change the power state
1018  */
1019 static int snd_ctl_set_power_state(snd_card_t *card, unsigned int power_state)
1020 {
1021         switch (power_state) {
1022         case SNDRV_CTL_POWER_D0:
1023         case SNDRV_CTL_POWER_D1:
1024         case SNDRV_CTL_POWER_D2:
1025                 if (card->power_state != power_state)
1026                         /* FIXME: pass the correct state value */
1027                         card->pm_resume(card, 0);
1028                 break;
1029         case SNDRV_CTL_POWER_D3hot:
1030         case SNDRV_CTL_POWER_D3cold:
1031                 if (card->power_state != power_state)
1032                         /* FIXME: pass the correct state value */
1033                         card->pm_suspend(card, 0);
1034                 break;
1035         default:
1036                 return -EINVAL;
1037         }
1038         return 0;
1039 }
1040 #endif
1041
1042 static inline int _snd_ctl_ioctl(struct inode *inode, struct file *file,
1043                                  unsigned int cmd, unsigned long arg)
1044 {
1045         snd_ctl_file_t *ctl;
1046         snd_card_t *card;
1047         struct list_head *list;
1048         snd_kctl_ioctl_t *p;
1049         void __user *argp = (void __user *)arg;
1050         int __user *ip = argp;
1051         int err;
1052
1053         ctl = file->private_data;
1054         card = ctl->card;
1055         snd_assert(card != NULL, return -ENXIO);
1056         switch (cmd) {
1057         case SNDRV_CTL_IOCTL_PVERSION:
1058                 return put_user(SNDRV_CTL_VERSION, ip) ? -EFAULT : 0;
1059         case SNDRV_CTL_IOCTL_CARD_INFO:
1060                 return snd_ctl_card_info(card, ctl, cmd, argp);
1061         case SNDRV_CTL_IOCTL_ELEM_LIST:
1062                 return snd_ctl_elem_list(ctl->card, argp);
1063         case SNDRV_CTL_IOCTL_ELEM_INFO:
1064                 return snd_ctl_elem_info(ctl, argp);
1065         case SNDRV_CTL_IOCTL_ELEM_READ:
1066                 return snd_ctl_elem_read_user(ctl->card, argp);
1067         case SNDRV_CTL_IOCTL_ELEM_WRITE:
1068                 return snd_ctl_elem_write_user(ctl, argp);
1069         case SNDRV_CTL_IOCTL_ELEM_LOCK:
1070                 return snd_ctl_elem_lock(ctl, argp);
1071         case SNDRV_CTL_IOCTL_ELEM_UNLOCK:
1072                 return snd_ctl_elem_unlock(ctl, argp);
1073         case SNDRV_CTL_IOCTL_ELEM_ADD:
1074                 return snd_ctl_elem_add(ctl, argp, 0);
1075         case SNDRV_CTL_IOCTL_ELEM_REPLACE:
1076                 return snd_ctl_elem_add(ctl, argp, 1);
1077         case SNDRV_CTL_IOCTL_ELEM_REMOVE:
1078                 return snd_ctl_elem_remove(ctl, argp);
1079         case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
1080                 return snd_ctl_subscribe_events(ctl, ip);
1081         case SNDRV_CTL_IOCTL_POWER:
1082                 if (get_user(err, ip))
1083                         return -EFAULT;
1084                 if (!capable(CAP_SYS_ADMIN))
1085                         return -EPERM;
1086 #ifdef CONFIG_PM
1087                 if (card->pm_suspend && card->pm_resume) {
1088                         snd_power_lock(card);
1089                         err = snd_ctl_set_power_state(card, err);
1090                         snd_power_unlock(card);
1091                 } else
1092 #endif
1093                         err = -ENOPROTOOPT;
1094                 return err;
1095         case SNDRV_CTL_IOCTL_POWER_STATE:
1096 #ifdef CONFIG_PM
1097                 return put_user(card->power_state, ip) ? -EFAULT : 0;
1098 #else
1099                 return put_user(SNDRV_CTL_POWER_D0, ip) ? -EFAULT : 0;
1100 #endif
1101         }
1102         down_read(&snd_ioctl_rwsem);
1103         list_for_each(list, &snd_control_ioctls) {
1104                 p = list_entry(list, snd_kctl_ioctl_t, list);
1105                 err = p->fioctl(card, ctl, cmd, arg);
1106                 if (err != -ENOIOCTLCMD) {
1107                         up_read(&snd_ioctl_rwsem);
1108                         return err;
1109                 }
1110         }
1111         up_read(&snd_ioctl_rwsem);
1112         snd_printd("unknown ioctl = 0x%x\n", cmd);
1113         return -ENOTTY;
1114 }
1115
1116 /* FIXME: need to unlock BKL to allow preemption */
1117 static int snd_ctl_ioctl(struct inode *inode, struct file *file,
1118                          unsigned int cmd, unsigned long arg)
1119 {
1120         int err;
1121         unlock_kernel();
1122         err = _snd_ctl_ioctl(inode, file, cmd, arg);
1123         lock_kernel();
1124         return err;
1125 }
1126
1127 static ssize_t snd_ctl_read(struct file *file, char __user *buffer, size_t count, loff_t * offset)
1128 {
1129         snd_ctl_file_t *ctl;
1130         int err = 0;
1131         ssize_t result = 0;
1132
1133         ctl = file->private_data;
1134         snd_assert(ctl != NULL && ctl->card != NULL, return -ENXIO);
1135         if (!ctl->subscribed)
1136                 return -EBADFD;
1137         if (count < sizeof(snd_ctl_event_t))
1138                 return -EINVAL;
1139         spin_lock_irq(&ctl->read_lock);
1140         while (count >= sizeof(snd_ctl_event_t)) {
1141                 snd_ctl_event_t ev;
1142                 snd_kctl_event_t *kev;
1143                 while (list_empty(&ctl->events)) {
1144                         wait_queue_t wait;
1145                         if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
1146                                 err = -EAGAIN;
1147                                 goto __end_lock;
1148                         }
1149                         init_waitqueue_entry(&wait, current);
1150                         add_wait_queue(&ctl->change_sleep, &wait);
1151                         set_current_state(TASK_INTERRUPTIBLE);
1152                         spin_unlock_irq(&ctl->read_lock);
1153                         schedule();
1154                         remove_wait_queue(&ctl->change_sleep, &wait);
1155                         if (signal_pending(current))
1156                                 return result > 0 ? result : -ERESTARTSYS;
1157                         spin_lock_irq(&ctl->read_lock);
1158                 }
1159                 kev = snd_kctl_event(ctl->events.next);
1160                 ev.type = SNDRV_CTL_EVENT_ELEM;
1161                 ev.data.elem.mask = kev->mask;
1162                 ev.data.elem.id = kev->id;
1163                 list_del(&kev->list);
1164                 spin_unlock_irq(&ctl->read_lock);
1165                 kfree(kev);
1166                 if (copy_to_user(buffer, &ev, sizeof(snd_ctl_event_t))) {
1167                         err = -EFAULT;
1168                         goto __end;
1169                 }
1170                 spin_lock_irq(&ctl->read_lock);
1171                 buffer += sizeof(snd_ctl_event_t);
1172                 count -= sizeof(snd_ctl_event_t);
1173                 result += sizeof(snd_ctl_event_t);
1174         }
1175       __end_lock:
1176         spin_unlock_irq(&ctl->read_lock);
1177       __end:
1178         return result > 0 ? result : err;
1179 }
1180
1181 static unsigned int snd_ctl_poll(struct file *file, poll_table * wait)
1182 {
1183         unsigned int mask;
1184         snd_ctl_file_t *ctl;
1185
1186         ctl = file->private_data;
1187         if (!ctl->subscribed)
1188                 return 0;
1189         poll_wait(file, &ctl->change_sleep, wait);
1190
1191         mask = 0;
1192         if (!list_empty(&ctl->events))
1193                 mask |= POLLIN | POLLRDNORM;
1194
1195         return mask;
1196 }
1197
1198 /*
1199  * register the device-specific control-ioctls.
1200  * called from each device manager like pcm.c, hwdep.c, etc.
1201  */
1202 int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn)
1203 {
1204         snd_kctl_ioctl_t *pn;
1205
1206         pn = kcalloc(1, sizeof(snd_kctl_ioctl_t), GFP_KERNEL);
1207         if (pn == NULL)
1208                 return -ENOMEM;
1209         pn->fioctl = fcn;
1210         down_write(&snd_ioctl_rwsem);
1211         list_add_tail(&pn->list, &snd_control_ioctls);
1212         up_write(&snd_ioctl_rwsem);
1213         return 0;
1214 }
1215
1216 /*
1217  * de-register the device-specific control-ioctls.
1218  */
1219 int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn)
1220 {
1221         struct list_head *list;
1222         snd_kctl_ioctl_t *p;
1223
1224         snd_runtime_check(fcn != NULL, return -EINVAL);
1225         down_write(&snd_ioctl_rwsem);
1226         list_for_each(list, &snd_control_ioctls) {
1227                 p = list_entry(list, snd_kctl_ioctl_t, list);
1228                 if (p->fioctl == fcn) {
1229                         list_del(&p->list);
1230                         up_write(&snd_ioctl_rwsem);
1231                         kfree(p);
1232                         return 0;
1233                 }
1234         }
1235         up_write(&snd_ioctl_rwsem);
1236         snd_BUG();
1237         return -EINVAL;
1238 }
1239
1240 static int snd_ctl_fasync(int fd, struct file * file, int on)
1241 {
1242         snd_ctl_file_t *ctl;
1243         int err;
1244         ctl = file->private_data;
1245         err = fasync_helper(fd, file, on, &ctl->fasync);
1246         if (err < 0)
1247                 return err;
1248         return 0;
1249 }
1250
1251 /*
1252  *  INIT PART
1253  */
1254
1255 static struct file_operations snd_ctl_f_ops =
1256 {
1257         .owner =        THIS_MODULE,
1258         .read =         snd_ctl_read,
1259         .open =         snd_ctl_open,
1260         .release =      snd_ctl_release,
1261         .poll =         snd_ctl_poll,
1262         .ioctl =        snd_ctl_ioctl,
1263         .fasync =       snd_ctl_fasync,
1264 };
1265
1266 static snd_minor_t snd_ctl_reg =
1267 {
1268         .comment =      "ctl",
1269         .f_ops =        &snd_ctl_f_ops,
1270 };
1271
1272 /*
1273  * registration of the control device:
1274  * called from init.c
1275  */
1276 int snd_ctl_register(snd_card_t *card)
1277 {
1278         int err, cardnum;
1279         char name[16];
1280
1281         snd_assert(card != NULL, return -ENXIO);
1282         cardnum = card->number;
1283         snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO);
1284         sprintf(name, "controlC%i", cardnum);
1285         if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL,
1286                                         card, 0, &snd_ctl_reg, name)) < 0)
1287                 return err;
1288         return 0;
1289 }
1290
1291 /*
1292  * disconnection of the control device:
1293  * called from init.c
1294  */
1295 int snd_ctl_disconnect(snd_card_t *card)
1296 {
1297         struct list_head *flist;
1298         snd_ctl_file_t *ctl;
1299
1300         down_read(&card->controls_rwsem);
1301         list_for_each(flist, &card->ctl_files) {
1302                 ctl = snd_ctl_file(flist);
1303                 wake_up(&ctl->change_sleep);
1304                 kill_fasync(&ctl->fasync, SIGIO, POLL_ERR);
1305         }
1306         up_read(&card->controls_rwsem);
1307         return 0;
1308 }
1309
1310 /*
1311  * de-registration of the control device:
1312  * called from init.c
1313  */
1314 int snd_ctl_unregister(snd_card_t *card)
1315 {
1316         int err, cardnum;
1317         snd_kcontrol_t *control;
1318
1319         snd_assert(card != NULL, return -ENXIO);
1320         cardnum = card->number;
1321         snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO);
1322         if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL, card, 0)) < 0)
1323                 return err;
1324         down_write(&card->controls_rwsem);
1325         while (!list_empty(&card->controls)) {
1326                 control = snd_kcontrol(card->controls.next);
1327                 snd_ctl_remove(card, control);
1328         }
1329         up_write(&card->controls_rwsem);
1330         return 0;
1331 }