OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [sound/] [core/] [control.c] - Blame information for rev 3

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.