1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include <linux/threads.h>
23#include <linux/interrupt.h>
24#include <linux/module.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>
32
33
34#define MAX_USER_CONTROLS 32
35#define MAX_CONTROL_COUNT 1028
36
37struct snd_kctl_ioctl {
38 struct list_head list;
39 snd_kctl_ioctl_func_t fioctl;
40};
41
42static DECLARE_RWSEM(snd_ioctl_rwsem);
43static LIST_HEAD(snd_control_ioctls);
44#ifdef CONFIG_COMPAT
45static LIST_HEAD(snd_control_compat_ioctls);
46#endif
47
48static int snd_ctl_open(struct inode *inode, struct file *file)
49{
50 unsigned long flags;
51 struct snd_card *card;
52 struct snd_ctl_file *ctl;
53 int err;
54
55 err = nonseekable_open(inode, file);
56 if (err < 0)
57 return err;
58
59 card = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_CONTROL);
60 if (!card) {
61 err = -ENODEV;
62 goto __error1;
63 }
64 err = snd_card_file_add(card, file);
65 if (err < 0) {
66 err = -ENODEV;
67 goto __error1;
68 }
69 if (!try_module_get(card->module)) {
70 err = -EFAULT;
71 goto __error2;
72 }
73 ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
74 if (ctl == NULL) {
75 err = -ENOMEM;
76 goto __error;
77 }
78 INIT_LIST_HEAD(&ctl->events);
79 init_waitqueue_head(&ctl->change_sleep);
80 spin_lock_init(&ctl->read_lock);
81 ctl->card = card;
82 ctl->prefer_pcm_subdevice = -1;
83 ctl->prefer_rawmidi_subdevice = -1;
84 ctl->pid = get_pid(task_pid(current));
85 file->private_data = ctl;
86 write_lock_irqsave(&card->ctl_files_rwlock, flags);
87 list_add_tail(&ctl->list, &card->ctl_files);
88 write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
89 snd_card_unref(card);
90 return 0;
91
92 __error:
93 module_put(card->module);
94 __error2:
95 snd_card_file_remove(card, file);
96 __error1:
97 if (card)
98 snd_card_unref(card);
99 return err;
100}
101
102static void snd_ctl_empty_read_queue(struct snd_ctl_file * ctl)
103{
104 unsigned long flags;
105 struct snd_kctl_event *cread;
106
107 spin_lock_irqsave(&ctl->read_lock, flags);
108 while (!list_empty(&ctl->events)) {
109 cread = snd_kctl_event(ctl->events.next);
110 list_del(&cread->list);
111 kfree(cread);
112 }
113 spin_unlock_irqrestore(&ctl->read_lock, flags);
114}
115
116static int snd_ctl_release(struct inode *inode, struct file *file)
117{
118 unsigned long flags;
119 struct snd_card *card;
120 struct snd_ctl_file *ctl;
121 struct snd_kcontrol *control;
122 unsigned int idx;
123
124 ctl = file->private_data;
125 file->private_data = NULL;
126 card = ctl->card;
127 write_lock_irqsave(&card->ctl_files_rwlock, flags);
128 list_del(&ctl->list);
129 write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
130 down_write(&card->controls_rwsem);
131 list_for_each_entry(control, &card->controls, list)
132 for (idx = 0; idx < control->count; idx++)
133 if (control->vd[idx].owner == ctl)
134 control->vd[idx].owner = NULL;
135 up_write(&card->controls_rwsem);
136 snd_ctl_empty_read_queue(ctl);
137 put_pid(ctl->pid);
138 kfree(ctl);
139 module_put(card->module);
140 snd_card_file_remove(card, file);
141 return 0;
142}
143
144void snd_ctl_notify(struct snd_card *card, unsigned int mask,
145 struct snd_ctl_elem_id *id)
146{
147 unsigned long flags;
148 struct snd_ctl_file *ctl;
149 struct snd_kctl_event *ev;
150
151 if (snd_BUG_ON(!card || !id))
152 return;
153 read_lock(&card->ctl_files_rwlock);
154#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
155 card->mixer_oss_change_count++;
156#endif
157 list_for_each_entry(ctl, &card->ctl_files, list) {
158 if (!ctl->subscribed)
159 continue;
160 spin_lock_irqsave(&ctl->read_lock, flags);
161 list_for_each_entry(ev, &ctl->events, list) {
162 if (ev->id.numid == id->numid) {
163 ev->mask |= mask;
164 goto _found;
165 }
166 }
167 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
168 if (ev) {
169 ev->id = *id;
170 ev->mask = mask;
171 list_add_tail(&ev->list, &ctl->events);
172 } else {
173 snd_printk(KERN_ERR "No memory available to allocate event\n");
174 }
175 _found:
176 wake_up(&ctl->change_sleep);
177 spin_unlock_irqrestore(&ctl->read_lock, flags);
178 kill_fasync(&ctl->fasync, SIGIO, POLL_IN);
179 }
180 read_unlock(&card->ctl_files_rwlock);
181}
182
183EXPORT_SYMBOL(snd_ctl_notify);
184
185
186
187
188
189
190
191
192
193
194
195static struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control,
196 unsigned int access)
197{
198 struct snd_kcontrol *kctl;
199 unsigned int idx;
200
201 if (snd_BUG_ON(!control || !control->count))
202 return NULL;
203
204 if (control->count > MAX_CONTROL_COUNT)
205 return NULL;
206
207 kctl = kzalloc(sizeof(*kctl) + sizeof(struct snd_kcontrol_volatile) * control->count, GFP_KERNEL);
208 if (kctl == NULL) {
209 snd_printk(KERN_ERR "Cannot allocate control instance\n");
210 return NULL;
211 }
212 *kctl = *control;
213 for (idx = 0; idx < kctl->count; idx++)
214 kctl->vd[idx].access = access;
215 return kctl;
216}
217
218
219
220
221
222
223
224
225
226
227
228
229struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,
230 void *private_data)
231{
232 struct snd_kcontrol kctl;
233 unsigned int access;
234
235 if (snd_BUG_ON(!ncontrol || !ncontrol->info))
236 return NULL;
237 memset(&kctl, 0, sizeof(kctl));
238 kctl.id.iface = ncontrol->iface;
239 kctl.id.device = ncontrol->device;
240 kctl.id.subdevice = ncontrol->subdevice;
241 if (ncontrol->name) {
242 strlcpy(kctl.id.name, ncontrol->name, sizeof(kctl.id.name));
243 if (strcmp(ncontrol->name, kctl.id.name) != 0)
244 snd_printk(KERN_WARNING
245 "Control name '%s' truncated to '%s'\n",
246 ncontrol->name, kctl.id.name);
247 }
248 kctl.id.index = ncontrol->index;
249 kctl.count = ncontrol->count ? ncontrol->count : 1;
250 access = ncontrol->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
251 (ncontrol->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|
252 SNDRV_CTL_ELEM_ACCESS_INACTIVE|
253 SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE|
254 SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND|
255 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK));
256 kctl.info = ncontrol->info;
257 kctl.get = ncontrol->get;
258 kctl.put = ncontrol->put;
259 kctl.tlv.p = ncontrol->tlv.p;
260 kctl.private_value = ncontrol->private_value;
261 kctl.private_data = private_data;
262 return snd_ctl_new(&kctl, access);
263}
264
265EXPORT_SYMBOL(snd_ctl_new1);
266
267
268
269
270
271
272
273
274
275void snd_ctl_free_one(struct snd_kcontrol *kcontrol)
276{
277 if (kcontrol) {
278 if (kcontrol->private_free)
279 kcontrol->private_free(kcontrol);
280 kfree(kcontrol);
281 }
282}
283
284EXPORT_SYMBOL(snd_ctl_free_one);
285
286static bool snd_ctl_remove_numid_conflict(struct snd_card *card,
287 unsigned int count)
288{
289 struct snd_kcontrol *kctl;
290
291 list_for_each_entry(kctl, &card->controls, list) {
292 if (kctl->id.numid < card->last_numid + 1 + count &&
293 kctl->id.numid + kctl->count > card->last_numid + 1) {
294 card->last_numid = kctl->id.numid + kctl->count - 1;
295 return true;
296 }
297 }
298 return false;
299}
300
301static int snd_ctl_find_hole(struct snd_card *card, unsigned int count)
302{
303 unsigned int iter = 100000;
304
305 while (snd_ctl_remove_numid_conflict(card, count)) {
306 if (--iter == 0) {
307
308 snd_printk(KERN_ERR "unable to allocate new control numid\n");
309 return -ENOMEM;
310 }
311 }
312 return 0;
313}
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
329{
330 struct snd_ctl_elem_id id;
331 unsigned int idx;
332 int err = -EINVAL;
333
334 if (! kcontrol)
335 return err;
336 if (snd_BUG_ON(!card || !kcontrol->info))
337 goto error;
338 id = kcontrol->id;
339 down_write(&card->controls_rwsem);
340 if (snd_ctl_find_id(card, &id)) {
341 up_write(&card->controls_rwsem);
342 snd_printd(KERN_ERR "control %i:%i:%i:%s:%i is already present\n",
343 id.iface,
344 id.device,
345 id.subdevice,
346 id.name,
347 id.index);
348 err = -EBUSY;
349 goto error;
350 }
351 if (snd_ctl_find_hole(card, kcontrol->count) < 0) {
352 up_write(&card->controls_rwsem);
353 err = -ENOMEM;
354 goto error;
355 }
356 list_add_tail(&kcontrol->list, &card->controls);
357 card->controls_count += kcontrol->count;
358 kcontrol->id.numid = card->last_numid + 1;
359 card->last_numid += kcontrol->count;
360 up_write(&card->controls_rwsem);
361 for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
362 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
363 return 0;
364
365 error:
366 snd_ctl_free_one(kcontrol);
367 return err;
368}
369
370EXPORT_SYMBOL(snd_ctl_add);
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
387 bool add_on_replace)
388{
389 struct snd_ctl_elem_id id;
390 unsigned int idx;
391 struct snd_kcontrol *old;
392 int ret;
393
394 if (!kcontrol)
395 return -EINVAL;
396 if (snd_BUG_ON(!card || !kcontrol->info)) {
397 ret = -EINVAL;
398 goto error;
399 }
400 id = kcontrol->id;
401 down_write(&card->controls_rwsem);
402 old = snd_ctl_find_id(card, &id);
403 if (!old) {
404 if (add_on_replace)
405 goto add;
406 up_write(&card->controls_rwsem);
407 ret = -EINVAL;
408 goto error;
409 }
410 ret = snd_ctl_remove(card, old);
411 if (ret < 0) {
412 up_write(&card->controls_rwsem);
413 goto error;
414 }
415add:
416 if (snd_ctl_find_hole(card, kcontrol->count) < 0) {
417 up_write(&card->controls_rwsem);
418 ret = -ENOMEM;
419 goto error;
420 }
421 list_add_tail(&kcontrol->list, &card->controls);
422 card->controls_count += kcontrol->count;
423 kcontrol->id.numid = card->last_numid + 1;
424 card->last_numid += kcontrol->count;
425 up_write(&card->controls_rwsem);
426 for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
427 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
428 return 0;
429
430error:
431 snd_ctl_free_one(kcontrol);
432 return ret;
433}
434EXPORT_SYMBOL(snd_ctl_replace);
435
436
437
438
439
440
441
442
443
444
445
446
447int snd_ctl_remove(struct snd_card *card, struct snd_kcontrol *kcontrol)
448{
449 struct snd_ctl_elem_id id;
450 unsigned int idx;
451
452 if (snd_BUG_ON(!card || !kcontrol))
453 return -EINVAL;
454 list_del(&kcontrol->list);
455 card->controls_count -= kcontrol->count;
456 id = kcontrol->id;
457 for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
458 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_REMOVE, &id);
459 snd_ctl_free_one(kcontrol);
460 return 0;
461}
462
463EXPORT_SYMBOL(snd_ctl_remove);
464
465
466
467
468
469
470
471
472
473
474
475int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id)
476{
477 struct snd_kcontrol *kctl;
478 int ret;
479
480 down_write(&card->controls_rwsem);
481 kctl = snd_ctl_find_id(card, id);
482 if (kctl == NULL) {
483 up_write(&card->controls_rwsem);
484 return -ENOENT;
485 }
486 ret = snd_ctl_remove(card, kctl);
487 up_write(&card->controls_rwsem);
488 return ret;
489}
490
491EXPORT_SYMBOL(snd_ctl_remove_id);
492
493
494
495
496
497
498
499
500
501
502
503static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file,
504 struct snd_ctl_elem_id *id)
505{
506 struct snd_card *card = file->card;
507 struct snd_kcontrol *kctl;
508 int idx, ret;
509
510 down_write(&card->controls_rwsem);
511 kctl = snd_ctl_find_id(card, id);
512 if (kctl == NULL) {
513 ret = -ENOENT;
514 goto error;
515 }
516 if (!(kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_USER)) {
517 ret = -EINVAL;
518 goto error;
519 }
520 for (idx = 0; idx < kctl->count; idx++)
521 if (kctl->vd[idx].owner != NULL && kctl->vd[idx].owner != file) {
522 ret = -EBUSY;
523 goto error;
524 }
525 ret = snd_ctl_remove(card, kctl);
526 if (ret < 0)
527 goto error;
528 card->user_ctl_count--;
529error:
530 up_write(&card->controls_rwsem);
531 return ret;
532}
533
534
535
536
537
538
539
540
541
542
543
544
545int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
546 int active)
547{
548 struct snd_kcontrol *kctl;
549 struct snd_kcontrol_volatile *vd;
550 unsigned int index_offset;
551 int ret;
552
553 down_write(&card->controls_rwsem);
554 kctl = snd_ctl_find_id(card, id);
555 if (kctl == NULL) {
556 ret = -ENOENT;
557 goto unlock;
558 }
559 index_offset = snd_ctl_get_ioff(kctl, &kctl->id);
560 vd = &kctl->vd[index_offset];
561 ret = 0;
562 if (active) {
563 if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE))
564 goto unlock;
565 vd->access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
566 } else {
567 if (vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE)
568 goto unlock;
569 vd->access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
570 }
571 ret = 1;
572 unlock:
573 up_write(&card->controls_rwsem);
574 if (ret > 0)
575 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, id);
576 return ret;
577}
578EXPORT_SYMBOL_GPL(snd_ctl_activate_id);
579
580
581
582
583
584
585
586
587
588
589
590
591int snd_ctl_rename_id(struct snd_card *card, struct snd_ctl_elem_id *src_id,
592 struct snd_ctl_elem_id *dst_id)
593{
594 struct snd_kcontrol *kctl;
595
596 down_write(&card->controls_rwsem);
597 kctl = snd_ctl_find_id(card, src_id);
598 if (kctl == NULL) {
599 up_write(&card->controls_rwsem);
600 return -ENOENT;
601 }
602 kctl->id = *dst_id;
603 kctl->id.numid = card->last_numid + 1;
604 card->last_numid += kctl->count;
605 up_write(&card->controls_rwsem);
606 return 0;
607}
608
609EXPORT_SYMBOL(snd_ctl_rename_id);
610
611
612
613
614
615
616
617
618
619
620
621
622
623struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numid)
624{
625 struct snd_kcontrol *kctl;
626
627 if (snd_BUG_ON(!card || !numid))
628 return NULL;
629 list_for_each_entry(kctl, &card->controls, list) {
630 if (kctl->id.numid <= numid && kctl->id.numid + kctl->count > numid)
631 return kctl;
632 }
633 return NULL;
634}
635
636EXPORT_SYMBOL(snd_ctl_find_numid);
637
638
639
640
641
642
643
644
645
646
647
648
649
650struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card,
651 struct snd_ctl_elem_id *id)
652{
653 struct snd_kcontrol *kctl;
654
655 if (snd_BUG_ON(!card || !id))
656 return NULL;
657 if (id->numid != 0)
658 return snd_ctl_find_numid(card, id->numid);
659 list_for_each_entry(kctl, &card->controls, list) {
660 if (kctl->id.iface != id->iface)
661 continue;
662 if (kctl->id.device != id->device)
663 continue;
664 if (kctl->id.subdevice != id->subdevice)
665 continue;
666 if (strncmp(kctl->id.name, id->name, sizeof(kctl->id.name)))
667 continue;
668 if (kctl->id.index > id->index)
669 continue;
670 if (kctl->id.index + kctl->count <= id->index)
671 continue;
672 return kctl;
673 }
674 return NULL;
675}
676
677EXPORT_SYMBOL(snd_ctl_find_id);
678
679static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl,
680 unsigned int cmd, void __user *arg)
681{
682 struct snd_ctl_card_info *info;
683
684 info = kzalloc(sizeof(*info), GFP_KERNEL);
685 if (! info)
686 return -ENOMEM;
687 down_read(&snd_ioctl_rwsem);
688 info->card = card->number;
689 strlcpy(info->id, card->id, sizeof(info->id));
690 strlcpy(info->driver, card->driver, sizeof(info->driver));
691 strlcpy(info->name, card->shortname, sizeof(info->name));
692 strlcpy(info->longname, card->longname, sizeof(info->longname));
693 strlcpy(info->mixername, card->mixername, sizeof(info->mixername));
694 strlcpy(info->components, card->components, sizeof(info->components));
695 up_read(&snd_ioctl_rwsem);
696 if (copy_to_user(arg, info, sizeof(struct snd_ctl_card_info))) {
697 kfree(info);
698 return -EFAULT;
699 }
700 kfree(info);
701 return 0;
702}
703
704static int snd_ctl_elem_list(struct snd_card *card,
705 struct snd_ctl_elem_list __user *_list)
706{
707 struct list_head *plist;
708 struct snd_ctl_elem_list list;
709 struct snd_kcontrol *kctl;
710 struct snd_ctl_elem_id *dst, *id;
711 unsigned int offset, space, jidx;
712
713 if (copy_from_user(&list, _list, sizeof(list)))
714 return -EFAULT;
715 offset = list.offset;
716 space = list.space;
717
718 if (space > 16384)
719 return -ENOMEM;
720 if (space > 0) {
721
722 dst = vmalloc(space * sizeof(struct snd_ctl_elem_id));
723 if (dst == NULL)
724 return -ENOMEM;
725 down_read(&card->controls_rwsem);
726 list.count = card->controls_count;
727 plist = card->controls.next;
728 while (plist != &card->controls) {
729 if (offset == 0)
730 break;
731 kctl = snd_kcontrol(plist);
732 if (offset < kctl->count)
733 break;
734 offset -= kctl->count;
735 plist = plist->next;
736 }
737 list.used = 0;
738 id = dst;
739 while (space > 0 && plist != &card->controls) {
740 kctl = snd_kcontrol(plist);
741 for (jidx = offset; space > 0 && jidx < kctl->count; jidx++) {
742 snd_ctl_build_ioff(id, kctl, jidx);
743 id++;
744 space--;
745 list.used++;
746 }
747 plist = plist->next;
748 offset = 0;
749 }
750 up_read(&card->controls_rwsem);
751 if (list.used > 0 &&
752 copy_to_user(list.pids, dst,
753 list.used * sizeof(struct snd_ctl_elem_id))) {
754 vfree(dst);
755 return -EFAULT;
756 }
757 vfree(dst);
758 } else {
759 down_read(&card->controls_rwsem);
760 list.count = card->controls_count;
761 up_read(&card->controls_rwsem);
762 }
763 if (copy_to_user(_list, &list, sizeof(list)))
764 return -EFAULT;
765 return 0;
766}
767
768static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
769 struct snd_ctl_elem_info *info)
770{
771 struct snd_card *card = ctl->card;
772 struct snd_kcontrol *kctl;
773 struct snd_kcontrol_volatile *vd;
774 unsigned int index_offset;
775 int result;
776
777 down_read(&card->controls_rwsem);
778 kctl = snd_ctl_find_id(card, &info->id);
779 if (kctl == NULL) {
780 up_read(&card->controls_rwsem);
781 return -ENOENT;
782 }
783#ifdef CONFIG_SND_DEBUG
784 info->access = 0;
785#endif
786 result = kctl->info(kctl, info);
787 if (result >= 0) {
788 snd_BUG_ON(info->access);
789 index_offset = snd_ctl_get_ioff(kctl, &info->id);
790 vd = &kctl->vd[index_offset];
791 snd_ctl_build_ioff(&info->id, kctl, index_offset);
792 info->access = vd->access;
793 if (vd->owner) {
794 info->access |= SNDRV_CTL_ELEM_ACCESS_LOCK;
795 if (vd->owner == ctl)
796 info->access |= SNDRV_CTL_ELEM_ACCESS_OWNER;
797 info->owner = pid_vnr(vd->owner->pid);
798 } else {
799 info->owner = -1;
800 }
801 }
802 up_read(&card->controls_rwsem);
803 return result;
804}
805
806static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl,
807 struct snd_ctl_elem_info __user *_info)
808{
809 struct snd_ctl_elem_info info;
810 int result;
811
812 if (copy_from_user(&info, _info, sizeof(info)))
813 return -EFAULT;
814 snd_power_lock(ctl->card);
815 result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
816 if (result >= 0)
817 result = snd_ctl_elem_info(ctl, &info);
818 snd_power_unlock(ctl->card);
819 if (result >= 0)
820 if (copy_to_user(_info, &info, sizeof(info)))
821 return -EFAULT;
822 return result;
823}
824
825static int snd_ctl_elem_read(struct snd_card *card,
826 struct snd_ctl_elem_value *control)
827{
828 struct snd_kcontrol *kctl;
829 struct snd_kcontrol_volatile *vd;
830 unsigned int index_offset;
831 int result;
832
833 down_read(&card->controls_rwsem);
834 kctl = snd_ctl_find_id(card, &control->id);
835 if (kctl == NULL) {
836 result = -ENOENT;
837 } else {
838 index_offset = snd_ctl_get_ioff(kctl, &control->id);
839 vd = &kctl->vd[index_offset];
840 if ((vd->access & SNDRV_CTL_ELEM_ACCESS_READ) &&
841 kctl->get != NULL) {
842 snd_ctl_build_ioff(&control->id, kctl, index_offset);
843 result = kctl->get(kctl, control);
844 } else
845 result = -EPERM;
846 }
847 up_read(&card->controls_rwsem);
848 return result;
849}
850
851static int snd_ctl_elem_read_user(struct snd_card *card,
852 struct snd_ctl_elem_value __user *_control)
853{
854 struct snd_ctl_elem_value *control;
855 int result;
856
857 control = memdup_user(_control, sizeof(*control));
858 if (IS_ERR(control))
859 return PTR_ERR(control);
860
861 snd_power_lock(card);
862 result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
863 if (result >= 0)
864 result = snd_ctl_elem_read(card, control);
865 snd_power_unlock(card);
866 if (result >= 0)
867 if (copy_to_user(_control, control, sizeof(*control)))
868 result = -EFAULT;
869 kfree(control);
870 return result;
871}
872
873static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
874 struct snd_ctl_elem_value *control)
875{
876 struct snd_kcontrol *kctl;
877 struct snd_kcontrol_volatile *vd;
878 unsigned int index_offset;
879 int result;
880
881 down_read(&card->controls_rwsem);
882 kctl = snd_ctl_find_id(card, &control->id);
883 if (kctl == NULL) {
884 result = -ENOENT;
885 } else {
886 index_offset = snd_ctl_get_ioff(kctl, &control->id);
887 vd = &kctl->vd[index_offset];
888 if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_WRITE) ||
889 kctl->put == NULL ||
890 (file && vd->owner && vd->owner != file)) {
891 result = -EPERM;
892 } else {
893 snd_ctl_build_ioff(&control->id, kctl, index_offset);
894 result = kctl->put(kctl, control);
895 }
896 if (result > 0) {
897 up_read(&card->controls_rwsem);
898 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
899 &control->id);
900 return 0;
901 }
902 }
903 up_read(&card->controls_rwsem);
904 return result;
905}
906
907static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
908 struct snd_ctl_elem_value __user *_control)
909{
910 struct snd_ctl_elem_value *control;
911 struct snd_card *card;
912 int result;
913
914 control = memdup_user(_control, sizeof(*control));
915 if (IS_ERR(control))
916 return PTR_ERR(control);
917
918 card = file->card;
919 snd_power_lock(card);
920 result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
921 if (result >= 0)
922 result = snd_ctl_elem_write(card, file, control);
923 snd_power_unlock(card);
924 if (result >= 0)
925 if (copy_to_user(_control, control, sizeof(*control)))
926 result = -EFAULT;
927 kfree(control);
928 return result;
929}
930
931static int snd_ctl_elem_lock(struct snd_ctl_file *file,
932 struct snd_ctl_elem_id __user *_id)
933{
934 struct snd_card *card = file->card;
935 struct snd_ctl_elem_id id;
936 struct snd_kcontrol *kctl;
937 struct snd_kcontrol_volatile *vd;
938 int result;
939
940 if (copy_from_user(&id, _id, sizeof(id)))
941 return -EFAULT;
942 down_write(&card->controls_rwsem);
943 kctl = snd_ctl_find_id(card, &id);
944 if (kctl == NULL) {
945 result = -ENOENT;
946 } else {
947 vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)];
948 if (vd->owner != NULL)
949 result = -EBUSY;
950 else {
951 vd->owner = file;
952 result = 0;
953 }
954 }
955 up_write(&card->controls_rwsem);
956 return result;
957}
958
959static int snd_ctl_elem_unlock(struct snd_ctl_file *file,
960 struct snd_ctl_elem_id __user *_id)
961{
962 struct snd_card *card = file->card;
963 struct snd_ctl_elem_id id;
964 struct snd_kcontrol *kctl;
965 struct snd_kcontrol_volatile *vd;
966 int result;
967
968 if (copy_from_user(&id, _id, sizeof(id)))
969 return -EFAULT;
970 down_write(&card->controls_rwsem);
971 kctl = snd_ctl_find_id(card, &id);
972 if (kctl == NULL) {
973 result = -ENOENT;
974 } else {
975 vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)];
976 if (vd->owner == NULL)
977 result = -EINVAL;
978 else if (vd->owner != file)
979 result = -EPERM;
980 else {
981 vd->owner = NULL;
982 result = 0;
983 }
984 }
985 up_write(&card->controls_rwsem);
986 return result;
987}
988
989struct user_element {
990 struct snd_ctl_elem_info info;
991 void *elem_data;
992 unsigned long elem_data_size;
993 void *tlv_data;
994 unsigned long tlv_data_size;
995 void *priv_data;
996};
997
998static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol,
999 struct snd_ctl_elem_info *uinfo)
1000{
1001 struct user_element *ue = kcontrol->private_data;
1002
1003 *uinfo = ue->info;
1004 return 0;
1005}
1006
1007static int snd_ctl_elem_user_enum_info(struct snd_kcontrol *kcontrol,
1008 struct snd_ctl_elem_info *uinfo)
1009{
1010 struct user_element *ue = kcontrol->private_data;
1011 const char *names;
1012 unsigned int item;
1013
1014 item = uinfo->value.enumerated.item;
1015
1016 *uinfo = ue->info;
1017
1018 item = min(item, uinfo->value.enumerated.items - 1);
1019 uinfo->value.enumerated.item = item;
1020
1021 names = ue->priv_data;
1022 for (; item > 0; --item)
1023 names += strlen(names) + 1;
1024 strcpy(uinfo->value.enumerated.name, names);
1025
1026 return 0;
1027}
1028
1029static int snd_ctl_elem_user_get(struct snd_kcontrol *kcontrol,
1030 struct snd_ctl_elem_value *ucontrol)
1031{
1032 struct user_element *ue = kcontrol->private_data;
1033
1034 memcpy(&ucontrol->value, ue->elem_data, ue->elem_data_size);
1035 return 0;
1036}
1037
1038static int snd_ctl_elem_user_put(struct snd_kcontrol *kcontrol,
1039 struct snd_ctl_elem_value *ucontrol)
1040{
1041 int change;
1042 struct user_element *ue = kcontrol->private_data;
1043
1044 change = memcmp(&ucontrol->value, ue->elem_data, ue->elem_data_size) != 0;
1045 if (change)
1046 memcpy(ue->elem_data, &ucontrol->value, ue->elem_data_size);
1047 return change;
1048}
1049
1050static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol,
1051 int op_flag,
1052 unsigned int size,
1053 unsigned int __user *tlv)
1054{
1055 struct user_element *ue = kcontrol->private_data;
1056 int change = 0;
1057 void *new_data;
1058
1059 if (op_flag > 0) {
1060 if (size > 1024 * 128)
1061 return -EINVAL;
1062
1063 new_data = memdup_user(tlv, size);
1064 if (IS_ERR(new_data))
1065 return PTR_ERR(new_data);
1066 change = ue->tlv_data_size != size;
1067 if (!change)
1068 change = memcmp(ue->tlv_data, new_data, size);
1069 kfree(ue->tlv_data);
1070 ue->tlv_data = new_data;
1071 ue->tlv_data_size = size;
1072 } else {
1073 if (! ue->tlv_data_size || ! ue->tlv_data)
1074 return -ENXIO;
1075 if (size < ue->tlv_data_size)
1076 return -ENOSPC;
1077 if (copy_to_user(tlv, ue->tlv_data, ue->tlv_data_size))
1078 return -EFAULT;
1079 }
1080 return change;
1081}
1082
1083static int snd_ctl_elem_init_enum_names(struct user_element *ue)
1084{
1085 char *names, *p;
1086 size_t buf_len, name_len;
1087 unsigned int i;
1088 const uintptr_t user_ptrval = ue->info.value.enumerated.names_ptr;
1089
1090 if (ue->info.value.enumerated.names_length > 64 * 1024)
1091 return -EINVAL;
1092
1093 names = memdup_user((const void __user *)user_ptrval,
1094 ue->info.value.enumerated.names_length);
1095 if (IS_ERR(names))
1096 return PTR_ERR(names);
1097
1098
1099 buf_len = ue->info.value.enumerated.names_length;
1100 p = names;
1101 for (i = 0; i < ue->info.value.enumerated.items; ++i) {
1102 name_len = strnlen(p, buf_len);
1103 if (name_len == 0 || name_len >= 64 || name_len == buf_len) {
1104 kfree(names);
1105 return -EINVAL;
1106 }
1107 p += name_len + 1;
1108 buf_len -= name_len + 1;
1109 }
1110
1111 ue->priv_data = names;
1112 ue->info.value.enumerated.names_ptr = 0;
1113
1114 return 0;
1115}
1116
1117static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol)
1118{
1119 struct user_element *ue = kcontrol->private_data;
1120
1121 kfree(ue->tlv_data);
1122 kfree(ue->priv_data);
1123 kfree(ue);
1124}
1125
1126static int snd_ctl_elem_add(struct snd_ctl_file *file,
1127 struct snd_ctl_elem_info *info, int replace)
1128{
1129 struct snd_card *card = file->card;
1130 struct snd_kcontrol kctl, *_kctl;
1131 unsigned int access;
1132 long private_size;
1133 struct user_element *ue;
1134 int idx, err;
1135
1136 if (!replace && card->user_ctl_count >= MAX_USER_CONTROLS)
1137 return -ENOMEM;
1138 if (info->count < 1)
1139 return -EINVAL;
1140 access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
1141 (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|
1142 SNDRV_CTL_ELEM_ACCESS_INACTIVE|
1143 SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE));
1144 info->id.numid = 0;
1145 memset(&kctl, 0, sizeof(kctl));
1146 down_write(&card->controls_rwsem);
1147 _kctl = snd_ctl_find_id(card, &info->id);
1148 err = 0;
1149 if (_kctl) {
1150 if (replace)
1151 err = snd_ctl_remove(card, _kctl);
1152 else
1153 err = -EBUSY;
1154 } else {
1155 if (replace)
1156 err = -ENOENT;
1157 }
1158 up_write(&card->controls_rwsem);
1159 if (err < 0)
1160 return err;
1161 memcpy(&kctl.id, &info->id, sizeof(info->id));
1162 kctl.count = info->owner ? info->owner : 1;
1163 access |= SNDRV_CTL_ELEM_ACCESS_USER;
1164 if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED)
1165 kctl.info = snd_ctl_elem_user_enum_info;
1166 else
1167 kctl.info = snd_ctl_elem_user_info;
1168 if (access & SNDRV_CTL_ELEM_ACCESS_READ)
1169 kctl.get = snd_ctl_elem_user_get;
1170 if (access & SNDRV_CTL_ELEM_ACCESS_WRITE)
1171 kctl.put = snd_ctl_elem_user_put;
1172 if (access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) {
1173 kctl.tlv.c = snd_ctl_elem_user_tlv;
1174 access |= SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
1175 }
1176 switch (info->type) {
1177 case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
1178 case SNDRV_CTL_ELEM_TYPE_INTEGER:
1179 private_size = sizeof(long);
1180 if (info->count > 128)
1181 return -EINVAL;
1182 break;
1183 case SNDRV_CTL_ELEM_TYPE_INTEGER64:
1184 private_size = sizeof(long long);
1185 if (info->count > 64)
1186 return -EINVAL;
1187 break;
1188 case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
1189 private_size = sizeof(unsigned int);
1190 if (info->count > 128 || info->value.enumerated.items == 0)
1191 return -EINVAL;
1192 break;
1193 case SNDRV_CTL_ELEM_TYPE_BYTES:
1194 private_size = sizeof(unsigned char);
1195 if (info->count > 512)
1196 return -EINVAL;
1197 break;
1198 case SNDRV_CTL_ELEM_TYPE_IEC958:
1199 private_size = sizeof(struct snd_aes_iec958);
1200 if (info->count != 1)
1201 return -EINVAL;
1202 break;
1203 default:
1204 return -EINVAL;
1205 }
1206 private_size *= info->count;
1207 ue = kzalloc(sizeof(struct user_element) + private_size, GFP_KERNEL);
1208 if (ue == NULL)
1209 return -ENOMEM;
1210 ue->info = *info;
1211 ue->info.access = 0;
1212 ue->elem_data = (char *)ue + sizeof(*ue);
1213 ue->elem_data_size = private_size;
1214 if (ue->info.type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
1215 err = snd_ctl_elem_init_enum_names(ue);
1216 if (err < 0) {
1217 kfree(ue);
1218 return err;
1219 }
1220 }
1221 kctl.private_free = snd_ctl_elem_user_free;
1222 _kctl = snd_ctl_new(&kctl, access);
1223 if (_kctl == NULL) {
1224 kfree(ue->priv_data);
1225 kfree(ue);
1226 return -ENOMEM;
1227 }
1228 _kctl->private_data = ue;
1229 for (idx = 0; idx < _kctl->count; idx++)
1230 _kctl->vd[idx].owner = file;
1231 err = snd_ctl_add(card, _kctl);
1232 if (err < 0)
1233 return err;
1234
1235 down_write(&card->controls_rwsem);
1236 card->user_ctl_count++;
1237 up_write(&card->controls_rwsem);
1238
1239 return 0;
1240}
1241
1242static int snd_ctl_elem_add_user(struct snd_ctl_file *file,
1243 struct snd_ctl_elem_info __user *_info, int replace)
1244{
1245 struct snd_ctl_elem_info info;
1246 if (copy_from_user(&info, _info, sizeof(info)))
1247 return -EFAULT;
1248 return snd_ctl_elem_add(file, &info, replace);
1249}
1250
1251static int snd_ctl_elem_remove(struct snd_ctl_file *file,
1252 struct snd_ctl_elem_id __user *_id)
1253{
1254 struct snd_ctl_elem_id id;
1255
1256 if (copy_from_user(&id, _id, sizeof(id)))
1257 return -EFAULT;
1258 return snd_ctl_remove_user_ctl(file, &id);
1259}
1260
1261static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr)
1262{
1263 int subscribe;
1264 if (get_user(subscribe, ptr))
1265 return -EFAULT;
1266 if (subscribe < 0) {
1267 subscribe = file->subscribed;
1268 if (put_user(subscribe, ptr))
1269 return -EFAULT;
1270 return 0;
1271 }
1272 if (subscribe) {
1273 file->subscribed = 1;
1274 return 0;
1275 } else if (file->subscribed) {
1276 snd_ctl_empty_read_queue(file);
1277 file->subscribed = 0;
1278 }
1279 return 0;
1280}
1281
1282static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
1283 struct snd_ctl_tlv __user *_tlv,
1284 int op_flag)
1285{
1286 struct snd_card *card = file->card;
1287 struct snd_ctl_tlv tlv;
1288 struct snd_kcontrol *kctl;
1289 struct snd_kcontrol_volatile *vd;
1290 unsigned int len;
1291 int err = 0;
1292
1293 if (copy_from_user(&tlv, _tlv, sizeof(tlv)))
1294 return -EFAULT;
1295 if (tlv.length < sizeof(unsigned int) * 2)
1296 return -EINVAL;
1297 down_read(&card->controls_rwsem);
1298 kctl = snd_ctl_find_numid(card, tlv.numid);
1299 if (kctl == NULL) {
1300 err = -ENOENT;
1301 goto __kctl_end;
1302 }
1303 if (kctl->tlv.p == NULL) {
1304 err = -ENXIO;
1305 goto __kctl_end;
1306 }
1307 vd = &kctl->vd[tlv.numid - kctl->id.numid];
1308 if ((op_flag == 0 && (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) == 0) ||
1309 (op_flag > 0 && (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) == 0) ||
1310 (op_flag < 0 && (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND) == 0)) {
1311 err = -ENXIO;
1312 goto __kctl_end;
1313 }
1314 if (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
1315 if (vd->owner != NULL && vd->owner != file) {
1316 err = -EPERM;
1317 goto __kctl_end;
1318 }
1319 err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv);
1320 if (err > 0) {
1321 up_read(&card->controls_rwsem);
1322 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &kctl->id);
1323 return 0;
1324 }
1325 } else {
1326 if (op_flag) {
1327 err = -ENXIO;
1328 goto __kctl_end;
1329 }
1330 len = kctl->tlv.p[1] + 2 * sizeof(unsigned int);
1331 if (tlv.length < len) {
1332 err = -ENOMEM;
1333 goto __kctl_end;
1334 }
1335 if (copy_to_user(_tlv->tlv, kctl->tlv.p, len))
1336 err = -EFAULT;
1337 }
1338 __kctl_end:
1339 up_read(&card->controls_rwsem);
1340 return err;
1341}
1342
1343static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1344{
1345 struct snd_ctl_file *ctl;
1346 struct snd_card *card;
1347 struct snd_kctl_ioctl *p;
1348 void __user *argp = (void __user *)arg;
1349 int __user *ip = argp;
1350 int err;
1351
1352 ctl = file->private_data;
1353 card = ctl->card;
1354 if (snd_BUG_ON(!card))
1355 return -ENXIO;
1356 switch (cmd) {
1357 case SNDRV_CTL_IOCTL_PVERSION:
1358 return put_user(SNDRV_CTL_VERSION, ip) ? -EFAULT : 0;
1359 case SNDRV_CTL_IOCTL_CARD_INFO:
1360 return snd_ctl_card_info(card, ctl, cmd, argp);
1361 case SNDRV_CTL_IOCTL_ELEM_LIST:
1362 return snd_ctl_elem_list(card, argp);
1363 case SNDRV_CTL_IOCTL_ELEM_INFO:
1364 return snd_ctl_elem_info_user(ctl, argp);
1365 case SNDRV_CTL_IOCTL_ELEM_READ:
1366 return snd_ctl_elem_read_user(card, argp);
1367 case SNDRV_CTL_IOCTL_ELEM_WRITE:
1368 return snd_ctl_elem_write_user(ctl, argp);
1369 case SNDRV_CTL_IOCTL_ELEM_LOCK:
1370 return snd_ctl_elem_lock(ctl, argp);
1371 case SNDRV_CTL_IOCTL_ELEM_UNLOCK:
1372 return snd_ctl_elem_unlock(ctl, argp);
1373 case SNDRV_CTL_IOCTL_ELEM_ADD:
1374 return snd_ctl_elem_add_user(ctl, argp, 0);
1375 case SNDRV_CTL_IOCTL_ELEM_REPLACE:
1376 return snd_ctl_elem_add_user(ctl, argp, 1);
1377 case SNDRV_CTL_IOCTL_ELEM_REMOVE:
1378 return snd_ctl_elem_remove(ctl, argp);
1379 case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
1380 return snd_ctl_subscribe_events(ctl, ip);
1381 case SNDRV_CTL_IOCTL_TLV_READ:
1382 return snd_ctl_tlv_ioctl(ctl, argp, 0);
1383 case SNDRV_CTL_IOCTL_TLV_WRITE:
1384 return snd_ctl_tlv_ioctl(ctl, argp, 1);
1385 case SNDRV_CTL_IOCTL_TLV_COMMAND:
1386 return snd_ctl_tlv_ioctl(ctl, argp, -1);
1387 case SNDRV_CTL_IOCTL_POWER:
1388 return -ENOPROTOOPT;
1389 case SNDRV_CTL_IOCTL_POWER_STATE:
1390#ifdef CONFIG_PM
1391 return put_user(card->power_state, ip) ? -EFAULT : 0;
1392#else
1393 return put_user(SNDRV_CTL_POWER_D0, ip) ? -EFAULT : 0;
1394#endif
1395 }
1396 down_read(&snd_ioctl_rwsem);
1397 list_for_each_entry(p, &snd_control_ioctls, list) {
1398 err = p->fioctl(card, ctl, cmd, arg);
1399 if (err != -ENOIOCTLCMD) {
1400 up_read(&snd_ioctl_rwsem);
1401 return err;
1402 }
1403 }
1404 up_read(&snd_ioctl_rwsem);
1405 snd_printdd("unknown ioctl = 0x%x\n", cmd);
1406 return -ENOTTY;
1407}
1408
1409static ssize_t snd_ctl_read(struct file *file, char __user *buffer,
1410 size_t count, loff_t * offset)
1411{
1412 struct snd_ctl_file *ctl;
1413 int err = 0;
1414 ssize_t result = 0;
1415
1416 ctl = file->private_data;
1417 if (snd_BUG_ON(!ctl || !ctl->card))
1418 return -ENXIO;
1419 if (!ctl->subscribed)
1420 return -EBADFD;
1421 if (count < sizeof(struct snd_ctl_event))
1422 return -EINVAL;
1423 spin_lock_irq(&ctl->read_lock);
1424 while (count >= sizeof(struct snd_ctl_event)) {
1425 struct snd_ctl_event ev;
1426 struct snd_kctl_event *kev;
1427 while (list_empty(&ctl->events)) {
1428 wait_queue_t wait;
1429 if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
1430 err = -EAGAIN;
1431 goto __end_lock;
1432 }
1433 init_waitqueue_entry(&wait, current);
1434 add_wait_queue(&ctl->change_sleep, &wait);
1435 set_current_state(TASK_INTERRUPTIBLE);
1436 spin_unlock_irq(&ctl->read_lock);
1437 schedule();
1438 remove_wait_queue(&ctl->change_sleep, &wait);
1439 if (ctl->card->shutdown)
1440 return -ENODEV;
1441 if (signal_pending(current))
1442 return -ERESTARTSYS;
1443 spin_lock_irq(&ctl->read_lock);
1444 }
1445 kev = snd_kctl_event(ctl->events.next);
1446 ev.type = SNDRV_CTL_EVENT_ELEM;
1447 ev.data.elem.mask = kev->mask;
1448 ev.data.elem.id = kev->id;
1449 list_del(&kev->list);
1450 spin_unlock_irq(&ctl->read_lock);
1451 kfree(kev);
1452 if (copy_to_user(buffer, &ev, sizeof(struct snd_ctl_event))) {
1453 err = -EFAULT;
1454 goto __end;
1455 }
1456 spin_lock_irq(&ctl->read_lock);
1457 buffer += sizeof(struct snd_ctl_event);
1458 count -= sizeof(struct snd_ctl_event);
1459 result += sizeof(struct snd_ctl_event);
1460 }
1461 __end_lock:
1462 spin_unlock_irq(&ctl->read_lock);
1463 __end:
1464 return result > 0 ? result : err;
1465}
1466
1467static unsigned int snd_ctl_poll(struct file *file, poll_table * wait)
1468{
1469 unsigned int mask;
1470 struct snd_ctl_file *ctl;
1471
1472 ctl = file->private_data;
1473 if (!ctl->subscribed)
1474 return 0;
1475 poll_wait(file, &ctl->change_sleep, wait);
1476
1477 mask = 0;
1478 if (!list_empty(&ctl->events))
1479 mask |= POLLIN | POLLRDNORM;
1480
1481 return mask;
1482}
1483
1484
1485
1486
1487
1488static int _snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head *lists)
1489{
1490 struct snd_kctl_ioctl *pn;
1491
1492 pn = kzalloc(sizeof(struct snd_kctl_ioctl), GFP_KERNEL);
1493 if (pn == NULL)
1494 return -ENOMEM;
1495 pn->fioctl = fcn;
1496 down_write(&snd_ioctl_rwsem);
1497 list_add_tail(&pn->list, lists);
1498 up_write(&snd_ioctl_rwsem);
1499 return 0;
1500}
1501
1502int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn)
1503{
1504 return _snd_ctl_register_ioctl(fcn, &snd_control_ioctls);
1505}
1506
1507EXPORT_SYMBOL(snd_ctl_register_ioctl);
1508
1509#ifdef CONFIG_COMPAT
1510int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn)
1511{
1512 return _snd_ctl_register_ioctl(fcn, &snd_control_compat_ioctls);
1513}
1514
1515EXPORT_SYMBOL(snd_ctl_register_ioctl_compat);
1516#endif
1517
1518
1519
1520
1521static int _snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn,
1522 struct list_head *lists)
1523{
1524 struct snd_kctl_ioctl *p;
1525
1526 if (snd_BUG_ON(!fcn))
1527 return -EINVAL;
1528 down_write(&snd_ioctl_rwsem);
1529 list_for_each_entry(p, lists, list) {
1530 if (p->fioctl == fcn) {
1531 list_del(&p->list);
1532 up_write(&snd_ioctl_rwsem);
1533 kfree(p);
1534 return 0;
1535 }
1536 }
1537 up_write(&snd_ioctl_rwsem);
1538 snd_BUG();
1539 return -EINVAL;
1540}
1541
1542int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn)
1543{
1544 return _snd_ctl_unregister_ioctl(fcn, &snd_control_ioctls);
1545}
1546
1547EXPORT_SYMBOL(snd_ctl_unregister_ioctl);
1548
1549#ifdef CONFIG_COMPAT
1550int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn)
1551{
1552 return _snd_ctl_unregister_ioctl(fcn, &snd_control_compat_ioctls);
1553}
1554
1555EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat);
1556#endif
1557
1558static int snd_ctl_fasync(int fd, struct file * file, int on)
1559{
1560 struct snd_ctl_file *ctl;
1561
1562 ctl = file->private_data;
1563 return fasync_helper(fd, file, on, &ctl->fasync);
1564}
1565
1566
1567
1568
1569#ifdef CONFIG_COMPAT
1570#include "control_compat.c"
1571#else
1572#define snd_ctl_ioctl_compat NULL
1573#endif
1574
1575
1576
1577
1578
1579static const struct file_operations snd_ctl_f_ops =
1580{
1581 .owner = THIS_MODULE,
1582 .read = snd_ctl_read,
1583 .open = snd_ctl_open,
1584 .release = snd_ctl_release,
1585 .llseek = no_llseek,
1586 .poll = snd_ctl_poll,
1587 .unlocked_ioctl = snd_ctl_ioctl,
1588 .compat_ioctl = snd_ctl_ioctl_compat,
1589 .fasync = snd_ctl_fasync,
1590};
1591
1592
1593
1594
1595static int snd_ctl_dev_register(struct snd_device *device)
1596{
1597 struct snd_card *card = device->device_data;
1598 int err, cardnum;
1599 char name[16];
1600
1601 if (snd_BUG_ON(!card))
1602 return -ENXIO;
1603 cardnum = card->number;
1604 if (snd_BUG_ON(cardnum < 0 || cardnum >= SNDRV_CARDS))
1605 return -ENXIO;
1606 sprintf(name, "controlC%i", cardnum);
1607 if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,
1608 &snd_ctl_f_ops, card, name)) < 0)
1609 return err;
1610 return 0;
1611}
1612
1613
1614
1615
1616static int snd_ctl_dev_disconnect(struct snd_device *device)
1617{
1618 struct snd_card *card = device->device_data;
1619 struct snd_ctl_file *ctl;
1620 int err, cardnum;
1621
1622 if (snd_BUG_ON(!card))
1623 return -ENXIO;
1624 cardnum = card->number;
1625 if (snd_BUG_ON(cardnum < 0 || cardnum >= SNDRV_CARDS))
1626 return -ENXIO;
1627
1628 read_lock(&card->ctl_files_rwlock);
1629 list_for_each_entry(ctl, &card->ctl_files, list) {
1630 wake_up(&ctl->change_sleep);
1631 kill_fasync(&ctl->fasync, SIGIO, POLL_ERR);
1632 }
1633 read_unlock(&card->ctl_files_rwlock);
1634
1635 if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL,
1636 card, -1)) < 0)
1637 return err;
1638 return 0;
1639}
1640
1641
1642
1643
1644static int snd_ctl_dev_free(struct snd_device *device)
1645{
1646 struct snd_card *card = device->device_data;
1647 struct snd_kcontrol *control;
1648
1649 down_write(&card->controls_rwsem);
1650 while (!list_empty(&card->controls)) {
1651 control = snd_kcontrol(card->controls.next);
1652 snd_ctl_remove(card, control);
1653 }
1654 up_write(&card->controls_rwsem);
1655 return 0;
1656}
1657
1658
1659
1660
1661
1662int snd_ctl_create(struct snd_card *card)
1663{
1664 static struct snd_device_ops ops = {
1665 .dev_free = snd_ctl_dev_free,
1666 .dev_register = snd_ctl_dev_register,
1667 .dev_disconnect = snd_ctl_dev_disconnect,
1668 };
1669
1670 if (snd_BUG_ON(!card))
1671 return -ENXIO;
1672 return snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops);
1673}
1674
1675
1676
1677
1678int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol,
1679 struct snd_ctl_elem_info *uinfo)
1680{
1681 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1682 uinfo->count = 1;
1683 uinfo->value.integer.min = 0;
1684 uinfo->value.integer.max = 1;
1685 return 0;
1686}
1687
1688EXPORT_SYMBOL(snd_ctl_boolean_mono_info);
1689
1690int snd_ctl_boolean_stereo_info(struct snd_kcontrol *kcontrol,
1691 struct snd_ctl_elem_info *uinfo)
1692{
1693 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1694 uinfo->count = 2;
1695 uinfo->value.integer.min = 0;
1696 uinfo->value.integer.max = 1;
1697 return 0;
1698}
1699
1700EXPORT_SYMBOL(snd_ctl_boolean_stereo_info);
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713int snd_ctl_enum_info(struct snd_ctl_elem_info *info, unsigned int channels,
1714 unsigned int items, const char *const names[])
1715{
1716 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1717 info->count = channels;
1718 info->value.enumerated.items = items;
1719 if (info->value.enumerated.item >= items)
1720 info->value.enumerated.item = items - 1;
1721 strlcpy(info->value.enumerated.name,
1722 names[info->value.enumerated.item],
1723 sizeof(info->value.enumerated.name));
1724 return 0;
1725}
1726EXPORT_SYMBOL(snd_ctl_enum_info);
1727