1/*
2 *  ALSA sequencer device management
3 *  Copyright (c) 1999 by Takashi Iwai <tiwai@suse.de>
4 *
5 *   This program is free software; you can redistribute it and/or modify
6 *   it under the terms of the GNU General Public License as published by
7 *   the Free Software Foundation; either version 2 of the License, or
8 *   (at your option) any later version.
9 *
10 *   This program is distributed in the hope that it will be useful,
11 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *   GNU General Public License for more details.
14 *
15 *   You should have received a copy of the GNU General Public License
16 *   along with this program; if not, write to the Free Software
17 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 *
19 *
20 *----------------------------------------------------------------
21 *
22 * This device handler separates the card driver module from sequencer
23 * stuff (sequencer core, synth drivers, etc), so that user can avoid
24 * to spend unnecessary resources e.g. if he needs only listening to
25 * MP3s.
26 *
27 * The card (or lowlevel) driver creates a sequencer device entry
28 * via snd_seq_device_new().  This is an entry pointer to communicate
29 * with the sequencer device "driver", which is involved with the
30 * actual part to communicate with the sequencer core.
31 * Each sequencer device entry has an id string and the corresponding
32 * driver with the same id is loaded when required.  For example,
33 * lowlevel codes to access emu8000 chip on sbawe card are included in
34 * emu8000-synth module.  To activate this module, the hardware
35 * resources like i/o port are passed via snd_seq_device argument.
36 *
37 */
38
39#include <sound/driver.h>
40#include <linux/init.h>
41#include <sound/core.h>
42#include <sound/info.h>
43#include <sound/seq_device.h>
44#include <sound/seq_kernel.h>
45#include <sound/initval.h>
46#include <linux/kmod.h>
47#include <linux/slab.h>
48#include <linux/mutex.h>
49
50MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
51MODULE_DESCRIPTION("ALSA sequencer device management");
52MODULE_LICENSE("GPL");
53
54/* driver state */
55#define DRIVER_EMPTY		0
56#define DRIVER_LOADED		(1<<0)
57#define DRIVER_REQUESTED	(1<<1)
58#define DRIVER_LOCKED		(1<<2)
59
60struct ops_list {
61	char id[ID_LEN];	/* driver id */
62	int driver;		/* driver state */
63	int used;		/* reference counter */
64	int argsize;		/* argument size */
65
66	/* operators */
67	struct snd_seq_dev_ops ops;
68
69	/* registred devices */
70	struct list_head dev_list;	/* list of devices */
71	int num_devices;	/* number of associated devices */
72	int num_init_devices;	/* number of initialized devices */
73	struct mutex reg_mutex;
74
75	struct list_head list;	/* next driver */
76};
77
78
79static LIST_HEAD(opslist);
80static int num_ops;
81static DEFINE_MUTEX(ops_mutex);
82#ifdef CONFIG_PROC_FS
83static struct snd_info_entry *info_entry;
84#endif
85
86/*
87 * prototypes
88 */
89static int snd_seq_device_free(struct snd_seq_device *dev);
90static int snd_seq_device_dev_free(struct snd_device *device);
91static int snd_seq_device_dev_register(struct snd_device *device);
92static int snd_seq_device_dev_disconnect(struct snd_device *device);
93
94static int init_device(struct snd_seq_device *dev, struct ops_list *ops);
95static int free_device(struct snd_seq_device *dev, struct ops_list *ops);
96static struct ops_list *find_driver(char *id, int create_if_empty);
97static struct ops_list *create_driver(char *id);
98static void unlock_driver(struct ops_list *ops);
99static void remove_drivers(void);
100
101/*
102 * show all drivers and their status
103 */
104
105#ifdef CONFIG_PROC_FS
106static void snd_seq_device_info(struct snd_info_entry *entry,
107				struct snd_info_buffer *buffer)
108{
109	struct ops_list *ops;
110
111	mutex_lock(&ops_mutex);
112	list_for_each_entry(ops, &opslist, list) {
113		snd_iprintf(buffer, "snd-%s%s%s%s,%d\n",
114				ops->id,
115				ops->driver & DRIVER_LOADED ? ",loaded" : (ops->driver == DRIVER_EMPTY ? ",empty" : ""),
116				ops->driver & DRIVER_REQUESTED ? ",requested" : "",
117				ops->driver & DRIVER_LOCKED ? ",locked" : "",
118				ops->num_devices);
119	}
120	mutex_unlock(&ops_mutex);
121}
122#endif
123
124/*
125 * load all registered drivers (called from seq_clientmgr.c)
126 */
127
128#ifdef CONFIG_KMOD
129/* avoid auto-loading during module_init() */
130static int snd_seq_in_init;
131void snd_seq_autoload_lock(void)
132{
133	snd_seq_in_init++;
134}
135
136void snd_seq_autoload_unlock(void)
137{
138	snd_seq_in_init--;
139}
140#endif
141
142void snd_seq_device_load_drivers(void)
143{
144#ifdef CONFIG_KMOD
145	struct ops_list *ops;
146
147	/* Calling request_module during module_init()
148	 * may cause blocking.
149	 */
150	if (snd_seq_in_init)
151		return;
152
153	if (! current->fs->root)
154		return;
155
156	mutex_lock(&ops_mutex);
157	list_for_each_entry(ops, &opslist, list) {
158		if (! (ops->driver & DRIVER_LOADED) &&
159		    ! (ops->driver & DRIVER_REQUESTED)) {
160			ops->used++;
161			mutex_unlock(&ops_mutex);
162			ops->driver |= DRIVER_REQUESTED;
163			request_module("snd-%s", ops->id);
164			mutex_lock(&ops_mutex);
165			ops->used--;
166		}
167	}
168	mutex_unlock(&ops_mutex);
169#endif
170}
171
172/*
173 * register a sequencer device
174 * card = card info (NULL allowed)
175 * device = device number (if any)
176 * id = id of driver
177 * result = return pointer (NULL allowed if unnecessary)
178 */
179int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize,
180		       struct snd_seq_device **result)
181{
182	struct snd_seq_device *dev;
183	struct ops_list *ops;
184	int err;
185	static struct snd_device_ops dops = {
186		.dev_free = snd_seq_device_dev_free,
187		.dev_register = snd_seq_device_dev_register,
188		.dev_disconnect = snd_seq_device_dev_disconnect,
189	};
190
191	if (result)
192		*result = NULL;
193
194	snd_assert(id != NULL, return -EINVAL);
195
196	ops = find_driver(id, 1);
197	if (ops == NULL)
198		return -ENOMEM;
199
200	dev = kzalloc(sizeof(*dev)*2 + argsize, GFP_KERNEL);
201	if (dev == NULL) {
202		unlock_driver(ops);
203		return -ENOMEM;
204	}
205
206	/* set up device info */
207	dev->card = card;
208	dev->device = device;
209	strlcpy(dev->id, id, sizeof(dev->id));
210	dev->argsize = argsize;
211	dev->status = SNDRV_SEQ_DEVICE_FREE;
212
213	/* add this device to the list */
214	mutex_lock(&ops->reg_mutex);
215	list_add_tail(&dev->list, &ops->dev_list);
216	ops->num_devices++;
217	mutex_unlock(&ops->reg_mutex);
218
219	unlock_driver(ops);
220
221	if ((err = snd_device_new(card, SNDRV_DEV_SEQUENCER, dev, &dops)) < 0) {
222		snd_seq_device_free(dev);
223		return err;
224	}
225
226	if (result)
227		*result = dev;
228
229	return 0;
230}
231
232/*
233 * free the existing device
234 */
235static int snd_seq_device_free(struct snd_seq_device *dev)
236{
237	struct ops_list *ops;
238
239	snd_assert(dev != NULL, return -EINVAL);
240
241	ops = find_driver(dev->id, 0);
242	if (ops == NULL)
243		return -ENXIO;
244
245	/* remove the device from the list */
246	mutex_lock(&ops->reg_mutex);
247	list_del(&dev->list);
248	ops->num_devices--;
249	mutex_unlock(&ops->reg_mutex);
250
251	free_device(dev, ops);
252	if (dev->private_free)
253		dev->private_free(dev);
254	kfree(dev);
255
256	unlock_driver(ops);
257
258	return 0;
259}
260
261static int snd_seq_device_dev_free(struct snd_device *device)
262{
263	struct snd_seq_device *dev = device->device_data;
264	return snd_seq_device_free(dev);
265}
266
267/*
268 * register the device
269 */
270static int snd_seq_device_dev_register(struct snd_device *device)
271{
272	struct snd_seq_device *dev = device->device_data;
273	struct ops_list *ops;
274
275	ops = find_driver(dev->id, 0);
276	if (ops == NULL)
277		return -ENOENT;
278
279	/* initialize this device if the corresponding driver was
280	 * already loaded
281	 */
282	if (ops->driver & DRIVER_LOADED)
283		init_device(dev, ops);
284
285	unlock_driver(ops);
286	return 0;
287}
288
289/*
290 * disconnect the device
291 */
292static int snd_seq_device_dev_disconnect(struct snd_device *device)
293{
294	struct snd_seq_device *dev = device->device_data;
295	struct ops_list *ops;
296
297	ops = find_driver(dev->id, 0);
298	if (ops == NULL)
299		return -ENOENT;
300
301	free_device(dev, ops);
302
303	unlock_driver(ops);
304	return 0;
305}
306
307/*
308 * register device driver
309 * id = driver id
310 * entry = driver operators - duplicated to each instance
311 */
312int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry,
313				   int argsize)
314{
315	struct ops_list *ops;
316	struct snd_seq_device *dev;
317
318	if (id == NULL || entry == NULL ||
319	    entry->init_device == NULL || entry->free_device == NULL)
320		return -EINVAL;
321
322	snd_seq_autoload_lock();
323	ops = find_driver(id, 1);
324	if (ops == NULL) {
325		snd_seq_autoload_unlock();
326		return -ENOMEM;
327	}
328	if (ops->driver & DRIVER_LOADED) {
329		snd_printk(KERN_WARNING "driver_register: driver '%s' already exists\n", id);
330		unlock_driver(ops);
331		snd_seq_autoload_unlock();
332		return -EBUSY;
333	}
334
335	mutex_lock(&ops->reg_mutex);
336	/* copy driver operators */
337	ops->ops = *entry;
338	ops->driver |= DRIVER_LOADED;
339	ops->argsize = argsize;
340
341	/* initialize existing devices if necessary */
342	list_for_each_entry(dev, &ops->dev_list, list) {
343		init_device(dev, ops);
344	}
345	mutex_unlock(&ops->reg_mutex);
346
347	unlock_driver(ops);
348	snd_seq_autoload_unlock();
349
350	return 0;
351}
352
353
354/*
355 * create driver record
356 */
357static struct ops_list * create_driver(char *id)
358{
359	struct ops_list *ops;
360
361	ops = kzalloc(sizeof(*ops), GFP_KERNEL);
362	if (ops == NULL)
363		return ops;
364
365	/* set up driver entry */
366	strlcpy(ops->id, id, sizeof(ops->id));
367	mutex_init(&ops->reg_mutex);
368	/*
369	 * The ->reg_mutex locking rules are per-driver, so we create
370	 * separate per-driver lock classes:
371	 */
372	lockdep_set_class(&ops->reg_mutex, (struct lock_class_key *)id);
373
374	ops->driver = DRIVER_EMPTY;
375	INIT_LIST_HEAD(&ops->dev_list);
376	/* lock this instance */
377	ops->used = 1;
378
379	/* register driver entry */
380	mutex_lock(&ops_mutex);
381	list_add_tail(&ops->list, &opslist);
382	num_ops++;
383	mutex_unlock(&ops_mutex);
384
385	return ops;
386}
387
388
389/*
390 * unregister the specified driver
391 */
392int snd_seq_device_unregister_driver(char *id)
393{
394	struct ops_list *ops;
395	struct snd_seq_device *dev;
396
397	ops = find_driver(id, 0);
398	if (ops == NULL)
399		return -ENXIO;
400	if (! (ops->driver & DRIVER_LOADED) ||
401	    (ops->driver & DRIVER_LOCKED)) {
402		snd_printk(KERN_ERR "driver_unregister: cannot unload driver '%s': status=%x\n",
403			   id, ops->driver);
404		unlock_driver(ops);
405		return -EBUSY;
406	}
407
408	/* close and release all devices associated with this driver */
409	mutex_lock(&ops->reg_mutex);
410	ops->driver |= DRIVER_LOCKED; /* do not remove this driver recursively */
411	list_for_each_entry(dev, &ops->dev_list, list) {
412		free_device(dev, ops);
413	}
414
415	ops->driver = 0;
416	if (ops->num_init_devices > 0)
417		snd_printk(KERN_ERR "free_driver: init_devices > 0!! (%d)\n",
418			   ops->num_init_devices);
419	mutex_unlock(&ops->reg_mutex);
420
421	unlock_driver(ops);
422
423	/* remove empty driver entries */
424	remove_drivers();
425
426	return 0;
427}
428
429
430/*
431 * remove empty driver entries
432 */
433static void remove_drivers(void)
434{
435	struct list_head *head;
436
437	mutex_lock(&ops_mutex);
438	head = opslist.next;
439	while (head != &opslist) {
440		struct ops_list *ops = list_entry(head, struct ops_list, list);
441		if (! (ops->driver & DRIVER_LOADED) &&
442		    ops->used == 0 && ops->num_devices == 0) {
443			head = head->next;
444			list_del(&ops->list);
445			kfree(ops);
446			num_ops--;
447		} else
448			head = head->next;
449	}
450	mutex_unlock(&ops_mutex);
451}
452
453/*
454 * initialize the device - call init_device operator
455 */
456static int init_device(struct snd_seq_device *dev, struct ops_list *ops)
457{
458	if (! (ops->driver & DRIVER_LOADED))
459		return 0; /* driver is not loaded yet */
460	if (dev->status != SNDRV_SEQ_DEVICE_FREE)
461		return 0; /* already initialized */
462	if (ops->argsize != dev->argsize) {
463		snd_printk(KERN_ERR "incompatible device '%s' for plug-in '%s' (%d %d)\n",
464			   dev->name, ops->id, ops->argsize, dev->argsize);
465		return -EINVAL;
466	}
467	if (ops->ops.init_device(dev) >= 0) {
468		dev->status = SNDRV_SEQ_DEVICE_REGISTERED;
469		ops->num_init_devices++;
470	} else {
471		snd_printk(KERN_ERR "init_device failed: %s: %s\n",
472			   dev->name, dev->id);
473	}
474
475	return 0;
476}
477
478/*
479 * release the device - call free_device operator
480 */
481static int free_device(struct snd_seq_device *dev, struct ops_list *ops)
482{
483	int result;
484
485	if (! (ops->driver & DRIVER_LOADED))
486		return 0; /* driver is not loaded yet */
487	if (dev->status != SNDRV_SEQ_DEVICE_REGISTERED)
488		return 0; /* not registered */
489	if (ops->argsize != dev->argsize) {
490		snd_printk(KERN_ERR "incompatible device '%s' for plug-in '%s' (%d %d)\n",
491			   dev->name, ops->id, ops->argsize, dev->argsize);
492		return -EINVAL;
493	}
494	if ((result = ops->ops.free_device(dev)) >= 0 || result == -ENXIO) {
495		dev->status = SNDRV_SEQ_DEVICE_FREE;
496		dev->driver_data = NULL;
497		ops->num_init_devices--;
498	} else {
499		snd_printk(KERN_ERR "free_device failed: %s: %s\n",
500			   dev->name, dev->id);
501	}
502
503	return 0;
504}
505
506/*
507 * find the matching driver with given id
508 */
509static struct ops_list * find_driver(char *id, int create_if_empty)
510{
511	struct ops_list *ops;
512
513	mutex_lock(&ops_mutex);
514	list_for_each_entry(ops, &opslist, list) {
515		if (strcmp(ops->id, id) == 0) {
516			ops->used++;
517			mutex_unlock(&ops_mutex);
518			return ops;
519		}
520	}
521	mutex_unlock(&ops_mutex);
522	if (create_if_empty)
523		return create_driver(id);
524	return NULL;
525}
526
527static void unlock_driver(struct ops_list *ops)
528{
529	mutex_lock(&ops_mutex);
530	ops->used--;
531	mutex_unlock(&ops_mutex);
532}
533
534
535/*
536 * module part
537 */
538
539static int __init alsa_seq_device_init(void)
540{
541#ifdef CONFIG_PROC_FS
542	info_entry = snd_info_create_module_entry(THIS_MODULE, "drivers",
543						  snd_seq_root);
544	if (info_entry == NULL)
545		return -ENOMEM;
546	info_entry->content = SNDRV_INFO_CONTENT_TEXT;
547	info_entry->c.text.read = snd_seq_device_info;
548	if (snd_info_register(info_entry) < 0) {
549		snd_info_free_entry(info_entry);
550		return -ENOMEM;
551	}
552#endif
553	return 0;
554}
555
556static void __exit alsa_seq_device_exit(void)
557{
558	remove_drivers();
559#ifdef CONFIG_PROC_FS
560	snd_info_free_entry(info_entry);
561#endif
562	if (num_ops)
563		snd_printk(KERN_ERR "drivers not released (%d)\n", num_ops);
564}
565
566module_init(alsa_seq_device_init)
567module_exit(alsa_seq_device_exit)
568
569EXPORT_SYMBOL(snd_seq_device_load_drivers);
570EXPORT_SYMBOL(snd_seq_device_new);
571EXPORT_SYMBOL(snd_seq_device_register_driver);
572EXPORT_SYMBOL(snd_seq_device_unregister_driver);
573#ifdef CONFIG_KMOD
574EXPORT_SYMBOL(snd_seq_autoload_lock);
575EXPORT_SYMBOL(snd_seq_autoload_unlock);
576#endif
577