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