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_simple *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_simple_device_add(sound_class, MKDEV(major, minor), device, 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_simple_device_remove(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 static int __init alsa_sound_init(void) 332 { 333 short controlnum; 334 int err; 335 int card; 336 337 snd_major = major; 338 snd_ecards_limit = cards_limit; 339 for (card = 0; card < SNDRV_CARDS; card++) 340 INIT_LIST_HEAD(&snd_minors_hash[card]); 341 if ((err = snd_oss_init_module()) < 0) 342 return err; 343 devfs_mk_dir("snd"); 344 if (register_chrdev(major, "alsa", &snd_fops)) { 345 snd_printk(KERN_ERR "unable to register native major device number %d\n", major); 346 devfs_remove("snd"); 347 return -EIO; 348 } 349 snd_memory_init(); 350 if (snd_info_init() < 0) { 351 snd_memory_done(); 352 unregister_chrdev(major, "alsa"); 353 devfs_remove("snd"); 354 return -ENOMEM; 355 } 356 snd_info_minor_register(); 357 for (controlnum = 0; controlnum < cards_limit; controlnum++) 358 devfs_mk_cdev(MKDEV(major, controlnum<<5), S_IFCHR | device_mode, "snd/controlC%d", controlnum); 359 #ifndef MODULE 360 printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n"); 361 #endif 362 return 0; 363 } 364 365 static void __exit alsa_sound_exit(void) 366 { 367 short controlnum; 368 369 for (controlnum = 0; controlnum < cards_limit; controlnum++) 370 devfs_remove("snd/controlC%d", controlnum); 371 372 snd_info_minor_unregister(); 373 snd_info_done(); 374 snd_memory_done(); 375 if (unregister_chrdev(major, "alsa") != 0) 376 snd_printk(KERN_ERR "unable to unregister major device number %d\n", major); 377 devfs_remove("snd"); 378 } 379 380 module_init(alsa_sound_init) 381 module_exit(alsa_sound_exit) 382 383 /* sound.c */ 384 EXPORT_SYMBOL(snd_major); 385 EXPORT_SYMBOL(snd_ecards_limit); 386 #if defined(CONFIG_KMOD) 387 EXPORT_SYMBOL(snd_request_card); 388 #endif 389 EXPORT_SYMBOL(snd_register_device); 390 EXPORT_SYMBOL(snd_unregister_device); 391 #if defined(CONFIG_SND_OSSEMUL) 392 EXPORT_SYMBOL(snd_register_oss_device); 393 EXPORT_SYMBOL(snd_unregister_oss_device); 394 #endif 395 /* memory.c */ 396 #ifdef CONFIG_SND_DEBUG_MEMORY 397 EXPORT_SYMBOL(snd_hidden_kmalloc); 398 EXPORT_SYMBOL(snd_hidden_kcalloc); 399 EXPORT_SYMBOL(snd_hidden_kfree); 400 EXPORT_SYMBOL(snd_hidden_vmalloc); 401 EXPORT_SYMBOL(snd_hidden_vfree); 402 #endif 403 EXPORT_SYMBOL(snd_kmalloc_strdup); 404 EXPORT_SYMBOL(copy_to_user_fromio); 405 EXPORT_SYMBOL(copy_from_user_toio); 406 /* init.c */ 407 EXPORT_SYMBOL(snd_cards); 408 #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) 409 EXPORT_SYMBOL(snd_mixer_oss_notify_callback); 410 #endif 411 EXPORT_SYMBOL(snd_card_new); 412 EXPORT_SYMBOL(snd_card_disconnect); 413 EXPORT_SYMBOL(snd_card_free); 414 EXPORT_SYMBOL(snd_card_free_in_thread); 415 EXPORT_SYMBOL(snd_card_register); 416 EXPORT_SYMBOL(snd_component_add); 417 EXPORT_SYMBOL(snd_card_file_add); 418 EXPORT_SYMBOL(snd_card_file_remove); 419 #ifdef CONFIG_PM 420 EXPORT_SYMBOL(snd_power_wait); 421 EXPORT_SYMBOL(snd_card_set_pm_callback); 422 #if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM) 423 EXPORT_SYMBOL(snd_card_set_generic_pm_callback); 424 #endif 425 #ifdef CONFIG_PCI 426 EXPORT_SYMBOL(snd_card_pci_suspend); 427 EXPORT_SYMBOL(snd_card_pci_resume); 428 #endif 429 #endif 430 /* device.c */ 431 EXPORT_SYMBOL(snd_device_new); 432 EXPORT_SYMBOL(snd_device_register); 433 EXPORT_SYMBOL(snd_device_free); 434 EXPORT_SYMBOL(snd_device_free_all); 435 /* isadma.c */ 436 #ifdef CONFIG_ISA 437 EXPORT_SYMBOL(snd_dma_program); 438 EXPORT_SYMBOL(snd_dma_disable); 439 EXPORT_SYMBOL(snd_dma_pointer); 440 #endif 441 /* info.c */ 442 #ifdef CONFIG_PROC_FS 443 EXPORT_SYMBOL(snd_seq_root); 444 EXPORT_SYMBOL(snd_iprintf); 445 EXPORT_SYMBOL(snd_info_get_line); 446 EXPORT_SYMBOL(snd_info_get_str); 447 EXPORT_SYMBOL(snd_info_create_module_entry); 448 EXPORT_SYMBOL(snd_info_create_card_entry); 449 EXPORT_SYMBOL(snd_info_free_entry); 450 EXPORT_SYMBOL(snd_info_register); 451 EXPORT_SYMBOL(snd_info_unregister); 452 EXPORT_SYMBOL(snd_card_proc_new); 453 #endif 454 /* info_oss.c */ 455 #if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS) 456 EXPORT_SYMBOL(snd_oss_info_register); 457 #endif 458 /* control.c */ 459 EXPORT_SYMBOL(snd_ctl_new); 460 EXPORT_SYMBOL(snd_ctl_new1); 461 EXPORT_SYMBOL(snd_ctl_free_one); 462 EXPORT_SYMBOL(snd_ctl_add); 463 EXPORT_SYMBOL(snd_ctl_remove); 464 EXPORT_SYMBOL(snd_ctl_remove_id); 465 EXPORT_SYMBOL(snd_ctl_rename_id); 466 EXPORT_SYMBOL(snd_ctl_find_numid); 467 EXPORT_SYMBOL(snd_ctl_find_id); 468 EXPORT_SYMBOL(snd_ctl_notify); 469 EXPORT_SYMBOL(snd_ctl_register_ioctl); 470 EXPORT_SYMBOL(snd_ctl_unregister_ioctl); 471 #ifdef CONFIG_COMPAT 472 EXPORT_SYMBOL(snd_ctl_register_ioctl_compat); 473 EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat); 474 #endif 475 EXPORT_SYMBOL(snd_ctl_elem_read); 476 EXPORT_SYMBOL(snd_ctl_elem_write); 477 /* misc.c */ 478 EXPORT_SYMBOL(snd_task_name); 479 #ifdef CONFIG_SND_VERBOSE_PRINTK 480 EXPORT_SYMBOL(snd_verbose_printk); 481 #endif 482 #if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK) 483 EXPORT_SYMBOL(snd_verbose_printd); 484 #endif 485 /* wrappers */ 486 #ifdef CONFIG_SND_DEBUG_MEMORY 487 EXPORT_SYMBOL(snd_wrapper_kmalloc); 488 EXPORT_SYMBOL(snd_wrapper_kfree); 489 EXPORT_SYMBOL(snd_wrapper_vmalloc); 490 EXPORT_SYMBOL(snd_wrapper_vfree); 491 #endif 492