xref: /linux/sound/core/sound.c (revision f3d9478b2ce468c3115b02ecae7e975990697f15)
1 /*
2  *  Advanced Linux Sound Architecture
3  *  Copyright (c) by Jaroslav Kysela <perex@suse.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/init.h>
24 #include <linux/slab.h>
25 #include <linux/time.h>
26 #include <linux/device.h>
27 #include <linux/moduleparam.h>
28 #include <sound/core.h>
29 #include <sound/minors.h>
30 #include <sound/info.h>
31 #include <sound/version.h>
32 #include <sound/control.h>
33 #include <sound/initval.h>
34 #include <linux/kmod.h>
35 #include <linux/devfs_fs_kernel.h>
36 #include <linux/mutex.h>
37 
38 #define SNDRV_OS_MINORS 256
39 
40 static int major = CONFIG_SND_MAJOR;
41 int snd_major;
42 EXPORT_SYMBOL(snd_major);
43 
44 static int cards_limit = 1;
45 static int device_mode = S_IFCHR | S_IRUGO | S_IWUGO;
46 
47 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
48 MODULE_DESCRIPTION("Advanced Linux Sound Architecture driver for soundcards.");
49 MODULE_LICENSE("GPL");
50 module_param(major, int, 0444);
51 MODULE_PARM_DESC(major, "Major # for sound driver.");
52 module_param(cards_limit, int, 0444);
53 MODULE_PARM_DESC(cards_limit, "Count of auto-loadable soundcards.");
54 #ifdef CONFIG_DEVFS_FS
55 module_param(device_mode, int, 0444);
56 MODULE_PARM_DESC(device_mode, "Device file permission mask for devfs.");
57 #endif
58 MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
59 
60 /* this one holds the actual max. card number currently available.
61  * as default, it's identical with cards_limit option.  when more
62  * modules are loaded manually, this limit number increases, too.
63  */
64 int snd_ecards_limit;
65 EXPORT_SYMBOL(snd_ecards_limit);
66 
67 static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
68 static DEFINE_MUTEX(sound_mutex);
69 
70 extern struct class *sound_class;
71 
72 
73 #ifdef CONFIG_KMOD
74 
75 /**
76  * snd_request_card - try to load the card module
77  * @card: the card number
78  *
79  * Tries to load the module "snd-card-X" for the given card number
80  * via KMOD.  Returns immediately if already loaded.
81  */
82 void snd_request_card(int card)
83 {
84 	if (! current->fs->root)
85 		return;
86 	if (snd_card_locked(card))
87 		return;
88 	if (card < 0 || card >= cards_limit)
89 		return;
90 	request_module("snd-card-%i", card);
91 }
92 
93 EXPORT_SYMBOL(snd_request_card);
94 
95 static void snd_request_other(int minor)
96 {
97 	char *str;
98 
99 	if (! current->fs->root)
100 		return;
101 	switch (minor) {
102 	case SNDRV_MINOR_SEQUENCER:	str = "snd-seq";	break;
103 	case SNDRV_MINOR_TIMER:		str = "snd-timer";	break;
104 	default:			return;
105 	}
106 	request_module(str);
107 }
108 
109 #endif				/* request_module support */
110 
111 /**
112  * snd_lookup_minor_data - get user data of a registered device
113  * @minor: the minor number
114  * @type: device type (SNDRV_DEVICE_TYPE_XXX)
115  *
116  * Checks that a minor device with the specified type is registered, and returns
117  * its user data pointer.
118  */
119 void *snd_lookup_minor_data(unsigned int minor, int type)
120 {
121 	struct snd_minor *mreg;
122 	void *private_data;
123 
124 	if (minor >= ARRAY_SIZE(snd_minors))
125 		return NULL;
126 	mutex_lock(&sound_mutex);
127 	mreg = snd_minors[minor];
128 	if (mreg && mreg->type == type)
129 		private_data = mreg->private_data;
130 	else
131 		private_data = NULL;
132 	mutex_unlock(&sound_mutex);
133 	return private_data;
134 }
135 
136 EXPORT_SYMBOL(snd_lookup_minor_data);
137 
138 static int snd_open(struct inode *inode, struct file *file)
139 {
140 	unsigned int minor = iminor(inode);
141 	struct snd_minor *mptr = NULL;
142 	const struct file_operations *old_fops;
143 	int err = 0;
144 
145 	if (minor >= ARRAY_SIZE(snd_minors))
146 		return -ENODEV;
147 	mptr = snd_minors[minor];
148 	if (mptr == NULL) {
149 #ifdef CONFIG_KMOD
150 		int dev = SNDRV_MINOR_DEVICE(minor);
151 		if (dev == SNDRV_MINOR_CONTROL) {
152 			/* /dev/aloadC? */
153 			int card = SNDRV_MINOR_CARD(minor);
154 			if (snd_cards[card] == NULL)
155 				snd_request_card(card);
156 		} else if (dev == SNDRV_MINOR_GLOBAL) {
157 			/* /dev/aloadSEQ */
158 			snd_request_other(minor);
159 		}
160 #ifndef CONFIG_SND_DYNAMIC_MINORS
161 		/* /dev/snd/{controlC?,seq} */
162 		mptr = snd_minors[minor];
163 		if (mptr == NULL)
164 #endif
165 #endif
166 			return -ENODEV;
167 	}
168 	old_fops = file->f_op;
169 	file->f_op = fops_get(mptr->f_ops);
170 	if (file->f_op->open)
171 		err = file->f_op->open(inode, file);
172 	if (err) {
173 		fops_put(file->f_op);
174 		file->f_op = fops_get(old_fops);
175 	}
176 	fops_put(old_fops);
177 	return err;
178 }
179 
180 static struct file_operations snd_fops =
181 {
182 	.owner =	THIS_MODULE,
183 	.open =		snd_open
184 };
185 
186 #ifdef CONFIG_SND_DYNAMIC_MINORS
187 static int snd_find_free_minor(void)
188 {
189 	int minor;
190 
191 	for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) {
192 		/* skip minors still used statically for autoloading devices */
193 		if (SNDRV_MINOR_DEVICE(minor) == SNDRV_MINOR_CONTROL ||
194 		    minor == SNDRV_MINOR_SEQUENCER)
195 			continue;
196 		if (!snd_minors[minor])
197 			return minor;
198 	}
199 	return -EBUSY;
200 }
201 #else
202 static int snd_kernel_minor(int type, struct snd_card *card, int dev)
203 {
204 	int minor;
205 
206 	switch (type) {
207 	case SNDRV_DEVICE_TYPE_SEQUENCER:
208 	case SNDRV_DEVICE_TYPE_TIMER:
209 		minor = type;
210 		break;
211 	case SNDRV_DEVICE_TYPE_CONTROL:
212 		snd_assert(card != NULL, return -EINVAL);
213 		minor = SNDRV_MINOR(card->number, type);
214 		break;
215 	case SNDRV_DEVICE_TYPE_HWDEP:
216 	case SNDRV_DEVICE_TYPE_RAWMIDI:
217 	case SNDRV_DEVICE_TYPE_PCM_PLAYBACK:
218 	case SNDRV_DEVICE_TYPE_PCM_CAPTURE:
219 		snd_assert(card != NULL, return -EINVAL);
220 		minor = SNDRV_MINOR(card->number, type + dev);
221 		break;
222 	default:
223 		return -EINVAL;
224 	}
225 	snd_assert(minor >= 0 && minor < SNDRV_OS_MINORS, return -EINVAL);
226 	return minor;
227 }
228 #endif
229 
230 /**
231  * snd_register_device - Register the ALSA device file for the card
232  * @type: the device type, SNDRV_DEVICE_TYPE_XXX
233  * @card: the card instance
234  * @dev: the device index
235  * @f_ops: the file operations
236  * @private_data: user pointer for f_ops->open()
237  * @name: the device file name
238  *
239  * Registers an ALSA device file for the given card.
240  * The operators have to be set in reg parameter.
241  *
242  * Retrurns zero if successful, or a negative error code on failure.
243  */
244 int snd_register_device(int type, struct snd_card *card, int dev,
245 			const struct file_operations *f_ops, void *private_data,
246 			const char *name)
247 {
248 	int minor;
249 	struct snd_minor *preg;
250 	struct device *device = NULL;
251 
252 	snd_assert(name, return -EINVAL);
253 	preg = kmalloc(sizeof(struct snd_minor) + strlen(name) + 1, GFP_KERNEL);
254 	if (preg == NULL)
255 		return -ENOMEM;
256 	preg->type = type;
257 	preg->card = card ? card->number : -1;
258 	preg->device = dev;
259 	preg->f_ops = f_ops;
260 	preg->private_data = private_data;
261 	strcpy(preg->name, name);
262 	mutex_lock(&sound_mutex);
263 #ifdef CONFIG_SND_DYNAMIC_MINORS
264 	minor = snd_find_free_minor();
265 #else
266 	minor = snd_kernel_minor(type, card, dev);
267 	if (minor >= 0 && snd_minors[minor])
268 		minor = -EBUSY;
269 #endif
270 	if (minor < 0) {
271 		mutex_unlock(&sound_mutex);
272 		kfree(preg);
273 		return minor;
274 	}
275 	snd_minors[minor] = preg;
276 	if (type != SNDRV_DEVICE_TYPE_CONTROL || preg->card >= cards_limit)
277 		devfs_mk_cdev(MKDEV(major, minor), S_IFCHR | device_mode, "snd/%s", name);
278 	if (card)
279 		device = card->dev;
280 	class_device_create(sound_class, NULL, MKDEV(major, minor), device, "%s", name);
281 
282 	mutex_unlock(&sound_mutex);
283 	return 0;
284 }
285 
286 EXPORT_SYMBOL(snd_register_device);
287 
288 /**
289  * snd_unregister_device - unregister the device on the given card
290  * @type: the device type, SNDRV_DEVICE_TYPE_XXX
291  * @card: the card instance
292  * @dev: the device index
293  *
294  * Unregisters the device file already registered via
295  * snd_register_device().
296  *
297  * Returns zero if sucecessful, or a negative error code on failure
298  */
299 int snd_unregister_device(int type, struct snd_card *card, int dev)
300 {
301 	int cardnum, minor;
302 	struct snd_minor *mptr;
303 
304 	cardnum = card ? card->number : -1;
305 	mutex_lock(&sound_mutex);
306 	for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor)
307 		if ((mptr = snd_minors[minor]) != NULL &&
308 		    mptr->type == type &&
309 		    mptr->card == cardnum &&
310 		    mptr->device == dev)
311 			break;
312 	if (minor == ARRAY_SIZE(snd_minors)) {
313 		mutex_unlock(&sound_mutex);
314 		return -EINVAL;
315 	}
316 
317 	if (mptr->type != SNDRV_DEVICE_TYPE_CONTROL ||
318 	    mptr->card >= cards_limit)			/* created in sound.c */
319 		devfs_remove("snd/%s", mptr->name);
320 	class_device_destroy(sound_class, MKDEV(major, minor));
321 
322 	snd_minors[minor] = NULL;
323 	mutex_unlock(&sound_mutex);
324 	kfree(mptr);
325 	return 0;
326 }
327 
328 EXPORT_SYMBOL(snd_unregister_device);
329 
330 #ifdef CONFIG_PROC_FS
331 /*
332  *  INFO PART
333  */
334 
335 static struct snd_info_entry *snd_minor_info_entry;
336 
337 static const char *snd_device_type_name(int type)
338 {
339 	switch (type) {
340 	case SNDRV_DEVICE_TYPE_CONTROL:
341 		return "control";
342 	case SNDRV_DEVICE_TYPE_HWDEP:
343 		return "hardware dependent";
344 	case SNDRV_DEVICE_TYPE_RAWMIDI:
345 		return "raw midi";
346 	case SNDRV_DEVICE_TYPE_PCM_PLAYBACK:
347 		return "digital audio playback";
348 	case SNDRV_DEVICE_TYPE_PCM_CAPTURE:
349 		return "digital audio capture";
350 	case SNDRV_DEVICE_TYPE_SEQUENCER:
351 		return "sequencer";
352 	case SNDRV_DEVICE_TYPE_TIMER:
353 		return "timer";
354 	default:
355 		return "?";
356 	}
357 }
358 
359 static void snd_minor_info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
360 {
361 	int minor;
362 	struct snd_minor *mptr;
363 
364 	mutex_lock(&sound_mutex);
365 	for (minor = 0; minor < SNDRV_OS_MINORS; ++minor) {
366 		if (!(mptr = snd_minors[minor]))
367 			continue;
368 		if (mptr->card >= 0) {
369 			if (mptr->device >= 0)
370 				snd_iprintf(buffer, "%3i: [%2i-%2i]: %s\n",
371 					    minor, mptr->card, mptr->device,
372 					    snd_device_type_name(mptr->type));
373 			else
374 				snd_iprintf(buffer, "%3i: [%2i]   : %s\n",
375 					    minor, mptr->card,
376 					    snd_device_type_name(mptr->type));
377 		} else
378 			snd_iprintf(buffer, "%3i:        : %s\n", minor,
379 				    snd_device_type_name(mptr->type));
380 	}
381 	mutex_unlock(&sound_mutex);
382 }
383 
384 int __init snd_minor_info_init(void)
385 {
386 	struct snd_info_entry *entry;
387 
388 	entry = snd_info_create_module_entry(THIS_MODULE, "devices", NULL);
389 	if (entry) {
390 		entry->c.text.read = snd_minor_info_read;
391 		if (snd_info_register(entry) < 0) {
392 			snd_info_free_entry(entry);
393 			entry = NULL;
394 		}
395 	}
396 	snd_minor_info_entry = entry;
397 	return 0;
398 }
399 
400 int __exit snd_minor_info_done(void)
401 {
402 	if (snd_minor_info_entry)
403 		snd_info_unregister(snd_minor_info_entry);
404 	return 0;
405 }
406 #endif /* CONFIG_PROC_FS */
407 
408 /*
409  *  INIT PART
410  */
411 
412 static int __init alsa_sound_init(void)
413 {
414 	short controlnum;
415 
416 	snd_major = major;
417 	snd_ecards_limit = cards_limit;
418 	devfs_mk_dir("snd");
419 	if (register_chrdev(major, "alsa", &snd_fops)) {
420 		snd_printk(KERN_ERR "unable to register native major device number %d\n", major);
421 		devfs_remove("snd");
422 		return -EIO;
423 	}
424 	if (snd_info_init() < 0) {
425 		unregister_chrdev(major, "alsa");
426 		devfs_remove("snd");
427 		return -ENOMEM;
428 	}
429 	snd_info_minor_register();
430 	for (controlnum = 0; controlnum < cards_limit; controlnum++)
431 		devfs_mk_cdev(MKDEV(major, controlnum<<5), S_IFCHR | device_mode, "snd/controlC%d", controlnum);
432 #ifndef MODULE
433 	printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n");
434 #endif
435 	return 0;
436 }
437 
438 static void __exit alsa_sound_exit(void)
439 {
440 	short controlnum;
441 
442 	for (controlnum = 0; controlnum < cards_limit; controlnum++)
443 		devfs_remove("snd/controlC%d", controlnum);
444 
445 	snd_info_minor_unregister();
446 	snd_info_done();
447 	if (unregister_chrdev(major, "alsa") != 0)
448 		snd_printk(KERN_ERR "unable to unregister major device number %d\n", major);
449 	devfs_remove("snd");
450 }
451 
452 module_init(alsa_sound_init)
453 module_exit(alsa_sound_exit)
454