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