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