1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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
50MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
51MODULE_DESCRIPTION("ALSA sequencer device management");
52MODULE_LICENSE("GPL");
53
54
55#define DRIVER_EMPTY 0
56#define DRIVER_LOADED (1<<0)
57#define DRIVER_REQUESTED (1<<1)
58#define DRIVER_LOCKED (1<<2)
59#define DRIVER_REQUESTING (1<<3)
60
61struct ops_list {
62 char id[ID_LEN];
63 int driver;
64 int used;
65 int argsize;
66
67
68 struct snd_seq_dev_ops ops;
69
70
71 struct list_head dev_list;
72 int num_devices;
73 int num_init_devices;
74 struct mutex reg_mutex;
75
76 struct list_head list;
77};
78
79
80static LIST_HEAD(opslist);
81static int num_ops;
82static DEFINE_MUTEX(ops_mutex);
83#ifdef CONFIG_PROC_FS
84static struct snd_info_entry *info_entry;
85#endif
86
87
88
89
90static int snd_seq_device_free(struct snd_seq_device *dev);
91static int snd_seq_device_dev_free(struct snd_device *device);
92static int snd_seq_device_dev_register(struct snd_device *device);
93static int snd_seq_device_dev_disconnect(struct snd_device *device);
94
95static int init_device(struct snd_seq_device *dev, struct ops_list *ops);
96static int free_device(struct snd_seq_device *dev, struct ops_list *ops);
97static struct ops_list *find_driver(char *id, int create_if_empty);
98static struct ops_list *create_driver(char *id);
99static void unlock_driver(struct ops_list *ops);
100static void remove_drivers(void);
101
102
103
104
105
106#ifdef CONFIG_PROC_FS
107static void snd_seq_device_info(struct snd_info_entry *entry,
108 struct snd_info_buffer *buffer)
109{
110 struct ops_list *ops;
111
112 mutex_lock(&ops_mutex);
113 list_for_each_entry(ops, &opslist, list) {
114 snd_iprintf(buffer, "snd-%s%s%s%s,%d\n",
115 ops->id,
116 ops->driver & DRIVER_LOADED ? ",loaded" : (ops->driver == DRIVER_EMPTY ? ",empty" : ""),
117 ops->driver & DRIVER_REQUESTED ? ",requested" : "",
118 ops->driver & DRIVER_LOCKED ? ",locked" : "",
119 ops->num_devices);
120 }
121 mutex_unlock(&ops_mutex);
122}
123#endif
124
125
126
127
128
129#ifdef CONFIG_MODULES
130
131static atomic_t snd_seq_in_init = ATOMIC_INIT(1);
132void snd_seq_autoload_lock(void)
133{
134 atomic_inc(&snd_seq_in_init);
135}
136
137void snd_seq_autoload_unlock(void)
138{
139 atomic_dec(&snd_seq_in_init);
140}
141
142static void autoload_drivers(void)
143{
144
145 if (atomic_inc_return(&snd_seq_in_init) == 1) {
146 struct ops_list *ops;
147
148 mutex_lock(&ops_mutex);
149 list_for_each_entry(ops, &opslist, list) {
150 if ((ops->driver & DRIVER_REQUESTING) &&
151 !(ops->driver & DRIVER_REQUESTED)) {
152 ops->used++;
153 mutex_unlock(&ops_mutex);
154 ops->driver |= DRIVER_REQUESTED;
155 request_module("snd-%s", ops->id);
156 mutex_lock(&ops_mutex);
157 ops->used--;
158 }
159 }
160 mutex_unlock(&ops_mutex);
161 }
162 atomic_dec(&snd_seq_in_init);
163}
164
165static void call_autoload(struct work_struct *work)
166{
167 autoload_drivers();
168}
169
170static DECLARE_WORK(autoload_work, call_autoload);
171
172static void try_autoload(struct ops_list *ops)
173{
174 if (!ops->driver) {
175 ops->driver |= DRIVER_REQUESTING;
176 schedule_work(&autoload_work);
177 }
178}
179
180static void queue_autoload_drivers(void)
181{
182 struct ops_list *ops;
183
184 mutex_lock(&ops_mutex);
185 list_for_each_entry(ops, &opslist, list)
186 try_autoload(ops);
187 mutex_unlock(&ops_mutex);
188}
189
190void snd_seq_autoload_init(void)
191{
192 atomic_dec(&snd_seq_in_init);
193#ifdef CONFIG_SND_SEQUENCER_MODULE
194
195 queue_autoload_drivers();
196#endif
197}
198#else
199#define try_autoload(ops)
200#endif
201
202void snd_seq_device_load_drivers(void)
203{
204#ifdef CONFIG_MODULES
205 queue_autoload_drivers();
206 flush_work(&autoload_work);
207#endif
208}
209
210
211
212
213
214
215
216
217int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize,
218 struct snd_seq_device **result)
219{
220 struct snd_seq_device *dev;
221 struct ops_list *ops;
222 int err;
223 static struct snd_device_ops dops = {
224 .dev_free = snd_seq_device_dev_free,
225 .dev_register = snd_seq_device_dev_register,
226 .dev_disconnect = snd_seq_device_dev_disconnect,
227 };
228
229 if (result)
230 *result = NULL;
231
232 if (snd_BUG_ON(!id))
233 return -EINVAL;
234
235 ops = find_driver(id, 1);
236 if (ops == NULL)
237 return -ENOMEM;
238
239 dev = kzalloc(sizeof(*dev)*2 + argsize, GFP_KERNEL);
240 if (dev == NULL) {
241 unlock_driver(ops);
242 return -ENOMEM;
243 }
244
245
246 dev->card = card;
247 dev->device = device;
248 strlcpy(dev->id, id, sizeof(dev->id));
249 dev->argsize = argsize;
250 dev->status = SNDRV_SEQ_DEVICE_FREE;
251
252
253 mutex_lock(&ops->reg_mutex);
254 list_add_tail(&dev->list, &ops->dev_list);
255 ops->num_devices++;
256 mutex_unlock(&ops->reg_mutex);
257
258 if ((err = snd_device_new(card, SNDRV_DEV_SEQUENCER, dev, &dops)) < 0) {
259 snd_seq_device_free(dev);
260 return err;
261 }
262
263 try_autoload(ops);
264 unlock_driver(ops);
265
266 if (result)
267 *result = dev;
268
269 return 0;
270}
271
272
273
274
275static int snd_seq_device_free(struct snd_seq_device *dev)
276{
277 struct ops_list *ops;
278
279 if (snd_BUG_ON(!dev))
280 return -EINVAL;
281
282 ops = find_driver(dev->id, 0);
283 if (ops == NULL)
284 return -ENXIO;
285
286
287 mutex_lock(&ops->reg_mutex);
288 list_del(&dev->list);
289 ops->num_devices--;
290 mutex_unlock(&ops->reg_mutex);
291
292 free_device(dev, ops);
293 if (dev->private_free)
294 dev->private_free(dev);
295 kfree(dev);
296
297 unlock_driver(ops);
298
299 return 0;
300}
301
302static int snd_seq_device_dev_free(struct snd_device *device)
303{
304 struct snd_seq_device *dev = device->device_data;
305 return snd_seq_device_free(dev);
306}
307
308
309
310
311static int snd_seq_device_dev_register(struct snd_device *device)
312{
313 struct snd_seq_device *dev = device->device_data;
314 struct ops_list *ops;
315
316 ops = find_driver(dev->id, 0);
317 if (ops == NULL)
318 return -ENOENT;
319
320
321
322
323 if (ops->driver & DRIVER_LOADED)
324 init_device(dev, ops);
325
326 unlock_driver(ops);
327 return 0;
328}
329
330
331
332
333static int snd_seq_device_dev_disconnect(struct snd_device *device)
334{
335 struct snd_seq_device *dev = device->device_data;
336 struct ops_list *ops;
337
338 ops = find_driver(dev->id, 0);
339 if (ops == NULL)
340 return -ENOENT;
341
342 free_device(dev, ops);
343
344 unlock_driver(ops);
345 return 0;
346}
347
348
349
350
351
352
353int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry,
354 int argsize)
355{
356 struct ops_list *ops;
357 struct snd_seq_device *dev;
358
359 if (id == NULL || entry == NULL ||
360 entry->init_device == NULL || entry->free_device == NULL)
361 return -EINVAL;
362
363 ops = find_driver(id, 1);
364 if (ops == NULL)
365 return -ENOMEM;
366 if (ops->driver & DRIVER_LOADED) {
367 pr_warn("ALSA: seq: driver_register: driver '%s' already exists\n", id);
368 unlock_driver(ops);
369 return -EBUSY;
370 }
371
372 mutex_lock(&ops->reg_mutex);
373
374 ops->ops = *entry;
375 ops->driver |= DRIVER_LOADED;
376 ops->argsize = argsize;
377
378
379 list_for_each_entry(dev, &ops->dev_list, list) {
380 init_device(dev, ops);
381 }
382 mutex_unlock(&ops->reg_mutex);
383
384 unlock_driver(ops);
385
386 return 0;
387}
388
389
390
391
392
393static struct ops_list * create_driver(char *id)
394{
395 struct ops_list *ops;
396
397 ops = kzalloc(sizeof(*ops), GFP_KERNEL);
398 if (ops == NULL)
399 return ops;
400
401
402 strlcpy(ops->id, id, sizeof(ops->id));
403 mutex_init(&ops->reg_mutex);
404
405
406
407
408 lockdep_set_class(&ops->reg_mutex, (struct lock_class_key *)id);
409
410 ops->driver = DRIVER_EMPTY;
411 INIT_LIST_HEAD(&ops->dev_list);
412
413 ops->used = 1;
414
415
416 mutex_lock(&ops_mutex);
417 list_add_tail(&ops->list, &opslist);
418 num_ops++;
419 mutex_unlock(&ops_mutex);
420
421 return ops;
422}
423
424
425
426
427
428int snd_seq_device_unregister_driver(char *id)
429{
430 struct ops_list *ops;
431 struct snd_seq_device *dev;
432
433 ops = find_driver(id, 0);
434 if (ops == NULL)
435 return -ENXIO;
436 if (! (ops->driver & DRIVER_LOADED) ||
437 (ops->driver & DRIVER_LOCKED)) {
438 pr_err("ALSA: seq: driver_unregister: cannot unload driver '%s': status=%x\n",
439 id, ops->driver);
440 unlock_driver(ops);
441 return -EBUSY;
442 }
443
444
445 mutex_lock(&ops->reg_mutex);
446 ops->driver |= DRIVER_LOCKED;
447 list_for_each_entry(dev, &ops->dev_list, list) {
448 free_device(dev, ops);
449 }
450
451 ops->driver = 0;
452 if (ops->num_init_devices > 0)
453 pr_err("ALSA: seq: free_driver: init_devices > 0!! (%d)\n",
454 ops->num_init_devices);
455 mutex_unlock(&ops->reg_mutex);
456
457 unlock_driver(ops);
458
459
460 remove_drivers();
461
462 return 0;
463}
464
465
466
467
468
469static void remove_drivers(void)
470{
471 struct list_head *head;
472
473 mutex_lock(&ops_mutex);
474 head = opslist.next;
475 while (head != &opslist) {
476 struct ops_list *ops = list_entry(head, struct ops_list, list);
477 if (! (ops->driver & DRIVER_LOADED) &&
478 ops->used == 0 && ops->num_devices == 0) {
479 head = head->next;
480 list_del(&ops->list);
481 kfree(ops);
482 num_ops--;
483 } else
484 head = head->next;
485 }
486 mutex_unlock(&ops_mutex);
487}
488
489
490
491
492static int init_device(struct snd_seq_device *dev, struct ops_list *ops)
493{
494 if (! (ops->driver & DRIVER_LOADED))
495 return 0;
496 if (dev->status != SNDRV_SEQ_DEVICE_FREE)
497 return 0;
498 if (ops->argsize != dev->argsize) {
499 pr_err("ALSA: seq: incompatible device '%s' for plug-in '%s' (%d %d)\n",
500 dev->name, ops->id, ops->argsize, dev->argsize);
501 return -EINVAL;
502 }
503 if (ops->ops.init_device(dev) >= 0) {
504 dev->status = SNDRV_SEQ_DEVICE_REGISTERED;
505 ops->num_init_devices++;
506 } else {
507 pr_err("ALSA: seq: init_device failed: %s: %s\n",
508 dev->name, dev->id);
509 }
510
511 return 0;
512}
513
514
515
516
517static int free_device(struct snd_seq_device *dev, struct ops_list *ops)
518{
519 int result;
520
521 if (! (ops->driver & DRIVER_LOADED))
522 return 0;
523 if (dev->status != SNDRV_SEQ_DEVICE_REGISTERED)
524 return 0;
525 if (ops->argsize != dev->argsize) {
526 pr_err("ALSA: seq: incompatible device '%s' for plug-in '%s' (%d %d)\n",
527 dev->name, ops->id, ops->argsize, dev->argsize);
528 return -EINVAL;
529 }
530 if ((result = ops->ops.free_device(dev)) >= 0 || result == -ENXIO) {
531 dev->status = SNDRV_SEQ_DEVICE_FREE;
532 dev->driver_data = NULL;
533 ops->num_init_devices--;
534 } else {
535 pr_err("ALSA: seq: free_device failed: %s: %s\n",
536 dev->name, dev->id);
537 }
538
539 return 0;
540}
541
542
543
544
545static struct ops_list * find_driver(char *id, int create_if_empty)
546{
547 struct ops_list *ops;
548
549 mutex_lock(&ops_mutex);
550 list_for_each_entry(ops, &opslist, list) {
551 if (strcmp(ops->id, id) == 0) {
552 ops->used++;
553 mutex_unlock(&ops_mutex);
554 return ops;
555 }
556 }
557 mutex_unlock(&ops_mutex);
558 if (create_if_empty)
559 return create_driver(id);
560 return NULL;
561}
562
563static void unlock_driver(struct ops_list *ops)
564{
565 mutex_lock(&ops_mutex);
566 ops->used--;
567 mutex_unlock(&ops_mutex);
568}
569
570
571
572
573
574
575static int __init alsa_seq_device_init(void)
576{
577#ifdef CONFIG_PROC_FS
578 info_entry = snd_info_create_module_entry(THIS_MODULE, "drivers",
579 snd_seq_root);
580 if (info_entry == NULL)
581 return -ENOMEM;
582 info_entry->content = SNDRV_INFO_CONTENT_TEXT;
583 info_entry->c.text.read = snd_seq_device_info;
584 if (snd_info_register(info_entry) < 0) {
585 snd_info_free_entry(info_entry);
586 return -ENOMEM;
587 }
588#endif
589 return 0;
590}
591
592static void __exit alsa_seq_device_exit(void)
593{
594#ifdef CONFIG_MODULES
595 cancel_work_sync(&autoload_work);
596#endif
597 remove_drivers();
598#ifdef CONFIG_PROC_FS
599 snd_info_free_entry(info_entry);
600#endif
601 if (num_ops)
602 pr_err("ALSA: seq: drivers not released (%d)\n", num_ops);
603}
604
605module_init(alsa_seq_device_init)
606module_exit(alsa_seq_device_exit)
607
608EXPORT_SYMBOL(snd_seq_device_load_drivers);
609EXPORT_SYMBOL(snd_seq_device_new);
610EXPORT_SYMBOL(snd_seq_device_register_driver);
611EXPORT_SYMBOL(snd_seq_device_unregister_driver);
612#ifdef CONFIG_MODULES
613EXPORT_SYMBOL(snd_seq_autoload_init);
614EXPORT_SYMBOL(snd_seq_autoload_lock);
615EXPORT_SYMBOL(snd_seq_autoload_unlock);
616#endif
617