1 /* 2 * Advanced Linux Sound Architecture 3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz> 4 * 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 */ 21 22 #include <sound/driver.h> 23 #include <linux/init.h> 24 #include <linux/slab.h> 25 #include <linux/time.h> 26 #include <linux/moduleparam.h> 27 #include <sound/core.h> 28 #include <sound/minors.h> 29 #include <sound/info.h> 30 #include <sound/version.h> 31 #include <sound/control.h> 32 #include <sound/initval.h> 33 #include <linux/kmod.h> 34 #include <linux/devfs_fs_kernel.h> 35 #include <linux/device.h> 36 37 #define SNDRV_OS_MINORS 256 38 39 static int major = CONFIG_SND_MAJOR; 40 int snd_major; 41 static int cards_limit = 1; 42 static int device_mode = S_IFCHR | S_IRUGO | S_IWUGO; 43 44 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); 45 MODULE_DESCRIPTION("Advanced Linux Sound Architecture driver for soundcards."); 46 MODULE_LICENSE("GPL"); 47 module_param(major, int, 0444); 48 MODULE_PARM_DESC(major, "Major # for sound driver."); 49 module_param(cards_limit, int, 0444); 50 MODULE_PARM_DESC(cards_limit, "Count of auto-loadable soundcards."); 51 #ifdef CONFIG_DEVFS_FS 52 module_param(device_mode, int, 0444); 53 MODULE_PARM_DESC(device_mode, "Device file permission mask for devfs."); 54 #endif 55 MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR); 56 57 /* this one holds the actual max. card number currently available. 58 * as default, it's identical with cards_limit option. when more 59 * modules are loaded manually, this limit number increases, too. 60 */ 61 int snd_ecards_limit; 62 63 static struct list_head snd_minors_hash[SNDRV_CARDS]; 64 65 static DECLARE_MUTEX(sound_mutex); 66 67 extern struct class *sound_class; 68 69 70 #ifdef CONFIG_KMOD 71 72 /** 73 * snd_request_card - try to load the card module 74 * @card: the card number 75 * 76 * Tries to load the module "snd-card-X" for the given card number 77 * via KMOD. Returns immediately if already loaded. 78 */ 79 void snd_request_card(int card) 80 { 81 int locked; 82 83 if (! current->fs->root) 84 return; 85 read_lock(&snd_card_rwlock); 86 locked = snd_cards_lock & (1 << card); 87 read_unlock(&snd_card_rwlock); 88 if (locked) 89 return; 90 if (card < 0 || card >= cards_limit) 91 return; 92 request_module("snd-card-%i", card); 93 } 94 95 static void snd_request_other(int minor) 96 { 97 char *str; 98 99 if (! current->fs->root) 100 return; 101 switch (minor) { 102 case SNDRV_MINOR_SEQUENCER: str = "snd-seq"; break; 103 case SNDRV_MINOR_TIMER: str = "snd-timer"; break; 104 default: return; 105 } 106 request_module(str); 107 } 108 109 #endif /* request_module support */ 110 111 static snd_minor_t *snd_minor_search(int minor) 112 { 113 struct list_head *list; 114 snd_minor_t *mptr; 115 116 list_for_each(list, &snd_minors_hash[SNDRV_MINOR_CARD(minor)]) { 117 mptr = list_entry(list, snd_minor_t, list); 118 if (mptr->number == minor) 119 return mptr; 120 } 121 return NULL; 122 } 123 124 static int snd_open(struct inode *inode, struct file *file) 125 { 126 int minor = iminor(inode); 127 int card = SNDRV_MINOR_CARD(minor); 128 int dev = SNDRV_MINOR_DEVICE(minor); 129 snd_minor_t *mptr = NULL; 130 struct file_operations *old_fops; 131 int err = 0; 132 133 if (dev != SNDRV_MINOR_SEQUENCER && dev != SNDRV_MINOR_TIMER) { 134 if (snd_cards[card] == NULL) { 135 #ifdef CONFIG_KMOD 136 snd_request_card(card); 137 if (snd_cards[card] == NULL) 138 #endif 139 return -ENODEV; 140 } 141 } else { 142 #ifdef CONFIG_KMOD 143 if ((mptr = snd_minor_search(minor)) == NULL) 144 snd_request_other(minor); 145 #endif 146 } 147 if (mptr == NULL && (mptr = snd_minor_search(minor)) == NULL) 148 return -ENODEV; 149 old_fops = file->f_op; 150 file->f_op = fops_get(mptr->f_ops); 151 if (file->f_op->open) 152 err = file->f_op->open(inode, file); 153 if (err) { 154 fops_put(file->f_op); 155 file->f_op = fops_get(old_fops); 156 } 157 fops_put(old_fops); 158 return err; 159 } 160 161 static struct file_operations snd_fops = 162 { 163 .owner = THIS_MODULE, 164 .open = snd_open 165 }; 166 167 static int snd_kernel_minor(int type, snd_card_t * card, int dev) 168 { 169 int minor; 170 171 switch (type) { 172 case SNDRV_DEVICE_TYPE_SEQUENCER: 173 case SNDRV_DEVICE_TYPE_TIMER: 174 minor = type; 175 break; 176 case SNDRV_DEVICE_TYPE_CONTROL: 177 snd_assert(card != NULL, return -EINVAL); 178 minor = SNDRV_MINOR(card->number, type); 179 break; 180 case SNDRV_DEVICE_TYPE_HWDEP: 181 case SNDRV_DEVICE_TYPE_RAWMIDI: 182 case SNDRV_DEVICE_TYPE_PCM_PLAYBACK: 183 case SNDRV_DEVICE_TYPE_PCM_CAPTURE: 184 snd_assert(card != NULL, return -EINVAL); 185 minor = SNDRV_MINOR(card->number, type + dev); 186 break; 187 default: 188 return -EINVAL; 189 } 190 snd_assert(minor >= 0 && minor < SNDRV_OS_MINORS, return -EINVAL); 191 return minor; 192 } 193 194 /** 195 * snd_register_device - Register the ALSA device file for the card 196 * @type: the device type, SNDRV_DEVICE_TYPE_XXX 197 * @card: the card instance 198 * @dev: the device index 199 * @reg: the snd_minor_t record 200 * @name: the device file name 201 * 202 * Registers an ALSA device file for the given card. 203 * The operators have to be set in reg parameter. 204 * 205 * Retrurns zero if successful, or a negative error code on failure. 206 */ 207 int snd_register_device(int type, snd_card_t * card, int dev, snd_minor_t * reg, const char *name) 208 { 209 int minor = snd_kernel_minor(type, card, dev); 210 snd_minor_t *preg; 211 struct device *device = NULL; 212 213 if (minor < 0) 214 return minor; 215 snd_assert(name, return -EINVAL); 216 preg = (snd_minor_t *)kmalloc(sizeof(snd_minor_t) + strlen(name) + 1, GFP_KERNEL); 217 if (preg == NULL) 218 return -ENOMEM; 219 *preg = *reg; 220 preg->number = minor; 221 preg->device = dev; 222 strcpy(preg->name, name); 223 down(&sound_mutex); 224 if (snd_minor_search(minor)) { 225 up(&sound_mutex); 226 kfree(preg); 227 return -EBUSY; 228 } 229 list_add_tail(&preg->list, &snd_minors_hash[SNDRV_MINOR_CARD(minor)]); 230 if (strncmp(name, "controlC", 8) || card->number >= cards_limit) 231 devfs_mk_cdev(MKDEV(major, minor), S_IFCHR | device_mode, "snd/%s", name); 232 if (card) 233 device = card->dev; 234 class_device_create(sound_class, NULL, MKDEV(major, minor), device, "%s", name); 235 236 up(&sound_mutex); 237 return 0; 238 } 239 240 /** 241 * snd_unregister_device - unregister the device on the given card 242 * @type: the device type, SNDRV_DEVICE_TYPE_XXX 243 * @card: the card instance 244 * @dev: the device index 245 * 246 * Unregisters the device file already registered via 247 * snd_register_device(). 248 * 249 * Returns zero if sucecessful, or a negative error code on failure 250 */ 251 int snd_unregister_device(int type, snd_card_t * card, int dev) 252 { 253 int minor = snd_kernel_minor(type, card, dev); 254 snd_minor_t *mptr; 255 256 if (minor < 0) 257 return minor; 258 down(&sound_mutex); 259 if ((mptr = snd_minor_search(minor)) == NULL) { 260 up(&sound_mutex); 261 return -EINVAL; 262 } 263 264 if (strncmp(mptr->name, "controlC", 8) || card->number >= cards_limit) /* created in sound.c */ 265 devfs_remove("snd/%s", mptr->name); 266 class_device_destroy(sound_class, MKDEV(major, minor)); 267 268 list_del(&mptr->list); 269 up(&sound_mutex); 270 kfree(mptr); 271 return 0; 272 } 273 274 /* 275 * INFO PART 276 */ 277 278 static snd_info_entry_t *snd_minor_info_entry = NULL; 279 280 static void snd_minor_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer) 281 { 282 int card, device; 283 struct list_head *list; 284 snd_minor_t *mptr; 285 286 down(&sound_mutex); 287 for (card = 0; card < SNDRV_CARDS; card++) { 288 list_for_each(list, &snd_minors_hash[card]) { 289 mptr = list_entry(list, snd_minor_t, list); 290 if (SNDRV_MINOR_DEVICE(mptr->number) != SNDRV_MINOR_SEQUENCER) { 291 if ((device = mptr->device) >= 0) 292 snd_iprintf(buffer, "%3i: [%i-%2i]: %s\n", mptr->number, card, device, mptr->comment); 293 else 294 snd_iprintf(buffer, "%3i: [%i] : %s\n", mptr->number, card, mptr->comment); 295 } else { 296 snd_iprintf(buffer, "%3i: : %s\n", mptr->number, mptr->comment); 297 } 298 } 299 } 300 up(&sound_mutex); 301 } 302 303 int __init snd_minor_info_init(void) 304 { 305 snd_info_entry_t *entry; 306 307 entry = snd_info_create_module_entry(THIS_MODULE, "devices", NULL); 308 if (entry) { 309 entry->c.text.read_size = PAGE_SIZE; 310 entry->c.text.read = snd_minor_info_read; 311 if (snd_info_register(entry) < 0) { 312 snd_info_free_entry(entry); 313 entry = NULL; 314 } 315 } 316 snd_minor_info_entry = entry; 317 return 0; 318 } 319 320 int __exit snd_minor_info_done(void) 321 { 322 if (snd_minor_info_entry) 323 snd_info_unregister(snd_minor_info_entry); 324 return 0; 325 } 326 327 /* 328 * INIT PART 329 */ 330 331 #ifdef CONFIG_SND_GENERIC_DRIVER 332 extern struct device_driver snd_generic_driver; 333 #endif 334 335 static int __init alsa_sound_init(void) 336 { 337 short controlnum; 338 int err; 339 int card; 340 341 snd_major = major; 342 snd_ecards_limit = cards_limit; 343 for (card = 0; card < SNDRV_CARDS; card++) 344 INIT_LIST_HEAD(&snd_minors_hash[card]); 345 if ((err = snd_oss_init_module()) < 0) 346 return err; 347 devfs_mk_dir("snd"); 348 if (register_chrdev(major, "alsa", &snd_fops)) { 349 snd_printk(KERN_ERR "unable to register native major device number %d\n", major); 350 devfs_remove("snd"); 351 return -EIO; 352 } 353 snd_memory_init(); 354 if (snd_info_init() < 0) { 355 snd_memory_done(); 356 unregister_chrdev(major, "alsa"); 357 devfs_remove("snd"); 358 return -ENOMEM; 359 } 360 snd_info_minor_register(); 361 #ifdef CONFIG_SND_GENERIC_DRIVER 362 driver_register(&snd_generic_driver); 363 #endif 364 for (controlnum = 0; controlnum < cards_limit; controlnum++) 365 devfs_mk_cdev(MKDEV(major, controlnum<<5), S_IFCHR | device_mode, "snd/controlC%d", controlnum); 366 #ifndef MODULE 367 printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n"); 368 #endif 369 return 0; 370 } 371 372 static void __exit alsa_sound_exit(void) 373 { 374 short controlnum; 375 376 for (controlnum = 0; controlnum < cards_limit; controlnum++) 377 devfs_remove("snd/controlC%d", controlnum); 378 379 #ifdef CONFIG_SND_GENERIC_DRIVER 380 driver_unregister(&snd_generic_driver); 381 #endif 382 snd_info_minor_unregister(); 383 snd_info_done(); 384 snd_memory_done(); 385 if (unregister_chrdev(major, "alsa") != 0) 386 snd_printk(KERN_ERR "unable to unregister major device number %d\n", major); 387 devfs_remove("snd"); 388 } 389 390 module_init(alsa_sound_init) 391 module_exit(alsa_sound_exit) 392 393 /* sound.c */ 394 EXPORT_SYMBOL(snd_major); 395 EXPORT_SYMBOL(snd_ecards_limit); 396 #if defined(CONFIG_KMOD) 397 EXPORT_SYMBOL(snd_request_card); 398 #endif 399 EXPORT_SYMBOL(snd_register_device); 400 EXPORT_SYMBOL(snd_unregister_device); 401 #if defined(CONFIG_SND_OSSEMUL) 402 EXPORT_SYMBOL(snd_register_oss_device); 403 EXPORT_SYMBOL(snd_unregister_oss_device); 404 #endif 405 /* memory.c */ 406 #ifdef CONFIG_SND_DEBUG_MEMORY 407 EXPORT_SYMBOL(snd_hidden_kmalloc); 408 EXPORT_SYMBOL(snd_hidden_kcalloc); 409 EXPORT_SYMBOL(snd_hidden_kfree); 410 EXPORT_SYMBOL(snd_hidden_vmalloc); 411 EXPORT_SYMBOL(snd_hidden_vfree); 412 EXPORT_SYMBOL(snd_hidden_kstrdup); 413 #endif 414 EXPORT_SYMBOL(copy_to_user_fromio); 415 EXPORT_SYMBOL(copy_from_user_toio); 416 /* init.c */ 417 EXPORT_SYMBOL(snd_cards); 418 #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) 419 EXPORT_SYMBOL(snd_mixer_oss_notify_callback); 420 #endif 421 EXPORT_SYMBOL(snd_card_new); 422 EXPORT_SYMBOL(snd_card_disconnect); 423 EXPORT_SYMBOL(snd_card_free); 424 EXPORT_SYMBOL(snd_card_free_in_thread); 425 EXPORT_SYMBOL(snd_card_register); 426 EXPORT_SYMBOL(snd_component_add); 427 EXPORT_SYMBOL(snd_card_file_add); 428 EXPORT_SYMBOL(snd_card_file_remove); 429 #ifdef CONFIG_SND_GENERIC_DRIVER 430 EXPORT_SYMBOL(snd_card_set_generic_dev); 431 #endif 432 #ifdef CONFIG_PM 433 EXPORT_SYMBOL(snd_power_wait); 434 EXPORT_SYMBOL(snd_card_set_pm_callback); 435 #ifdef CONFIG_SND_GENERIC_DRIVER 436 EXPORT_SYMBOL(snd_card_set_generic_pm_callback); 437 #endif 438 #ifdef CONFIG_PCI 439 EXPORT_SYMBOL(snd_card_pci_suspend); 440 EXPORT_SYMBOL(snd_card_pci_resume); 441 #endif 442 #endif 443 /* device.c */ 444 EXPORT_SYMBOL(snd_device_new); 445 EXPORT_SYMBOL(snd_device_register); 446 EXPORT_SYMBOL(snd_device_free); 447 /* isadma.c */ 448 #ifdef CONFIG_ISA_DMA_API 449 EXPORT_SYMBOL(snd_dma_program); 450 EXPORT_SYMBOL(snd_dma_disable); 451 EXPORT_SYMBOL(snd_dma_pointer); 452 #endif 453 /* info.c */ 454 #ifdef CONFIG_PROC_FS 455 EXPORT_SYMBOL(snd_seq_root); 456 EXPORT_SYMBOL(snd_iprintf); 457 EXPORT_SYMBOL(snd_info_get_line); 458 EXPORT_SYMBOL(snd_info_get_str); 459 EXPORT_SYMBOL(snd_info_create_module_entry); 460 EXPORT_SYMBOL(snd_info_create_card_entry); 461 EXPORT_SYMBOL(snd_info_free_entry); 462 EXPORT_SYMBOL(snd_info_register); 463 EXPORT_SYMBOL(snd_info_unregister); 464 EXPORT_SYMBOL(snd_card_proc_new); 465 #endif 466 /* info_oss.c */ 467 #if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS) 468 EXPORT_SYMBOL(snd_oss_info_register); 469 #endif 470 /* control.c */ 471 EXPORT_SYMBOL(snd_ctl_new); 472 EXPORT_SYMBOL(snd_ctl_new1); 473 EXPORT_SYMBOL(snd_ctl_free_one); 474 EXPORT_SYMBOL(snd_ctl_add); 475 EXPORT_SYMBOL(snd_ctl_remove); 476 EXPORT_SYMBOL(snd_ctl_remove_id); 477 EXPORT_SYMBOL(snd_ctl_rename_id); 478 EXPORT_SYMBOL(snd_ctl_find_numid); 479 EXPORT_SYMBOL(snd_ctl_find_id); 480 EXPORT_SYMBOL(snd_ctl_notify); 481 EXPORT_SYMBOL(snd_ctl_register_ioctl); 482 EXPORT_SYMBOL(snd_ctl_unregister_ioctl); 483 #ifdef CONFIG_COMPAT 484 EXPORT_SYMBOL(snd_ctl_register_ioctl_compat); 485 EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat); 486 #endif 487 EXPORT_SYMBOL(snd_ctl_elem_read); 488 EXPORT_SYMBOL(snd_ctl_elem_write); 489 /* misc.c */ 490 EXPORT_SYMBOL(snd_task_name); 491 #ifdef CONFIG_SND_VERBOSE_PRINTK 492 EXPORT_SYMBOL(snd_verbose_printk); 493 #endif 494 #if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK) 495 EXPORT_SYMBOL(snd_verbose_printd); 496 #endif 497 /* wrappers */ 498 #ifdef CONFIG_SND_DEBUG_MEMORY 499 EXPORT_SYMBOL(snd_wrapper_kmalloc); 500 EXPORT_SYMBOL(snd_wrapper_kfree); 501 EXPORT_SYMBOL(snd_wrapper_vmalloc); 502 EXPORT_SYMBOL(snd_wrapper_vfree); 503 #endif 504