0001
0002
0003
0004
0005
0006
0007 #include <linux/init.h>
0008 #include <linux/slab.h>
0009 #include <linux/time.h>
0010 #include <linux/device.h>
0011 #include <linux/module.h>
0012 #include <linux/debugfs.h>
0013 #include <sound/core.h>
0014 #include <sound/minors.h>
0015 #include <sound/info.h>
0016 #include <sound/control.h>
0017 #include <sound/initval.h>
0018 #include <linux/kmod.h>
0019 #include <linux/mutex.h>
0020
0021 static int major = CONFIG_SND_MAJOR;
0022 int snd_major;
0023 EXPORT_SYMBOL(snd_major);
0024
0025 static int cards_limit = 1;
0026
0027 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
0028 MODULE_DESCRIPTION("Advanced Linux Sound Architecture driver for soundcards.");
0029 MODULE_LICENSE("GPL");
0030 module_param(major, int, 0444);
0031 MODULE_PARM_DESC(major, "Major # for sound driver.");
0032 module_param(cards_limit, int, 0444);
0033 MODULE_PARM_DESC(cards_limit, "Count of auto-loadable soundcards.");
0034 MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
0035
0036
0037
0038
0039
0040 int snd_ecards_limit;
0041 EXPORT_SYMBOL(snd_ecards_limit);
0042
0043 #ifdef CONFIG_SND_DEBUG
0044 struct dentry *sound_debugfs_root;
0045 EXPORT_SYMBOL_GPL(sound_debugfs_root);
0046 #endif
0047
0048 static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
0049 static DEFINE_MUTEX(sound_mutex);
0050
0051 #ifdef CONFIG_MODULES
0052
0053
0054
0055
0056
0057
0058
0059
0060 void snd_request_card(int card)
0061 {
0062 if (snd_card_locked(card))
0063 return;
0064 if (card < 0 || card >= cards_limit)
0065 return;
0066 request_module("snd-card-%i", card);
0067 }
0068 EXPORT_SYMBOL(snd_request_card);
0069
0070 static void snd_request_other(int minor)
0071 {
0072 char *str;
0073
0074 switch (minor) {
0075 case SNDRV_MINOR_SEQUENCER: str = "snd-seq"; break;
0076 case SNDRV_MINOR_TIMER: str = "snd-timer"; break;
0077 default: return;
0078 }
0079 request_module(str);
0080 }
0081
0082 #endif
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099 void *snd_lookup_minor_data(unsigned int minor, int type)
0100 {
0101 struct snd_minor *mreg;
0102 void *private_data;
0103
0104 if (minor >= ARRAY_SIZE(snd_minors))
0105 return NULL;
0106 mutex_lock(&sound_mutex);
0107 mreg = snd_minors[minor];
0108 if (mreg && mreg->type == type) {
0109 private_data = mreg->private_data;
0110 if (private_data && mreg->card_ptr)
0111 get_device(&mreg->card_ptr->card_dev);
0112 } else
0113 private_data = NULL;
0114 mutex_unlock(&sound_mutex);
0115 return private_data;
0116 }
0117 EXPORT_SYMBOL(snd_lookup_minor_data);
0118
0119 #ifdef CONFIG_MODULES
0120 static struct snd_minor *autoload_device(unsigned int minor)
0121 {
0122 int dev;
0123 mutex_unlock(&sound_mutex);
0124 dev = SNDRV_MINOR_DEVICE(minor);
0125 if (dev == SNDRV_MINOR_CONTROL) {
0126
0127 int card = SNDRV_MINOR_CARD(minor);
0128 struct snd_card *ref = snd_card_ref(card);
0129 if (!ref)
0130 snd_request_card(card);
0131 else
0132 snd_card_unref(ref);
0133 } else if (dev == SNDRV_MINOR_GLOBAL) {
0134
0135 snd_request_other(minor);
0136 }
0137 mutex_lock(&sound_mutex);
0138 return snd_minors[minor];
0139 }
0140 #else
0141 #define autoload_device(minor) NULL
0142 #endif
0143
0144 static int snd_open(struct inode *inode, struct file *file)
0145 {
0146 unsigned int minor = iminor(inode);
0147 struct snd_minor *mptr = NULL;
0148 const struct file_operations *new_fops;
0149 int err = 0;
0150
0151 if (minor >= ARRAY_SIZE(snd_minors))
0152 return -ENODEV;
0153 mutex_lock(&sound_mutex);
0154 mptr = snd_minors[minor];
0155 if (mptr == NULL) {
0156 mptr = autoload_device(minor);
0157 if (!mptr) {
0158 mutex_unlock(&sound_mutex);
0159 return -ENODEV;
0160 }
0161 }
0162 new_fops = fops_get(mptr->f_ops);
0163 mutex_unlock(&sound_mutex);
0164 if (!new_fops)
0165 return -ENODEV;
0166 replace_fops(file, new_fops);
0167
0168 if (file->f_op->open)
0169 err = file->f_op->open(inode, file);
0170 return err;
0171 }
0172
0173 static const struct file_operations snd_fops =
0174 {
0175 .owner = THIS_MODULE,
0176 .open = snd_open,
0177 .llseek = noop_llseek,
0178 };
0179
0180 #ifdef CONFIG_SND_DYNAMIC_MINORS
0181 static int snd_find_free_minor(int type, struct snd_card *card, int dev)
0182 {
0183 int minor;
0184
0185
0186 if (type == SNDRV_DEVICE_TYPE_SEQUENCER)
0187 return SNDRV_MINOR_SEQUENCER;
0188 if (type == SNDRV_DEVICE_TYPE_TIMER)
0189 return SNDRV_MINOR_TIMER;
0190
0191 for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) {
0192
0193 if (SNDRV_MINOR_DEVICE(minor) == SNDRV_MINOR_CONTROL)
0194 continue;
0195 if (minor == SNDRV_MINOR_SEQUENCER ||
0196 minor == SNDRV_MINOR_TIMER)
0197 continue;
0198 if (!snd_minors[minor])
0199 return minor;
0200 }
0201 return -EBUSY;
0202 }
0203 #else
0204 static int snd_find_free_minor(int type, struct snd_card *card, int dev)
0205 {
0206 int minor;
0207
0208 switch (type) {
0209 case SNDRV_DEVICE_TYPE_SEQUENCER:
0210 case SNDRV_DEVICE_TYPE_TIMER:
0211 minor = type;
0212 break;
0213 case SNDRV_DEVICE_TYPE_CONTROL:
0214 if (snd_BUG_ON(!card))
0215 return -EINVAL;
0216 minor = SNDRV_MINOR(card->number, type);
0217 break;
0218 case SNDRV_DEVICE_TYPE_HWDEP:
0219 case SNDRV_DEVICE_TYPE_RAWMIDI:
0220 case SNDRV_DEVICE_TYPE_PCM_PLAYBACK:
0221 case SNDRV_DEVICE_TYPE_PCM_CAPTURE:
0222 case SNDRV_DEVICE_TYPE_COMPRESS:
0223 if (snd_BUG_ON(!card))
0224 return -EINVAL;
0225 minor = SNDRV_MINOR(card->number, type + dev);
0226 break;
0227 default:
0228 return -EINVAL;
0229 }
0230 if (snd_BUG_ON(minor < 0 || minor >= SNDRV_OS_MINORS))
0231 return -EINVAL;
0232 if (snd_minors[minor])
0233 return -EBUSY;
0234 return minor;
0235 }
0236 #endif
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252 int snd_register_device(int type, struct snd_card *card, int dev,
0253 const struct file_operations *f_ops,
0254 void *private_data, struct device *device)
0255 {
0256 int minor;
0257 int err = 0;
0258 struct snd_minor *preg;
0259
0260 if (snd_BUG_ON(!device))
0261 return -EINVAL;
0262
0263 preg = kmalloc(sizeof *preg, GFP_KERNEL);
0264 if (preg == NULL)
0265 return -ENOMEM;
0266 preg->type = type;
0267 preg->card = card ? card->number : -1;
0268 preg->device = dev;
0269 preg->f_ops = f_ops;
0270 preg->private_data = private_data;
0271 preg->card_ptr = card;
0272 mutex_lock(&sound_mutex);
0273 minor = snd_find_free_minor(type, card, dev);
0274 if (minor < 0) {
0275 err = minor;
0276 goto error;
0277 }
0278
0279 preg->dev = device;
0280 device->devt = MKDEV(major, minor);
0281 err = device_add(device);
0282 if (err < 0)
0283 goto error;
0284
0285 snd_minors[minor] = preg;
0286 error:
0287 mutex_unlock(&sound_mutex);
0288 if (err < 0)
0289 kfree(preg);
0290 return err;
0291 }
0292 EXPORT_SYMBOL(snd_register_device);
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303 int snd_unregister_device(struct device *dev)
0304 {
0305 int minor;
0306 struct snd_minor *preg;
0307
0308 mutex_lock(&sound_mutex);
0309 for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) {
0310 preg = snd_minors[minor];
0311 if (preg && preg->dev == dev) {
0312 snd_minors[minor] = NULL;
0313 device_del(dev);
0314 kfree(preg);
0315 break;
0316 }
0317 }
0318 mutex_unlock(&sound_mutex);
0319 if (minor >= ARRAY_SIZE(snd_minors))
0320 return -ENOENT;
0321 return 0;
0322 }
0323 EXPORT_SYMBOL(snd_unregister_device);
0324
0325 #ifdef CONFIG_SND_PROC_FS
0326
0327
0328
0329 static const char *snd_device_type_name(int type)
0330 {
0331 switch (type) {
0332 case SNDRV_DEVICE_TYPE_CONTROL:
0333 return "control";
0334 case SNDRV_DEVICE_TYPE_HWDEP:
0335 return "hardware dependent";
0336 case SNDRV_DEVICE_TYPE_RAWMIDI:
0337 return "raw midi";
0338 case SNDRV_DEVICE_TYPE_PCM_PLAYBACK:
0339 return "digital audio playback";
0340 case SNDRV_DEVICE_TYPE_PCM_CAPTURE:
0341 return "digital audio capture";
0342 case SNDRV_DEVICE_TYPE_SEQUENCER:
0343 return "sequencer";
0344 case SNDRV_DEVICE_TYPE_TIMER:
0345 return "timer";
0346 case SNDRV_DEVICE_TYPE_COMPRESS:
0347 return "compress";
0348 default:
0349 return "?";
0350 }
0351 }
0352
0353 static void snd_minor_info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
0354 {
0355 int minor;
0356 struct snd_minor *mptr;
0357
0358 mutex_lock(&sound_mutex);
0359 for (minor = 0; minor < SNDRV_OS_MINORS; ++minor) {
0360 mptr = snd_minors[minor];
0361 if (!mptr)
0362 continue;
0363 if (mptr->card >= 0) {
0364 if (mptr->device >= 0)
0365 snd_iprintf(buffer, "%3i: [%2i-%2i]: %s\n",
0366 minor, mptr->card, mptr->device,
0367 snd_device_type_name(mptr->type));
0368 else
0369 snd_iprintf(buffer, "%3i: [%2i] : %s\n",
0370 minor, mptr->card,
0371 snd_device_type_name(mptr->type));
0372 } else
0373 snd_iprintf(buffer, "%3i: : %s\n", minor,
0374 snd_device_type_name(mptr->type));
0375 }
0376 mutex_unlock(&sound_mutex);
0377 }
0378
0379 int __init snd_minor_info_init(void)
0380 {
0381 struct snd_info_entry *entry;
0382
0383 entry = snd_info_create_module_entry(THIS_MODULE, "devices", NULL);
0384 if (!entry)
0385 return -ENOMEM;
0386 entry->c.text.read = snd_minor_info_read;
0387 return snd_info_register(entry);
0388 }
0389 #endif
0390
0391
0392
0393
0394
0395 static int __init alsa_sound_init(void)
0396 {
0397 snd_major = major;
0398 snd_ecards_limit = cards_limit;
0399 if (register_chrdev(major, "alsa", &snd_fops)) {
0400 pr_err("ALSA core: unable to register native major device number %d\n", major);
0401 return -EIO;
0402 }
0403 if (snd_info_init() < 0) {
0404 unregister_chrdev(major, "alsa");
0405 return -ENOMEM;
0406 }
0407
0408 #ifdef CONFIG_SND_DEBUG
0409 sound_debugfs_root = debugfs_create_dir("sound", NULL);
0410 #endif
0411 #ifndef MODULE
0412 pr_info("Advanced Linux Sound Architecture Driver Initialized.\n");
0413 #endif
0414 return 0;
0415 }
0416
0417 static void __exit alsa_sound_exit(void)
0418 {
0419 #ifdef CONFIG_SND_DEBUG
0420 debugfs_remove(sound_debugfs_root);
0421 #endif
0422 snd_info_done();
0423 unregister_chrdev(major, "alsa");
0424 }
0425
0426 subsys_initcall(alsa_sound_init);
0427 module_exit(alsa_sound_exit);