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/device.h> 27 #include <linux/moduleparam.h> 28 #include <sound/core.h> 29 #include <sound/minors.h> 30 #include <sound/info.h> 31 #include <sound/version.h> 32 #include <sound/control.h> 33 #include <sound/initval.h> 34 #include <linux/kmod.h> 35 #include <linux/devfs_fs_kernel.h> 36 #include <linux/mutex.h> 37 38 #define SNDRV_OS_MINORS 256 39 40 static int major = CONFIG_SND_MAJOR; 41 int snd_major; 42 EXPORT_SYMBOL(snd_major); 43 44 static int cards_limit = 1; 45 static int device_mode = S_IFCHR | S_IRUGO | S_IWUGO; 46 47 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); 48 MODULE_DESCRIPTION("Advanced Linux Sound Architecture driver for soundcards."); 49 MODULE_LICENSE("GPL"); 50 module_param(major, int, 0444); 51 MODULE_PARM_DESC(major, "Major # for sound driver."); 52 module_param(cards_limit, int, 0444); 53 MODULE_PARM_DESC(cards_limit, "Count of auto-loadable soundcards."); 54 #ifdef CONFIG_DEVFS_FS 55 module_param(device_mode, int, 0444); 56 MODULE_PARM_DESC(device_mode, "Device file permission mask for devfs."); 57 #endif 58 MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR); 59 60 /* this one holds the actual max. card number currently available. 61 * as default, it's identical with cards_limit option. when more 62 * modules are loaded manually, this limit number increases, too. 63 */ 64 int snd_ecards_limit; 65 EXPORT_SYMBOL(snd_ecards_limit); 66 67 static struct snd_minor *snd_minors[SNDRV_OS_MINORS]; 68 static DEFINE_MUTEX(sound_mutex); 69 70 extern struct class *sound_class; 71 72 73 #ifdef CONFIG_KMOD 74 75 /** 76 * snd_request_card - try to load the card module 77 * @card: the card number 78 * 79 * Tries to load the module "snd-card-X" for the given card number 80 * via KMOD. Returns immediately if already loaded. 81 */ 82 void snd_request_card(int card) 83 { 84 if (! current->fs->root) 85 return; 86 if (snd_card_locked(card)) 87 return; 88 if (card < 0 || card >= cards_limit) 89 return; 90 request_module("snd-card-%i", card); 91 } 92 93 EXPORT_SYMBOL(snd_request_card); 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 /** 112 * snd_lookup_minor_data - get user data of a registered device 113 * @minor: the minor number 114 * @type: device type (SNDRV_DEVICE_TYPE_XXX) 115 * 116 * Checks that a minor device with the specified type is registered, and returns 117 * its user data pointer. 118 */ 119 void *snd_lookup_minor_data(unsigned int minor, int type) 120 { 121 struct snd_minor *mreg; 122 void *private_data; 123 124 if (minor >= ARRAY_SIZE(snd_minors)) 125 return NULL; 126 mutex_lock(&sound_mutex); 127 mreg = snd_minors[minor]; 128 if (mreg && mreg->type == type) 129 private_data = mreg->private_data; 130 else 131 private_data = NULL; 132 mutex_unlock(&sound_mutex); 133 return private_data; 134 } 135 136 EXPORT_SYMBOL(snd_lookup_minor_data); 137 138 static int snd_open(struct inode *inode, struct file *file) 139 { 140 unsigned int minor = iminor(inode); 141 struct snd_minor *mptr = NULL; 142 const struct file_operations *old_fops; 143 int err = 0; 144 145 if (minor >= ARRAY_SIZE(snd_minors)) 146 return -ENODEV; 147 mptr = snd_minors[minor]; 148 if (mptr == NULL) { 149 #ifdef CONFIG_KMOD 150 int dev = SNDRV_MINOR_DEVICE(minor); 151 if (dev == SNDRV_MINOR_CONTROL) { 152 /* /dev/aloadC? */ 153 int card = SNDRV_MINOR_CARD(minor); 154 if (snd_cards[card] == NULL) 155 snd_request_card(card); 156 } else if (dev == SNDRV_MINOR_GLOBAL) { 157 /* /dev/aloadSEQ */ 158 snd_request_other(minor); 159 } 160 #ifndef CONFIG_SND_DYNAMIC_MINORS 161 /* /dev/snd/{controlC?,seq} */ 162 mptr = snd_minors[minor]; 163 if (mptr == NULL) 164 #endif 165 #endif 166 return -ENODEV; 167 } 168 old_fops = file->f_op; 169 file->f_op = fops_get(mptr->f_ops); 170 if (file->f_op->open) 171 err = file->f_op->open(inode, file); 172 if (err) { 173 fops_put(file->f_op); 174 file->f_op = fops_get(old_fops); 175 } 176 fops_put(old_fops); 177 return err; 178 } 179 180 static struct file_operations snd_fops = 181 { 182 .owner = THIS_MODULE, 183 .open = snd_open 184 }; 185 186 #ifdef CONFIG_SND_DYNAMIC_MINORS 187 static int snd_find_free_minor(void) 188 { 189 int minor; 190 191 for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) { 192 /* skip minors still used statically for autoloading devices */ 193 if (SNDRV_MINOR_DEVICE(minor) == SNDRV_MINOR_CONTROL || 194 minor == SNDRV_MINOR_SEQUENCER) 195 continue; 196 if (!snd_minors[minor]) 197 return minor; 198 } 199 return -EBUSY; 200 } 201 #else 202 static int snd_kernel_minor(int type, struct snd_card *card, int dev) 203 { 204 int minor; 205 206 switch (type) { 207 case SNDRV_DEVICE_TYPE_SEQUENCER: 208 case SNDRV_DEVICE_TYPE_TIMER: 209 minor = type; 210 break; 211 case SNDRV_DEVICE_TYPE_CONTROL: 212 snd_assert(card != NULL, return -EINVAL); 213 minor = SNDRV_MINOR(card->number, type); 214 break; 215 case SNDRV_DEVICE_TYPE_HWDEP: 216 case SNDRV_DEVICE_TYPE_RAWMIDI: 217 case SNDRV_DEVICE_TYPE_PCM_PLAYBACK: 218 case SNDRV_DEVICE_TYPE_PCM_CAPTURE: 219 snd_assert(card != NULL, return -EINVAL); 220 minor = SNDRV_MINOR(card->number, type + dev); 221 break; 222 default: 223 return -EINVAL; 224 } 225 snd_assert(minor >= 0 && minor < SNDRV_OS_MINORS, return -EINVAL); 226 return minor; 227 } 228 #endif 229 230 /** 231 * snd_register_device - Register the ALSA device file for the card 232 * @type: the device type, SNDRV_DEVICE_TYPE_XXX 233 * @card: the card instance 234 * @dev: the device index 235 * @f_ops: the file operations 236 * @private_data: user pointer for f_ops->open() 237 * @name: the device file name 238 * 239 * Registers an ALSA device file for the given card. 240 * The operators have to be set in reg parameter. 241 * 242 * Retrurns zero if successful, or a negative error code on failure. 243 */ 244 int snd_register_device(int type, struct snd_card *card, int dev, 245 const struct file_operations *f_ops, void *private_data, 246 const char *name) 247 { 248 int minor; 249 struct snd_minor *preg; 250 struct device *device = NULL; 251 252 snd_assert(name, return -EINVAL); 253 preg = kmalloc(sizeof(struct snd_minor) + strlen(name) + 1, GFP_KERNEL); 254 if (preg == NULL) 255 return -ENOMEM; 256 preg->type = type; 257 preg->card = card ? card->number : -1; 258 preg->device = dev; 259 preg->f_ops = f_ops; 260 preg->private_data = private_data; 261 strcpy(preg->name, name); 262 mutex_lock(&sound_mutex); 263 #ifdef CONFIG_SND_DYNAMIC_MINORS 264 minor = snd_find_free_minor(); 265 #else 266 minor = snd_kernel_minor(type, card, dev); 267 if (minor >= 0 && snd_minors[minor]) 268 minor = -EBUSY; 269 #endif 270 if (minor < 0) { 271 mutex_unlock(&sound_mutex); 272 kfree(preg); 273 return minor; 274 } 275 snd_minors[minor] = preg; 276 if (type != SNDRV_DEVICE_TYPE_CONTROL || preg->card >= cards_limit) 277 devfs_mk_cdev(MKDEV(major, minor), S_IFCHR | device_mode, "snd/%s", name); 278 if (card) 279 device = card->dev; 280 class_device_create(sound_class, NULL, MKDEV(major, minor), device, "%s", name); 281 282 mutex_unlock(&sound_mutex); 283 return 0; 284 } 285 286 EXPORT_SYMBOL(snd_register_device); 287 288 /** 289 * snd_unregister_device - unregister the device on the given card 290 * @type: the device type, SNDRV_DEVICE_TYPE_XXX 291 * @card: the card instance 292 * @dev: the device index 293 * 294 * Unregisters the device file already registered via 295 * snd_register_device(). 296 * 297 * Returns zero if sucecessful, or a negative error code on failure 298 */ 299 int snd_unregister_device(int type, struct snd_card *card, int dev) 300 { 301 int cardnum, minor; 302 struct snd_minor *mptr; 303 304 cardnum = card ? card->number : -1; 305 mutex_lock(&sound_mutex); 306 for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) 307 if ((mptr = snd_minors[minor]) != NULL && 308 mptr->type == type && 309 mptr->card == cardnum && 310 mptr->device == dev) 311 break; 312 if (minor == ARRAY_SIZE(snd_minors)) { 313 mutex_unlock(&sound_mutex); 314 return -EINVAL; 315 } 316 317 if (mptr->type != SNDRV_DEVICE_TYPE_CONTROL || 318 mptr->card >= cards_limit) /* created in sound.c */ 319 devfs_remove("snd/%s", mptr->name); 320 class_device_destroy(sound_class, MKDEV(major, minor)); 321 322 snd_minors[minor] = NULL; 323 mutex_unlock(&sound_mutex); 324 kfree(mptr); 325 return 0; 326 } 327 328 EXPORT_SYMBOL(snd_unregister_device); 329 330 #ifdef CONFIG_PROC_FS 331 /* 332 * INFO PART 333 */ 334 335 static struct snd_info_entry *snd_minor_info_entry; 336 337 static const char *snd_device_type_name(int type) 338 { 339 switch (type) { 340 case SNDRV_DEVICE_TYPE_CONTROL: 341 return "control"; 342 case SNDRV_DEVICE_TYPE_HWDEP: 343 return "hardware dependent"; 344 case SNDRV_DEVICE_TYPE_RAWMIDI: 345 return "raw midi"; 346 case SNDRV_DEVICE_TYPE_PCM_PLAYBACK: 347 return "digital audio playback"; 348 case SNDRV_DEVICE_TYPE_PCM_CAPTURE: 349 return "digital audio capture"; 350 case SNDRV_DEVICE_TYPE_SEQUENCER: 351 return "sequencer"; 352 case SNDRV_DEVICE_TYPE_TIMER: 353 return "timer"; 354 default: 355 return "?"; 356 } 357 } 358 359 static void snd_minor_info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) 360 { 361 int minor; 362 struct snd_minor *mptr; 363 364 mutex_lock(&sound_mutex); 365 for (minor = 0; minor < SNDRV_OS_MINORS; ++minor) { 366 if (!(mptr = snd_minors[minor])) 367 continue; 368 if (mptr->card >= 0) { 369 if (mptr->device >= 0) 370 snd_iprintf(buffer, "%3i: [%2i-%2i]: %s\n", 371 minor, mptr->card, mptr->device, 372 snd_device_type_name(mptr->type)); 373 else 374 snd_iprintf(buffer, "%3i: [%2i] : %s\n", 375 minor, mptr->card, 376 snd_device_type_name(mptr->type)); 377 } else 378 snd_iprintf(buffer, "%3i: : %s\n", minor, 379 snd_device_type_name(mptr->type)); 380 } 381 mutex_unlock(&sound_mutex); 382 } 383 384 int __init snd_minor_info_init(void) 385 { 386 struct snd_info_entry *entry; 387 388 entry = snd_info_create_module_entry(THIS_MODULE, "devices", NULL); 389 if (entry) { 390 entry->c.text.read = snd_minor_info_read; 391 if (snd_info_register(entry) < 0) { 392 snd_info_free_entry(entry); 393 entry = NULL; 394 } 395 } 396 snd_minor_info_entry = entry; 397 return 0; 398 } 399 400 int __exit snd_minor_info_done(void) 401 { 402 if (snd_minor_info_entry) 403 snd_info_unregister(snd_minor_info_entry); 404 return 0; 405 } 406 #endif /* CONFIG_PROC_FS */ 407 408 /* 409 * INIT PART 410 */ 411 412 static int __init alsa_sound_init(void) 413 { 414 short controlnum; 415 416 snd_major = major; 417 snd_ecards_limit = cards_limit; 418 devfs_mk_dir("snd"); 419 if (register_chrdev(major, "alsa", &snd_fops)) { 420 snd_printk(KERN_ERR "unable to register native major device number %d\n", major); 421 devfs_remove("snd"); 422 return -EIO; 423 } 424 if (snd_info_init() < 0) { 425 unregister_chrdev(major, "alsa"); 426 devfs_remove("snd"); 427 return -ENOMEM; 428 } 429 snd_info_minor_register(); 430 for (controlnum = 0; controlnum < cards_limit; controlnum++) 431 devfs_mk_cdev(MKDEV(major, controlnum<<5), S_IFCHR | device_mode, "snd/controlC%d", controlnum); 432 #ifndef MODULE 433 printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n"); 434 #endif 435 return 0; 436 } 437 438 static void __exit alsa_sound_exit(void) 439 { 440 short controlnum; 441 442 for (controlnum = 0; controlnum < cards_limit; controlnum++) 443 devfs_remove("snd/controlC%d", controlnum); 444 445 snd_info_minor_unregister(); 446 snd_info_done(); 447 if (unregister_chrdev(major, "alsa") != 0) 448 snd_printk(KERN_ERR "unable to unregister major device number %d\n", major); 449 devfs_remove("snd"); 450 } 451 452 module_init(alsa_sound_init) 453 module_exit(alsa_sound_exit) 454