Commit f87135f56cb266e031f5ec081dfbde7e43f55e80
Committed by
Jaroslav Kysela
1 parent
6983b7240c
Exists in
master
and in
39 other branches
[ALSA] dynamic minors (3/6): store device-specific object pointers dynamically
Instead of storing the pointers to the device-specific structures in an array, put them into the struct snd_minor, and look them up dynamically. This makes the device type modules independent of the minor number encoding. Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Showing 17 changed files with 278 additions and 197 deletions Side-by-side Diff
- include/sound/core.h
- include/sound/hwdep.h
- include/sound/pcm.h
- include/sound/rawmidi.h
- sound/core/control.c
- sound/core/hwdep.c
- sound/core/oss/mixer_oss.c
- sound/core/oss/pcm_oss.c
- sound/core/pcm.c
- sound/core/pcm_native.c
- sound/core/rawmidi.c
- sound/core/seq/oss/seq_oss.c
- sound/core/seq/seq_clientmgr.c
- sound/core/seq/seq_midi.c
- sound/core/sound.c
- sound/core/sound_oss.c
- sound/core/timer.c
include/sound/core.h
... | ... | @@ -187,6 +187,7 @@ |
187 | 187 | int card; /* card number */ |
188 | 188 | int device; /* device number */ |
189 | 189 | struct file_operations *f_ops; /* file operations */ |
190 | + void *private_data; /* private data for f_ops->open */ | |
190 | 191 | char name[0]; /* device name (keep at the end of |
191 | 192 | structure) */ |
192 | 193 | }; |
193 | 194 | |
194 | 195 | |
195 | 196 | |
... | ... | @@ -199,13 +200,17 @@ |
199 | 200 | void snd_request_card(int card); |
200 | 201 | |
201 | 202 | int snd_register_device(int type, struct snd_card *card, int dev, |
202 | - struct file_operations *f_ops, const char *name); | |
203 | + struct file_operations *f_ops, void *private_data, | |
204 | + const char *name); | |
203 | 205 | int snd_unregister_device(int type, struct snd_card *card, int dev); |
206 | +void *snd_lookup_minor_data(unsigned int minor, int type); | |
204 | 207 | |
205 | 208 | #ifdef CONFIG_SND_OSSEMUL |
206 | 209 | int snd_register_oss_device(int type, struct snd_card *card, int dev, |
207 | - struct file_operations *f_ops, const char *name); | |
210 | + struct file_operations *f_ops, void *private_data, | |
211 | + const char *name); | |
208 | 212 | int snd_unregister_oss_device(int type, struct snd_card *card, int dev); |
213 | +void *snd_lookup_oss_minor_data(unsigned int minor, int type); | |
209 | 214 | #endif |
210 | 215 | |
211 | 216 | int snd_minor_info_init(void); |
include/sound/hwdep.h
include/sound/pcm.h
... | ... | @@ -412,6 +412,7 @@ |
412 | 412 | |
413 | 413 | struct snd_pcm { |
414 | 414 | struct snd_card *card; |
415 | + struct list_head list; | |
415 | 416 | unsigned int device; /* device number */ |
416 | 417 | unsigned int info_flags; |
417 | 418 | unsigned short dev_class; |
... | ... | @@ -439,7 +440,6 @@ |
439 | 440 | * Registering |
440 | 441 | */ |
441 | 442 | |
442 | -extern struct snd_pcm *snd_pcm_devices[]; | |
443 | 443 | extern struct file_operations snd_pcm_f_ops[2]; |
444 | 444 | |
445 | 445 | int snd_pcm_new(struct snd_card *card, char *id, int device, |
include/sound/rawmidi.h
... | ... | @@ -113,7 +113,7 @@ |
113 | 113 | |
114 | 114 | struct snd_rawmidi { |
115 | 115 | struct snd_card *card; |
116 | - | |
116 | + struct list_head list; | |
117 | 117 | unsigned int device; /* device number */ |
118 | 118 | unsigned int info_flags; /* SNDRV_RAWMIDI_INFO_XXXX */ |
119 | 119 | char id[64]; |
... | ... | @@ -165,8 +165,8 @@ |
165 | 165 | /* main midi functions */ |
166 | 166 | |
167 | 167 | int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info); |
168 | -int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice, int mode, | |
169 | - struct snd_rawmidi_file *rfile); | |
168 | +int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, | |
169 | + int mode, struct snd_rawmidi_file *rfile); | |
170 | 170 | int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile); |
171 | 171 | int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, |
172 | 172 | struct snd_rawmidi_params *params); |
sound/core/control.c
... | ... | @@ -47,13 +47,12 @@ |
47 | 47 | |
48 | 48 | static int snd_ctl_open(struct inode *inode, struct file *file) |
49 | 49 | { |
50 | - int cardnum = SNDRV_MINOR_CARD(iminor(inode)); | |
51 | 50 | unsigned long flags; |
52 | 51 | struct snd_card *card; |
53 | 52 | struct snd_ctl_file *ctl; |
54 | 53 | int err; |
55 | 54 | |
56 | - card = snd_cards[cardnum]; | |
55 | + card = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_CONTROL); | |
57 | 56 | if (!card) { |
58 | 57 | err = -ENODEV; |
59 | 58 | goto __error1; |
... | ... | @@ -1277,8 +1276,8 @@ |
1277 | 1276 | cardnum = card->number; |
1278 | 1277 | snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO); |
1279 | 1278 | sprintf(name, "controlC%i", cardnum); |
1280 | - if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, | |
1281 | - card, -1, &snd_ctl_f_ops, name)) < 0) | |
1279 | + if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1, | |
1280 | + &snd_ctl_f_ops, card, name)) < 0) | |
1282 | 1281 | return err; |
1283 | 1282 | return 0; |
1284 | 1283 | } |
sound/core/hwdep.c
... | ... | @@ -35,8 +35,7 @@ |
35 | 35 | MODULE_DESCRIPTION("Hardware dependent layer"); |
36 | 36 | MODULE_LICENSE("GPL"); |
37 | 37 | |
38 | -static struct snd_hwdep *snd_hwdep_devices[SNDRV_CARDS * SNDRV_MINOR_HWDEPS]; | |
39 | - | |
38 | +static LIST_HEAD(snd_hwdep_devices); | |
40 | 39 | static DECLARE_MUTEX(register_mutex); |
41 | 40 | |
42 | 41 | static int snd_hwdep_free(struct snd_hwdep *hwdep); |
43 | 42 | |
44 | 43 | |
... | ... | @@ -44,10 +43,20 @@ |
44 | 43 | static int snd_hwdep_dev_register(struct snd_device *device); |
45 | 44 | static int snd_hwdep_dev_unregister(struct snd_device *device); |
46 | 45 | |
47 | -/* | |
48 | 46 | |
49 | - */ | |
47 | +static struct snd_hwdep *snd_hwdep_search(struct snd_card *card, int device) | |
48 | +{ | |
49 | + struct list_head *p; | |
50 | + struct snd_hwdep *hwdep; | |
50 | 51 | |
52 | + list_for_each(p, &snd_hwdep_devices) { | |
53 | + hwdep = list_entry(p, struct snd_hwdep, list); | |
54 | + if (hwdep->card == card && hwdep->device == device) | |
55 | + return hwdep; | |
56 | + } | |
57 | + return NULL; | |
58 | +} | |
59 | + | |
51 | 60 | static loff_t snd_hwdep_llseek(struct file * file, loff_t offset, int orig) |
52 | 61 | { |
53 | 62 | struct snd_hwdep *hw = file->private_data; |
54 | 63 | |
55 | 64 | |
56 | 65 | |
57 | 66 | |
... | ... | @@ -77,34 +86,25 @@ |
77 | 86 | static int snd_hwdep_open(struct inode *inode, struct file * file) |
78 | 87 | { |
79 | 88 | int major = imajor(inode); |
80 | - int cardnum; | |
81 | - int device; | |
82 | 89 | struct snd_hwdep *hw; |
83 | 90 | int err; |
84 | 91 | wait_queue_t wait; |
85 | 92 | |
86 | 93 | if (major == snd_major) { |
87 | - cardnum = SNDRV_MINOR_CARD(iminor(inode)); | |
88 | - device = SNDRV_MINOR_DEVICE(iminor(inode)) - SNDRV_MINOR_HWDEP; | |
94 | + hw = snd_lookup_minor_data(iminor(inode), | |
95 | + SNDRV_DEVICE_TYPE_HWDEP); | |
89 | 96 | #ifdef CONFIG_SND_OSSEMUL |
90 | 97 | } else if (major == SOUND_MAJOR) { |
91 | - cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode)); | |
92 | - device = 0; | |
98 | + hw = snd_lookup_oss_minor_data(iminor(inode), | |
99 | + SNDRV_OSS_DEVICE_TYPE_DMFM); | |
93 | 100 | #endif |
94 | 101 | } else |
95 | 102 | return -ENXIO; |
96 | - cardnum %= SNDRV_CARDS; | |
97 | - device %= SNDRV_MINOR_HWDEPS; | |
98 | - hw = snd_hwdep_devices[(cardnum * SNDRV_MINOR_HWDEPS) + device]; | |
99 | 103 | if (hw == NULL) |
100 | 104 | return -ENODEV; |
101 | 105 | |
102 | 106 | if (!hw->ops.open) |
103 | 107 | return -ENXIO; |
104 | -#ifdef CONFIG_SND_OSSEMUL | |
105 | - if (major == SOUND_MAJOR && hw->oss_type < 0) | |
106 | - return -ENXIO; | |
107 | -#endif | |
108 | 108 | |
109 | 109 | if (!try_module_get(hw->card->module)) |
110 | 110 | return -EFAULT; |
... | ... | @@ -265,9 +265,6 @@ |
265 | 265 | struct snd_ctl_file * control, |
266 | 266 | unsigned int cmd, unsigned long arg) |
267 | 267 | { |
268 | - unsigned int tmp; | |
269 | - | |
270 | - tmp = card->number * SNDRV_MINOR_HWDEPS; | |
271 | 268 | switch (cmd) { |
272 | 269 | case SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE: |
273 | 270 | { |
274 | 271 | |
275 | 272 | |
... | ... | @@ -275,14 +272,16 @@ |
275 | 272 | |
276 | 273 | if (get_user(device, (int __user *)arg)) |
277 | 274 | return -EFAULT; |
275 | + down(®ister_mutex); | |
278 | 276 | device = device < 0 ? 0 : device + 1; |
279 | 277 | while (device < SNDRV_MINOR_HWDEPS) { |
280 | - if (snd_hwdep_devices[tmp + device]) | |
278 | + if (snd_hwdep_search(card, device)) | |
281 | 279 | break; |
282 | 280 | device++; |
283 | 281 | } |
284 | 282 | if (device >= SNDRV_MINOR_HWDEPS) |
285 | 283 | device = -1; |
284 | + up(®ister_mutex); | |
286 | 285 | if (put_user(device, (int __user *)arg)) |
287 | 286 | return -EFAULT; |
288 | 287 | return 0; |
289 | 288 | |
... | ... | @@ -290,17 +289,19 @@ |
290 | 289 | case SNDRV_CTL_IOCTL_HWDEP_INFO: |
291 | 290 | { |
292 | 291 | struct snd_hwdep_info __user *info = (struct snd_hwdep_info __user *)arg; |
293 | - int device; | |
292 | + int device, err; | |
294 | 293 | struct snd_hwdep *hwdep; |
295 | 294 | |
296 | 295 | if (get_user(device, &info->device)) |
297 | 296 | return -EFAULT; |
298 | - if (device < 0 || device >= SNDRV_MINOR_HWDEPS) | |
299 | - return -ENXIO; | |
300 | - hwdep = snd_hwdep_devices[tmp + device]; | |
301 | - if (hwdep == NULL) | |
302 | - return -ENXIO; | |
303 | - return snd_hwdep_info(hwdep, info); | |
297 | + down(®ister_mutex); | |
298 | + hwdep = snd_hwdep_search(card, device); | |
299 | + if (hwdep) | |
300 | + err = snd_hwdep_info(hwdep, info); | |
301 | + else | |
302 | + err = -ENXIO; | |
303 | + up(®ister_mutex); | |
304 | + return err; | |
304 | 305 | } |
305 | 306 | } |
306 | 307 | return -ENOIOCTLCMD; |
307 | 308 | |
308 | 309 | |
309 | 310 | |
310 | 311 | |
... | ... | @@ -397,23 +398,22 @@ |
397 | 398 | static int snd_hwdep_dev_register(struct snd_device *device) |
398 | 399 | { |
399 | 400 | struct snd_hwdep *hwdep = device->device_data; |
400 | - int idx, err; | |
401 | + int err; | |
401 | 402 | char name[32]; |
402 | 403 | |
403 | 404 | down(®ister_mutex); |
404 | - idx = (hwdep->card->number * SNDRV_MINOR_HWDEPS) + hwdep->device; | |
405 | - if (snd_hwdep_devices[idx]) { | |
405 | + if (snd_hwdep_search(hwdep->card, hwdep->device)) { | |
406 | 406 | up(®ister_mutex); |
407 | 407 | return -EBUSY; |
408 | 408 | } |
409 | - snd_hwdep_devices[idx] = hwdep; | |
409 | + list_add_tail(&hwdep->list, &snd_hwdep_devices); | |
410 | 410 | sprintf(name, "hwC%iD%i", hwdep->card->number, hwdep->device); |
411 | 411 | if ((err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP, |
412 | 412 | hwdep->card, hwdep->device, |
413 | - &snd_hwdep_f_ops, name)) < 0) { | |
413 | + &snd_hwdep_f_ops, hwdep, name)) < 0) { | |
414 | 414 | snd_printk(KERN_ERR "unable to register hardware dependent device %i:%i\n", |
415 | 415 | hwdep->card->number, hwdep->device); |
416 | - snd_hwdep_devices[idx] = NULL; | |
416 | + list_del(&hwdep->list); | |
417 | 417 | up(®ister_mutex); |
418 | 418 | return err; |
419 | 419 | } |
... | ... | @@ -425,7 +425,7 @@ |
425 | 425 | } else { |
426 | 426 | if (snd_register_oss_device(hwdep->oss_type, |
427 | 427 | hwdep->card, hwdep->device, |
428 | - &snd_hwdep_f_ops, | |
428 | + &snd_hwdep_f_ops, hwdep, | |
429 | 429 | hwdep->oss_dev) < 0) { |
430 | 430 | snd_printk(KERN_ERR "unable to register OSS compatibility device %i:%i\n", |
431 | 431 | hwdep->card->number, hwdep->device); |
432 | 432 | |
... | ... | @@ -441,12 +441,10 @@ |
441 | 441 | static int snd_hwdep_dev_unregister(struct snd_device *device) |
442 | 442 | { |
443 | 443 | struct snd_hwdep *hwdep = device->device_data; |
444 | - int idx; | |
445 | 444 | |
446 | 445 | snd_assert(hwdep != NULL, return -ENXIO); |
447 | 446 | down(®ister_mutex); |
448 | - idx = (hwdep->card->number * SNDRV_MINOR_HWDEPS) + hwdep->device; | |
449 | - if (snd_hwdep_devices[idx] != hwdep) { | |
447 | + if (snd_hwdep_search(hwdep->card, hwdep->device) != hwdep) { | |
450 | 448 | up(®ister_mutex); |
451 | 449 | return -EINVAL; |
452 | 450 | } |
... | ... | @@ -455,7 +453,7 @@ |
455 | 453 | snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); |
456 | 454 | #endif |
457 | 455 | snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); |
458 | - snd_hwdep_devices[idx] = NULL; | |
456 | + list_del(&hwdep->list); | |
459 | 457 | up(®ister_mutex); |
460 | 458 | return snd_hwdep_free(hwdep); |
461 | 459 | } |
462 | 460 | |
463 | 461 | |
... | ... | @@ -467,18 +465,14 @@ |
467 | 465 | static void snd_hwdep_proc_read(struct snd_info_entry *entry, |
468 | 466 | struct snd_info_buffer *buffer) |
469 | 467 | { |
470 | - int idx; | |
468 | + struct list_head *p; | |
471 | 469 | struct snd_hwdep *hwdep; |
472 | 470 | |
473 | 471 | down(®ister_mutex); |
474 | - for (idx = 0; idx < SNDRV_CARDS * SNDRV_MINOR_HWDEPS; idx++) { | |
475 | - hwdep = snd_hwdep_devices[idx]; | |
476 | - if (hwdep == NULL) | |
477 | - continue; | |
472 | + list_for_each(p, &snd_hwdep_devices) { | |
473 | + hwdep = list_entry(p, struct snd_hwdep, list); | |
478 | 474 | snd_iprintf(buffer, "%02i-%02i: %s\n", |
479 | - idx / SNDRV_MINOR_HWDEPS, | |
480 | - idx % SNDRV_MINOR_HWDEPS, | |
481 | - hwdep->name); | |
475 | + hwdep->card->number, hwdep->device, hwdep->name); | |
482 | 476 | } |
483 | 477 | up(®ister_mutex); |
484 | 478 | } |
485 | 479 | |
... | ... | @@ -493,9 +487,8 @@ |
493 | 487 | { |
494 | 488 | struct snd_info_entry *entry; |
495 | 489 | |
496 | - memset(snd_hwdep_devices, 0, sizeof(snd_hwdep_devices)); | |
497 | 490 | if ((entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL)) != NULL) { |
498 | - entry->c.text.read_size = 512; | |
491 | + entry->c.text.read_size = PAGE_SIZE; | |
499 | 492 | entry->c.text.read = snd_hwdep_proc_read; |
500 | 493 | if (snd_info_register(entry) < 0) { |
501 | 494 | snd_info_free_entry(entry); |
sound/core/oss/mixer_oss.c
... | ... | @@ -41,12 +41,13 @@ |
41 | 41 | |
42 | 42 | static int snd_mixer_oss_open(struct inode *inode, struct file *file) |
43 | 43 | { |
44 | - int cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode)); | |
45 | 44 | struct snd_card *card; |
46 | 45 | struct snd_mixer_oss_file *fmixer; |
47 | 46 | int err; |
48 | 47 | |
49 | - if ((card = snd_cards[cardnum]) == NULL) | |
48 | + card = snd_lookup_oss_minor_data(iminor(inode), | |
49 | + SNDRV_OSS_DEVICE_TYPE_MIXER); | |
50 | + if (card == NULL) | |
50 | 51 | return -ENODEV; |
51 | 52 | if (card->mixer_oss == NULL) |
52 | 53 | return -ENODEV; |
... | ... | @@ -1286,7 +1287,7 @@ |
1286 | 1287 | sprintf(name, "mixer%i%i", card->number, 0); |
1287 | 1288 | if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, |
1288 | 1289 | card, 0, |
1289 | - &snd_mixer_oss_f_ops, | |
1290 | + &snd_mixer_oss_f_ops, card, | |
1290 | 1291 | name)) < 0) { |
1291 | 1292 | snd_printk(KERN_ERR "unable to register OSS mixer device %i:%i\n", |
1292 | 1293 | card->number, 0); |
sound/core/oss/pcm_oss.c
... | ... | @@ -1834,9 +1834,6 @@ |
1834 | 1834 | |
1835 | 1835 | static int snd_pcm_oss_open(struct inode *inode, struct file *file) |
1836 | 1836 | { |
1837 | - int minor = iminor(inode); | |
1838 | - int cardnum = SNDRV_MINOR_OSS_CARD(minor); | |
1839 | - int device; | |
1840 | 1837 | int err; |
1841 | 1838 | char task_name[32]; |
1842 | 1839 | struct snd_pcm *pcm; |
... | ... | @@ -1845,11 +1842,8 @@ |
1845 | 1842 | int nonblock; |
1846 | 1843 | wait_queue_t wait; |
1847 | 1844 | |
1848 | - snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO); | |
1849 | - device = SNDRV_MINOR_OSS_DEVICE(minor) == SNDRV_MINOR_OSS_PCM1 ? | |
1850 | - adsp_map[cardnum] : dsp_map[cardnum]; | |
1851 | - | |
1852 | - pcm = snd_pcm_devices[(cardnum * SNDRV_PCM_DEVICES) + device]; | |
1845 | + pcm = snd_lookup_oss_minor_data(iminor(inode), | |
1846 | + SNDRV_OSS_DEVICE_TYPE_PCM); | |
1853 | 1847 | if (pcm == NULL) { |
1854 | 1848 | err = -ENODEV; |
1855 | 1849 | goto __error1; |
... | ... | @@ -1890,7 +1884,7 @@ |
1890 | 1884 | down(&pcm->open_mutex); |
1891 | 1885 | while (1) { |
1892 | 1886 | err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file, |
1893 | - minor, psetup, csetup); | |
1887 | + iminor(inode), psetup, csetup); | |
1894 | 1888 | if (err >= 0) |
1895 | 1889 | break; |
1896 | 1890 | if (err == -EAGAIN) { |
... | ... | @@ -2450,7 +2444,7 @@ |
2450 | 2444 | sprintf(name, "dsp%i%i", pcm->card->number, pcm->device); |
2451 | 2445 | if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, |
2452 | 2446 | pcm->card, index, &snd_pcm_oss_f_reg, |
2453 | - name) < 0) { | |
2447 | + pcm, name) < 0) { | |
2454 | 2448 | snd_printk(KERN_ERR "unable to register OSS PCM device %i:%i\n", |
2455 | 2449 | pcm->card->number, pcm->device); |
2456 | 2450 | } |
sound/core/pcm.c
... | ... | @@ -33,7 +33,7 @@ |
33 | 33 | MODULE_DESCRIPTION("Midlevel PCM code for ALSA."); |
34 | 34 | MODULE_LICENSE("GPL"); |
35 | 35 | |
36 | -struct snd_pcm *snd_pcm_devices[SNDRV_CARDS * SNDRV_PCM_DEVICES]; | |
36 | +static LIST_HEAD(snd_pcm_devices); | |
37 | 37 | static LIST_HEAD(snd_pcm_notify_list); |
38 | 38 | static DECLARE_MUTEX(register_mutex); |
39 | 39 | |
40 | 40 | |
... | ... | @@ -43,13 +43,23 @@ |
43 | 43 | static int snd_pcm_dev_disconnect(struct snd_device *device); |
44 | 44 | static int snd_pcm_dev_unregister(struct snd_device *device); |
45 | 45 | |
46 | +static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device) | |
47 | +{ | |
48 | + struct list_head *p; | |
49 | + struct snd_pcm *pcm; | |
50 | + | |
51 | + list_for_each(p, &snd_pcm_devices) { | |
52 | + pcm = list_entry(p, struct snd_pcm, list); | |
53 | + if (pcm->card == card && pcm->device == device) | |
54 | + return pcm; | |
55 | + } | |
56 | + return NULL; | |
57 | +} | |
58 | + | |
46 | 59 | static int snd_pcm_control_ioctl(struct snd_card *card, |
47 | 60 | struct snd_ctl_file *control, |
48 | 61 | unsigned int cmd, unsigned long arg) |
49 | 62 | { |
50 | - unsigned int tmp; | |
51 | - | |
52 | - tmp = card->number * SNDRV_PCM_DEVICES; | |
53 | 63 | switch (cmd) { |
54 | 64 | case SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE: |
55 | 65 | { |
56 | 66 | |
57 | 67 | |
... | ... | @@ -57,14 +67,16 @@ |
57 | 67 | |
58 | 68 | if (get_user(device, (int __user *)arg)) |
59 | 69 | return -EFAULT; |
70 | + down(®ister_mutex); | |
60 | 71 | device = device < 0 ? 0 : device + 1; |
61 | 72 | while (device < SNDRV_PCM_DEVICES) { |
62 | - if (snd_pcm_devices[tmp + device]) | |
73 | + if (snd_pcm_search(card, device)) | |
63 | 74 | break; |
64 | 75 | device++; |
65 | 76 | } |
66 | 77 | if (device == SNDRV_PCM_DEVICES) |
67 | 78 | device = -1; |
79 | + up(®ister_mutex); | |
68 | 80 | if (put_user(device, (int __user *)arg)) |
69 | 81 | return -EFAULT; |
70 | 82 | return 0; |
71 | 83 | |
72 | 84 | |
73 | 85 | |
74 | 86 | |
... | ... | @@ -77,31 +89,44 @@ |
77 | 89 | struct snd_pcm *pcm; |
78 | 90 | struct snd_pcm_str *pstr; |
79 | 91 | struct snd_pcm_substream *substream; |
92 | + int err; | |
93 | + | |
80 | 94 | info = (struct snd_pcm_info __user *)arg; |
81 | 95 | if (get_user(device, &info->device)) |
82 | 96 | return -EFAULT; |
83 | - if (device >= SNDRV_PCM_DEVICES) | |
84 | - return -ENXIO; | |
85 | - pcm = snd_pcm_devices[tmp + device]; | |
86 | - if (pcm == NULL) | |
87 | - return -ENXIO; | |
88 | 97 | if (get_user(stream, &info->stream)) |
89 | 98 | return -EFAULT; |
90 | 99 | if (stream < 0 || stream > 1) |
91 | 100 | return -EINVAL; |
92 | - pstr = &pcm->streams[stream]; | |
93 | - if (pstr->substream_count == 0) | |
94 | - return -ENOENT; | |
95 | 101 | if (get_user(subdevice, &info->subdevice)) |
96 | 102 | return -EFAULT; |
97 | - if (subdevice >= pstr->substream_count) | |
98 | - return -ENXIO; | |
99 | - for (substream = pstr->substream; substream; substream = substream->next) | |
103 | + down(®ister_mutex); | |
104 | + pcm = snd_pcm_search(card, device); | |
105 | + if (pcm == NULL) { | |
106 | + err = -ENXIO; | |
107 | + goto _error; | |
108 | + } | |
109 | + pstr = &pcm->streams[stream]; | |
110 | + if (pstr->substream_count == 0) { | |
111 | + err = -ENOENT; | |
112 | + goto _error; | |
113 | + } | |
114 | + if (subdevice >= pstr->substream_count) { | |
115 | + err = -ENXIO; | |
116 | + goto _error; | |
117 | + } | |
118 | + for (substream = pstr->substream; substream; | |
119 | + substream = substream->next) | |
100 | 120 | if (substream->number == (int)subdevice) |
101 | 121 | break; |
102 | - if (substream == NULL) | |
103 | - return -ENXIO; | |
104 | - return snd_pcm_info_user(substream, info); | |
122 | + if (substream == NULL) { | |
123 | + err = -ENXIO; | |
124 | + goto _error; | |
125 | + } | |
126 | + err = snd_pcm_info_user(substream, info); | |
127 | + _error: | |
128 | + up(®ister_mutex); | |
129 | + return err; | |
105 | 130 | } |
106 | 131 | case SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE: |
107 | 132 | { |
... | ... | @@ -865,8 +890,7 @@ |
865 | 890 | |
866 | 891 | static int snd_pcm_dev_register(struct snd_device *device) |
867 | 892 | { |
868 | - int idx, cidx, err; | |
869 | - unsigned short minor; | |
893 | + int cidx, err; | |
870 | 894 | struct snd_pcm_substream *substream; |
871 | 895 | struct list_head *list; |
872 | 896 | char str[16]; |
873 | 897 | |
... | ... | @@ -874,12 +898,11 @@ |
874 | 898 | |
875 | 899 | snd_assert(pcm != NULL && device != NULL, return -ENXIO); |
876 | 900 | down(®ister_mutex); |
877 | - idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device; | |
878 | - if (snd_pcm_devices[idx]) { | |
901 | + if (snd_pcm_search(pcm->card, pcm->device)) { | |
879 | 902 | up(®ister_mutex); |
880 | 903 | return -EBUSY; |
881 | 904 | } |
882 | - snd_pcm_devices[idx] = pcm; | |
905 | + list_add_tail(&pcm->list, &snd_pcm_devices); | |
883 | 906 | for (cidx = 0; cidx < 2; cidx++) { |
884 | 907 | int devtype = -1; |
885 | 908 | if (pcm->streams[cidx].substream == NULL) |
886 | 909 | |
887 | 910 | |
888 | 911 | |
... | ... | @@ -887,20 +910,19 @@ |
887 | 910 | switch (cidx) { |
888 | 911 | case SNDRV_PCM_STREAM_PLAYBACK: |
889 | 912 | sprintf(str, "pcmC%iD%ip", pcm->card->number, pcm->device); |
890 | - minor = SNDRV_MINOR_PCM_PLAYBACK + idx; | |
891 | 913 | devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK; |
892 | 914 | break; |
893 | 915 | case SNDRV_PCM_STREAM_CAPTURE: |
894 | 916 | sprintf(str, "pcmC%iD%ic", pcm->card->number, pcm->device); |
895 | - minor = SNDRV_MINOR_PCM_CAPTURE + idx; | |
896 | 917 | devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE; |
897 | 918 | break; |
898 | 919 | } |
899 | 920 | if ((err = snd_register_device(devtype, pcm->card, |
900 | 921 | pcm->device, |
901 | - &snd_pcm_f_ops[cidx], str)) < 0) | |
922 | + &snd_pcm_f_ops[cidx], | |
923 | + pcm, str)) < 0) | |
902 | 924 | { |
903 | - snd_pcm_devices[idx] = NULL; | |
925 | + list_del(&pcm->list); | |
904 | 926 | up(®ister_mutex); |
905 | 927 | return err; |
906 | 928 | } |
907 | 929 | |
... | ... | @@ -921,11 +943,10 @@ |
921 | 943 | struct snd_pcm *pcm = device->device_data; |
922 | 944 | struct list_head *list; |
923 | 945 | struct snd_pcm_substream *substream; |
924 | - int idx, cidx; | |
946 | + int cidx; | |
925 | 947 | |
926 | 948 | down(®ister_mutex); |
927 | - idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device; | |
928 | - snd_pcm_devices[idx] = NULL; | |
949 | + list_del_init(&pcm->list); | |
929 | 950 | for (cidx = 0; cidx < 2; cidx++) |
930 | 951 | for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) |
931 | 952 | if (substream->runtime) |
932 | 953 | |
... | ... | @@ -941,15 +962,14 @@ |
941 | 962 | |
942 | 963 | static int snd_pcm_dev_unregister(struct snd_device *device) |
943 | 964 | { |
944 | - int idx, cidx, devtype; | |
965 | + int cidx, devtype; | |
945 | 966 | struct snd_pcm_substream *substream; |
946 | 967 | struct list_head *list; |
947 | 968 | struct snd_pcm *pcm = device->device_data; |
948 | 969 | |
949 | 970 | snd_assert(pcm != NULL, return -ENXIO); |
950 | 971 | down(®ister_mutex); |
951 | - idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device; | |
952 | - snd_pcm_devices[idx] = NULL; | |
972 | + list_del(&pcm->list); | |
953 | 973 | for (cidx = 0; cidx < 2; cidx++) { |
954 | 974 | devtype = -1; |
955 | 975 | switch (cidx) { |
956 | 976 | |
957 | 977 | |
... | ... | @@ -975,24 +995,19 @@ |
975 | 995 | |
976 | 996 | int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) |
977 | 997 | { |
978 | - int idx; | |
998 | + struct list_head *p; | |
979 | 999 | |
980 | 1000 | snd_assert(notify != NULL && notify->n_register != NULL && notify->n_unregister != NULL, return -EINVAL); |
981 | 1001 | down(®ister_mutex); |
982 | 1002 | if (nfree) { |
983 | 1003 | list_del(¬ify->list); |
984 | - for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) { | |
985 | - if (snd_pcm_devices[idx] == NULL) | |
986 | - continue; | |
987 | - notify->n_unregister(snd_pcm_devices[idx]); | |
988 | - } | |
1004 | + list_for_each(p, &snd_pcm_devices) | |
1005 | + notify->n_unregister(list_entry(p, | |
1006 | + struct snd_pcm, list)); | |
989 | 1007 | } else { |
990 | 1008 | list_add_tail(¬ify->list, &snd_pcm_notify_list); |
991 | - for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) { | |
992 | - if (snd_pcm_devices[idx] == NULL) | |
993 | - continue; | |
994 | - notify->n_register(snd_pcm_devices[idx]); | |
995 | - } | |
1009 | + list_for_each(p, &snd_pcm_devices) | |
1010 | + notify->n_register(list_entry(p, struct snd_pcm, list)); | |
996 | 1011 | } |
997 | 1012 | up(®ister_mutex); |
998 | 1013 | return 0; |
999 | 1014 | |
... | ... | @@ -1005,16 +1020,14 @@ |
1005 | 1020 | static void snd_pcm_proc_read(struct snd_info_entry *entry, |
1006 | 1021 | struct snd_info_buffer *buffer) |
1007 | 1022 | { |
1008 | - int idx; | |
1023 | + struct list_head *p; | |
1009 | 1024 | struct snd_pcm *pcm; |
1010 | 1025 | |
1011 | 1026 | down(®ister_mutex); |
1012 | - for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) { | |
1013 | - pcm = snd_pcm_devices[idx]; | |
1014 | - if (pcm == NULL) | |
1015 | - continue; | |
1016 | - snd_iprintf(buffer, "%02i-%02i: %s : %s", idx / SNDRV_PCM_DEVICES, | |
1017 | - idx % SNDRV_PCM_DEVICES, pcm->id, pcm->name); | |
1027 | + list_for_each(p, &snd_pcm_devices) { | |
1028 | + pcm = list_entry(p, struct snd_pcm, list); | |
1029 | + snd_iprintf(buffer, "%02i-%02i: %s : %s", | |
1030 | + pcm->card->number, pcm->device, pcm->id, pcm->name); | |
1018 | 1031 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) |
1019 | 1032 | snd_iprintf(buffer, " : playback %i", |
1020 | 1033 | pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count); |
... | ... | @@ -1063,7 +1076,6 @@ |
1063 | 1076 | module_init(alsa_pcm_init) |
1064 | 1077 | module_exit(alsa_pcm_exit) |
1065 | 1078 | |
1066 | -EXPORT_SYMBOL(snd_pcm_devices); | |
1067 | 1079 | EXPORT_SYMBOL(snd_pcm_new); |
1068 | 1080 | EXPORT_SYMBOL(snd_pcm_new_stream); |
1069 | 1081 | EXPORT_SYMBOL(snd_pcm_notify); |
sound/core/pcm_native.c
... | ... | @@ -62,6 +62,7 @@ |
62 | 62 | struct snd_pcm_hw_params_old __user * _oparams); |
63 | 63 | static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream, |
64 | 64 | struct snd_pcm_hw_params_old __user * _oparams); |
65 | +static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream); | |
65 | 66 | |
66 | 67 | /* |
67 | 68 | * |
... | ... | @@ -1554,7 +1555,8 @@ |
1554 | 1555 | { |
1555 | 1556 | struct file *file; |
1556 | 1557 | struct inode *inode; |
1557 | - unsigned short minor; | |
1558 | + unsigned int minor; | |
1559 | + | |
1558 | 1560 | file = fget(fd); |
1559 | 1561 | if (!file) |
1560 | 1562 | return NULL; |
... | ... | @@ -1565,8 +1567,8 @@ |
1565 | 1567 | return NULL; |
1566 | 1568 | } |
1567 | 1569 | minor = iminor(inode); |
1568 | - if (minor >= 256 || | |
1569 | - minor % SNDRV_MINOR_DEVICES < SNDRV_MINOR_PCM_PLAYBACK) { | |
1570 | + if (!snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_PLAYBACK) && | |
1571 | + !snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_CAPTURE)) { | |
1570 | 1572 | fput(file); |
1571 | 1573 | return NULL; |
1572 | 1574 | } |
1573 | 1575 | |
1574 | 1576 | |
1575 | 1577 | |
... | ... | @@ -2071,18 +2073,30 @@ |
2071 | 2073 | return 0; |
2072 | 2074 | } |
2073 | 2075 | |
2074 | -static int snd_pcm_open(struct inode *inode, struct file *file) | |
2076 | +static int snd_pcm_playback_open(struct inode *inode, struct file *file) | |
2075 | 2077 | { |
2076 | - int cardnum = SNDRV_MINOR_CARD(iminor(inode)); | |
2077 | - int device = SNDRV_MINOR_DEVICE(iminor(inode)); | |
2078 | - int err; | |
2079 | 2078 | struct snd_pcm *pcm; |
2079 | + | |
2080 | + pcm = snd_lookup_minor_data(iminor(inode), | |
2081 | + SNDRV_DEVICE_TYPE_PCM_PLAYBACK); | |
2082 | + return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); | |
2083 | +} | |
2084 | + | |
2085 | +static int snd_pcm_capture_open(struct inode *inode, struct file *file) | |
2086 | +{ | |
2087 | + struct snd_pcm *pcm; | |
2088 | + | |
2089 | + pcm = snd_lookup_minor_data(iminor(inode), | |
2090 | + SNDRV_DEVICE_TYPE_PCM_CAPTURE); | |
2091 | + return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); | |
2092 | +} | |
2093 | + | |
2094 | +static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) | |
2095 | +{ | |
2096 | + int err; | |
2080 | 2097 | struct snd_pcm_file *pcm_file; |
2081 | 2098 | wait_queue_t wait; |
2082 | 2099 | |
2083 | - if (device < SNDRV_MINOR_PCM_PLAYBACK || device >= SNDRV_MINOR_DEVICES) | |
2084 | - return -ENXIO; | |
2085 | - pcm = snd_pcm_devices[(cardnum * SNDRV_PCM_DEVICES) + (device % SNDRV_MINOR_PCMS)]; | |
2086 | 2100 | if (pcm == NULL) { |
2087 | 2101 | err = -ENODEV; |
2088 | 2102 | goto __error1; |
... | ... | @@ -2098,7 +2112,7 @@ |
2098 | 2112 | add_wait_queue(&pcm->open_wait, &wait); |
2099 | 2113 | down(&pcm->open_mutex); |
2100 | 2114 | while (1) { |
2101 | - err = snd_pcm_open_file(file, pcm, device >= SNDRV_MINOR_PCM_CAPTURE ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK, &pcm_file); | |
2115 | + err = snd_pcm_open_file(file, pcm, stream, &pcm_file); | |
2102 | 2116 | if (err >= 0) |
2103 | 2117 | break; |
2104 | 2118 | if (err == -EAGAIN) { |
... | ... | @@ -3375,7 +3389,7 @@ |
3375 | 3389 | .owner = THIS_MODULE, |
3376 | 3390 | .write = snd_pcm_write, |
3377 | 3391 | .writev = snd_pcm_writev, |
3378 | - .open = snd_pcm_open, | |
3392 | + .open = snd_pcm_playback_open, | |
3379 | 3393 | .release = snd_pcm_release, |
3380 | 3394 | .poll = snd_pcm_playback_poll, |
3381 | 3395 | .unlocked_ioctl = snd_pcm_playback_ioctl, |
... | ... | @@ -3387,7 +3401,7 @@ |
3387 | 3401 | .owner = THIS_MODULE, |
3388 | 3402 | .read = snd_pcm_read, |
3389 | 3403 | .readv = snd_pcm_readv, |
3390 | - .open = snd_pcm_open, | |
3404 | + .open = snd_pcm_capture_open, | |
3391 | 3405 | .release = snd_pcm_release, |
3392 | 3406 | .poll = snd_pcm_capture_poll, |
3393 | 3407 | .unlocked_ioctl = snd_pcm_capture_ioctl, |
sound/core/rawmidi.c
... | ... | @@ -56,10 +56,22 @@ |
56 | 56 | static int snd_rawmidi_dev_disconnect(struct snd_device *device); |
57 | 57 | static int snd_rawmidi_dev_unregister(struct snd_device *device); |
58 | 58 | |
59 | -static struct snd_rawmidi *snd_rawmidi_devices[SNDRV_CARDS * SNDRV_RAWMIDI_DEVICES]; | |
60 | - | |
59 | +static LIST_HEAD(snd_rawmidi_devices); | |
61 | 60 | static DECLARE_MUTEX(register_mutex); |
62 | 61 | |
62 | +static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device) | |
63 | +{ | |
64 | + struct list_head *p; | |
65 | + struct snd_rawmidi *rawmidi; | |
66 | + | |
67 | + list_for_each(p, &snd_rawmidi_devices) { | |
68 | + rawmidi = list_entry(p, struct snd_rawmidi, list); | |
69 | + if (rawmidi->card == card && rawmidi->device == device) | |
70 | + return rawmidi; | |
71 | + } | |
72 | + return NULL; | |
73 | +} | |
74 | + | |
63 | 75 | static inline unsigned short snd_rawmidi_file_flags(struct file *file) |
64 | 76 | { |
65 | 77 | switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) { |
... | ... | @@ -214,7 +226,7 @@ |
214 | 226 | return 0; |
215 | 227 | } |
216 | 228 | |
217 | -int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice, | |
229 | +int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, | |
218 | 230 | int mode, struct snd_rawmidi_file * rfile) |
219 | 231 | { |
220 | 232 | struct snd_rawmidi *rmidi; |
... | ... | @@ -225,7 +237,9 @@ |
225 | 237 | |
226 | 238 | if (rfile) |
227 | 239 | rfile->input = rfile->output = NULL; |
228 | - rmidi = snd_rawmidi_devices[(cardnum * SNDRV_RAWMIDI_DEVICES) + device]; | |
240 | + down(®ister_mutex); | |
241 | + rmidi = snd_rawmidi_search(card, device); | |
242 | + up(®ister_mutex); | |
229 | 243 | if (rmidi == NULL) { |
230 | 244 | err = -ENODEV; |
231 | 245 | goto __error1; |
232 | 246 | |
... | ... | @@ -368,9 +382,8 @@ |
368 | 382 | static int snd_rawmidi_open(struct inode *inode, struct file *file) |
369 | 383 | { |
370 | 384 | int maj = imajor(inode); |
371 | - int cardnum; | |
372 | 385 | struct snd_card *card; |
373 | - int device, subdevice; | |
386 | + int subdevice; | |
374 | 387 | unsigned short fflags; |
375 | 388 | int err; |
376 | 389 | struct snd_rawmidi *rmidi; |
377 | 390 | |
378 | 391 | |
379 | 392 | |
... | ... | @@ -380,27 +393,18 @@ |
380 | 393 | struct snd_ctl_file *kctl; |
381 | 394 | |
382 | 395 | if (maj == snd_major) { |
383 | - cardnum = SNDRV_MINOR_CARD(iminor(inode)); | |
384 | - cardnum %= SNDRV_CARDS; | |
385 | - device = SNDRV_MINOR_DEVICE(iminor(inode)) - SNDRV_MINOR_RAWMIDI; | |
386 | - device %= SNDRV_MINOR_RAWMIDIS; | |
396 | + rmidi = snd_lookup_minor_data(iminor(inode), | |
397 | + SNDRV_DEVICE_TYPE_RAWMIDI); | |
387 | 398 | #ifdef CONFIG_SND_OSSEMUL |
388 | 399 | } else if (maj == SOUND_MAJOR) { |
389 | - cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode)); | |
390 | - cardnum %= SNDRV_CARDS; | |
391 | - device = SNDRV_MINOR_OSS_DEVICE(iminor(inode)) == SNDRV_MINOR_OSS_MIDI ? | |
392 | - midi_map[cardnum] : amidi_map[cardnum]; | |
400 | + rmidi = snd_lookup_oss_minor_data(iminor(inode), | |
401 | + SNDRV_OSS_DEVICE_TYPE_MIDI); | |
393 | 402 | #endif |
394 | 403 | } else |
395 | 404 | return -ENXIO; |
396 | 405 | |
397 | - rmidi = snd_rawmidi_devices[(cardnum * SNDRV_RAWMIDI_DEVICES) + device]; | |
398 | 406 | if (rmidi == NULL) |
399 | 407 | return -ENODEV; |
400 | -#ifdef CONFIG_SND_OSSEMUL | |
401 | - if (maj == SOUND_MAJOR && !rmidi->ossreg) | |
402 | - return -ENXIO; | |
403 | -#endif | |
404 | 408 | if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) |
405 | 409 | return -EINVAL; /* invalid combination */ |
406 | 410 | card = rmidi->card; |
... | ... | @@ -430,7 +434,8 @@ |
430 | 434 | } |
431 | 435 | } |
432 | 436 | up_read(&card->controls_rwsem); |
433 | - err = snd_rawmidi_kernel_open(cardnum, device, subdevice, fflags, rawmidi_file); | |
437 | + err = snd_rawmidi_kernel_open(rmidi->card, rmidi->device, | |
438 | + subdevice, fflags, rawmidi_file); | |
434 | 439 | if (err >= 0) |
435 | 440 | break; |
436 | 441 | if (err == -EAGAIN) { |
... | ... | @@ -570,9 +575,10 @@ |
570 | 575 | struct snd_rawmidi_str *pstr; |
571 | 576 | struct snd_rawmidi_substream *substream; |
572 | 577 | struct list_head *list; |
573 | - if (info->device >= SNDRV_RAWMIDI_DEVICES) | |
574 | - return -ENXIO; | |
575 | - rmidi = snd_rawmidi_devices[card->number * SNDRV_RAWMIDI_DEVICES + info->device]; | |
578 | + | |
579 | + down(®ister_mutex); | |
580 | + rmidi = snd_rawmidi_search(card, info->device); | |
581 | + up(®ister_mutex); | |
576 | 582 | if (!rmidi) |
577 | 583 | return -ENXIO; |
578 | 584 | if (info->stream < 0 || info->stream > 1) |
579 | 585 | |
... | ... | @@ -803,9 +809,7 @@ |
803 | 809 | unsigned long arg) |
804 | 810 | { |
805 | 811 | void __user *argp = (void __user *)arg; |
806 | - unsigned int tmp; | |
807 | 812 | |
808 | - tmp = card->number * SNDRV_RAWMIDI_DEVICES; | |
809 | 813 | switch (cmd) { |
810 | 814 | case SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE: |
811 | 815 | { |
812 | 816 | |
813 | 817 | |
... | ... | @@ -813,14 +817,16 @@ |
813 | 817 | |
814 | 818 | if (get_user(device, (int __user *)argp)) |
815 | 819 | return -EFAULT; |
820 | + down(®ister_mutex); | |
816 | 821 | device = device < 0 ? 0 : device + 1; |
817 | 822 | while (device < SNDRV_RAWMIDI_DEVICES) { |
818 | - if (snd_rawmidi_devices[tmp + device]) | |
823 | + if (snd_rawmidi_search(card, device)) | |
819 | 824 | break; |
820 | 825 | device++; |
821 | 826 | } |
822 | 827 | if (device == SNDRV_RAWMIDI_DEVICES) |
823 | 828 | device = -1; |
829 | + up(®ister_mutex); | |
824 | 830 | if (put_user(device, (int __user *)argp)) |
825 | 831 | return -EFAULT; |
826 | 832 | return 0; |
... | ... | @@ -1493,7 +1499,7 @@ |
1493 | 1499 | |
1494 | 1500 | static int snd_rawmidi_dev_register(struct snd_device *device) |
1495 | 1501 | { |
1496 | - int idx, err; | |
1502 | + int err; | |
1497 | 1503 | struct snd_info_entry *entry; |
1498 | 1504 | char name[16]; |
1499 | 1505 | struct snd_rawmidi *rmidi = device->device_data; |
1500 | 1506 | |
1501 | 1507 | |
1502 | 1508 | |
1503 | 1509 | |
... | ... | @@ -1501,25 +1507,24 @@ |
1501 | 1507 | if (rmidi->device >= SNDRV_RAWMIDI_DEVICES) |
1502 | 1508 | return -ENOMEM; |
1503 | 1509 | down(®ister_mutex); |
1504 | - idx = (rmidi->card->number * SNDRV_RAWMIDI_DEVICES) + rmidi->device; | |
1505 | - if (snd_rawmidi_devices[idx] != NULL) { | |
1510 | + if (snd_rawmidi_search(rmidi->card, rmidi->device)) { | |
1506 | 1511 | up(®ister_mutex); |
1507 | 1512 | return -EBUSY; |
1508 | 1513 | } |
1509 | - snd_rawmidi_devices[idx] = rmidi; | |
1514 | + list_add_tail(&rmidi->list, &snd_rawmidi_devices); | |
1510 | 1515 | sprintf(name, "midiC%iD%i", rmidi->card->number, rmidi->device); |
1511 | 1516 | if ((err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI, |
1512 | 1517 | rmidi->card, rmidi->device, |
1513 | - &snd_rawmidi_f_ops, name)) < 0) { | |
1518 | + &snd_rawmidi_f_ops, rmidi, name)) < 0) { | |
1514 | 1519 | snd_printk(KERN_ERR "unable to register rawmidi device %i:%i\n", rmidi->card->number, rmidi->device); |
1515 | - snd_rawmidi_devices[idx] = NULL; | |
1520 | + list_del(&rmidi->list); | |
1516 | 1521 | up(®ister_mutex); |
1517 | 1522 | return err; |
1518 | 1523 | } |
1519 | 1524 | if (rmidi->ops && rmidi->ops->dev_register && |
1520 | 1525 | (err = rmidi->ops->dev_register(rmidi)) < 0) { |
1521 | 1526 | snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); |
1522 | - snd_rawmidi_devices[idx] = NULL; | |
1527 | + list_del(&rmidi->list); | |
1523 | 1528 | up(®ister_mutex); |
1524 | 1529 | return err; |
1525 | 1530 | } |
... | ... | @@ -1527,8 +1532,8 @@ |
1527 | 1532 | rmidi->ossreg = 0; |
1528 | 1533 | if ((int)rmidi->device == midi_map[rmidi->card->number]) { |
1529 | 1534 | if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, |
1530 | - rmidi->card, 0, | |
1531 | - &snd_rawmidi_f_ops, name) < 0) { | |
1535 | + rmidi->card, 0, &snd_rawmidi_f_ops, | |
1536 | + rmidi, name) < 0) { | |
1532 | 1537 | snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 0); |
1533 | 1538 | } else { |
1534 | 1539 | rmidi->ossreg++; |
... | ... | @@ -1539,8 +1544,8 @@ |
1539 | 1544 | } |
1540 | 1545 | if ((int)rmidi->device == amidi_map[rmidi->card->number]) { |
1541 | 1546 | if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, |
1542 | - rmidi->card, 1, | |
1543 | - &snd_rawmidi_f_ops, name) < 0) { | |
1547 | + rmidi->card, 1, &snd_rawmidi_f_ops, | |
1548 | + rmidi, name) < 0) { | |
1544 | 1549 | snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 1); |
1545 | 1550 | } else { |
1546 | 1551 | rmidi->ossreg++; |
1547 | 1552 | |
1548 | 1553 | |
1549 | 1554 | |
... | ... | @@ -1576,24 +1581,20 @@ |
1576 | 1581 | static int snd_rawmidi_dev_disconnect(struct snd_device *device) |
1577 | 1582 | { |
1578 | 1583 | struct snd_rawmidi *rmidi = device->device_data; |
1579 | - int idx; | |
1580 | 1584 | |
1581 | 1585 | down(®ister_mutex); |
1582 | - idx = (rmidi->card->number * SNDRV_RAWMIDI_DEVICES) + rmidi->device; | |
1583 | - snd_rawmidi_devices[idx] = NULL; | |
1586 | + list_del_init(&rmidi->list); | |
1584 | 1587 | up(®ister_mutex); |
1585 | 1588 | return 0; |
1586 | 1589 | } |
1587 | 1590 | |
1588 | 1591 | static int snd_rawmidi_dev_unregister(struct snd_device *device) |
1589 | 1592 | { |
1590 | - int idx; | |
1591 | 1593 | struct snd_rawmidi *rmidi = device->device_data; |
1592 | 1594 | |
1593 | 1595 | snd_assert(rmidi != NULL, return -ENXIO); |
1594 | 1596 | down(®ister_mutex); |
1595 | - idx = (rmidi->card->number * SNDRV_RAWMIDI_DEVICES) + rmidi->device; | |
1596 | - snd_rawmidi_devices[idx] = NULL; | |
1597 | + list_del(&rmidi->list); | |
1597 | 1598 | if (rmidi->proc_entry) { |
1598 | 1599 | snd_info_unregister(rmidi->proc_entry); |
1599 | 1600 | rmidi->proc_entry = NULL; |
sound/core/seq/oss/seq_oss.c
... | ... | @@ -225,7 +225,7 @@ |
225 | 225 | down(®ister_mutex); |
226 | 226 | if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, |
227 | 227 | NULL, 0, |
228 | - &seq_oss_f_ops, | |
228 | + &seq_oss_f_ops, NULL, | |
229 | 229 | SNDRV_SEQ_OSS_DEVNAME)) < 0) { |
230 | 230 | snd_printk(KERN_ERR "can't register device seq\n"); |
231 | 231 | up(®ister_mutex); |
... | ... | @@ -233,7 +233,7 @@ |
233 | 233 | } |
234 | 234 | if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, |
235 | 235 | NULL, 0, |
236 | - &seq_oss_f_ops, | |
236 | + &seq_oss_f_ops, NULL, | |
237 | 237 | SNDRV_SEQ_OSS_DEVNAME)) < 0) { |
238 | 238 | snd_printk(KERN_ERR "can't register device music\n"); |
239 | 239 | snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0); |
sound/core/seq/seq_clientmgr.c
sound/core/seq/seq_midi.c
... | ... | @@ -183,7 +183,10 @@ |
183 | 183 | struct snd_rawmidi_params params; |
184 | 184 | |
185 | 185 | /* open midi port */ |
186 | - if ((err = snd_rawmidi_kernel_open(msynth->card->number, msynth->device, msynth->subdevice, SNDRV_RAWMIDI_LFLG_INPUT, &msynth->input_rfile)) < 0) { | |
186 | + if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device, | |
187 | + msynth->subdevice, | |
188 | + SNDRV_RAWMIDI_LFLG_INPUT, | |
189 | + &msynth->input_rfile)) < 0) { | |
187 | 190 | snd_printd("midi input open failed!!!\n"); |
188 | 191 | return err; |
189 | 192 | } |
... | ... | @@ -221,7 +224,10 @@ |
221 | 224 | struct snd_rawmidi_params params; |
222 | 225 | |
223 | 226 | /* open midi port */ |
224 | - if ((err = snd_rawmidi_kernel_open(msynth->card->number, msynth->device, msynth->subdevice, SNDRV_RAWMIDI_LFLG_OUTPUT, &msynth->output_rfile)) < 0) { | |
227 | + if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device, | |
228 | + msynth->subdevice, | |
229 | + SNDRV_RAWMIDI_LFLG_OUTPUT, | |
230 | + &msynth->output_rfile)) < 0) { | |
225 | 231 | snd_printd("midi output open failed!!!\n"); |
226 | 232 | return err; |
227 | 233 | } |
sound/core/sound.c
... | ... | @@ -60,7 +60,6 @@ |
60 | 60 | int snd_ecards_limit; |
61 | 61 | |
62 | 62 | static struct snd_minor *snd_minors[SNDRV_OS_MINORS]; |
63 | - | |
64 | 63 | static DECLARE_MUTEX(sound_mutex); |
65 | 64 | |
66 | 65 | extern struct class *sound_class; |
... | ... | @@ -107,6 +106,31 @@ |
107 | 106 | |
108 | 107 | #endif /* request_module support */ |
109 | 108 | |
109 | +/** | |
110 | + * snd_lookup_minor_data - get user data of a registered device | |
111 | + * @minor: the minor number | |
112 | + * @type: device type (SNDRV_DEVICE_TYPE_XXX) | |
113 | + * | |
114 | + * Checks that a minor device with the specified type is registered, and returns | |
115 | + * its user data pointer. | |
116 | + */ | |
117 | +void *snd_lookup_minor_data(unsigned int minor, int type) | |
118 | +{ | |
119 | + struct snd_minor *mreg; | |
120 | + void *private_data; | |
121 | + | |
122 | + if (minor > ARRAY_SIZE(snd_minors)) | |
123 | + return NULL; | |
124 | + down(&sound_mutex); | |
125 | + mreg = snd_minors[minor]; | |
126 | + if (mreg && mreg->type == type) | |
127 | + private_data = mreg->private_data; | |
128 | + else | |
129 | + private_data = NULL; | |
130 | + up(&sound_mutex); | |
131 | + return private_data; | |
132 | +} | |
133 | + | |
110 | 134 | static int snd_open(struct inode *inode, struct file *file) |
111 | 135 | { |
112 | 136 | int minor = iminor(inode); |
... | ... | @@ -183,6 +207,7 @@ |
183 | 207 | * @card: the card instance |
184 | 208 | * @dev: the device index |
185 | 209 | * @f_ops: the file operations |
210 | + * @private_data: user pointer for f_ops->open() | |
186 | 211 | * @name: the device file name |
187 | 212 | * |
188 | 213 | * Registers an ALSA device file for the given card. |
... | ... | @@ -191,7 +216,8 @@ |
191 | 216 | * Retrurns zero if successful, or a negative error code on failure. |
192 | 217 | */ |
193 | 218 | int snd_register_device(int type, struct snd_card *card, int dev, |
194 | - struct file_operations *f_ops, const char *name) | |
219 | + struct file_operations *f_ops, void *private_data, | |
220 | + const char *name) | |
195 | 221 | { |
196 | 222 | int minor = snd_kernel_minor(type, card, dev); |
197 | 223 | struct snd_minor *preg; |
... | ... | @@ -207,6 +233,7 @@ |
207 | 233 | preg->card = card ? card->number : -1; |
208 | 234 | preg->device = dev; |
209 | 235 | preg->f_ops = f_ops; |
236 | + preg->private_data = private_data; | |
210 | 237 | strcpy(preg->name, name); |
211 | 238 | down(&sound_mutex); |
212 | 239 | if (snd_minors[minor]) { |
213 | 240 | |
214 | 241 | |
... | ... | @@ -238,13 +265,18 @@ |
238 | 265 | */ |
239 | 266 | int snd_unregister_device(int type, struct snd_card *card, int dev) |
240 | 267 | { |
241 | - int minor = snd_kernel_minor(type, card, dev); | |
268 | + int cardnum, minor; | |
242 | 269 | struct snd_minor *mptr; |
243 | 270 | |
244 | - if (minor < 0) | |
245 | - return minor; | |
271 | + cardnum = card ? card->number : -1; | |
246 | 272 | down(&sound_mutex); |
247 | - if ((mptr = snd_minors[minor]) == NULL) { | |
273 | + for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) | |
274 | + if ((mptr = snd_minors[minor]) != NULL && | |
275 | + mptr->type == type && | |
276 | + mptr->card == cardnum && | |
277 | + mptr->device == dev) | |
278 | + break; | |
279 | + if (minor == ARRAY_SIZE(snd_minors)) { | |
248 | 280 | up(&sound_mutex); |
249 | 281 | return -EINVAL; |
250 | 282 | } |
251 | 283 | |
... | ... | @@ -392,9 +424,11 @@ |
392 | 424 | #endif |
393 | 425 | EXPORT_SYMBOL(snd_register_device); |
394 | 426 | EXPORT_SYMBOL(snd_unregister_device); |
427 | +EXPORT_SYMBOL(snd_lookup_minor_data); | |
395 | 428 | #if defined(CONFIG_SND_OSSEMUL) |
396 | 429 | EXPORT_SYMBOL(snd_register_oss_device); |
397 | 430 | EXPORT_SYMBOL(snd_unregister_oss_device); |
431 | +EXPORT_SYMBOL(snd_lookup_oss_minor_data); | |
398 | 432 | #endif |
399 | 433 | /* memory.c */ |
400 | 434 | EXPORT_SYMBOL(copy_to_user_fromio); |
sound/core/sound_oss.c
... | ... | @@ -38,9 +38,25 @@ |
38 | 38 | #define SNDRV_OSS_MINORS 128 |
39 | 39 | |
40 | 40 | static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS]; |
41 | - | |
42 | 41 | static DECLARE_MUTEX(sound_oss_mutex); |
43 | 42 | |
43 | +void *snd_lookup_oss_minor_data(unsigned int minor, int type) | |
44 | +{ | |
45 | + struct snd_minor *mreg; | |
46 | + void *private_data; | |
47 | + | |
48 | + if (minor > ARRAY_SIZE(snd_oss_minors)) | |
49 | + return NULL; | |
50 | + down(&sound_oss_mutex); | |
51 | + mreg = snd_oss_minors[minor]; | |
52 | + if (mreg && mreg->type == type) | |
53 | + private_data = mreg->private_data; | |
54 | + else | |
55 | + private_data = NULL; | |
56 | + up(&sound_oss_mutex); | |
57 | + return private_data; | |
58 | +} | |
59 | + | |
44 | 60 | static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) |
45 | 61 | { |
46 | 62 | int minor; |
... | ... | @@ -78,7 +94,8 @@ |
78 | 94 | } |
79 | 95 | |
80 | 96 | int snd_register_oss_device(int type, struct snd_card *card, int dev, |
81 | - struct file_operations *f_ops, const char *name) | |
97 | + struct file_operations *f_ops, void *private_data, | |
98 | + const char *name) | |
82 | 99 | { |
83 | 100 | int minor = snd_oss_kernel_minor(type, card, dev); |
84 | 101 | int minor_unit; |
... | ... | @@ -97,6 +114,7 @@ |
97 | 114 | preg->card = card ? card->number : -1; |
98 | 115 | preg->device = dev; |
99 | 116 | preg->f_ops = f_ops; |
117 | + preg->private_data = private_data; | |
100 | 118 | down(&sound_oss_mutex); |
101 | 119 | snd_oss_minors[minor] = preg; |
102 | 120 | minor_unit = SNDRV_MINOR_OSS_DEVICE(minor); |
... | ... | @@ -121,6 +139,7 @@ |
121 | 139 | carddev); |
122 | 140 | if (register2 != track2) |
123 | 141 | goto __end; |
142 | + snd_oss_minors[track2] = preg; | |
124 | 143 | } |
125 | 144 | up(&sound_oss_mutex); |
126 | 145 | return 0; |
127 | 146 | |
... | ... | @@ -163,8 +182,10 @@ |
163 | 182 | track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1); |
164 | 183 | break; |
165 | 184 | } |
166 | - if (track2 >= 0) | |
185 | + if (track2 >= 0) { | |
167 | 186 | unregister_sound_special(track2); |
187 | + snd_oss_minors[track2] = NULL; | |
188 | + } | |
168 | 189 | snd_oss_minors[minor] = NULL; |
169 | 190 | up(&sound_oss_mutex); |
170 | 191 | kfree(mptr); |
sound/core/timer.c
... | ... | @@ -1952,8 +1952,8 @@ |
1952 | 1952 | if ((err = snd_timer_register_system()) < 0) |
1953 | 1953 | snd_printk(KERN_ERR "unable to register system timer (%i)\n", |
1954 | 1954 | err); |
1955 | - if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, | |
1956 | - NULL, 0, &snd_timer_f_ops, "timer")) < 0) | |
1955 | + if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0, | |
1956 | + &snd_timer_f_ops, NULL, "timer")) < 0) | |
1957 | 1957 | snd_printk(KERN_ERR "unable to register timer device (%i)\n", |
1958 | 1958 | err); |
1959 | 1959 | return 0; |