[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>
This commit is contained in:
committed by
Jaroslav Kysela
parent
f87135f56c
commit
332682b1cd
@@ -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
|
||||||
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
#ifdef CONFIG_KMOD
|
|
||||||
if ((mptr = snd_minors[minor]) == NULL)
|
|
||||||
snd_request_other(minor);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (mptr == NULL && (mptr = snd_minors[minor]) == NULL)
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
mptr = snd_minors[minor];
|
||||||
|
if (mptr == NULL) {
|
||||||
|
#ifdef CONFIG_KMOD
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
#ifndef CONFIG_SND_DYNAMIC_MINORS
|
||||||
|
/* /dev/snd/{controlC?,seq} */
|
||||||
|
mptr = snd_minors[minor];
|
||||||
|
if (mptr == NULL)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
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)
|
||||||
@@ -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;
|
||||||
@@ -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
|
||||||
@@ -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)
|
||||||
@@ -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)
|
||||||
|
Reference in New Issue
Block a user