1/*
2 *  Initialization routines
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 <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) */
35struct 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
42static DEFINE_SPINLOCK(shutdown_lock);
43static LIST_HEAD(shutdown_files);
44
45static const struct file_operations snd_shutdown_f_ops;
46
47static unsigned int snd_cards_lock;	/* locked for registering/using */
48struct snd_card *snd_cards[SNDRV_CARDS];
49EXPORT_SYMBOL(snd_cards);
50
51static DEFINE_MUTEX(snd_card_mutex);
52
53static char *slots[SNDRV_CARDS];
54module_param_array(slots, charp, NULL, 0444);
55MODULE_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 */
60static 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)
95int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag);
96EXPORT_SYMBOL(snd_mixer_oss_notify_callback);
97#endif
98
99#ifdef CONFIG_PROC_FS
100static 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
106static 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 */
147int 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}
241EXPORT_SYMBOL(snd_card_create);
242
243/* return non-zero if a card is already locked */
244int 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
254static loff_t snd_disconnect_llseek(struct file *file, loff_t offset, int orig)
255{
256	return -ENODEV;
257}
258
259static ssize_t snd_disconnect_read(struct file *file, char __user *buf,
260				   size_t count, loff_t *offset)
261{
262	return -ENODEV;
263}
264
265static 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
271static 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
294static unsigned int snd_disconnect_poll(struct file * file, poll_table * wait)
295{
296	return POLLERR | POLLNVAL;
297}
298
299static long snd_disconnect_ioctl(struct file *file,
300				 unsigned int cmd, unsigned long arg)
301{
302	return -ENODEV;
303}
304
305static int snd_disconnect_mmap(struct file *file, struct vm_area_struct *vma)
306{
307	return -ENODEV;
308}
309
310static int snd_disconnect_fasync(int fd, struct file *file, int on)
311{
312	return -ENODEV;
313}
314
315static 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 */
342int snd_card_disconnect(struct snd_card *card)
343{
344	struct snd_monitor_file *mfile;
345	struct file *file;
346	int err;
347
348	if (!card)
349		return -EINVAL;
350
351	spin_lock(&card->files_lock);
352	if (card->shutdown) {
353		spin_unlock(&card->files_lock);
354		return 0;
355	}
356	card->shutdown = 1;
357	spin_unlock(&card->files_lock);
358
359	/* phase 1: disable fops (user space) operations for ALSA API */
360	mutex_lock(&snd_card_mutex);
361	snd_cards[card->number] = NULL;
362	snd_cards_lock &= ~(1 << card->number);
363	mutex_unlock(&snd_card_mutex);
364
365	/* phase 2: replace file->f_op with special dummy operations */
366
367	spin_lock(&card->files_lock);
368	list_for_each_entry(mfile, &card->files_list, list) {
369		file = mfile->file;
370
371		/* it's critical part, use endless loop */
372		/* we have no room to fail */
373		mfile->disconnected_f_op = mfile->file->f_op;
374
375		spin_lock(&shutdown_lock);
376		list_add(&mfile->shutdown_list, &shutdown_files);
377		spin_unlock(&shutdown_lock);
378
379		mfile->file->f_op = &snd_shutdown_f_ops;
380		fops_get(mfile->file->f_op);
381	}
382	spin_unlock(&card->files_lock);
383
384	/* phase 3: notify all connected devices about disconnection */
385	/* at this point, they cannot respond to any calls except release() */
386
387#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
388	if (snd_mixer_oss_notify_callback)
389		snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_DISCONNECT);
390#endif
391
392	/* notify all devices that we are disconnected */
393	err = snd_device_disconnect_all(card);
394	if (err < 0)
395		snd_printk(KERN_ERR "not all devices for card %i can be disconnected\n", card->number);
396
397	snd_info_card_disconnect(card);
398#ifndef CONFIG_SYSFS_DEPRECATED
399	if (card->card_dev) {
400		device_unregister(card->card_dev);
401		card->card_dev = NULL;
402	}
403#endif
404#ifdef CONFIG_PM
405	wake_up(&card->power_sleep);
406#endif
407	return 0;
408}
409
410EXPORT_SYMBOL(snd_card_disconnect);
411
412/**
413 *  snd_card_free - frees given soundcard structure
414 *  @card: soundcard structure
415 *
416 *  This function releases the soundcard structure and the all assigned
417 *  devices automatically.  That is, you don't have to release the devices
418 *  by yourself.
419 *
420 *  Returns zero. Frees all associated devices and frees the control
421 *  interface associated to given soundcard.
422 */
423static int snd_card_do_free(struct snd_card *card)
424{
425#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
426	if (snd_mixer_oss_notify_callback)
427		snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE);
428#endif
429	if (snd_device_free_all(card, SNDRV_DEV_CMD_PRE) < 0) {
430		snd_printk(KERN_ERR "unable to free all devices (pre)\n");
431		/* Fatal, but this situation should never occur */
432	}
433	if (snd_device_free_all(card, SNDRV_DEV_CMD_NORMAL) < 0) {
434		snd_printk(KERN_ERR "unable to free all devices (normal)\n");
435		/* Fatal, but this situation should never occur */
436	}
437	if (snd_device_free_all(card, SNDRV_DEV_CMD_POST) < 0) {
438		snd_printk(KERN_ERR "unable to free all devices (post)\n");
439		/* Fatal, but this situation should never occur */
440	}
441	if (card->private_free)
442		card->private_free(card);
443	snd_info_free_entry(card->proc_id);
444	if (snd_info_card_free(card) < 0) {
445		snd_printk(KERN_WARNING "unable to free card info\n");
446		/* Not fatal error */
447	}
448	kfree(card);
449	return 0;
450}
451
452int snd_card_free_when_closed(struct snd_card *card)
453{
454	int free_now = 0;
455	int ret = snd_card_disconnect(card);
456	if (ret)
457		return ret;
458
459	spin_lock(&card->files_lock);
460	if (list_empty(&card->files_list))
461		free_now = 1;
462	else
463		card->free_on_last_close = 1;
464	spin_unlock(&card->files_lock);
465
466	if (free_now)
467		snd_card_do_free(card);
468	return 0;
469}
470
471EXPORT_SYMBOL(snd_card_free_when_closed);
472
473int snd_card_free(struct snd_card *card)
474{
475	int ret = snd_card_disconnect(card);
476	if (ret)
477		return ret;
478
479	/* wait, until all devices are ready for the free operation */
480	wait_event(card->shutdown_sleep, list_empty(&card->files_list));
481	snd_card_do_free(card);
482	return 0;
483}
484
485EXPORT_SYMBOL(snd_card_free);
486
487static void snd_card_set_id_no_lock(struct snd_card *card, const char *nid)
488{
489	int i, len, idx_flag = 0, loops = SNDRV_CARDS;
490	const char *spos, *src;
491	char *id;
492
493	if (nid == NULL) {
494		id = card->shortname;
495		spos = src = id;
496		while (*id != '\0') {
497			if (*id == ' ')
498				spos = id + 1;
499			id++;
500		}
501	} else {
502		spos = src = nid;
503	}
504	id = card->id;
505	while (*spos != '\0' && !isalnum(*spos))
506		spos++;
507	if (isdigit(*spos))
508		*id++ = isalpha(src[0]) ? src[0] : 'D';
509	while (*spos != '\0' && (size_t)(id - card->id) < sizeof(card->id) - 1) {
510		if (isalnum(*spos))
511			*id++ = *spos;
512		spos++;
513	}
514	*id = '\0';
515
516	id = card->id;
517
518	if (*id == '\0')
519		strcpy(id, "default");
520
521	while (1) {
522	      	if (loops-- == 0) {
523			snd_printk(KERN_ERR "unable to set card id (%s)\n", id);
524      			strcpy(card->id, card->proc_root->name);
525      			return;
526      		}
527	      	if (!snd_info_check_reserved_words(id))
528      			goto __change;
529		for (i = 0; i < snd_ecards_limit; i++) {
530			if (snd_cards[i] && !strcmp(snd_cards[i]->id, id))
531				goto __change;
532		}
533		break;
534
535	      __change:
536		len = strlen(id);
537		if (idx_flag) {
538			if (id[len-1] != '9')
539				id[len-1]++;
540			else
541				id[len-1] = 'A';
542		} else if ((size_t)len <= sizeof(card->id) - 3) {
543			strcat(id, "_1");
544			idx_flag++;
545		} else {
546			spos = id + len - 2;
547			if ((size_t)len <= sizeof(card->id) - 2)
548				spos++;
549			*(char *)spos++ = '_';
550			*(char *)spos++ = '1';
551			*(char *)spos++ = '\0';
552			idx_flag++;
553		}
554	}
555}
556
557/**
558 *  snd_card_set_id - set card identification name
559 *  @card: soundcard structure
560 *  @nid: new identification string
561 *
562 *  This function sets the card identification and checks for name
563 *  collisions.
564 */
565void snd_card_set_id(struct snd_card *card, const char *nid)
566{
567	/* check if user specified own card->id */
568	if (card->id[0] != '\0')
569		return;
570	mutex_lock(&snd_card_mutex);
571	snd_card_set_id_no_lock(card, nid);
572	mutex_unlock(&snd_card_mutex);
573}
574EXPORT_SYMBOL(snd_card_set_id);
575
576#ifndef CONFIG_SYSFS_DEPRECATED
577static ssize_t
578card_id_show_attr(struct device *dev,
579		  struct device_attribute *attr, char *buf)
580{
581	struct snd_card *card = dev_get_drvdata(dev);
582	return snprintf(buf, PAGE_SIZE, "%s\n", card ? card->id : "(null)");
583}
584
585static ssize_t
586card_id_store_attr(struct device *dev, struct device_attribute *attr,
587		   const char *buf, size_t count)
588{
589	struct snd_card *card = dev_get_drvdata(dev);
590	char buf1[sizeof(card->id)];
591	size_t copy = count > sizeof(card->id) - 1 ?
592					sizeof(card->id) - 1 : count;
593	size_t idx;
594	int c;
595
596	for (idx = 0; idx < copy; idx++) {
597		c = buf[idx];
598		if (!isalnum(c) && c != '_' && c != '-')
599			return -EINVAL;
600	}
601	memcpy(buf1, buf, copy);
602	buf1[copy] = '\0';
603	mutex_lock(&snd_card_mutex);
604	if (!snd_info_check_reserved_words(buf1)) {
605	     __exist:
606		mutex_unlock(&snd_card_mutex);
607		return -EEXIST;
608	}
609	for (idx = 0; idx < snd_ecards_limit; idx++) {
610		if (snd_cards[idx] && !strcmp(snd_cards[idx]->id, buf1))
611			goto __exist;
612	}
613	strcpy(card->id, buf1);
614	snd_info_card_id_change(card);
615	mutex_unlock(&snd_card_mutex);
616
617	return count;
618}
619
620static struct device_attribute card_id_attrs =
621	__ATTR(id, S_IRUGO | S_IWUSR, card_id_show_attr, card_id_store_attr);
622
623static ssize_t
624card_number_show_attr(struct device *dev,
625		     struct device_attribute *attr, char *buf)
626{
627	struct snd_card *card = dev_get_drvdata(dev);
628	return snprintf(buf, PAGE_SIZE, "%i\n", card ? card->number : -1);
629}
630
631static struct device_attribute card_number_attrs =
632	__ATTR(number, S_IRUGO, card_number_show_attr, NULL);
633#endif /* CONFIG_SYSFS_DEPRECATED */
634
635/**
636 *  snd_card_register - register the soundcard
637 *  @card: soundcard structure
638 *
639 *  This function registers all the devices assigned to the soundcard.
640 *  Until calling this, the ALSA control interface is blocked from the
641 *  external accesses.  Thus, you should call this function at the end
642 *  of the initialization of the card.
643 *
644 *  Returns zero otherwise a negative error code if the registrain failed.
645 */
646int snd_card_register(struct snd_card *card)
647{
648	int err;
649
650	if (snd_BUG_ON(!card))
651		return -EINVAL;
652#ifndef CONFIG_SYSFS_DEPRECATED
653	if (!card->card_dev) {
654		card->card_dev = device_create(sound_class, card->dev,
655					       MKDEV(0, 0), card,
656					       "card%i", card->number);
657		if (IS_ERR(card->card_dev))
658			card->card_dev = NULL;
659	}
660#endif
661	if ((err = snd_device_register_all(card)) < 0)
662		return err;
663	mutex_lock(&snd_card_mutex);
664	if (snd_cards[card->number]) {
665		/* already registered */
666		mutex_unlock(&snd_card_mutex);
667		return 0;
668	}
669	snd_card_set_id_no_lock(card, card->id[0] == '\0' ? NULL : card->id);
670	snd_cards[card->number] = card;
671	mutex_unlock(&snd_card_mutex);
672	init_info_for_card(card);
673#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
674	if (snd_mixer_oss_notify_callback)
675		snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER);
676#endif
677#ifndef CONFIG_SYSFS_DEPRECATED
678	if (card->card_dev) {
679		err = device_create_file(card->card_dev, &card_id_attrs);
680		if (err < 0)
681			return err;
682		err = device_create_file(card->card_dev, &card_number_attrs);
683		if (err < 0)
684			return err;
685	}
686#endif
687	return 0;
688}
689
690EXPORT_SYMBOL(snd_card_register);
691
692#ifdef CONFIG_PROC_FS
693static struct snd_info_entry *snd_card_info_entry;
694
695static void snd_card_info_read(struct snd_info_entry *entry,
696			       struct snd_info_buffer *buffer)
697{
698	int idx, count;
699	struct snd_card *card;
700
701	for (idx = count = 0; idx < SNDRV_CARDS; idx++) {
702		mutex_lock(&snd_card_mutex);
703		if ((card = snd_cards[idx]) != NULL) {
704			count++;
705			snd_iprintf(buffer, "%2i [%-15s]: %s - %s\n",
706					idx,
707					card->id,
708					card->driver,
709					card->shortname);
710			snd_iprintf(buffer, "                      %s\n",
711					card->longname);
712		}
713		mutex_unlock(&snd_card_mutex);
714	}
715	if (!count)
716		snd_iprintf(buffer, "--- no soundcards ---\n");
717}
718
719#ifdef CONFIG_SND_OSSEMUL
720
721void snd_card_info_read_oss(struct snd_info_buffer *buffer)
722{
723	int idx, count;
724	struct snd_card *card;
725
726	for (idx = count = 0; idx < SNDRV_CARDS; idx++) {
727		mutex_lock(&snd_card_mutex);
728		if ((card = snd_cards[idx]) != NULL) {
729			count++;
730			snd_iprintf(buffer, "%s\n", card->longname);
731		}
732		mutex_unlock(&snd_card_mutex);
733	}
734	if (!count) {
735		snd_iprintf(buffer, "--- no soundcards ---\n");
736	}
737}
738
739#endif
740
741#ifdef MODULE
742static struct snd_info_entry *snd_card_module_info_entry;
743static void snd_card_module_info_read(struct snd_info_entry *entry,
744				      struct snd_info_buffer *buffer)
745{
746	int idx;
747	struct snd_card *card;
748
749	for (idx = 0; idx < SNDRV_CARDS; idx++) {
750		mutex_lock(&snd_card_mutex);
751		if ((card = snd_cards[idx]) != NULL)
752			snd_iprintf(buffer, "%2i %s\n",
753				    idx, card->module->name);
754		mutex_unlock(&snd_card_mutex);
755	}
756}
757#endif
758
759int __init snd_card_info_init(void)
760{
761	struct snd_info_entry *entry;
762
763	entry = snd_info_create_module_entry(THIS_MODULE, "cards", NULL);
764	if (! entry)
765		return -ENOMEM;
766	entry->c.text.read = snd_card_info_read;
767	if (snd_info_register(entry) < 0) {
768		snd_info_free_entry(entry);
769		return -ENOMEM;
770	}
771	snd_card_info_entry = entry;
772
773#ifdef MODULE
774	entry = snd_info_create_module_entry(THIS_MODULE, "modules", NULL);
775	if (entry) {
776		entry->c.text.read = snd_card_module_info_read;
777		if (snd_info_register(entry) < 0)
778			snd_info_free_entry(entry);
779		else
780			snd_card_module_info_entry = entry;
781	}
782#endif
783
784	return 0;
785}
786
787int __exit snd_card_info_done(void)
788{
789	snd_info_free_entry(snd_card_info_entry);
790#ifdef MODULE
791	snd_info_free_entry(snd_card_module_info_entry);
792#endif
793	return 0;
794}
795
796#endif /* CONFIG_PROC_FS */
797
798/**
799 *  snd_component_add - add a component string
800 *  @card: soundcard structure
801 *  @component: the component id string
802 *
803 *  This function adds the component id string to the supported list.
804 *  The component can be referred from the alsa-lib.
805 *
806 *  Returns zero otherwise a negative error code.
807 */
808
809int snd_component_add(struct snd_card *card, const char *component)
810{
811	char *ptr;
812	int len = strlen(component);
813
814	ptr = strstr(card->components, component);
815	if (ptr != NULL) {
816		if (ptr[len] == '\0' || ptr[len] == ' ')	/* already there */
817			return 1;
818	}
819	if (strlen(card->components) + 1 + len + 1 > sizeof(card->components)) {
820		snd_BUG();
821		return -ENOMEM;
822	}
823	if (card->components[0] != '\0')
824		strcat(card->components, " ");
825	strcat(card->components, component);
826	return 0;
827}
828
829EXPORT_SYMBOL(snd_component_add);
830
831/**
832 *  snd_card_file_add - add the file to the file list of the card
833 *  @card: soundcard structure
834 *  @file: file pointer
835 *
836 *  This function adds the file to the file linked-list of the card.
837 *  This linked-list is used to keep tracking the connection state,
838 *  and to avoid the release of busy resources by hotplug.
839 *
840 *  Returns zero or a negative error code.
841 */
842int snd_card_file_add(struct snd_card *card, struct file *file)
843{
844	struct snd_monitor_file *mfile;
845
846	mfile = kmalloc(sizeof(*mfile), GFP_KERNEL);
847	if (mfile == NULL)
848		return -ENOMEM;
849	mfile->file = file;
850	mfile->disconnected_f_op = NULL;
851	spin_lock(&card->files_lock);
852	if (card->shutdown) {
853		spin_unlock(&card->files_lock);
854		kfree(mfile);
855		return -ENODEV;
856	}
857	list_add(&mfile->list, &card->files_list);
858	spin_unlock(&card->files_lock);
859	return 0;
860}
861
862EXPORT_SYMBOL(snd_card_file_add);
863
864/**
865 *  snd_card_file_remove - remove the file from the file list
866 *  @card: soundcard structure
867 *  @file: file pointer
868 *
869 *  This function removes the file formerly added to the card via
870 *  snd_card_file_add() function.
871 *  If all files are removed and snd_card_free_when_closed() was
872 *  called beforehand, it processes the pending release of
873 *  resources.
874 *
875 *  Returns zero or a negative error code.
876 */
877int snd_card_file_remove(struct snd_card *card, struct file *file)
878{
879	struct snd_monitor_file *mfile, *found = NULL;
880	int last_close = 0;
881
882	spin_lock(&card->files_lock);
883	list_for_each_entry(mfile, &card->files_list, list) {
884		if (mfile->file == file) {
885			list_del(&mfile->list);
886			if (mfile->disconnected_f_op)
887				fops_put(mfile->disconnected_f_op);
888			found = mfile;
889			break;
890		}
891	}
892	if (list_empty(&card->files_list))
893		last_close = 1;
894	spin_unlock(&card->files_lock);
895	if (last_close) {
896		wake_up(&card->shutdown_sleep);
897		if (card->free_on_last_close)
898			snd_card_do_free(card);
899	}
900	if (!found) {
901		snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file);
902		return -ENOENT;
903	}
904	kfree(found);
905	return 0;
906}
907
908EXPORT_SYMBOL(snd_card_file_remove);
909
910#ifdef CONFIG_PM
911/**
912 *  snd_power_wait - wait until the power-state is changed.
913 *  @card: soundcard structure
914 *  @power_state: expected power state
915 *
916 *  Waits until the power-state is changed.
917 *
918 *  Note: the power lock must be active before call.
919 */
920int snd_power_wait(struct snd_card *card, unsigned int power_state)
921{
922	wait_queue_t wait;
923	int result = 0;
924
925	/* fastpath */
926	if (snd_power_get_state(card) == power_state)
927		return 0;
928	init_waitqueue_entry(&wait, current);
929	add_wait_queue(&card->power_sleep, &wait);
930	while (1) {
931		if (card->shutdown) {
932			result = -ENODEV;
933			break;
934		}
935		if (snd_power_get_state(card) == power_state)
936			break;
937		set_current_state(TASK_UNINTERRUPTIBLE);
938		snd_power_unlock(card);
939		schedule_timeout(30 * HZ);
940		snd_power_lock(card);
941	}
942	remove_wait_queue(&card->power_sleep, &wait);
943	return result;
944}
945
946EXPORT_SYMBOL(snd_power_wait);
947#endif /* CONFIG_PM */
948