Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/core/init.c
10814 views
1
/*
2
* Initialization routines
3
* Copyright (c) by Jaroslav Kysela <[email protected]>
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 <linux/init.h>
23
#include <linux/sched.h>
24
#include <linux/file.h>
25
#include <linux/slab.h>
26
#include <linux/time.h>
27
#include <linux/ctype.h>
28
#include <linux/pm.h>
29
30
#include <sound/core.h>
31
#include <sound/control.h>
32
#include <sound/info.h>
33
34
/* monitor files for graceful shutdown (hotplug) */
35
struct snd_monitor_file {
36
struct file *file;
37
const struct file_operations *disconnected_f_op;
38
struct list_head shutdown_list; /* still need to shutdown */
39
struct list_head list; /* link of monitor files */
40
};
41
42
static DEFINE_SPINLOCK(shutdown_lock);
43
static LIST_HEAD(shutdown_files);
44
45
static const struct file_operations snd_shutdown_f_ops;
46
47
static unsigned int snd_cards_lock; /* locked for registering/using */
48
struct snd_card *snd_cards[SNDRV_CARDS];
49
EXPORT_SYMBOL(snd_cards);
50
51
static DEFINE_MUTEX(snd_card_mutex);
52
53
static char *slots[SNDRV_CARDS];
54
module_param_array(slots, charp, NULL, 0444);
55
MODULE_PARM_DESC(slots, "Module names assigned to the slots.");
56
57
/* return non-zero if the given index is reserved for the given
58
* module via slots option
59
*/
60
static int module_slot_match(struct module *module, int idx)
61
{
62
int match = 1;
63
#ifdef MODULE
64
const char *s1, *s2;
65
66
if (!module || !module->name || !slots[idx])
67
return 0;
68
69
s1 = module->name;
70
s2 = slots[idx];
71
if (*s2 == '!') {
72
match = 0; /* negative match */
73
s2++;
74
}
75
/* compare module name strings
76
* hyphens are handled as equivalent with underscore
77
*/
78
for (;;) {
79
char c1 = *s1++;
80
char c2 = *s2++;
81
if (c1 == '-')
82
c1 = '_';
83
if (c2 == '-')
84
c2 = '_';
85
if (c1 != c2)
86
return !match;
87
if (!c1)
88
break;
89
}
90
#endif /* MODULE */
91
return match;
92
}
93
94
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
95
int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag);
96
EXPORT_SYMBOL(snd_mixer_oss_notify_callback);
97
#endif
98
99
#ifdef CONFIG_PROC_FS
100
static void snd_card_id_read(struct snd_info_entry *entry,
101
struct snd_info_buffer *buffer)
102
{
103
snd_iprintf(buffer, "%s\n", entry->card->id);
104
}
105
106
static inline int init_info_for_card(struct snd_card *card)
107
{
108
int err;
109
struct snd_info_entry *entry;
110
111
if ((err = snd_info_card_register(card)) < 0) {
112
snd_printd("unable to create card info\n");
113
return err;
114
}
115
if ((entry = snd_info_create_card_entry(card, "id", card->proc_root)) == NULL) {
116
snd_printd("unable to create card entry\n");
117
return err;
118
}
119
entry->c.text.read = snd_card_id_read;
120
if (snd_info_register(entry) < 0) {
121
snd_info_free_entry(entry);
122
entry = NULL;
123
}
124
card->proc_id = entry;
125
return 0;
126
}
127
#else /* !CONFIG_PROC_FS */
128
#define init_info_for_card(card)
129
#endif
130
131
/**
132
* snd_card_create - create and initialize a soundcard structure
133
* @idx: card index (address) [0 ... (SNDRV_CARDS-1)]
134
* @xid: card identification (ASCII string)
135
* @module: top level module for locking
136
* @extra_size: allocate this extra size after the main soundcard structure
137
* @card_ret: the pointer to store the created card instance
138
*
139
* Creates and initializes a soundcard structure.
140
*
141
* The function allocates snd_card instance via kzalloc with the given
142
* space for the driver to use freely. The allocated struct is stored
143
* in the given card_ret pointer.
144
*
145
* Returns zero if successful or a negative error code.
146
*/
147
int snd_card_create(int idx, const char *xid,
148
struct module *module, int extra_size,
149
struct snd_card **card_ret)
150
{
151
struct snd_card *card;
152
int err, idx2;
153
154
if (snd_BUG_ON(!card_ret))
155
return -EINVAL;
156
*card_ret = NULL;
157
158
if (extra_size < 0)
159
extra_size = 0;
160
card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);
161
if (!card)
162
return -ENOMEM;
163
if (xid)
164
strlcpy(card->id, xid, sizeof(card->id));
165
err = 0;
166
mutex_lock(&snd_card_mutex);
167
if (idx < 0) {
168
for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
169
/* idx == -1 == 0xffff means: take any free slot */
170
if (~snd_cards_lock & idx & 1<<idx2) {
171
if (module_slot_match(module, idx2)) {
172
idx = idx2;
173
break;
174
}
175
}
176
}
177
if (idx < 0) {
178
for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
179
/* idx == -1 == 0xffff means: take any free slot */
180
if (~snd_cards_lock & idx & 1<<idx2) {
181
if (!slots[idx2] || !*slots[idx2]) {
182
idx = idx2;
183
break;
184
}
185
}
186
}
187
if (idx < 0)
188
err = -ENODEV;
189
else if (idx < snd_ecards_limit) {
190
if (snd_cards_lock & (1 << idx))
191
err = -EBUSY; /* invalid */
192
} else if (idx >= SNDRV_CARDS)
193
err = -ENODEV;
194
if (err < 0) {
195
mutex_unlock(&snd_card_mutex);
196
snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i), error: %d\n",
197
idx, snd_ecards_limit - 1, err);
198
goto __error;
199
}
200
snd_cards_lock |= 1 << idx; /* lock it */
201
if (idx >= snd_ecards_limit)
202
snd_ecards_limit = idx + 1; /* increase the limit */
203
mutex_unlock(&snd_card_mutex);
204
card->number = idx;
205
card->module = module;
206
INIT_LIST_HEAD(&card->devices);
207
init_rwsem(&card->controls_rwsem);
208
rwlock_init(&card->ctl_files_rwlock);
209
INIT_LIST_HEAD(&card->controls);
210
INIT_LIST_HEAD(&card->ctl_files);
211
spin_lock_init(&card->files_lock);
212
INIT_LIST_HEAD(&card->files_list);
213
init_waitqueue_head(&card->shutdown_sleep);
214
#ifdef CONFIG_PM
215
mutex_init(&card->power_lock);
216
init_waitqueue_head(&card->power_sleep);
217
#endif
218
/* the control interface cannot be accessed from the user space until */
219
/* snd_cards_bitmask and snd_cards are set with snd_card_register */
220
err = snd_ctl_create(card);
221
if (err < 0) {
222
snd_printk(KERN_ERR "unable to register control minors\n");
223
goto __error;
224
}
225
err = snd_info_card_create(card);
226
if (err < 0) {
227
snd_printk(KERN_ERR "unable to create card info\n");
228
goto __error_ctl;
229
}
230
if (extra_size > 0)
231
card->private_data = (char *)card + sizeof(struct snd_card);
232
*card_ret = card;
233
return 0;
234
235
__error_ctl:
236
snd_device_free_all(card, SNDRV_DEV_CMD_PRE);
237
__error:
238
kfree(card);
239
return err;
240
}
241
EXPORT_SYMBOL(snd_card_create);
242
243
/* return non-zero if a card is already locked */
244
int snd_card_locked(int card)
245
{
246
int locked;
247
248
mutex_lock(&snd_card_mutex);
249
locked = snd_cards_lock & (1 << card);
250
mutex_unlock(&snd_card_mutex);
251
return locked;
252
}
253
254
static loff_t snd_disconnect_llseek(struct file *file, loff_t offset, int orig)
255
{
256
return -ENODEV;
257
}
258
259
static ssize_t snd_disconnect_read(struct file *file, char __user *buf,
260
size_t count, loff_t *offset)
261
{
262
return -ENODEV;
263
}
264
265
static ssize_t snd_disconnect_write(struct file *file, const char __user *buf,
266
size_t count, loff_t *offset)
267
{
268
return -ENODEV;
269
}
270
271
static int snd_disconnect_release(struct inode *inode, struct file *file)
272
{
273
struct snd_monitor_file *df = NULL, *_df;
274
275
spin_lock(&shutdown_lock);
276
list_for_each_entry(_df, &shutdown_files, shutdown_list) {
277
if (_df->file == file) {
278
df = _df;
279
list_del_init(&df->shutdown_list);
280
break;
281
}
282
}
283
spin_unlock(&shutdown_lock);
284
285
if (likely(df)) {
286
if ((file->f_flags & FASYNC) && df->disconnected_f_op->fasync)
287
df->disconnected_f_op->fasync(-1, file, 0);
288
return df->disconnected_f_op->release(inode, file);
289
}
290
291
panic("%s(%p, %p) failed!", __func__, inode, file);
292
}
293
294
static unsigned int snd_disconnect_poll(struct file * file, poll_table * wait)
295
{
296
return POLLERR | POLLNVAL;
297
}
298
299
static long snd_disconnect_ioctl(struct file *file,
300
unsigned int cmd, unsigned long arg)
301
{
302
return -ENODEV;
303
}
304
305
static int snd_disconnect_mmap(struct file *file, struct vm_area_struct *vma)
306
{
307
return -ENODEV;
308
}
309
310
static int snd_disconnect_fasync(int fd, struct file *file, int on)
311
{
312
return -ENODEV;
313
}
314
315
static const struct file_operations snd_shutdown_f_ops =
316
{
317
.owner = THIS_MODULE,
318
.llseek = snd_disconnect_llseek,
319
.read = snd_disconnect_read,
320
.write = snd_disconnect_write,
321
.release = snd_disconnect_release,
322
.poll = snd_disconnect_poll,
323
.unlocked_ioctl = snd_disconnect_ioctl,
324
#ifdef CONFIG_COMPAT
325
.compat_ioctl = snd_disconnect_ioctl,
326
#endif
327
.mmap = snd_disconnect_mmap,
328
.fasync = snd_disconnect_fasync
329
};
330
331
/**
332
* snd_card_disconnect - disconnect all APIs from the file-operations (user space)
333
* @card: soundcard structure
334
*
335
* Disconnects all APIs from the file-operations (user space).
336
*
337
* Returns zero, otherwise a negative error code.
338
*
339
* Note: The current implementation replaces all active file->f_op with special
340
* dummy file operations (they do nothing except release).
341
*/
342
int snd_card_disconnect(struct snd_card *card)
343
{
344
struct snd_monitor_file *mfile;
345
int err;
346
347
if (!card)
348
return -EINVAL;
349
350
spin_lock(&card->files_lock);
351
if (card->shutdown) {
352
spin_unlock(&card->files_lock);
353
return 0;
354
}
355
card->shutdown = 1;
356
spin_unlock(&card->files_lock);
357
358
/* phase 1: disable fops (user space) operations for ALSA API */
359
mutex_lock(&snd_card_mutex);
360
snd_cards[card->number] = NULL;
361
snd_cards_lock &= ~(1 << card->number);
362
mutex_unlock(&snd_card_mutex);
363
364
/* phase 2: replace file->f_op with special dummy operations */
365
366
spin_lock(&card->files_lock);
367
list_for_each_entry(mfile, &card->files_list, list) {
368
/* it's critical part, use endless loop */
369
/* we have no room to fail */
370
mfile->disconnected_f_op = mfile->file->f_op;
371
372
spin_lock(&shutdown_lock);
373
list_add(&mfile->shutdown_list, &shutdown_files);
374
spin_unlock(&shutdown_lock);
375
376
mfile->file->f_op = &snd_shutdown_f_ops;
377
fops_get(mfile->file->f_op);
378
}
379
spin_unlock(&card->files_lock);
380
381
/* phase 3: notify all connected devices about disconnection */
382
/* at this point, they cannot respond to any calls except release() */
383
384
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
385
if (snd_mixer_oss_notify_callback)
386
snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_DISCONNECT);
387
#endif
388
389
/* notify all devices that we are disconnected */
390
err = snd_device_disconnect_all(card);
391
if (err < 0)
392
snd_printk(KERN_ERR "not all devices for card %i can be disconnected\n", card->number);
393
394
snd_info_card_disconnect(card);
395
if (card->card_dev) {
396
device_unregister(card->card_dev);
397
card->card_dev = NULL;
398
}
399
#ifdef CONFIG_PM
400
wake_up(&card->power_sleep);
401
#endif
402
return 0;
403
}
404
405
EXPORT_SYMBOL(snd_card_disconnect);
406
407
/**
408
* snd_card_free - frees given soundcard structure
409
* @card: soundcard structure
410
*
411
* This function releases the soundcard structure and the all assigned
412
* devices automatically. That is, you don't have to release the devices
413
* by yourself.
414
*
415
* Returns zero. Frees all associated devices and frees the control
416
* interface associated to given soundcard.
417
*/
418
static int snd_card_do_free(struct snd_card *card)
419
{
420
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
421
if (snd_mixer_oss_notify_callback)
422
snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE);
423
#endif
424
if (snd_device_free_all(card, SNDRV_DEV_CMD_PRE) < 0) {
425
snd_printk(KERN_ERR "unable to free all devices (pre)\n");
426
/* Fatal, but this situation should never occur */
427
}
428
if (snd_device_free_all(card, SNDRV_DEV_CMD_NORMAL) < 0) {
429
snd_printk(KERN_ERR "unable to free all devices (normal)\n");
430
/* Fatal, but this situation should never occur */
431
}
432
if (snd_device_free_all(card, SNDRV_DEV_CMD_POST) < 0) {
433
snd_printk(KERN_ERR "unable to free all devices (post)\n");
434
/* Fatal, but this situation should never occur */
435
}
436
if (card->private_free)
437
card->private_free(card);
438
snd_info_free_entry(card->proc_id);
439
if (snd_info_card_free(card) < 0) {
440
snd_printk(KERN_WARNING "unable to free card info\n");
441
/* Not fatal error */
442
}
443
kfree(card);
444
return 0;
445
}
446
447
int snd_card_free_when_closed(struct snd_card *card)
448
{
449
int free_now = 0;
450
int ret = snd_card_disconnect(card);
451
if (ret)
452
return ret;
453
454
spin_lock(&card->files_lock);
455
if (list_empty(&card->files_list))
456
free_now = 1;
457
else
458
card->free_on_last_close = 1;
459
spin_unlock(&card->files_lock);
460
461
if (free_now)
462
snd_card_do_free(card);
463
return 0;
464
}
465
466
EXPORT_SYMBOL(snd_card_free_when_closed);
467
468
int snd_card_free(struct snd_card *card)
469
{
470
int ret = snd_card_disconnect(card);
471
if (ret)
472
return ret;
473
474
/* wait, until all devices are ready for the free operation */
475
wait_event(card->shutdown_sleep, list_empty(&card->files_list));
476
snd_card_do_free(card);
477
return 0;
478
}
479
480
EXPORT_SYMBOL(snd_card_free);
481
482
static void snd_card_set_id_no_lock(struct snd_card *card, const char *nid)
483
{
484
int i, len, idx_flag = 0, loops = SNDRV_CARDS;
485
const char *spos, *src;
486
char *id;
487
488
if (nid == NULL) {
489
id = card->shortname;
490
spos = src = id;
491
while (*id != '\0') {
492
if (*id == ' ')
493
spos = id + 1;
494
id++;
495
}
496
} else {
497
spos = src = nid;
498
}
499
id = card->id;
500
while (*spos != '\0' && !isalnum(*spos))
501
spos++;
502
if (isdigit(*spos))
503
*id++ = isalpha(src[0]) ? src[0] : 'D';
504
while (*spos != '\0' && (size_t)(id - card->id) < sizeof(card->id) - 1) {
505
if (isalnum(*spos))
506
*id++ = *spos;
507
spos++;
508
}
509
*id = '\0';
510
511
id = card->id;
512
513
if (*id == '\0')
514
strcpy(id, "Default");
515
516
while (1) {
517
if (loops-- == 0) {
518
snd_printk(KERN_ERR "unable to set card id (%s)\n", id);
519
strcpy(card->id, card->proc_root->name);
520
return;
521
}
522
if (!snd_info_check_reserved_words(id))
523
goto __change;
524
for (i = 0; i < snd_ecards_limit; i++) {
525
if (snd_cards[i] && !strcmp(snd_cards[i]->id, id))
526
goto __change;
527
}
528
break;
529
530
__change:
531
len = strlen(id);
532
if (idx_flag) {
533
if (id[len-1] != '9')
534
id[len-1]++;
535
else
536
id[len-1] = 'A';
537
} else if ((size_t)len <= sizeof(card->id) - 3) {
538
strcat(id, "_1");
539
idx_flag++;
540
} else {
541
spos = id + len - 2;
542
if ((size_t)len <= sizeof(card->id) - 2)
543
spos++;
544
*(char *)spos++ = '_';
545
*(char *)spos++ = '1';
546
*(char *)spos++ = '\0';
547
idx_flag++;
548
}
549
}
550
}
551
552
/**
553
* snd_card_set_id - set card identification name
554
* @card: soundcard structure
555
* @nid: new identification string
556
*
557
* This function sets the card identification and checks for name
558
* collisions.
559
*/
560
void snd_card_set_id(struct snd_card *card, const char *nid)
561
{
562
/* check if user specified own card->id */
563
if (card->id[0] != '\0')
564
return;
565
mutex_lock(&snd_card_mutex);
566
snd_card_set_id_no_lock(card, nid);
567
mutex_unlock(&snd_card_mutex);
568
}
569
EXPORT_SYMBOL(snd_card_set_id);
570
571
static ssize_t
572
card_id_show_attr(struct device *dev,
573
struct device_attribute *attr, char *buf)
574
{
575
struct snd_card *card = dev_get_drvdata(dev);
576
return snprintf(buf, PAGE_SIZE, "%s\n", card ? card->id : "(null)");
577
}
578
579
static ssize_t
580
card_id_store_attr(struct device *dev, struct device_attribute *attr,
581
const char *buf, size_t count)
582
{
583
struct snd_card *card = dev_get_drvdata(dev);
584
char buf1[sizeof(card->id)];
585
size_t copy = count > sizeof(card->id) - 1 ?
586
sizeof(card->id) - 1 : count;
587
size_t idx;
588
int c;
589
590
for (idx = 0; idx < copy; idx++) {
591
c = buf[idx];
592
if (!isalnum(c) && c != '_' && c != '-')
593
return -EINVAL;
594
}
595
memcpy(buf1, buf, copy);
596
buf1[copy] = '\0';
597
mutex_lock(&snd_card_mutex);
598
if (!snd_info_check_reserved_words(buf1)) {
599
__exist:
600
mutex_unlock(&snd_card_mutex);
601
return -EEXIST;
602
}
603
for (idx = 0; idx < snd_ecards_limit; idx++) {
604
if (snd_cards[idx] && !strcmp(snd_cards[idx]->id, buf1)) {
605
if (card == snd_cards[idx])
606
goto __ok;
607
else
608
goto __exist;
609
}
610
}
611
strcpy(card->id, buf1);
612
snd_info_card_id_change(card);
613
__ok:
614
mutex_unlock(&snd_card_mutex);
615
616
return count;
617
}
618
619
static struct device_attribute card_id_attrs =
620
__ATTR(id, S_IRUGO | S_IWUSR, card_id_show_attr, card_id_store_attr);
621
622
static ssize_t
623
card_number_show_attr(struct device *dev,
624
struct device_attribute *attr, char *buf)
625
{
626
struct snd_card *card = dev_get_drvdata(dev);
627
return snprintf(buf, PAGE_SIZE, "%i\n", card ? card->number : -1);
628
}
629
630
static struct device_attribute card_number_attrs =
631
__ATTR(number, S_IRUGO, card_number_show_attr, NULL);
632
633
/**
634
* snd_card_register - register the soundcard
635
* @card: soundcard structure
636
*
637
* This function registers all the devices assigned to the soundcard.
638
* Until calling this, the ALSA control interface is blocked from the
639
* external accesses. Thus, you should call this function at the end
640
* of the initialization of the card.
641
*
642
* Returns zero otherwise a negative error code if the registration failed.
643
*/
644
int snd_card_register(struct snd_card *card)
645
{
646
int err;
647
648
if (snd_BUG_ON(!card))
649
return -EINVAL;
650
651
if (!card->card_dev) {
652
card->card_dev = device_create(sound_class, card->dev,
653
MKDEV(0, 0), card,
654
"card%i", card->number);
655
if (IS_ERR(card->card_dev))
656
card->card_dev = NULL;
657
}
658
659
if ((err = snd_device_register_all(card)) < 0)
660
return err;
661
mutex_lock(&snd_card_mutex);
662
if (snd_cards[card->number]) {
663
/* already registered */
664
mutex_unlock(&snd_card_mutex);
665
return 0;
666
}
667
snd_card_set_id_no_lock(card, card->id[0] == '\0' ? NULL : card->id);
668
snd_cards[card->number] = card;
669
mutex_unlock(&snd_card_mutex);
670
init_info_for_card(card);
671
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
672
if (snd_mixer_oss_notify_callback)
673
snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER);
674
#endif
675
if (card->card_dev) {
676
err = device_create_file(card->card_dev, &card_id_attrs);
677
if (err < 0)
678
return err;
679
err = device_create_file(card->card_dev, &card_number_attrs);
680
if (err < 0)
681
return err;
682
}
683
684
return 0;
685
}
686
687
EXPORT_SYMBOL(snd_card_register);
688
689
#ifdef CONFIG_PROC_FS
690
static struct snd_info_entry *snd_card_info_entry;
691
692
static void snd_card_info_read(struct snd_info_entry *entry,
693
struct snd_info_buffer *buffer)
694
{
695
int idx, count;
696
struct snd_card *card;
697
698
for (idx = count = 0; idx < SNDRV_CARDS; idx++) {
699
mutex_lock(&snd_card_mutex);
700
if ((card = snd_cards[idx]) != NULL) {
701
count++;
702
snd_iprintf(buffer, "%2i [%-15s]: %s - %s\n",
703
idx,
704
card->id,
705
card->driver,
706
card->shortname);
707
snd_iprintf(buffer, " %s\n",
708
card->longname);
709
}
710
mutex_unlock(&snd_card_mutex);
711
}
712
if (!count)
713
snd_iprintf(buffer, "--- no soundcards ---\n");
714
}
715
716
#ifdef CONFIG_SND_OSSEMUL
717
718
void snd_card_info_read_oss(struct snd_info_buffer *buffer)
719
{
720
int idx, count;
721
struct snd_card *card;
722
723
for (idx = count = 0; idx < SNDRV_CARDS; idx++) {
724
mutex_lock(&snd_card_mutex);
725
if ((card = snd_cards[idx]) != NULL) {
726
count++;
727
snd_iprintf(buffer, "%s\n", card->longname);
728
}
729
mutex_unlock(&snd_card_mutex);
730
}
731
if (!count) {
732
snd_iprintf(buffer, "--- no soundcards ---\n");
733
}
734
}
735
736
#endif
737
738
#ifdef MODULE
739
static struct snd_info_entry *snd_card_module_info_entry;
740
static void snd_card_module_info_read(struct snd_info_entry *entry,
741
struct snd_info_buffer *buffer)
742
{
743
int idx;
744
struct snd_card *card;
745
746
for (idx = 0; idx < SNDRV_CARDS; idx++) {
747
mutex_lock(&snd_card_mutex);
748
if ((card = snd_cards[idx]) != NULL)
749
snd_iprintf(buffer, "%2i %s\n",
750
idx, card->module->name);
751
mutex_unlock(&snd_card_mutex);
752
}
753
}
754
#endif
755
756
int __init snd_card_info_init(void)
757
{
758
struct snd_info_entry *entry;
759
760
entry = snd_info_create_module_entry(THIS_MODULE, "cards", NULL);
761
if (! entry)
762
return -ENOMEM;
763
entry->c.text.read = snd_card_info_read;
764
if (snd_info_register(entry) < 0) {
765
snd_info_free_entry(entry);
766
return -ENOMEM;
767
}
768
snd_card_info_entry = entry;
769
770
#ifdef MODULE
771
entry = snd_info_create_module_entry(THIS_MODULE, "modules", NULL);
772
if (entry) {
773
entry->c.text.read = snd_card_module_info_read;
774
if (snd_info_register(entry) < 0)
775
snd_info_free_entry(entry);
776
else
777
snd_card_module_info_entry = entry;
778
}
779
#endif
780
781
return 0;
782
}
783
784
int __exit snd_card_info_done(void)
785
{
786
snd_info_free_entry(snd_card_info_entry);
787
#ifdef MODULE
788
snd_info_free_entry(snd_card_module_info_entry);
789
#endif
790
return 0;
791
}
792
793
#endif /* CONFIG_PROC_FS */
794
795
/**
796
* snd_component_add - add a component string
797
* @card: soundcard structure
798
* @component: the component id string
799
*
800
* This function adds the component id string to the supported list.
801
* The component can be referred from the alsa-lib.
802
*
803
* Returns zero otherwise a negative error code.
804
*/
805
806
int snd_component_add(struct snd_card *card, const char *component)
807
{
808
char *ptr;
809
int len = strlen(component);
810
811
ptr = strstr(card->components, component);
812
if (ptr != NULL) {
813
if (ptr[len] == '\0' || ptr[len] == ' ') /* already there */
814
return 1;
815
}
816
if (strlen(card->components) + 1 + len + 1 > sizeof(card->components)) {
817
snd_BUG();
818
return -ENOMEM;
819
}
820
if (card->components[0] != '\0')
821
strcat(card->components, " ");
822
strcat(card->components, component);
823
return 0;
824
}
825
826
EXPORT_SYMBOL(snd_component_add);
827
828
/**
829
* snd_card_file_add - add the file to the file list of the card
830
* @card: soundcard structure
831
* @file: file pointer
832
*
833
* This function adds the file to the file linked-list of the card.
834
* This linked-list is used to keep tracking the connection state,
835
* and to avoid the release of busy resources by hotplug.
836
*
837
* Returns zero or a negative error code.
838
*/
839
int snd_card_file_add(struct snd_card *card, struct file *file)
840
{
841
struct snd_monitor_file *mfile;
842
843
mfile = kmalloc(sizeof(*mfile), GFP_KERNEL);
844
if (mfile == NULL)
845
return -ENOMEM;
846
mfile->file = file;
847
mfile->disconnected_f_op = NULL;
848
INIT_LIST_HEAD(&mfile->shutdown_list);
849
spin_lock(&card->files_lock);
850
if (card->shutdown) {
851
spin_unlock(&card->files_lock);
852
kfree(mfile);
853
return -ENODEV;
854
}
855
list_add(&mfile->list, &card->files_list);
856
spin_unlock(&card->files_lock);
857
return 0;
858
}
859
860
EXPORT_SYMBOL(snd_card_file_add);
861
862
/**
863
* snd_card_file_remove - remove the file from the file list
864
* @card: soundcard structure
865
* @file: file pointer
866
*
867
* This function removes the file formerly added to the card via
868
* snd_card_file_add() function.
869
* If all files are removed and snd_card_free_when_closed() was
870
* called beforehand, it processes the pending release of
871
* resources.
872
*
873
* Returns zero or a negative error code.
874
*/
875
int snd_card_file_remove(struct snd_card *card, struct file *file)
876
{
877
struct snd_monitor_file *mfile, *found = NULL;
878
int last_close = 0;
879
880
spin_lock(&card->files_lock);
881
list_for_each_entry(mfile, &card->files_list, list) {
882
if (mfile->file == file) {
883
list_del(&mfile->list);
884
spin_lock(&shutdown_lock);
885
list_del(&mfile->shutdown_list);
886
spin_unlock(&shutdown_lock);
887
if (mfile->disconnected_f_op)
888
fops_put(mfile->disconnected_f_op);
889
found = mfile;
890
break;
891
}
892
}
893
if (list_empty(&card->files_list))
894
last_close = 1;
895
spin_unlock(&card->files_lock);
896
if (last_close) {
897
wake_up(&card->shutdown_sleep);
898
if (card->free_on_last_close)
899
snd_card_do_free(card);
900
}
901
if (!found) {
902
snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file);
903
return -ENOENT;
904
}
905
kfree(found);
906
return 0;
907
}
908
909
EXPORT_SYMBOL(snd_card_file_remove);
910
911
#ifdef CONFIG_PM
912
/**
913
* snd_power_wait - wait until the power-state is changed.
914
* @card: soundcard structure
915
* @power_state: expected power state
916
*
917
* Waits until the power-state is changed.
918
*
919
* Note: the power lock must be active before call.
920
*/
921
int snd_power_wait(struct snd_card *card, unsigned int power_state)
922
{
923
wait_queue_t wait;
924
int result = 0;
925
926
/* fastpath */
927
if (snd_power_get_state(card) == power_state)
928
return 0;
929
init_waitqueue_entry(&wait, current);
930
add_wait_queue(&card->power_sleep, &wait);
931
while (1) {
932
if (card->shutdown) {
933
result = -ENODEV;
934
break;
935
}
936
if (snd_power_get_state(card) == power_state)
937
break;
938
set_current_state(TASK_UNINTERRUPTIBLE);
939
snd_power_unlock(card);
940
schedule_timeout(30 * HZ);
941
snd_power_lock(card);
942
}
943
remove_wait_queue(&card->power_sleep, &wait);
944
return result;
945
}
946
947
EXPORT_SYMBOL(snd_power_wait);
948
#endif /* CONFIG_PM */
949
950