2 * Routines for driver control interface
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
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.
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.
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
22 #define __NO_VERSION__
23 #include <sound/driver.h>
24 #include <linux/interrupt.h>
25 #include <linux/slab.h>
26 #include <linux/vmalloc.h>
27 #include <linux/time.h>
28 #include <sound/core.h>
29 #include <sound/minors.h>
30 #include <sound/info.h>
31 #include <sound/control.h>
33 typedef struct _snd_kctl_ioctl
{
34 struct list_head list
; /* list of all ioctls */
35 snd_kctl_ioctl_func_t fioctl
;
38 #define snd_kctl_ioctl(n) list_entry(n, snd_kctl_ioctl_t, list)
40 static rwlock_t snd_ioctl_rwlock
= RW_LOCK_UNLOCKED
;
41 static LIST_HEAD(snd_control_ioctls
);
43 static inline void dec_mod_count(struct module
*module
)
46 __MOD_DEC_USE_COUNT(module
);
49 static int snd_ctl_open(struct inode
*inode
, struct file
*file
)
51 int cardnum
= SNDRV_MINOR_CARD(minor(inode
->i_rdev
));
60 card
= snd_cards
[cardnum
];
65 if (!try_inc_mod_count(card
->module
)) {
69 ctl
= snd_magic_kcalloc(snd_ctl_file_t
, 0, GFP_KERNEL
);
74 INIT_LIST_HEAD(&ctl
->events
);
75 init_waitqueue_head(&ctl
->change_sleep
);
76 spin_lock_init(&ctl
->read_lock
);
78 ctl
->pid
= current
->pid
;
79 file
->private_data
= ctl
;
80 write_lock_irqsave(&card
->control_rwlock
, flags
);
81 list_add_tail(&ctl
->list
, &card
->ctl_files
);
82 write_unlock_irqrestore(&card
->control_rwlock
, flags
);
86 dec_mod_count(card
->module
);
94 static void snd_ctl_empty_read_queue(snd_ctl_file_t
* ctl
)
96 snd_kctl_event_t
*cread
;
98 spin_lock(&ctl
->read_lock
);
99 while (!list_empty(&ctl
->events
)) {
100 cread
= snd_kctl_event(ctl
->events
.next
);
101 list_del(&cread
->list
);
104 spin_unlock(&ctl
->read_lock
);
107 static int snd_ctl_release(struct inode
*inode
, struct file
*file
)
110 struct list_head
*list
;
113 snd_kcontrol_t
*control
;
115 ctl
= snd_magic_cast(snd_ctl_file_t
, file
->private_data
, return -ENXIO
);
116 fasync_helper(-1, file
, 0, &ctl
->fasync
);
117 file
->private_data
= NULL
;
119 write_lock_irqsave(&card
->control_rwlock
, flags
);
120 list_del(&ctl
->list
);
121 write_unlock_irqrestore(&card
->control_rwlock
, flags
);
122 write_lock(&card
->control_owner_lock
);
123 list_for_each(list
, &card
->controls
) {
124 control
= snd_kcontrol(list
);
125 if (control
->owner
== ctl
)
126 control
->owner
= NULL
;
128 write_unlock(&card
->control_owner_lock
);
129 snd_ctl_empty_read_queue(ctl
);
130 snd_magic_kfree(ctl
);
131 dec_mod_count(card
->module
);
138 void snd_ctl_notify(snd_card_t
*card
, unsigned int mask
, snd_ctl_elem_id_t
*id
)
141 struct list_head
*flist
;
143 snd_kctl_event_t
*ev
;
145 snd_runtime_check(card
!= NULL
&& id
!= NULL
, return);
146 read_lock_irqsave(&card
->control_rwlock
, flags
);
147 #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
148 card
->mixer_oss_change_count
++;
150 list_for_each(flist
, &card
->ctl_files
) {
151 struct list_head
*elist
;
152 ctl
= snd_ctl_file(flist
);
153 if (!ctl
->subscribed
)
155 spin_lock(&ctl
->read_lock
);
156 list_for_each(elist
, &ctl
->events
) {
157 ev
= snd_kctl_event(elist
);
158 if (ev
->id
.numid
== id
->numid
) {
163 ev
= snd_kcalloc(sizeof(*ev
), in_interrupt() ? GFP_ATOMIC
: GFP_KERNEL
);
167 list_add_tail(&ev
->list
, &ctl
->events
);
169 snd_printk(KERN_ERR
"No memory available to allocate event\n");
172 wake_up(&ctl
->change_sleep
);
173 kill_fasync(&ctl
->fasync
, SIGIO
, POLL_IN
);
174 spin_unlock(&ctl
->read_lock
);
176 read_unlock_irqrestore(&card
->control_rwlock
, flags
);
179 snd_kcontrol_t
*snd_ctl_new(snd_kcontrol_t
* control
)
181 snd_kcontrol_t
*kctl
;
183 snd_runtime_check(control
!= NULL
, return NULL
);
184 kctl
= (snd_kcontrol_t
*)snd_magic_kmalloc(snd_kcontrol_t
, 0, GFP_KERNEL
);
191 snd_kcontrol_t
*snd_ctl_new1(snd_kcontrol_new_t
* ncontrol
, void *private_data
)
195 snd_runtime_check(ncontrol
!= NULL
, return NULL
);
196 snd_assert(ncontrol
->info
!= NULL
, return NULL
);
197 memset(&kctl
, 0, sizeof(kctl
));
198 kctl
.id
.iface
= ncontrol
->iface
;
199 kctl
.id
.device
= ncontrol
->device
;
200 kctl
.id
.subdevice
= ncontrol
->subdevice
;
201 strncpy(kctl
.id
.name
, ncontrol
->name
, sizeof(kctl
.id
.name
)-1);
202 kctl
.id
.index
= ncontrol
->index
;
203 kctl
.access
= ncontrol
->access
== 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE
:
204 (ncontrol
->access
& (SNDRV_CTL_ELEM_ACCESS_READWRITE
|SNDRV_CTL_ELEM_ACCESS_INACTIVE
|SNDRV_CTL_ELEM_ACCESS_INDIRECT
));
205 kctl
.info
= ncontrol
->info
;
206 kctl
.get
= ncontrol
->get
;
207 kctl
.put
= ncontrol
->put
;
208 kctl
.private_value
= ncontrol
->private_value
;
209 kctl
.private_data
= private_data
;
210 return snd_ctl_new(&kctl
);
213 void snd_ctl_free_one(snd_kcontrol_t
* kcontrol
)
216 if (kcontrol
->private_free
)
217 kcontrol
->private_free(kcontrol
);
218 snd_magic_kfree(kcontrol
);
222 int snd_ctl_add(snd_card_t
* card
, snd_kcontrol_t
* kcontrol
)
224 snd_runtime_check(card
!= NULL
&& kcontrol
!= NULL
, return -EINVAL
);
225 snd_assert(kcontrol
->info
!= NULL
, return -EINVAL
);
226 snd_assert(!(kcontrol
->access
& SNDRV_CTL_ELEM_ACCESS_READ
) || kcontrol
->get
!= NULL
, return -EINVAL
);
227 snd_assert(!(kcontrol
->access
& SNDRV_CTL_ELEM_ACCESS_WRITE
) || kcontrol
->put
!= NULL
, return -EINVAL
);
228 write_lock(&card
->control_rwlock
);
229 list_add_tail(&kcontrol
->list
, &card
->controls
);
230 card
->controls_count
++;
231 kcontrol
->id
.numid
= ++card
->last_numid
;
232 write_unlock(&card
->control_rwlock
);
233 snd_ctl_notify(card
, SNDRV_CTL_EVENT_MASK_ADD
, &kcontrol
->id
);
237 int snd_ctl_remove(snd_card_t
* card
, snd_kcontrol_t
* kcontrol
)
239 snd_runtime_check(card
!= NULL
&& kcontrol
!= NULL
, return -EINVAL
);
240 write_lock(&card
->control_rwlock
);
241 list_del(&kcontrol
->list
);
242 card
->controls_count
--;
243 write_unlock(&card
->control_rwlock
);
244 snd_ctl_notify(card
, SNDRV_CTL_EVENT_MASK_REMOVE
, &kcontrol
->id
);
245 snd_ctl_free_one(kcontrol
);
249 int snd_ctl_remove_id(snd_card_t
* card
, snd_ctl_elem_id_t
*id
)
251 snd_kcontrol_t
*kctl
;
253 kctl
= snd_ctl_find_id(card
, id
);
256 return snd_ctl_remove(card
, kctl
);
259 int snd_ctl_rename_id(snd_card_t
* card
, snd_ctl_elem_id_t
*src_id
, snd_ctl_elem_id_t
*dst_id
)
261 snd_kcontrol_t
*kctl
;
263 kctl
= snd_ctl_find_id(card
, src_id
);
266 write_lock(&card
->control_rwlock
);
268 kctl
->id
.numid
= ++card
->last_numid
;
269 write_unlock(&card
->control_rwlock
);
273 snd_kcontrol_t
*snd_ctl_find_numid(snd_card_t
* card
, unsigned int numid
)
275 struct list_head
*list
;
276 snd_kcontrol_t
*kctl
;
278 snd_runtime_check(card
!= NULL
&& numid
!= 0, return NULL
);
279 read_lock(&card
->control_rwlock
);
280 list_for_each(list
, &card
->controls
) {
281 kctl
= snd_kcontrol(list
);
282 if (kctl
->id
.numid
== numid
) {
283 read_unlock(&card
->control_rwlock
);
287 read_unlock(&card
->control_rwlock
);
291 snd_kcontrol_t
*snd_ctl_find_id(snd_card_t
* card
, snd_ctl_elem_id_t
*id
)
293 struct list_head
*list
;
294 snd_kcontrol_t
*kctl
;
296 snd_runtime_check(card
!= NULL
&& id
!= NULL
, return NULL
);
298 return snd_ctl_find_numid(card
, id
->numid
);
299 read_lock(&card
->control_rwlock
);
300 list_for_each(list
, &card
->controls
) {
301 kctl
= snd_kcontrol(list
);
302 if (kctl
->id
.iface
!= id
->iface
)
304 if (kctl
->id
.device
!= id
->device
)
306 if (kctl
->id
.subdevice
!= id
->subdevice
)
308 if (strncmp(kctl
->id
.name
, id
->name
, sizeof(kctl
->id
.name
)))
310 if (kctl
->id
.index
!= id
->index
)
312 read_unlock(&card
->control_rwlock
);
315 read_unlock(&card
->control_rwlock
);
319 static int snd_ctl_card_info(snd_card_t
* card
, snd_ctl_file_t
* ctl
,
320 unsigned int cmd
, unsigned long arg
)
322 snd_ctl_card_info_t info
;
324 memset(&info
, 0, sizeof(info
));
325 read_lock(&snd_ioctl_rwlock
);
326 info
.card
= card
->number
;
327 strncpy(info
.id
, card
->id
, sizeof(info
.id
) - 1);
328 strncpy(info
.driver
, card
->driver
, sizeof(info
.driver
) - 1);
329 strncpy(info
.name
, card
->shortname
, sizeof(info
.name
) - 1);
330 strncpy(info
.longname
, card
->longname
, sizeof(info
.longname
) - 1);
331 strncpy(info
.mixername
, card
->mixername
, sizeof(info
.mixername
) - 1);
332 strncpy(info
.components
, card
->components
, sizeof(info
.components
) - 1);
333 read_unlock(&snd_ioctl_rwlock
);
334 if (copy_to_user((void *) arg
, &info
, sizeof(snd_ctl_card_info_t
)))
339 static int snd_ctl_elem_list(snd_card_t
*card
, snd_ctl_elem_list_t
*_list
)
341 struct list_head
*plist
;
342 snd_ctl_elem_list_t list
;
343 snd_kcontrol_t
*kctl
;
344 snd_ctl_elem_id_t
*dst
, *id
;
347 if (copy_from_user(&list
, _list
, sizeof(list
)))
349 offset
= list
.offset
;
351 /* try limit maximum space */
355 /* allocate temporary buffer for atomic operation */
356 dst
= vmalloc(space
* sizeof(snd_ctl_elem_id_t
));
359 read_lock(&card
->control_rwlock
);
360 list
.count
= card
->controls_count
;
361 plist
= card
->controls
.next
;
362 while (offset
-- > 0 && plist
!= &card
->controls
)
366 while (space
> 0 && plist
!= &card
->controls
) {
367 kctl
= snd_kcontrol(plist
);
368 memcpy(id
, &kctl
->id
, sizeof(snd_ctl_elem_id_t
));
374 read_unlock(&card
->control_rwlock
);
375 if (list
.used
> 0 && copy_to_user(list
.pids
, dst
, list
.used
* sizeof(snd_ctl_elem_id_t
)))
379 read_lock(&card
->control_rwlock
);
380 list
.count
= card
->controls_count
;
381 read_unlock(&card
->control_rwlock
);
383 if (copy_to_user(_list
, &list
, sizeof(list
)))
388 static int snd_ctl_elem_info(snd_ctl_file_t
*ctl
, snd_ctl_elem_info_t
*_info
)
390 snd_card_t
*card
= ctl
->card
;
391 snd_ctl_elem_info_t info
;
392 snd_kcontrol_t
*kctl
;
395 if (copy_from_user(&info
, _info
, sizeof(info
)))
397 read_lock(&card
->control_rwlock
);
398 kctl
= snd_ctl_find_id(card
, &info
.id
);
400 read_unlock(&card
->control_rwlock
);
403 #ifdef CONFIG_SND_DEBUG
406 result
= kctl
->info(kctl
, &info
);
408 snd_assert(info
.access
== 0, );
410 info
.access
= kctl
->access
;
412 info
.access
|= SNDRV_CTL_ELEM_ACCESS_LOCK
;
413 if (kctl
->owner
== ctl
)
414 info
.access
|= SNDRV_CTL_ELEM_ACCESS_OWNER
;
415 info
.owner
= kctl
->owner_pid
;
420 read_unlock(&card
->control_rwlock
);
422 if (copy_to_user(_info
, &info
, sizeof(info
)))
427 static int snd_ctl_elem_read(snd_card_t
*card
, snd_ctl_elem_value_t
*_control
)
429 snd_ctl_elem_value_t control
;
430 snd_kcontrol_t
*kctl
;
431 int result
, indirect
;
433 if (copy_from_user(&control
, _control
, sizeof(control
)))
435 read_lock(&card
->control_rwlock
);
436 kctl
= snd_ctl_find_id(card
, &control
.id
);
440 indirect
= kctl
->access
& SNDRV_CTL_ELEM_ACCESS_INDIRECT
? 1 : 0;
441 if (control
.indirect
!= indirect
) {
444 if ((kctl
->access
& SNDRV_CTL_ELEM_ACCESS_READ
) && kctl
->get
!= NULL
) {
445 result
= kctl
->get(kctl
, &control
);
447 control
.id
= kctl
->id
;
452 read_unlock(&card
->control_rwlock
);
454 if (copy_to_user(_control
, &control
, sizeof(control
)))
459 static int snd_ctl_elem_write(snd_ctl_file_t
*file
, snd_ctl_elem_value_t
*_control
)
461 snd_card_t
*card
= file
->card
;
462 snd_ctl_elem_value_t control
;
463 snd_kcontrol_t
*kctl
;
464 int result
, indirect
;
466 if (copy_from_user(&control
, _control
, sizeof(control
)))
468 read_lock(&card
->control_rwlock
);
469 kctl
= snd_ctl_find_id(card
, &control
.id
);
473 indirect
= kctl
->access
& SNDRV_CTL_ELEM_ACCESS_INDIRECT
? 1 : 0;
474 if (control
.indirect
!= indirect
) {
477 read_lock(&card
->control_owner_lock
);
478 if (!(kctl
->access
& SNDRV_CTL_ELEM_ACCESS_WRITE
) ||
480 (kctl
->owner
!= NULL
&& kctl
->owner
!= file
)) {
483 result
= kctl
->put(kctl
, &control
);
485 control
.id
= kctl
->id
;
487 read_unlock(&card
->control_owner_lock
);
490 snd_ctl_notify(card
, SNDRV_CTL_EVENT_MASK_VALUE
, &kctl
->id
);
494 read_unlock(&card
->control_rwlock
);
496 if (copy_to_user(_control
, &control
, sizeof(control
)))
501 static int snd_ctl_elem_lock(snd_ctl_file_t
*file
, snd_ctl_elem_id_t
*_id
)
503 snd_card_t
*card
= file
->card
;
504 snd_ctl_elem_id_t id
;
505 snd_kcontrol_t
*kctl
;
508 if (copy_from_user(&id
, _id
, sizeof(id
)))
510 read_lock(&card
->control_rwlock
);
511 kctl
= snd_ctl_find_id(card
, &id
);
515 write_lock(&card
->control_owner_lock
);
516 if (kctl
->owner
!= NULL
)
520 kctl
->owner_pid
= current
->pid
;
523 write_unlock(&card
->control_owner_lock
);
525 read_unlock(&card
->control_rwlock
);
529 static int snd_ctl_elem_unlock(snd_ctl_file_t
*file
, snd_ctl_elem_id_t
*_id
)
531 snd_card_t
*card
= file
->card
;
532 snd_ctl_elem_id_t id
;
533 snd_kcontrol_t
*kctl
;
536 if (copy_from_user(&id
, _id
, sizeof(id
)))
538 read_lock(&card
->control_rwlock
);
539 kctl
= snd_ctl_find_id(card
, &id
);
543 write_lock(&card
->control_owner_lock
);
544 if (kctl
->owner
== NULL
)
546 else if (kctl
->owner
!= file
)
553 write_unlock(&card
->control_owner_lock
);
555 read_unlock(&card
->control_rwlock
);
559 static int snd_ctl_subscribe_events(snd_ctl_file_t
*file
, int *ptr
)
562 if (get_user(subscribe
, ptr
))
565 subscribe
= file
->subscribed
;
566 if (put_user(subscribe
, ptr
))
571 file
->subscribed
= 1;
573 } else if (file
->subscribed
) {
574 snd_ctl_empty_read_queue(file
);
575 file
->subscribed
= 0;
580 static int snd_ctl_ioctl(struct inode
*inode
, struct file
*file
,
581 unsigned int cmd
, unsigned long arg
)
585 struct list_head
*list
;
589 ctl
= snd_magic_cast(snd_ctl_file_t
, file
->private_data
, return -ENXIO
);
591 snd_assert(card
!= NULL
, return -ENXIO
);
593 case SNDRV_CTL_IOCTL_PVERSION
:
594 return put_user(SNDRV_CTL_VERSION
, (int *)arg
) ? -EFAULT
: 0;
595 case SNDRV_CTL_IOCTL_CARD_INFO
:
596 return snd_ctl_card_info(card
, ctl
, cmd
, arg
);
597 case SNDRV_CTL_IOCTL_ELEM_LIST
:
598 return snd_ctl_elem_list(ctl
->card
, (snd_ctl_elem_list_t
*) arg
);
599 case SNDRV_CTL_IOCTL_ELEM_INFO
:
600 return snd_ctl_elem_info(ctl
, (snd_ctl_elem_info_t
*) arg
);
601 case SNDRV_CTL_IOCTL_ELEM_READ
:
602 return snd_ctl_elem_read(ctl
->card
, (snd_ctl_elem_value_t
*) arg
);
603 case SNDRV_CTL_IOCTL_ELEM_WRITE
:
604 return snd_ctl_elem_write(ctl
, (snd_ctl_elem_value_t
*) arg
);
605 case SNDRV_CTL_IOCTL_ELEM_LOCK
:
606 return snd_ctl_elem_lock(ctl
, (snd_ctl_elem_id_t
*) arg
);
607 case SNDRV_CTL_IOCTL_ELEM_UNLOCK
:
608 return snd_ctl_elem_unlock(ctl
, (snd_ctl_elem_id_t
*) arg
);
609 case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS
:
610 return snd_ctl_subscribe_events(ctl
, (int *) arg
);
611 case SNDRV_CTL_IOCTL_POWER
:
612 if (get_user(err
, (int *)arg
))
614 if (!capable(CAP_SYS_ADMIN
))
617 if (card
->set_power_state
== NULL
)
619 return card
->set_power_state(card
, err
);
623 case SNDRV_CTL_IOCTL_POWER_STATE
:
625 return put_user(card
->power_state
, (int *)arg
) ? -EFAULT
: 0;
627 return put_user(SNDRV_CTL_POWER_D0
, (int *)arg
) ? -EFAULT
: 0;
630 read_lock(&snd_ioctl_rwlock
);
631 list_for_each(list
, &snd_control_ioctls
) {
632 p
= list_entry(list
, snd_kctl_ioctl_t
, list
);
633 err
= p
->fioctl(card
, ctl
, cmd
, arg
);
634 if (err
!= -ENOIOCTLCMD
) {
635 read_unlock(&snd_ioctl_rwlock
);
639 read_unlock(&snd_ioctl_rwlock
);
640 snd_printd("unknown ioctl = 0x%x\n", cmd
);
644 static ssize_t
snd_ctl_read(struct file
*file
, char *buffer
, size_t count
, loff_t
* offset
)
650 ctl
= snd_magic_cast(snd_ctl_file_t
, file
->private_data
, return -ENXIO
);
651 snd_assert(ctl
!= NULL
&& ctl
->card
!= NULL
, return -ENXIO
);
652 if (!ctl
->subscribed
)
654 if (count
< sizeof(snd_ctl_event_t
))
656 spin_lock_irq(&ctl
->read_lock
);
657 while (count
>= sizeof(snd_ctl_event_t
)) {
659 snd_kctl_event_t
*kev
;
660 while (list_empty(&ctl
->events
)) {
662 if (file
->f_flags
& O_NONBLOCK
) {
666 init_waitqueue_entry(&wait
, current
);
667 add_wait_queue(&ctl
->change_sleep
, &wait
);
668 spin_unlock_irq(&ctl
->read_lock
);
669 set_current_state(TASK_INTERRUPTIBLE
);
671 set_current_state(TASK_RUNNING
);
672 remove_wait_queue(&ctl
->change_sleep
, &wait
);
673 if (signal_pending(current
))
674 return result
> 0 ? result
: -ERESTARTSYS
;
675 spin_lock_irq(&ctl
->read_lock
);
677 kev
= snd_kctl_event(ctl
->events
.next
);
678 ev
.type
= SNDRV_CTL_EVENT_ELEM
;
679 ev
.data
.elem
.mask
= kev
->mask
;
680 ev
.data
.elem
.id
= kev
->id
;
681 list_del(&kev
->list
);
682 spin_unlock_irq(&ctl
->read_lock
);
684 if (copy_to_user(buffer
, &ev
, sizeof(snd_ctl_event_t
))) {
688 spin_lock_irq(&ctl
->read_lock
);
689 buffer
+= sizeof(snd_ctl_event_t
);
690 count
-= sizeof(snd_ctl_event_t
);
691 result
+= sizeof(snd_ctl_event_t
);
694 spin_unlock_irq(&ctl
->read_lock
);
695 return result
> 0 ? result
: err
;
698 static unsigned int snd_ctl_poll(struct file
*file
, poll_table
* wait
)
703 ctl
= snd_magic_cast(snd_ctl_file_t
, file
->private_data
, return 0);
704 if (!ctl
->subscribed
)
706 poll_wait(file
, &ctl
->change_sleep
, wait
);
709 if (!list_empty(&ctl
->events
))
710 mask
|= POLLIN
| POLLRDNORM
;
715 int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn
)
717 snd_kctl_ioctl_t
*pn
;
719 pn
= (snd_kctl_ioctl_t
*)
720 snd_kcalloc(sizeof(snd_kctl_ioctl_t
), GFP_KERNEL
);
724 write_lock(&snd_ioctl_rwlock
);
725 list_add_tail(&pn
->list
, &snd_control_ioctls
);
726 write_unlock(&snd_ioctl_rwlock
);
730 int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn
)
732 struct list_head
*list
;
735 snd_runtime_check(fcn
!= NULL
, return -EINVAL
);
736 write_lock(&snd_ioctl_rwlock
);
737 list_for_each(list
, &snd_control_ioctls
) {
738 p
= list_entry(list
, snd_kctl_ioctl_t
, list
);
739 if (p
->fioctl
== fcn
) {
741 write_unlock(&snd_ioctl_rwlock
);
746 write_unlock(&snd_ioctl_rwlock
);
751 static int snd_ctl_fasync(int fd
, struct file
* file
, int on
)
755 ctl
= snd_magic_cast(snd_ctl_file_t
, file
->private_data
, return -ENXIO
);
756 err
= fasync_helper(fd
, file
, on
, &ctl
->fasync
);
766 static struct file_operations snd_ctl_f_ops
=
773 release
: snd_ctl_release
,
775 ioctl
: snd_ctl_ioctl
,
776 fasync
: snd_ctl_fasync
,
779 static snd_minor_t snd_ctl_reg
=
782 f_ops
: &snd_ctl_f_ops
,
785 int snd_ctl_register(snd_card_t
*card
)
790 snd_assert(card
!= NULL
, return -ENXIO
);
791 cardnum
= card
->number
;
792 snd_assert(cardnum
>= 0 && cardnum
< SNDRV_CARDS
, return -ENXIO
);
793 sprintf(name
, "controlC%i", cardnum
);
794 if ((err
= snd_register_device(SNDRV_DEVICE_TYPE_CONTROL
,
795 card
, 0, &snd_ctl_reg
, name
)) < 0)
800 int snd_ctl_unregister(snd_card_t
*card
)
803 snd_kcontrol_t
*control
;
805 snd_assert(card
!= NULL
, return -ENXIO
);
806 cardnum
= card
->number
;
807 snd_assert(cardnum
>= 0 && cardnum
< SNDRV_CARDS
, return -ENXIO
);
808 if ((err
= snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL
, card
, 0)) < 0)
810 while (!list_empty(&card
->controls
)) {
811 control
= snd_kcontrol(card
->controls
.next
);
812 snd_ctl_remove(card
, control
);