• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <linux/init.h>
40 #include <linux/module.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 
50 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
51 MODULE_DESCRIPTION("ALSA sequencer device management");
52 MODULE_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 
60 struct 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 	/* registered 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 
79 static LIST_HEAD(opslist);
80 static int num_ops;
81 static DEFINE_MUTEX(ops_mutex);
82 #ifdef CONFIG_PROC_FS
83 static struct snd_info_entry *info_entry;
84 #endif
85 
86 /*
87  * prototypes
88  */
89 static int snd_seq_device_free(struct snd_seq_device *dev);
90 static int snd_seq_device_dev_free(struct snd_device *device);
91 static int snd_seq_device_dev_register(struct snd_device *device);
92 static int snd_seq_device_dev_disconnect(struct snd_device *device);
93 
94 static int init_device(struct snd_seq_device *dev, struct ops_list *ops);
95 static int free_device(struct snd_seq_device *dev, struct ops_list *ops);
96 static struct ops_list *find_driver(char *id, int create_if_empty);
97 static struct ops_list *create_driver(char *id);
98 static void unlock_driver(struct ops_list *ops);
99 static void remove_drivers(void);
100 
101 /*
102  * show all drivers and their status
103  */
104 
105 #ifdef CONFIG_PROC_FS
snd_seq_device_info(struct snd_info_entry * entry,struct snd_info_buffer * buffer)106 static 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_MODULES
129 /* avoid auto-loading during module_init() */
130 static int snd_seq_in_init;
snd_seq_autoload_lock(void)131 void snd_seq_autoload_lock(void)
132 {
133 	snd_seq_in_init++;
134 }
135 
snd_seq_autoload_unlock(void)136 void snd_seq_autoload_unlock(void)
137 {
138 	snd_seq_in_init--;
139 }
140 #endif
141 
snd_seq_device_load_drivers(void)142 void snd_seq_device_load_drivers(void)
143 {
144 #ifdef CONFIG_MODULES
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 	mutex_lock(&ops_mutex);
154 	list_for_each_entry(ops, &opslist, list) {
155 		if (! (ops->driver & DRIVER_LOADED) &&
156 		    ! (ops->driver & DRIVER_REQUESTED)) {
157 			ops->used++;
158 			mutex_unlock(&ops_mutex);
159 			ops->driver |= DRIVER_REQUESTED;
160 			request_module("snd-%s", ops->id);
161 			mutex_lock(&ops_mutex);
162 			ops->used--;
163 		}
164 	}
165 	mutex_unlock(&ops_mutex);
166 #endif
167 }
168 
169 /*
170  * register a sequencer device
171  * card = card info (NULL allowed)
172  * device = device number (if any)
173  * id = id of driver
174  * result = return pointer (NULL allowed if unnecessary)
175  */
snd_seq_device_new(struct snd_card * card,int device,char * id,int argsize,struct snd_seq_device ** result)176 int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize,
177 		       struct snd_seq_device **result)
178 {
179 	struct snd_seq_device *dev;
180 	struct ops_list *ops;
181 	int err;
182 	static struct snd_device_ops dops = {
183 		.dev_free = snd_seq_device_dev_free,
184 		.dev_register = snd_seq_device_dev_register,
185 		.dev_disconnect = snd_seq_device_dev_disconnect,
186 	};
187 
188 	if (result)
189 		*result = NULL;
190 
191 	if (snd_BUG_ON(!id))
192 		return -EINVAL;
193 
194 	ops = find_driver(id, 1);
195 	if (ops == NULL)
196 		return -ENOMEM;
197 
198 	dev = kzalloc(sizeof(*dev)*2 + argsize, GFP_KERNEL);
199 	if (dev == NULL) {
200 		unlock_driver(ops);
201 		return -ENOMEM;
202 	}
203 
204 	/* set up device info */
205 	dev->card = card;
206 	dev->device = device;
207 	strlcpy(dev->id, id, sizeof(dev->id));
208 	dev->argsize = argsize;
209 	dev->status = SNDRV_SEQ_DEVICE_FREE;
210 
211 	/* add this device to the list */
212 	mutex_lock(&ops->reg_mutex);
213 	list_add_tail(&dev->list, &ops->dev_list);
214 	ops->num_devices++;
215 	mutex_unlock(&ops->reg_mutex);
216 
217 	unlock_driver(ops);
218 
219 	if ((err = snd_device_new(card, SNDRV_DEV_SEQUENCER, dev, &dops)) < 0) {
220 		snd_seq_device_free(dev);
221 		return err;
222 	}
223 
224 	if (result)
225 		*result = dev;
226 
227 	return 0;
228 }
229 
230 /*
231  * free the existing device
232  */
snd_seq_device_free(struct snd_seq_device * dev)233 static int snd_seq_device_free(struct snd_seq_device *dev)
234 {
235 	struct ops_list *ops;
236 
237 	if (snd_BUG_ON(!dev))
238 		return -EINVAL;
239 
240 	ops = find_driver(dev->id, 0);
241 	if (ops == NULL)
242 		return -ENXIO;
243 
244 	/* remove the device from the list */
245 	mutex_lock(&ops->reg_mutex);
246 	list_del(&dev->list);
247 	ops->num_devices--;
248 	mutex_unlock(&ops->reg_mutex);
249 
250 	free_device(dev, ops);
251 	if (dev->private_free)
252 		dev->private_free(dev);
253 	kfree(dev);
254 
255 	unlock_driver(ops);
256 
257 	return 0;
258 }
259 
snd_seq_device_dev_free(struct snd_device * device)260 static int snd_seq_device_dev_free(struct snd_device *device)
261 {
262 	struct snd_seq_device *dev = device->device_data;
263 	return snd_seq_device_free(dev);
264 }
265 
266 /*
267  * register the device
268  */
snd_seq_device_dev_register(struct snd_device * device)269 static int snd_seq_device_dev_register(struct snd_device *device)
270 {
271 	struct snd_seq_device *dev = device->device_data;
272 	struct ops_list *ops;
273 
274 	ops = find_driver(dev->id, 0);
275 	if (ops == NULL)
276 		return -ENOENT;
277 
278 	/* initialize this device if the corresponding driver was
279 	 * already loaded
280 	 */
281 	if (ops->driver & DRIVER_LOADED)
282 		init_device(dev, ops);
283 
284 	unlock_driver(ops);
285 	return 0;
286 }
287 
288 /*
289  * disconnect the device
290  */
snd_seq_device_dev_disconnect(struct snd_device * device)291 static int snd_seq_device_dev_disconnect(struct snd_device *device)
292 {
293 	struct snd_seq_device *dev = device->device_data;
294 	struct ops_list *ops;
295 
296 	ops = find_driver(dev->id, 0);
297 	if (ops == NULL)
298 		return -ENOENT;
299 
300 	free_device(dev, ops);
301 
302 	unlock_driver(ops);
303 	return 0;
304 }
305 
306 /*
307  * register device driver
308  * id = driver id
309  * entry = driver operators - duplicated to each instance
310  */
snd_seq_device_register_driver(char * id,struct snd_seq_dev_ops * entry,int argsize)311 int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry,
312 				   int argsize)
313 {
314 	struct ops_list *ops;
315 	struct snd_seq_device *dev;
316 
317 	if (id == NULL || entry == NULL ||
318 	    entry->init_device == NULL || entry->free_device == NULL)
319 		return -EINVAL;
320 
321 	snd_seq_autoload_lock();
322 	ops = find_driver(id, 1);
323 	if (ops == NULL) {
324 		snd_seq_autoload_unlock();
325 		return -ENOMEM;
326 	}
327 	if (ops->driver & DRIVER_LOADED) {
328 		snd_printk(KERN_WARNING "driver_register: driver '%s' already exists\n", id);
329 		unlock_driver(ops);
330 		snd_seq_autoload_unlock();
331 		return -EBUSY;
332 	}
333 
334 	mutex_lock(&ops->reg_mutex);
335 	/* copy driver operators */
336 	ops->ops = *entry;
337 	ops->driver |= DRIVER_LOADED;
338 	ops->argsize = argsize;
339 
340 	/* initialize existing devices if necessary */
341 	list_for_each_entry(dev, &ops->dev_list, list) {
342 		init_device(dev, ops);
343 	}
344 	mutex_unlock(&ops->reg_mutex);
345 
346 	unlock_driver(ops);
347 	snd_seq_autoload_unlock();
348 
349 	return 0;
350 }
351 
352 
353 /*
354  * create driver record
355  */
create_driver(char * id)356 static struct ops_list * create_driver(char *id)
357 {
358 	struct ops_list *ops;
359 
360 	ops = kzalloc(sizeof(*ops), GFP_KERNEL);
361 	if (ops == NULL)
362 		return ops;
363 
364 	/* set up driver entry */
365 	strlcpy(ops->id, id, sizeof(ops->id));
366 	mutex_init(&ops->reg_mutex);
367 	/*
368 	 * The ->reg_mutex locking rules are per-driver, so we create
369 	 * separate per-driver lock classes:
370 	 */
371 	lockdep_set_class(&ops->reg_mutex, (struct lock_class_key *)id);
372 
373 	ops->driver = DRIVER_EMPTY;
374 	INIT_LIST_HEAD(&ops->dev_list);
375 	/* lock this instance */
376 	ops->used = 1;
377 
378 	/* register driver entry */
379 	mutex_lock(&ops_mutex);
380 	list_add_tail(&ops->list, &opslist);
381 	num_ops++;
382 	mutex_unlock(&ops_mutex);
383 
384 	return ops;
385 }
386 
387 
388 /*
389  * unregister the specified driver
390  */
snd_seq_device_unregister_driver(char * id)391 int snd_seq_device_unregister_driver(char *id)
392 {
393 	struct ops_list *ops;
394 	struct snd_seq_device *dev;
395 
396 	ops = find_driver(id, 0);
397 	if (ops == NULL)
398 		return -ENXIO;
399 	if (! (ops->driver & DRIVER_LOADED) ||
400 	    (ops->driver & DRIVER_LOCKED)) {
401 		snd_printk(KERN_ERR "driver_unregister: cannot unload driver '%s': status=%x\n",
402 			   id, ops->driver);
403 		unlock_driver(ops);
404 		return -EBUSY;
405 	}
406 
407 	/* close and release all devices associated with this driver */
408 	mutex_lock(&ops->reg_mutex);
409 	ops->driver |= DRIVER_LOCKED; /* do not remove this driver recursively */
410 	list_for_each_entry(dev, &ops->dev_list, list) {
411 		free_device(dev, ops);
412 	}
413 
414 	ops->driver = 0;
415 	if (ops->num_init_devices > 0)
416 		snd_printk(KERN_ERR "free_driver: init_devices > 0!! (%d)\n",
417 			   ops->num_init_devices);
418 	mutex_unlock(&ops->reg_mutex);
419 
420 	unlock_driver(ops);
421 
422 	/* remove empty driver entries */
423 	remove_drivers();
424 
425 	return 0;
426 }
427 
428 
429 /*
430  * remove empty driver entries
431  */
remove_drivers(void)432 static void remove_drivers(void)
433 {
434 	struct list_head *head;
435 
436 	mutex_lock(&ops_mutex);
437 	head = opslist.next;
438 	while (head != &opslist) {
439 		struct ops_list *ops = list_entry(head, struct ops_list, list);
440 		if (! (ops->driver & DRIVER_LOADED) &&
441 		    ops->used == 0 && ops->num_devices == 0) {
442 			head = head->next;
443 			list_del(&ops->list);
444 			kfree(ops);
445 			num_ops--;
446 		} else
447 			head = head->next;
448 	}
449 	mutex_unlock(&ops_mutex);
450 }
451 
452 /*
453  * initialize the device - call init_device operator
454  */
init_device(struct snd_seq_device * dev,struct ops_list * ops)455 static int init_device(struct snd_seq_device *dev, struct ops_list *ops)
456 {
457 	if (! (ops->driver & DRIVER_LOADED))
458 		return 0; /* driver is not loaded yet */
459 	if (dev->status != SNDRV_SEQ_DEVICE_FREE)
460 		return 0; /* already initialized */
461 	if (ops->argsize != dev->argsize) {
462 		snd_printk(KERN_ERR "incompatible device '%s' for plug-in '%s' (%d %d)\n",
463 			   dev->name, ops->id, ops->argsize, dev->argsize);
464 		return -EINVAL;
465 	}
466 	if (ops->ops.init_device(dev) >= 0) {
467 		dev->status = SNDRV_SEQ_DEVICE_REGISTERED;
468 		ops->num_init_devices++;
469 	} else {
470 		snd_printk(KERN_ERR "init_device failed: %s: %s\n",
471 			   dev->name, dev->id);
472 	}
473 
474 	return 0;
475 }
476 
477 /*
478  * release the device - call free_device operator
479  */
free_device(struct snd_seq_device * dev,struct ops_list * ops)480 static int free_device(struct snd_seq_device *dev, struct ops_list *ops)
481 {
482 	int result;
483 
484 	if (! (ops->driver & DRIVER_LOADED))
485 		return 0; /* driver is not loaded yet */
486 	if (dev->status != SNDRV_SEQ_DEVICE_REGISTERED)
487 		return 0; /* not registered */
488 	if (ops->argsize != dev->argsize) {
489 		snd_printk(KERN_ERR "incompatible device '%s' for plug-in '%s' (%d %d)\n",
490 			   dev->name, ops->id, ops->argsize, dev->argsize);
491 		return -EINVAL;
492 	}
493 	if ((result = ops->ops.free_device(dev)) >= 0 || result == -ENXIO) {
494 		dev->status = SNDRV_SEQ_DEVICE_FREE;
495 		dev->driver_data = NULL;
496 		ops->num_init_devices--;
497 	} else {
498 		snd_printk(KERN_ERR "free_device failed: %s: %s\n",
499 			   dev->name, dev->id);
500 	}
501 
502 	return 0;
503 }
504 
505 /*
506  * find the matching driver with given id
507  */
find_driver(char * id,int create_if_empty)508 static struct ops_list * find_driver(char *id, int create_if_empty)
509 {
510 	struct ops_list *ops;
511 
512 	mutex_lock(&ops_mutex);
513 	list_for_each_entry(ops, &opslist, list) {
514 		if (strcmp(ops->id, id) == 0) {
515 			ops->used++;
516 			mutex_unlock(&ops_mutex);
517 			return ops;
518 		}
519 	}
520 	mutex_unlock(&ops_mutex);
521 	if (create_if_empty)
522 		return create_driver(id);
523 	return NULL;
524 }
525 
unlock_driver(struct ops_list * ops)526 static void unlock_driver(struct ops_list *ops)
527 {
528 	mutex_lock(&ops_mutex);
529 	ops->used--;
530 	mutex_unlock(&ops_mutex);
531 }
532 
533 
534 /*
535  * module part
536  */
537 
alsa_seq_device_init(void)538 static int __init alsa_seq_device_init(void)
539 {
540 #ifdef CONFIG_PROC_FS
541 	info_entry = snd_info_create_module_entry(THIS_MODULE, "drivers",
542 						  snd_seq_root);
543 	if (info_entry == NULL)
544 		return -ENOMEM;
545 	info_entry->content = SNDRV_INFO_CONTENT_TEXT;
546 	info_entry->c.text.read = snd_seq_device_info;
547 	if (snd_info_register(info_entry) < 0) {
548 		snd_info_free_entry(info_entry);
549 		return -ENOMEM;
550 	}
551 #endif
552 	return 0;
553 }
554 
alsa_seq_device_exit(void)555 static void __exit alsa_seq_device_exit(void)
556 {
557 	remove_drivers();
558 #ifdef CONFIG_PROC_FS
559 	snd_info_free_entry(info_entry);
560 #endif
561 	if (num_ops)
562 		snd_printk(KERN_ERR "drivers not released (%d)\n", num_ops);
563 }
564 
565 module_init(alsa_seq_device_init)
566 module_exit(alsa_seq_device_exit)
567 
568 EXPORT_SYMBOL(snd_seq_device_load_drivers);
569 EXPORT_SYMBOL(snd_seq_device_new);
570 EXPORT_SYMBOL(snd_seq_device_register_driver);
571 EXPORT_SYMBOL(snd_seq_device_unregister_driver);
572 #ifdef CONFIG_MODULES
573 EXPORT_SYMBOL(snd_seq_autoload_lock);
574 EXPORT_SYMBOL(snd_seq_autoload_unlock);
575 #endif
576