Loading include/sound/minors.h +25 −4 Original line number Original line Diff line number Diff line Loading @@ -26,18 +26,20 @@ #define SNDRV_MINOR_DEVICE(minor) ((minor) & 0x001f) #define SNDRV_MINOR_DEVICE(minor) ((minor) & 0x001f) #define SNDRV_MINOR(card, dev) (((card) << 5) | (dev)) #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_GLOBAL 1 /* 1 */ #define SNDRV_MINOR_SEQUENCER (SNDRV_MINOR_GLOBAL + 0 * 32) #define SNDRV_MINOR_SEQUENCER (SNDRV_MINOR_GLOBAL + 0 * 32) #define SNDRV_MINOR_TIMER (SNDRV_MINOR_GLOBAL + 1 * 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_HWDEP 4 /* 4 - 7 */ #define SNDRV_MINOR_HWDEPS 4 #define SNDRV_MINOR_RAWMIDI 8 /* 8 - 15 */ #define SNDRV_MINOR_RAWMIDI 8 /* 8 - 15 */ #define SNDRV_MINOR_RAWMIDIS 8 #define SNDRV_MINOR_PCM_PLAYBACK 16 /* 16 - 23 */ #define SNDRV_MINOR_PCM_PLAYBACK 16 /* 16 - 23 */ #define SNDRV_MINOR_PCM_CAPTURE 24 /* 24 - 31 */ #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_CONTROL SNDRV_MINOR_CONTROL #define SNDRV_DEVICE_TYPE_HWDEP SNDRV_MINOR_HWDEP #define SNDRV_DEVICE_TYPE_HWDEP SNDRV_MINOR_HWDEP #define SNDRV_DEVICE_TYPE_RAWMIDI SNDRV_MINOR_RAWMIDI #define SNDRV_DEVICE_TYPE_RAWMIDI SNDRV_MINOR_RAWMIDI Loading @@ -46,6 +48,25 @@ #define SNDRV_DEVICE_TYPE_SEQUENCER SNDRV_MINOR_SEQUENCER #define SNDRV_DEVICE_TYPE_SEQUENCER SNDRV_MINOR_SEQUENCER #define SNDRV_DEVICE_TYPE_TIMER SNDRV_MINOR_TIMER #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 #ifdef CONFIG_SND_OSSEMUL #define SNDRV_MINOR_OSS_DEVICES 16 #define SNDRV_MINOR_OSS_DEVICES 16 Loading sound/core/Kconfig +11 −0 Original line number Original line Diff line number Diff line Loading @@ -111,6 +111,17 @@ config SND_SEQ_RTCTIMER_DEFAULT If in doubt, say Y. 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 config SND_VERBOSE_PRINTK bool "Verbose printk" bool "Verbose printk" depends on SND depends on SND Loading sound/core/sound.c +46 −19 Original line number Original line Diff line number Diff line Loading @@ -133,29 +133,34 @@ void *snd_lookup_minor_data(unsigned int minor, int type) static int snd_open(struct inode *inode, struct file *file) static int snd_open(struct inode *inode, struct file *file) { { int minor = iminor(inode); unsigned int minor = iminor(inode); int card = SNDRV_MINOR_CARD(minor); int dev = SNDRV_MINOR_DEVICE(minor); struct snd_minor *mptr = NULL; struct snd_minor *mptr = NULL; struct file_operations *old_fops; struct file_operations *old_fops; int err = 0; int err = 0; if (dev != SNDRV_MINOR_GLOBAL) { if (minor > ARRAY_SIZE(snd_minors)) if (snd_cards[card] == NULL) { #ifdef CONFIG_KMOD snd_request_card(card); if (snd_cards[card] == NULL) #endif return -ENODEV; return -ENODEV; } mptr = snd_minors[minor]; } else { if (mptr == NULL) { #ifdef CONFIG_KMOD #ifdef CONFIG_KMOD if ((mptr = snd_minors[minor]) == NULL) int dev = SNDRV_MINOR_DEVICE(minor); if (dev == SNDRV_MINOR_CONTROL) { /* /dev/aloadC? */ int card = SNDRV_MINOR_CARD(minor); if (snd_cards[card] == NULL) snd_request_card(card); } else if (dev == SNDRV_MINOR_GLOBAL) { /* /dev/aloadSEQ */ snd_request_other(minor); snd_request_other(minor); #endif } } if (mptr == NULL && (mptr = snd_minors[minor]) == NULL) #ifndef CONFIG_SND_DYNAMIC_MINORS /* /dev/snd/{controlC?,seq} */ mptr = snd_minors[minor]; if (mptr == NULL) #endif #endif return -ENODEV; return -ENODEV; } old_fops = file->f_op; old_fops = file->f_op; file->f_op = fops_get(mptr->f_ops); file->f_op = fops_get(mptr->f_ops); if (file->f_op->open) if (file->f_op->open) Loading @@ -174,6 +179,22 @@ static struct file_operations snd_fops = .open = snd_open .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) static int snd_kernel_minor(int type, struct snd_card *card, int dev) { { int minor; int minor; Loading @@ -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); snd_assert(minor >= 0 && minor < SNDRV_OS_MINORS, return -EINVAL); return minor; return minor; } } #endif /** /** * snd_register_device - Register the ALSA device file for the card * snd_register_device - Register the ALSA device file for the card Loading @@ -219,12 +241,10 @@ int snd_register_device(int type, struct snd_card *card, int dev, struct file_operations *f_ops, void *private_data, struct file_operations *f_ops, void *private_data, const char *name) const char *name) { { int minor = snd_kernel_minor(type, card, dev); int minor; struct snd_minor *preg; struct snd_minor *preg; struct device *device = NULL; struct device *device = NULL; if (minor < 0) return minor; snd_assert(name, return -EINVAL); snd_assert(name, return -EINVAL); preg = kmalloc(sizeof(struct snd_minor) + strlen(name) + 1, GFP_KERNEL); preg = kmalloc(sizeof(struct snd_minor) + strlen(name) + 1, GFP_KERNEL); if (preg == NULL) if (preg == NULL) Loading @@ -236,10 +256,17 @@ int snd_register_device(int type, struct snd_card *card, int dev, preg->private_data = private_data; preg->private_data = private_data; strcpy(preg->name, name); strcpy(preg->name, name); down(&sound_mutex); 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); up(&sound_mutex); kfree(preg); kfree(preg); return -EBUSY; return minor; } } snd_minors[minor] = preg; snd_minors[minor] = preg; if (type != SNDRV_DEVICE_TYPE_CONTROL || preg->card >= cards_limit) if (type != SNDRV_DEVICE_TYPE_CONTROL || preg->card >= cards_limit) Loading Loading
include/sound/minors.h +25 −4 Original line number Original line Diff line number Diff line Loading @@ -26,18 +26,20 @@ #define SNDRV_MINOR_DEVICE(minor) ((minor) & 0x001f) #define SNDRV_MINOR_DEVICE(minor) ((minor) & 0x001f) #define SNDRV_MINOR(card, dev) (((card) << 5) | (dev)) #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_GLOBAL 1 /* 1 */ #define SNDRV_MINOR_SEQUENCER (SNDRV_MINOR_GLOBAL + 0 * 32) #define SNDRV_MINOR_SEQUENCER (SNDRV_MINOR_GLOBAL + 0 * 32) #define SNDRV_MINOR_TIMER (SNDRV_MINOR_GLOBAL + 1 * 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_HWDEP 4 /* 4 - 7 */ #define SNDRV_MINOR_HWDEPS 4 #define SNDRV_MINOR_RAWMIDI 8 /* 8 - 15 */ #define SNDRV_MINOR_RAWMIDI 8 /* 8 - 15 */ #define SNDRV_MINOR_RAWMIDIS 8 #define SNDRV_MINOR_PCM_PLAYBACK 16 /* 16 - 23 */ #define SNDRV_MINOR_PCM_PLAYBACK 16 /* 16 - 23 */ #define SNDRV_MINOR_PCM_CAPTURE 24 /* 24 - 31 */ #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_CONTROL SNDRV_MINOR_CONTROL #define SNDRV_DEVICE_TYPE_HWDEP SNDRV_MINOR_HWDEP #define SNDRV_DEVICE_TYPE_HWDEP SNDRV_MINOR_HWDEP #define SNDRV_DEVICE_TYPE_RAWMIDI SNDRV_MINOR_RAWMIDI #define SNDRV_DEVICE_TYPE_RAWMIDI SNDRV_MINOR_RAWMIDI Loading @@ -46,6 +48,25 @@ #define SNDRV_DEVICE_TYPE_SEQUENCER SNDRV_MINOR_SEQUENCER #define SNDRV_DEVICE_TYPE_SEQUENCER SNDRV_MINOR_SEQUENCER #define SNDRV_DEVICE_TYPE_TIMER SNDRV_MINOR_TIMER #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 #ifdef CONFIG_SND_OSSEMUL #define SNDRV_MINOR_OSS_DEVICES 16 #define SNDRV_MINOR_OSS_DEVICES 16 Loading
sound/core/Kconfig +11 −0 Original line number Original line Diff line number Diff line Loading @@ -111,6 +111,17 @@ config SND_SEQ_RTCTIMER_DEFAULT If in doubt, say Y. 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 config SND_VERBOSE_PRINTK bool "Verbose printk" bool "Verbose printk" depends on SND depends on SND Loading
sound/core/sound.c +46 −19 Original line number Original line Diff line number Diff line Loading @@ -133,29 +133,34 @@ void *snd_lookup_minor_data(unsigned int minor, int type) static int snd_open(struct inode *inode, struct file *file) static int snd_open(struct inode *inode, struct file *file) { { int minor = iminor(inode); unsigned int minor = iminor(inode); int card = SNDRV_MINOR_CARD(minor); int dev = SNDRV_MINOR_DEVICE(minor); struct snd_minor *mptr = NULL; struct snd_minor *mptr = NULL; struct file_operations *old_fops; struct file_operations *old_fops; int err = 0; int err = 0; if (dev != SNDRV_MINOR_GLOBAL) { if (minor > ARRAY_SIZE(snd_minors)) if (snd_cards[card] == NULL) { #ifdef CONFIG_KMOD snd_request_card(card); if (snd_cards[card] == NULL) #endif return -ENODEV; return -ENODEV; } mptr = snd_minors[minor]; } else { if (mptr == NULL) { #ifdef CONFIG_KMOD #ifdef CONFIG_KMOD if ((mptr = snd_minors[minor]) == NULL) int dev = SNDRV_MINOR_DEVICE(minor); if (dev == SNDRV_MINOR_CONTROL) { /* /dev/aloadC? */ int card = SNDRV_MINOR_CARD(minor); if (snd_cards[card] == NULL) snd_request_card(card); } else if (dev == SNDRV_MINOR_GLOBAL) { /* /dev/aloadSEQ */ snd_request_other(minor); snd_request_other(minor); #endif } } if (mptr == NULL && (mptr = snd_minors[minor]) == NULL) #ifndef CONFIG_SND_DYNAMIC_MINORS /* /dev/snd/{controlC?,seq} */ mptr = snd_minors[minor]; if (mptr == NULL) #endif #endif return -ENODEV; return -ENODEV; } old_fops = file->f_op; old_fops = file->f_op; file->f_op = fops_get(mptr->f_ops); file->f_op = fops_get(mptr->f_ops); if (file->f_op->open) if (file->f_op->open) Loading @@ -174,6 +179,22 @@ static struct file_operations snd_fops = .open = snd_open .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) static int snd_kernel_minor(int type, struct snd_card *card, int dev) { { int minor; int minor; Loading @@ -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); snd_assert(minor >= 0 && minor < SNDRV_OS_MINORS, return -EINVAL); return minor; return minor; } } #endif /** /** * snd_register_device - Register the ALSA device file for the card * snd_register_device - Register the ALSA device file for the card Loading @@ -219,12 +241,10 @@ int snd_register_device(int type, struct snd_card *card, int dev, struct file_operations *f_ops, void *private_data, struct file_operations *f_ops, void *private_data, const char *name) const char *name) { { int minor = snd_kernel_minor(type, card, dev); int minor; struct snd_minor *preg; struct snd_minor *preg; struct device *device = NULL; struct device *device = NULL; if (minor < 0) return minor; snd_assert(name, return -EINVAL); snd_assert(name, return -EINVAL); preg = kmalloc(sizeof(struct snd_minor) + strlen(name) + 1, GFP_KERNEL); preg = kmalloc(sizeof(struct snd_minor) + strlen(name) + 1, GFP_KERNEL); if (preg == NULL) if (preg == NULL) Loading @@ -236,10 +256,17 @@ int snd_register_device(int type, struct snd_card *card, int dev, preg->private_data = private_data; preg->private_data = private_data; strcpy(preg->name, name); strcpy(preg->name, name); down(&sound_mutex); 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); up(&sound_mutex); kfree(preg); kfree(preg); return -EBUSY; return minor; } } snd_minors[minor] = preg; snd_minors[minor] = preg; if (type != SNDRV_DEVICE_TYPE_CONTROL || preg->card >= cards_limit) if (type != SNDRV_DEVICE_TYPE_CONTROL || preg->card >= cards_limit) Loading