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/rawmidi.c | |
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/rawmidi.c')
-rw-r--r-- | sound/core/rawmidi.c | 87 |
1 files changed, 44 insertions, 43 deletions
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 7ac77e5ddcb..e6ee0d81378 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; |