aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2005-11-20 08:07:47 -0500
committerJaroslav Kysela <perex@suse.cz>2006-01-03 06:29:19 -0500
commit332682b1cd540dd7abbbbfc1905af8139e76e1b7 (patch)
treee2e858870972073b2e01f7f8d5948c187c11e2bb
parentf87135f56cb266e031f5ec081dfbde7e43f55e80 (diff)
[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.h29
-rw-r--r--sound/core/Kconfig11
-rw-r--r--sound/core/sound.c65
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 @@
26#define SNDRV_MINOR_DEVICE(minor) ((minor) & 0x001f) 26#define SNDRV_MINOR_DEVICE(minor) ((minor) & 0x001f)
27#define SNDRV_MINOR(card, dev) (((card) << 5) | (dev)) 27#define SNDRV_MINOR(card, dev) (((card) << 5) | (dev))
28 28
29#define SNDRV_MINOR_CONTROL 0 /* 0 - 0 */ 29/* these minors can still be used for autoloading devices (/dev/aload*) */
30#define SNDRV_MINOR_CONTROL 0 /* 0 */
30#define SNDRV_MINOR_GLOBAL 1 /* 1 */ 31#define SNDRV_MINOR_GLOBAL 1 /* 1 */
31#define SNDRV_MINOR_SEQUENCER (SNDRV_MINOR_GLOBAL + 0 * 32) 32#define SNDRV_MINOR_SEQUENCER (SNDRV_MINOR_GLOBAL + 0 * 32)
32#define SNDRV_MINOR_TIMER (SNDRV_MINOR_GLOBAL + 1 * 32) 33#define SNDRV_MINOR_TIMER (SNDRV_MINOR_GLOBAL + 1 * 32)
34
35#ifndef CONFIG_SND_DYNAMIC_MINORS
36 /* 2 - 3 (reserved) */
33#define SNDRV_MINOR_HWDEP 4 /* 4 - 7 */ 37#define SNDRV_MINOR_HWDEP 4 /* 4 - 7 */
34#define SNDRV_MINOR_HWDEPS 4
35#define SNDRV_MINOR_RAWMIDI 8 /* 8 - 15 */ 38#define SNDRV_MINOR_RAWMIDI 8 /* 8 - 15 */
36#define SNDRV_MINOR_RAWMIDIS 8
37#define SNDRV_MINOR_PCM_PLAYBACK 16 /* 16 - 23 */ 39#define SNDRV_MINOR_PCM_PLAYBACK 16 /* 16 - 23 */
38#define SNDRV_MINOR_PCM_CAPTURE 24 /* 24 - 31 */ 40#define SNDRV_MINOR_PCM_CAPTURE 24 /* 24 - 31 */
39#define SNDRV_MINOR_PCMS 8
40 41
42/* same as first respective minor number to make minor allocation easier */
41#define SNDRV_DEVICE_TYPE_CONTROL SNDRV_MINOR_CONTROL 43#define SNDRV_DEVICE_TYPE_CONTROL SNDRV_MINOR_CONTROL
42#define SNDRV_DEVICE_TYPE_HWDEP SNDRV_MINOR_HWDEP 44#define SNDRV_DEVICE_TYPE_HWDEP SNDRV_MINOR_HWDEP
43#define SNDRV_DEVICE_TYPE_RAWMIDI SNDRV_MINOR_RAWMIDI 45#define SNDRV_DEVICE_TYPE_RAWMIDI SNDRV_MINOR_RAWMIDI
@@ -46,6 +48,25 @@
46#define SNDRV_DEVICE_TYPE_SEQUENCER SNDRV_MINOR_SEQUENCER 48#define SNDRV_DEVICE_TYPE_SEQUENCER SNDRV_MINOR_SEQUENCER
47#define SNDRV_DEVICE_TYPE_TIMER SNDRV_MINOR_TIMER 49#define SNDRV_DEVICE_TYPE_TIMER SNDRV_MINOR_TIMER
48 50
51#else /* CONFIG_SND_DYNAMIC_MINORS */
52
53enum {
54 SNDRV_DEVICE_TYPE_CONTROL,
55 SNDRV_DEVICE_TYPE_SEQUENCER,
56 SNDRV_DEVICE_TYPE_TIMER,
57 SNDRV_DEVICE_TYPE_HWDEP,
58 SNDRV_DEVICE_TYPE_RAWMIDI,
59 SNDRV_DEVICE_TYPE_PCM_PLAYBACK,
60 SNDRV_DEVICE_TYPE_PCM_CAPTURE,
61};
62
63#endif /* CONFIG_SND_DYNAMIC_MINORS */
64
65#define SNDRV_MINOR_HWDEPS 4
66#define SNDRV_MINOR_RAWMIDIS 8
67#define SNDRV_MINOR_PCMS 8
68
69
49#ifdef CONFIG_SND_OSSEMUL 70#ifdef CONFIG_SND_OSSEMUL
50 71
51#define SNDRV_MINOR_OSS_DEVICES 16 72#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
111 111
112 If in doubt, say Y. 112 If in doubt, say Y.
113 113
114config SND_DYNAMIC_MINORS
115 bool "Dynamic device file minor numbers (EXPERIMENTAL)"
116 depends on SND && EXPERIMENTAL
117 help
118 If you say Y here, the minor numbers of ALSA device files in
119 /dev/snd/ are allocated dynamically. This allows you to have
120 more than 8 sound cards, but requires a dynamic device file
121 system like udev.
122
123 If you are unsure about this, say N here.
124
114config SND_VERBOSE_PRINTK 125config SND_VERBOSE_PRINTK
115 bool "Verbose printk" 126 bool "Verbose printk"
116 depends on SND 127 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)
133 133
134static int snd_open(struct inode *inode, struct file *file) 134static int snd_open(struct inode *inode, struct file *file)
135{ 135{
136 int minor = iminor(inode); 136 unsigned int minor = iminor(inode);
137 int card = SNDRV_MINOR_CARD(minor);
138 int dev = SNDRV_MINOR_DEVICE(minor);
139 struct snd_minor *mptr = NULL; 137 struct snd_minor *mptr = NULL;
140 struct file_operations *old_fops; 138 struct file_operations *old_fops;
141 int err = 0; 139 int err = 0;
142 140
143 if (dev != SNDRV_MINOR_GLOBAL) { 141 if (minor > ARRAY_SIZE(snd_minors))
144 if (snd_cards[card] == NULL) { 142 return -ENODEV;
143 mptr = snd_minors[minor];
144 if (mptr == NULL) {
145#ifdef CONFIG_KMOD 145#ifdef CONFIG_KMOD
146 snd_request_card(card); 146 int dev = SNDRV_MINOR_DEVICE(minor);
147 if (dev == SNDRV_MINOR_CONTROL) {
148 /* /dev/aloadC? */
149 int card = SNDRV_MINOR_CARD(minor);
147 if (snd_cards[card] == NULL) 150 if (snd_cards[card] == NULL)
148#endif 151 snd_request_card(card);
149 return -ENODEV; 152 } else if (dev == SNDRV_MINOR_GLOBAL) {
150 } 153 /* /dev/aloadSEQ */
151 } else {
152#ifdef CONFIG_KMOD
153 if ((mptr = snd_minors[minor]) == NULL)
154 snd_request_other(minor); 154 snd_request_other(minor);
155 }
156#ifndef CONFIG_SND_DYNAMIC_MINORS
157 /* /dev/snd/{controlC?,seq} */
158 mptr = snd_minors[minor];
159 if (mptr == NULL)
160#endif
155#endif 161#endif
162 return -ENODEV;
156 } 163 }
157 if (mptr == NULL && (mptr = snd_minors[minor]) == NULL)
158 return -ENODEV;
159 old_fops = file->f_op; 164 old_fops = file->f_op;
160 file->f_op = fops_get(mptr->f_ops); 165 file->f_op = fops_get(mptr->f_ops);
161 if (file->f_op->open) 166 if (file->f_op->open)
@@ -174,6 +179,22 @@ static struct file_operations snd_fops =
174 .open = snd_open 179 .open = snd_open
175}; 180};
176 181
182#ifdef CONFIG_SND_DYNAMIC_MINORS
183static int snd_find_free_minor(void)
184{
185 int minor;
186
187 for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) {
188 /* skip minors still used statically for autoloading devices */
189 if (SNDRV_MINOR_DEVICE(minor) == SNDRV_MINOR_CONTROL ||
190 minor == SNDRV_MINOR_SEQUENCER)
191 continue;
192 if (!snd_minors[minor])
193 return minor;
194 }
195 return -EBUSY;
196}
197#else
177static int snd_kernel_minor(int type, struct snd_card *card, int dev) 198static int snd_kernel_minor(int type, struct snd_card *card, int dev)
178{ 199{
179 int minor; 200 int minor;
@@ -200,6 +221,7 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)
200 snd_assert(minor >= 0 && minor < SNDRV_OS_MINORS, return -EINVAL); 221 snd_assert(minor >= 0 && minor < SNDRV_OS_MINORS, return -EINVAL);
201 return minor; 222 return minor;
202} 223}
224#endif
203 225
204/** 226/**
205 * snd_register_device - Register the ALSA device file for the card 227 * 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,
219 struct file_operations *f_ops, void *private_data, 241 struct file_operations *f_ops, void *private_data,
220 const char *name) 242 const char *name)
221{ 243{
222 int minor = snd_kernel_minor(type, card, dev); 244 int minor;
223 struct snd_minor *preg; 245 struct snd_minor *preg;
224 struct device *device = NULL; 246 struct device *device = NULL;
225 247
226 if (minor < 0)
227 return minor;
228 snd_assert(name, return -EINVAL); 248 snd_assert(name, return -EINVAL);
229 preg = kmalloc(sizeof(struct snd_minor) + strlen(name) + 1, GFP_KERNEL); 249 preg = kmalloc(sizeof(struct snd_minor) + strlen(name) + 1, GFP_KERNEL);
230 if (preg == NULL) 250 if (preg == NULL)
@@ -236,10 +256,17 @@ int snd_register_device(int type, struct snd_card *card, int dev,
236 preg->private_data = private_data; 256 preg->private_data = private_data;
237 strcpy(preg->name, name); 257 strcpy(preg->name, name);
238 down(&sound_mutex); 258 down(&sound_mutex);
239 if (snd_minors[minor]) { 259#ifdef CONFIG_SND_DYNAMIC_MINORS
260 minor = snd_find_free_minor();
261#else
262 minor = snd_kernel_minor(type, card, dev);
263 if (minor >= 0 && snd_minors[minor])
264 minor = -EBUSY;
265#endif
266 if (minor < 0) {
240 up(&sound_mutex); 267 up(&sound_mutex);
241 kfree(preg); 268 kfree(preg);
242 return -EBUSY; 269 return minor;
243 } 270 }
244 snd_minors[minor] = preg; 271 snd_minors[minor] = preg;
245 if (type != SNDRV_DEVICE_TYPE_CONTROL || preg->card >= cards_limit) 272 if (type != SNDRV_DEVICE_TYPE_CONTROL || preg->card >= cards_limit)