diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2005-11-20 14:07:47 +0100 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-01-03 12:29:19 +0100 |
commit | 332682b1cd540dd7abbbbfc1905af8139e76e1b7 (patch) | |
tree | e2e858870972073b2e01f7f8d5948c187c11e2bb | |
parent | [ALSA] dynamic minors (3/6): store device-specific object pointers dynamically (diff) | |
download | linux-332682b1cd540dd7abbbbfc1905af8139e76e1b7.tar.xz linux-332682b1cd540dd7abbbbfc1905af8139e76e1b7.zip |
[ALSA] dynamic minors (4/6): dynamic minor number allocation
Modules: ALSA Core,ALSA Minor Numbers
Add an option to allocate device file minor numbers dynamically.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
-rw-r--r-- | include/sound/minors.h | 29 | ||||
-rw-r--r-- | sound/core/Kconfig | 11 | ||||
-rw-r--r-- | sound/core/sound.c | 65 |
3 files changed, 82 insertions, 23 deletions
diff --git a/include/sound/minors.h b/include/sound/minors.h index a17b5c9961bb..46bcd2023ed8 100644 --- a/include/sound/minors.h +++ b/include/sound/minors.h @@ -26,18 +26,20 @@ #define SNDRV_MINOR_DEVICE(minor) ((minor) & 0x001f) #define SNDRV_MINOR(card, dev) (((card) << 5) | (dev)) -#define SNDRV_MINOR_CONTROL 0 /* 0 - 0 */ +/* these minors can still be used for autoloading devices (/dev/aload*) */ +#define SNDRV_MINOR_CONTROL 0 /* 0 */ #define SNDRV_MINOR_GLOBAL 1 /* 1 */ #define SNDRV_MINOR_SEQUENCER (SNDRV_MINOR_GLOBAL + 0 * 32) #define SNDRV_MINOR_TIMER (SNDRV_MINOR_GLOBAL + 1 * 32) + +#ifndef CONFIG_SND_DYNAMIC_MINORS + /* 2 - 3 (reserved) */ #define SNDRV_MINOR_HWDEP 4 /* 4 - 7 */ -#define SNDRV_MINOR_HWDEPS 4 #define SNDRV_MINOR_RAWMIDI 8 /* 8 - 15 */ -#define SNDRV_MINOR_RAWMIDIS 8 #define SNDRV_MINOR_PCM_PLAYBACK 16 /* 16 - 23 */ #define SNDRV_MINOR_PCM_CAPTURE 24 /* 24 - 31 */ -#define SNDRV_MINOR_PCMS 8 +/* same as first respective minor number to make minor allocation easier */ #define SNDRV_DEVICE_TYPE_CONTROL SNDRV_MINOR_CONTROL #define SNDRV_DEVICE_TYPE_HWDEP SNDRV_MINOR_HWDEP #define SNDRV_DEVICE_TYPE_RAWMIDI SNDRV_MINOR_RAWMIDI @@ -46,6 +48,25 @@ #define SNDRV_DEVICE_TYPE_SEQUENCER SNDRV_MINOR_SEQUENCER #define SNDRV_DEVICE_TYPE_TIMER SNDRV_MINOR_TIMER +#else /* CONFIG_SND_DYNAMIC_MINORS */ + +enum { + SNDRV_DEVICE_TYPE_CONTROL, + SNDRV_DEVICE_TYPE_SEQUENCER, + SNDRV_DEVICE_TYPE_TIMER, + SNDRV_DEVICE_TYPE_HWDEP, + SNDRV_DEVICE_TYPE_RAWMIDI, + SNDRV_DEVICE_TYPE_PCM_PLAYBACK, + SNDRV_DEVICE_TYPE_PCM_CAPTURE, +}; + +#endif /* CONFIG_SND_DYNAMIC_MINORS */ + +#define SNDRV_MINOR_HWDEPS 4 +#define SNDRV_MINOR_RAWMIDIS 8 +#define SNDRV_MINOR_PCMS 8 + + #ifdef CONFIG_SND_OSSEMUL #define SNDRV_MINOR_OSS_DEVICES 16 diff --git a/sound/core/Kconfig b/sound/core/Kconfig index b46efff2e4c4..83cbe20c9c9e 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig @@ -111,6 +111,17 @@ config SND_SEQ_RTCTIMER_DEFAULT If in doubt, say Y. +config SND_DYNAMIC_MINORS + bool "Dynamic device file minor numbers (EXPERIMENTAL)" + depends on SND && EXPERIMENTAL + help + If you say Y here, the minor numbers of ALSA device files in + /dev/snd/ are allocated dynamically. This allows you to have + more than 8 sound cards, but requires a dynamic device file + system like udev. + + If you are unsure about this, say N here. + config SND_VERBOSE_PRINTK bool "Verbose printk" depends on SND diff --git a/sound/core/sound.c b/sound/core/sound.c index 1e5eca546925..5e22283078fc 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -133,29 +133,34 @@ void *snd_lookup_minor_data(unsigned int minor, int type) static int snd_open(struct inode *inode, struct file *file) { - int minor = iminor(inode); - int card = SNDRV_MINOR_CARD(minor); - int dev = SNDRV_MINOR_DEVICE(minor); + unsigned int minor = iminor(inode); struct snd_minor *mptr = NULL; struct file_operations *old_fops; int err = 0; - if (dev != SNDRV_MINOR_GLOBAL) { - if (snd_cards[card] == NULL) { + if (minor > ARRAY_SIZE(snd_minors)) + return -ENODEV; + mptr = snd_minors[minor]; + if (mptr == NULL) { #ifdef CONFIG_KMOD - snd_request_card(card); + int dev = SNDRV_MINOR_DEVICE(minor); + if (dev == SNDRV_MINOR_CONTROL) { + /* /dev/aloadC? */ + int card = SNDRV_MINOR_CARD(minor); if (snd_cards[card] == NULL) -#endif - return -ENODEV; - } - } else { -#ifdef CONFIG_KMOD - if ((mptr = snd_minors[minor]) == NULL) + snd_request_card(card); + } else if (dev == SNDRV_MINOR_GLOBAL) { + /* /dev/aloadSEQ */ snd_request_other(minor); + } +#ifndef CONFIG_SND_DYNAMIC_MINORS + /* /dev/snd/{controlC?,seq} */ + mptr = snd_minors[minor]; + if (mptr == NULL) +#endif #endif + return -ENODEV; } - if (mptr == NULL && (mptr = snd_minors[minor]) == NULL) - return -ENODEV; old_fops = file->f_op; file->f_op = fops_get(mptr->f_ops); if (file->f_op->open) @@ -174,6 +179,22 @@ static struct file_operations snd_fops = .open = snd_open }; +#ifdef CONFIG_SND_DYNAMIC_MINORS +static int snd_find_free_minor(void) +{ + int minor; + + for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) { + /* skip minors still used statically for autoloading devices */ + if (SNDRV_MINOR_DEVICE(minor) == SNDRV_MINOR_CONTROL || + minor == SNDRV_MINOR_SEQUENCER) + continue; + if (!snd_minors[minor]) + return minor; + } + return -EBUSY; +} +#else static int snd_kernel_minor(int type, struct snd_card *card, int dev) { int minor; @@ -200,6 +221,7 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev) snd_assert(minor >= 0 && minor < SNDRV_OS_MINORS, return -EINVAL); return minor; } +#endif /** * snd_register_device - Register the ALSA device file for the card @@ -219,12 +241,10 @@ int snd_register_device(int type, struct snd_card *card, int dev, struct file_operations *f_ops, void *private_data, const char *name) { - int minor = snd_kernel_minor(type, card, dev); + int minor; struct snd_minor *preg; struct device *device = NULL; - if (minor < 0) - return minor; snd_assert(name, return -EINVAL); preg = kmalloc(sizeof(struct snd_minor) + strlen(name) + 1, GFP_KERNEL); if (preg == NULL) @@ -236,10 +256,17 @@ int snd_register_device(int type, struct snd_card *card, int dev, preg->private_data = private_data; strcpy(preg->name, name); down(&sound_mutex); - if (snd_minors[minor]) { +#ifdef CONFIG_SND_DYNAMIC_MINORS + minor = snd_find_free_minor(); +#else + minor = snd_kernel_minor(type, card, dev); + if (minor >= 0 && snd_minors[minor]) + minor = -EBUSY; +#endif + if (minor < 0) { up(&sound_mutex); kfree(preg); - return -EBUSY; + return minor; } snd_minors[minor] = preg; if (type != SNDRV_DEVICE_TYPE_CONTROL || preg->card >= cards_limit) |