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