Commit 332682b1 authored by Clemens Ladisch's avatar Clemens Ladisch Committed by Jaroslav Kysela
Browse files

[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: default avatarClemens Ladisch <clemens@ladisch.de>
parent f87135f5
Loading
Loading
Loading
Loading
+25 −4
Original line number Diff line number Diff line
@@ -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
+11 −0
Original line number Diff line number Diff line
@@ -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
+46 −19
Original line number Diff line number Diff line
@@ -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) {
#ifdef CONFIG_KMOD
			snd_request_card(card);
			if (snd_cards[card] == NULL)
#endif
	if (minor > ARRAY_SIZE(snd_minors))
		return -ENODEV;
		}
	} else {
	mptr = snd_minors[minor];
	if (mptr == NULL) {
#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);
#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;
	}
	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)