1/*
2 *	Sound core.  This file is composed of two parts.  sound_class
3 *	which is common to both OSS and ALSA and OSS sound core which
4 *	is used OSS or emulation of it.
5 */
6
7/*
8 * First, the common part.
9 */
10#include <linux/module.h>
11#include <linux/device.h>
12#include <linux/err.h>
13#include <linux/kdev_t.h>
14#include <linux/major.h>
15#include <sound/core.h>
16
17#ifdef CONFIG_SOUND_OSS_CORE
18static int __init init_oss_soundcore(void);
19static void cleanup_oss_soundcore(void);
20#else
21static inline int init_oss_soundcore(void)	{ return 0; }
22static inline void cleanup_oss_soundcore(void)	{ }
23#endif
24
25struct class *sound_class;
26EXPORT_SYMBOL(sound_class);
27
28MODULE_DESCRIPTION("Core sound module");
29MODULE_AUTHOR("Alan Cox");
30MODULE_LICENSE("GPL");
31
32static char *sound_devnode(struct device *dev, mode_t *mode)
33{
34	if (MAJOR(dev->devt) == SOUND_MAJOR)
35		return NULL;
36	return kasprintf(GFP_KERNEL, "snd/%s", dev_name(dev));
37}
38
39static int __init init_soundcore(void)
40{
41	int rc;
42
43	rc = init_oss_soundcore();
44	if (rc)
45		return rc;
46
47	sound_class = class_create(THIS_MODULE, "sound");
48	if (IS_ERR(sound_class)) {
49		cleanup_oss_soundcore();
50		return PTR_ERR(sound_class);
51	}
52
53	sound_class->devnode = sound_devnode;
54
55	return 0;
56}
57
58static void __exit cleanup_soundcore(void)
59{
60	cleanup_oss_soundcore();
61	class_destroy(sound_class);
62}
63
64subsys_initcall(init_soundcore);
65module_exit(cleanup_soundcore);
66
67
68#ifdef CONFIG_SOUND_OSS_CORE
69
70#include <linux/init.h>
71#include <linux/slab.h>
72#include <linux/smp_lock.h>
73#include <linux/types.h>
74#include <linux/kernel.h>
75#include <linux/sound.h>
76#include <linux/kmod.h>
77
78#define SOUND_STEP 16
79
80struct sound_unit
81{
82	int unit_minor;
83	const struct file_operations *unit_fops;
84	struct sound_unit *next;
85	char name[32];
86};
87
88#ifdef CONFIG_SOUND_MSNDCLAS
89extern int msnd_classic_init(void);
90#endif
91#ifdef CONFIG_SOUND_MSNDPIN
92extern int msnd_pinnacle_init(void);
93#endif
94
95/*
96 * By default, OSS sound_core claims full legacy minor range (0-255)
97 * of SOUND_MAJOR to trap open attempts to any sound minor and
98 * requests modules using custom sound-slot/service-* module aliases.
99 * The only benefit of doing this is allowing use of custom module
100 * aliases instead of the standard char-major-* ones.  This behavior
101 * prevents alternative OSS implementation and is scheduled to be
102 * removed.
103 *
104 * CONFIG_SOUND_OSS_CORE_PRECLAIM and soundcore.preclaim_oss kernel
105 * parameter are added to allow distros and developers to try and
106 * switch to alternative implementations without needing to rebuild
107 * the kernel in the meantime.  If preclaim_oss is non-zero, the
108 * kernel will behave the same as before.  All SOUND_MAJOR minors are
109 * preclaimed and the custom module aliases along with standard chrdev
110 * ones are emitted if a missing device is opened.  If preclaim_oss is
111 * zero, sound_core only grabs what's actually in use and for missing
112 * devices only the standard chrdev aliases are requested.
113 *
114 * All these clutters are scheduled to be removed along with
115 * sound-slot/service-* module aliases.  Please take a look at
116 * feature-removal-schedule.txt for details.
117 */
118#ifdef CONFIG_SOUND_OSS_CORE_PRECLAIM
119static int preclaim_oss = 1;
120#else
121static int preclaim_oss = 0;
122#endif
123
124module_param(preclaim_oss, int, 0444);
125
126static int soundcore_open(struct inode *, struct file *);
127
128static const struct file_operations soundcore_fops =
129{
130	/* We must have an owner or the module locking fails */
131	.owner	= THIS_MODULE,
132	.open	= soundcore_open,
133};
134
135/*
136 *	Low level list operator. Scan the ordered list, find a hole and
137 *	join into it. Called with the lock asserted
138 */
139
140static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list, const struct file_operations *fops, int index, int low, int top)
141{
142	int n=low;
143
144	if (index < 0) {	/* first free */
145
146		while (*list && (*list)->unit_minor<n)
147			list=&((*list)->next);
148
149		while(n<top)
150		{
151			/* Found a hole ? */
152			if(*list==NULL || (*list)->unit_minor>n)
153				break;
154			list=&((*list)->next);
155			n+=SOUND_STEP;
156		}
157
158		if(n>=top)
159			return -ENOENT;
160	} else {
161		n = low+(index*16);
162		while (*list) {
163			if ((*list)->unit_minor==n)
164				return -EBUSY;
165			if ((*list)->unit_minor>n)
166				break;
167			list=&((*list)->next);
168		}
169	}
170
171	/*
172	 *	Fill it in
173	 */
174
175	s->unit_minor=n;
176	s->unit_fops=fops;
177
178	/*
179	 *	Link it
180	 */
181
182	s->next=*list;
183	*list=s;
184
185
186	return n;
187}
188
189/*
190 *	Remove a node from the chain. Called with the lock asserted
191 */
192
193static struct sound_unit *__sound_remove_unit(struct sound_unit **list, int unit)
194{
195	while(*list)
196	{
197		struct sound_unit *p=*list;
198		if(p->unit_minor==unit)
199		{
200			*list=p->next;
201			return p;
202		}
203		list=&(p->next);
204	}
205	printk(KERN_ERR "Sound device %d went missing!\n", unit);
206	return NULL;
207}
208
209/*
210 *	This lock guards the sound loader list.
211 */
212
213static DEFINE_SPINLOCK(sound_loader_lock);
214
215/*
216 *	Allocate the controlling structure and add it to the sound driver
217 *	list. Acquires locks as needed
218 */
219
220static int sound_insert_unit(struct sound_unit **list, const struct file_operations *fops, int index, int low, int top, const char *name, umode_t mode, struct device *dev)
221{
222	struct sound_unit *s = kmalloc(sizeof(*s), GFP_KERNEL);
223	int r;
224
225	if (!s)
226		return -ENOMEM;
227
228	spin_lock(&sound_loader_lock);
229retry:
230	r = __sound_insert_unit(s, list, fops, index, low, top);
231	spin_unlock(&sound_loader_lock);
232
233	if (r < 0)
234		goto fail;
235	else if (r < SOUND_STEP)
236		sprintf(s->name, "sound/%s", name);
237	else
238		sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP);
239
240	if (!preclaim_oss) {
241		/*
242		 * Something else might have grabbed the minor.  If
243		 * first free slot is requested, rescan with @low set
244		 * to the next unit; otherwise, -EBUSY.
245		 */
246		r = __register_chrdev(SOUND_MAJOR, s->unit_minor, 1, s->name,
247				      &soundcore_fops);
248		if (r < 0) {
249			spin_lock(&sound_loader_lock);
250			__sound_remove_unit(list, s->unit_minor);
251			if (index < 0) {
252				low = s->unit_minor + SOUND_STEP;
253				goto retry;
254			}
255			spin_unlock(&sound_loader_lock);
256			return -EBUSY;
257		}
258	}
259
260	device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor),
261		      NULL, s->name+6);
262	return s->unit_minor;
263
264fail:
265	kfree(s);
266	return r;
267}
268
269/*
270 *	Remove a unit. Acquires locks as needed. The drivers MUST have
271 *	completed the removal before their file operations become
272 *	invalid.
273 */
274
275static void sound_remove_unit(struct sound_unit **list, int unit)
276{
277	struct sound_unit *p;
278
279	spin_lock(&sound_loader_lock);
280	p = __sound_remove_unit(list, unit);
281	spin_unlock(&sound_loader_lock);
282	if (p) {
283		if (!preclaim_oss)
284			__unregister_chrdev(SOUND_MAJOR, p->unit_minor, 1,
285					    p->name);
286		device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor));
287		kfree(p);
288	}
289}
290
291/*
292 *	Allocations
293 *
294 *	0	*16		Mixers
295 *	1	*8		Sequencers
296 *	2	*16		Midi
297 *	3	*16		DSP
298 *	4	*16		SunDSP
299 *	5	*16		DSP16
300 *	6	--		sndstat (obsolete)
301 *	7	*16		unused
302 *	8	--		alternate sequencer (see above)
303 *	9	*16		raw synthesizer access
304 *	10	*16		unused
305 *	11	*16		unused
306 *	12	*16		unused
307 *	13	*16		unused
308 *	14	*16		unused
309 *	15	*16		unused
310 */
311
312static struct sound_unit *chains[SOUND_STEP];
313
314/**
315 *	register_sound_special_device - register a special sound node
316 *	@fops: File operations for the driver
317 *	@unit: Unit number to allocate
318 *      @dev: device pointer
319 *
320 *	Allocate a special sound device by minor number from the sound
321 *	subsystem. The allocated number is returned on success. On failure
322 *	a negative error code is returned.
323 */
324
325int register_sound_special_device(const struct file_operations *fops, int unit,
326				  struct device *dev)
327{
328	const int chain = unit % SOUND_STEP;
329	int max_unit = 128 + chain;
330	const char *name;
331	char _name[16];
332
333	switch (chain) {
334	    case 0:
335		name = "mixer";
336		break;
337	    case 1:
338		name = "sequencer";
339		if (unit >= SOUND_STEP)
340			goto __unknown;
341		max_unit = unit + 1;
342		break;
343	    case 2:
344		name = "midi";
345		break;
346	    case 3:
347		name = "dsp";
348		break;
349	    case 4:
350		name = "audio";
351		break;
352	    case 8:
353		name = "sequencer2";
354		if (unit >= SOUND_STEP)
355			goto __unknown;
356		max_unit = unit + 1;
357		break;
358	    case 9:
359		name = "dmmidi";
360		break;
361	    case 10:
362		name = "dmfm";
363		break;
364	    case 12:
365		name = "adsp";
366		break;
367	    case 13:
368		name = "amidi";
369		break;
370	    case 14:
371		name = "admmidi";
372		break;
373	    default:
374	    	{
375		    __unknown:
376			sprintf(_name, "unknown%d", chain);
377		    	if (unit >= SOUND_STEP)
378		    		strcat(_name, "-");
379		    	name = _name;
380		}
381		break;
382	}
383	return sound_insert_unit(&chains[chain], fops, -1, unit, max_unit,
384				 name, S_IRUSR | S_IWUSR, dev);
385}
386
387EXPORT_SYMBOL(register_sound_special_device);
388
389int register_sound_special(const struct file_operations *fops, int unit)
390{
391	return register_sound_special_device(fops, unit, NULL);
392}
393
394EXPORT_SYMBOL(register_sound_special);
395
396/**
397 *	register_sound_mixer - register a mixer device
398 *	@fops: File operations for the driver
399 *	@dev: Unit number to allocate
400 *
401 *	Allocate a mixer device. Unit is the number of the mixer requested.
402 *	Pass -1 to request the next free mixer unit. On success the allocated
403 *	number is returned, on failure a negative error code is returned.
404 */
405
406int register_sound_mixer(const struct file_operations *fops, int dev)
407{
408	return sound_insert_unit(&chains[0], fops, dev, 0, 128,
409				 "mixer", S_IRUSR | S_IWUSR, NULL);
410}
411
412EXPORT_SYMBOL(register_sound_mixer);
413
414/**
415 *	register_sound_midi - register a midi device
416 *	@fops: File operations for the driver
417 *	@dev: Unit number to allocate
418 *
419 *	Allocate a midi device. Unit is the number of the midi device requested.
420 *	Pass -1 to request the next free midi unit. On success the allocated
421 *	number is returned, on failure a negative error code is returned.
422 */
423
424int register_sound_midi(const struct file_operations *fops, int dev)
425{
426	return sound_insert_unit(&chains[2], fops, dev, 2, 130,
427				 "midi", S_IRUSR | S_IWUSR, NULL);
428}
429
430EXPORT_SYMBOL(register_sound_midi);
431
432/*
433 *	DSP's are registered as a triple. Register only one and cheat
434 *	in open - see below.
435 */
436
437/**
438 *	register_sound_dsp - register a DSP device
439 *	@fops: File operations for the driver
440 *	@dev: Unit number to allocate
441 *
442 *	Allocate a DSP device. Unit is the number of the DSP requested.
443 *	Pass -1 to request the next free DSP unit. On success the allocated
444 *	number is returned, on failure a negative error code is returned.
445 *
446 *	This function allocates both the audio and dsp device entries together
447 *	and will always allocate them as a matching pair - eg dsp3/audio3
448 */
449
450int register_sound_dsp(const struct file_operations *fops, int dev)
451{
452	return sound_insert_unit(&chains[3], fops, dev, 3, 131,
453				 "dsp", S_IWUSR | S_IRUSR, NULL);
454}
455
456EXPORT_SYMBOL(register_sound_dsp);
457
458/**
459 *	unregister_sound_special - unregister a special sound device
460 *	@unit: unit number to allocate
461 *
462 *	Release a sound device that was allocated with
463 *	register_sound_special(). The unit passed is the return value from
464 *	the register function.
465 */
466
467
468void unregister_sound_special(int unit)
469{
470	sound_remove_unit(&chains[unit % SOUND_STEP], unit);
471}
472
473EXPORT_SYMBOL(unregister_sound_special);
474
475/**
476 *	unregister_sound_mixer - unregister a mixer
477 *	@unit: unit number to allocate
478 *
479 *	Release a sound device that was allocated with register_sound_mixer().
480 *	The unit passed is the return value from the register function.
481 */
482
483void unregister_sound_mixer(int unit)
484{
485	sound_remove_unit(&chains[0], unit);
486}
487
488EXPORT_SYMBOL(unregister_sound_mixer);
489
490/**
491 *	unregister_sound_midi - unregister a midi device
492 *	@unit: unit number to allocate
493 *
494 *	Release a sound device that was allocated with register_sound_midi().
495 *	The unit passed is the return value from the register function.
496 */
497
498void unregister_sound_midi(int unit)
499{
500	sound_remove_unit(&chains[2], unit);
501}
502
503EXPORT_SYMBOL(unregister_sound_midi);
504
505/**
506 *	unregister_sound_dsp - unregister a DSP device
507 *	@unit: unit number to allocate
508 *
509 *	Release a sound device that was allocated with register_sound_dsp().
510 *	The unit passed is the return value from the register function.
511 *
512 *	Both of the allocated units are released together automatically.
513 */
514
515void unregister_sound_dsp(int unit)
516{
517	sound_remove_unit(&chains[3], unit);
518}
519
520
521EXPORT_SYMBOL(unregister_sound_dsp);
522
523static struct sound_unit *__look_for_unit(int chain, int unit)
524{
525	struct sound_unit *s;
526
527	s=chains[chain];
528	while(s && s->unit_minor <= unit)
529	{
530		if(s->unit_minor==unit)
531			return s;
532		s=s->next;
533	}
534	return NULL;
535}
536
537static int soundcore_open(struct inode *inode, struct file *file)
538{
539	int chain;
540	int unit = iminor(inode);
541	struct sound_unit *s;
542	const struct file_operations *new_fops = NULL;
543
544	chain=unit&0x0F;
545	if(chain==4 || chain==5)	/* dsp/audio/dsp16 */
546	{
547		unit&=0xF0;
548		unit|=3;
549		chain=3;
550	}
551
552	spin_lock(&sound_loader_lock);
553	s = __look_for_unit(chain, unit);
554	if (s)
555		new_fops = fops_get(s->unit_fops);
556	if (preclaim_oss && !new_fops) {
557		spin_unlock(&sound_loader_lock);
558
559		/*
560		 *  Please, don't change this order or code.
561		 *  For ALSA slot means soundcard and OSS emulation code
562		 *  comes as add-on modules which aren't depend on
563		 *  ALSA toplevel modules for soundcards, thus we need
564		 *  load them at first.	  [Jaroslav Kysela <perex@jcu.cz>]
565		 */
566		request_module("sound-slot-%i", unit>>4);
567		request_module("sound-service-%i-%i", unit>>4, chain);
568
569		/*
570		 * sound-slot/service-* module aliases are scheduled
571		 * for removal in favor of the standard char-major-*
572		 * module aliases.  For the time being, generate both
573		 * the legacy and standard module aliases to ease
574		 * transition.
575		 */
576		if (request_module("char-major-%d-%d", SOUND_MAJOR, unit) > 0)
577			request_module("char-major-%d", SOUND_MAJOR);
578
579		spin_lock(&sound_loader_lock);
580		s = __look_for_unit(chain, unit);
581		if (s)
582			new_fops = fops_get(s->unit_fops);
583	}
584	if (new_fops) {
585		/*
586		 * We rely upon the fact that we can't be unloaded while the
587		 * subdriver is there, so if ->open() is successful we can
588		 * safely drop the reference counter and if it is not we can
589		 * revert to old ->f_op. Ugly, indeed, but that's the cost of
590		 * switching ->f_op in the first place.
591		 */
592		int err = 0;
593		const struct file_operations *old_fops = file->f_op;
594		file->f_op = new_fops;
595		spin_unlock(&sound_loader_lock);
596
597		if (file->f_op->open)
598			err = file->f_op->open(inode,file);
599
600		if (err) {
601			fops_put(file->f_op);
602			file->f_op = fops_get(old_fops);
603		}
604
605		fops_put(old_fops);
606		return err;
607	}
608	spin_unlock(&sound_loader_lock);
609	return -ENODEV;
610}
611
612MODULE_ALIAS_CHARDEV_MAJOR(SOUND_MAJOR);
613
614static void cleanup_oss_soundcore(void)
615{
616	/* We have nothing to really do here - we know the lists must be
617	   empty */
618	unregister_chrdev(SOUND_MAJOR, "sound");
619}
620
621static int __init init_oss_soundcore(void)
622{
623	if (preclaim_oss &&
624	    register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops) == -1) {
625		printk(KERN_ERR "soundcore: sound device already in use.\n");
626		return -EBUSY;
627	}
628
629	return 0;
630}
631
632#endif /* CONFIG_SOUND_OSS_CORE */
633