[ALSA] dynamic minors (3/6): store device-specific object pointers dynamically
Clemens Ladisch [Sun, 20 Nov 2005 13:06:59 +0000 (14:06 +0100)]
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>

17 files changed:
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

index 67b0a7e..90ac613 100644 (file)
@@ -187,6 +187,7 @@ struct snd_minor {
        int card;                       /* card number */
        int device;                     /* device number */
        struct file_operations *f_ops;  /* file operations */
+       void *private_data;             /* private data for f_ops->open */
        char name[0];                   /* device name (keep at the end of
                                                                structure) */
 };
@@ -199,13 +200,17 @@ extern int snd_ecards_limit;
 void snd_request_card(int card);
 
 int snd_register_device(int type, struct snd_card *card, int dev,
-                       struct file_operations *f_ops, const char *name);
+                       struct file_operations *f_ops, void *private_data,
+                       const char *name);
 int snd_unregister_device(int type, struct snd_card *card, int dev);
+void *snd_lookup_minor_data(unsigned int minor, int type);
 
 #ifdef CONFIG_SND_OSSEMUL
 int snd_register_oss_device(int type, struct snd_card *card, int dev,
-                           struct file_operations *f_ops, const char *name);
+                           struct file_operations *f_ops, void *private_data,
+                           const char *name);
 int snd_unregister_oss_device(int type, struct snd_card *card, int dev);
+void *snd_lookup_oss_minor_data(unsigned int minor, int type);
 #endif
 
 int snd_minor_info_init(void);
index 04b20bc..c679e5b 100644 (file)
@@ -43,6 +43,7 @@ struct snd_hwdep_ops {
 
 struct snd_hwdep {
        struct snd_card *card;
+       struct list_head list;
        int device;
        char id[32];
        char name[80];
index 5e29b0e..314268a 100644 (file)
@@ -412,6 +412,7 @@ struct snd_pcm_str {
 
 struct snd_pcm {
        struct snd_card *card;
+       struct list_head list;
        unsigned int device;    /* device number */
        unsigned int info_flags;
        unsigned short dev_class;
@@ -439,7 +440,6 @@ struct snd_pcm_notify {
  *  Registering
  */
 
-extern struct snd_pcm *snd_pcm_devices[];
 extern struct file_operations snd_pcm_f_ops[2];
 
 int snd_pcm_new(struct snd_card *card, char *id, int device,
index 9492a32..d19bddf 100644 (file)
@@ -113,7 +113,7 @@ struct snd_rawmidi_str {
 
 struct snd_rawmidi {
        struct snd_card *card;
-
+       struct list_head list;
        unsigned int device;            /* device number */
        unsigned int info_flags;        /* SNDRV_RAWMIDI_INFO_XXXX */
        char id[64];
@@ -165,8 +165,8 @@ int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
 /* main midi functions */
 
 int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info);
-int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice, int mode,
-                           struct snd_rawmidi_file *rfile);
+int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice,
+                           int mode, struct snd_rawmidi_file *rfile);
 int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile);
 int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,
                              struct snd_rawmidi_params *params);
index 23561e7..abd62f9 100644 (file)
@@ -47,13 +47,12 @@ static LIST_HEAD(snd_control_compat_ioctls);
 
 static int snd_ctl_open(struct inode *inode, struct file *file)
 {
-       int cardnum = SNDRV_MINOR_CARD(iminor(inode));
        unsigned long flags;
        struct snd_card *card;
        struct snd_ctl_file *ctl;
        int err;
 
-       card = snd_cards[cardnum];
+       card = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_CONTROL);
        if (!card) {
                err = -ENODEV;
                goto __error1;
@@ -1277,8 +1276,8 @@ static int snd_ctl_dev_register(struct snd_device *device)
        cardnum = card->number;
        snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO);
        sprintf(name, "controlC%i", cardnum);
-       if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL,
-                                      card, -1, &snd_ctl_f_ops, name)) < 0)
+       if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,
+                                      &snd_ctl_f_ops, card, name)) < 0)
                return err;
        return 0;
 }
index 27d5bf7..b8c0c8c 100644 (file)
@@ -35,8 +35,7 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Hardware dependent layer");
 MODULE_LICENSE("GPL");
 
-static struct snd_hwdep *snd_hwdep_devices[SNDRV_CARDS * SNDRV_MINOR_HWDEPS];
-
+static LIST_HEAD(snd_hwdep_devices);
 static DECLARE_MUTEX(register_mutex);
 
 static int snd_hwdep_free(struct snd_hwdep *hwdep);
@@ -44,9 +43,19 @@ static int snd_hwdep_dev_free(struct snd_device *device);
 static int snd_hwdep_dev_register(struct snd_device *device);
 static int snd_hwdep_dev_unregister(struct snd_device *device);
 
-/*
 
- */
+static struct snd_hwdep *snd_hwdep_search(struct snd_card *card, int device)
+{
+       struct list_head *p;
+       struct snd_hwdep *hwdep;
+
+       list_for_each(p, &snd_hwdep_devices) {
+               hwdep = list_entry(p, struct snd_hwdep, list);
+               if (hwdep->card == card && hwdep->device == device)
+                       return hwdep;
+       }
+       return NULL;
+}
 
 static loff_t snd_hwdep_llseek(struct file * file, loff_t offset, int orig)
 {
@@ -77,34 +86,25 @@ static ssize_t snd_hwdep_write(struct file * file, const char __user *buf,
 static int snd_hwdep_open(struct inode *inode, struct file * file)
 {
        int major = imajor(inode);
-       int cardnum;
-       int device;
        struct snd_hwdep *hw;
        int err;
        wait_queue_t wait;
 
        if (major == snd_major) {
-               cardnum = SNDRV_MINOR_CARD(iminor(inode));
-               device = SNDRV_MINOR_DEVICE(iminor(inode)) - SNDRV_MINOR_HWDEP;
+               hw = snd_lookup_minor_data(iminor(inode),
+                                          SNDRV_DEVICE_TYPE_HWDEP);
 #ifdef CONFIG_SND_OSSEMUL
        } else if (major == SOUND_MAJOR) {
-               cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode));
-               device = 0;
+               hw = snd_lookup_oss_minor_data(iminor(inode),
+                                              SNDRV_OSS_DEVICE_TYPE_DMFM);
 #endif
        } else
                return -ENXIO;
-       cardnum %= SNDRV_CARDS;
-       device %= SNDRV_MINOR_HWDEPS;
-       hw = snd_hwdep_devices[(cardnum * SNDRV_MINOR_HWDEPS) + device];
        if (hw == NULL)
                return -ENODEV;
 
        if (!hw->ops.open)
                return -ENXIO;
-#ifdef CONFIG_SND_OSSEMUL
-       if (major == SOUND_MAJOR && hw->oss_type < 0)
-               return -ENXIO;
-#endif
 
        if (!try_module_get(hw->card->module))
                return -EFAULT;
@@ -265,9 +265,6 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
                                   struct snd_ctl_file * control,
                                   unsigned int cmd, unsigned long arg)
 {
-       unsigned int tmp;
-       
-       tmp = card->number * SNDRV_MINOR_HWDEPS;
        switch (cmd) {
        case SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE:
                {
@@ -275,14 +272,16 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
 
                        if (get_user(device, (int __user *)arg))
                                return -EFAULT;
+                       down(&register_mutex);
                        device = device < 0 ? 0 : device + 1;
                        while (device < SNDRV_MINOR_HWDEPS) {
-                               if (snd_hwdep_devices[tmp + device])
+                               if (snd_hwdep_search(card, device))
                                        break;
                                device++;
                        }
                        if (device >= SNDRV_MINOR_HWDEPS)
                                device = -1;
+                       up(&register_mutex);
                        if (put_user(device, (int __user *)arg))
                                return -EFAULT;
                        return 0;
@@ -290,17 +289,19 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
        case SNDRV_CTL_IOCTL_HWDEP_INFO:
                {
                        struct snd_hwdep_info __user *info = (struct snd_hwdep_info __user *)arg;
-                       int device;
+                       int device, err;
                        struct snd_hwdep *hwdep;
 
                        if (get_user(device, &info->device))
                                return -EFAULT;
-                       if (device < 0 || device >= SNDRV_MINOR_HWDEPS)
-                               return -ENXIO;
-                       hwdep = snd_hwdep_devices[tmp + device];
-                       if (hwdep == NULL)
-                               return -ENXIO;
-                       return snd_hwdep_info(hwdep, info);
+                       down(&register_mutex);
+                       hwdep = snd_hwdep_search(card, device);
+                       if (hwdep)
+                               err = snd_hwdep_info(hwdep, info);
+                       else
+                               err = -ENXIO;
+                       up(&register_mutex);
+                       return err;
                }
        }
        return -ENOIOCTLCMD;
@@ -397,23 +398,22 @@ static int snd_hwdep_dev_free(struct snd_device *device)
 static int snd_hwdep_dev_register(struct snd_device *device)
 {
        struct snd_hwdep *hwdep = device->device_data;
-       int idx, err;
+       int err;
        char name[32];
 
        down(&register_mutex);
-       idx = (hwdep->card->number * SNDRV_MINOR_HWDEPS) + hwdep->device;
-       if (snd_hwdep_devices[idx]) {
+       if (snd_hwdep_search(hwdep->card, hwdep->device)) {
                up(&register_mutex);
                return -EBUSY;
        }
-       snd_hwdep_devices[idx] = hwdep;
+       list_add_tail(&hwdep->list, &snd_hwdep_devices);
        sprintf(name, "hwC%iD%i", hwdep->card->number, hwdep->device);
        if ((err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP,
                                       hwdep->card, hwdep->device,
-                                      &snd_hwdep_f_ops, name)) < 0) {
+                                      &snd_hwdep_f_ops, hwdep, name)) < 0) {
                snd_printk(KERN_ERR "unable to register hardware dependent device %i:%i\n",
                           hwdep->card->number, hwdep->device);
-               snd_hwdep_devices[idx] = NULL;
+               list_del(&hwdep->list);
                up(&register_mutex);
                return err;
        }
@@ -425,7 +425,7 @@ static int snd_hwdep_dev_register(struct snd_device *device)
                } else {
                        if (snd_register_oss_device(hwdep->oss_type,
                                                    hwdep->card, hwdep->device,
-                                                   &snd_hwdep_f_ops,
+                                                   &snd_hwdep_f_ops, hwdep,
                                                    hwdep->oss_dev) < 0) {
                                snd_printk(KERN_ERR "unable to register OSS compatibility device %i:%i\n",
                                           hwdep->card->number, hwdep->device);
@@ -441,12 +441,10 @@ static int snd_hwdep_dev_register(struct snd_device *device)
 static int snd_hwdep_dev_unregister(struct snd_device *device)
 {
        struct snd_hwdep *hwdep = device->device_data;
-       int idx;
 
        snd_assert(hwdep != NULL, return -ENXIO);
        down(&register_mutex);
-       idx = (hwdep->card->number * SNDRV_MINOR_HWDEPS) + hwdep->device;
-       if (snd_hwdep_devices[idx] != hwdep) {
+       if (snd_hwdep_search(hwdep->card, hwdep->device) != hwdep) {
                up(&register_mutex);
                return -EINVAL;
        }
@@ -455,7 +453,7 @@ static int snd_hwdep_dev_unregister(struct snd_device *device)
                snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device);
 #endif
        snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device);
-       snd_hwdep_devices[idx] = NULL;
+       list_del(&hwdep->list);
        up(&register_mutex);
        return snd_hwdep_free(hwdep);
 }
@@ -467,18 +465,14 @@ static int snd_hwdep_dev_unregister(struct snd_device *device)
 static void snd_hwdep_proc_read(struct snd_info_entry *entry,
                                struct snd_info_buffer *buffer)
 {
-       int idx;
+       struct list_head *p;
        struct snd_hwdep *hwdep;
 
        down(&register_mutex);
-       for (idx = 0; idx < SNDRV_CARDS * SNDRV_MINOR_HWDEPS; idx++) {
-               hwdep = snd_hwdep_devices[idx];
-               if (hwdep == NULL)
-                       continue;
+       list_for_each(p, &snd_hwdep_devices) {
+               hwdep = list_entry(p, struct snd_hwdep, list);
                snd_iprintf(buffer, "%02i-%02i: %s\n",
-                                       idx / SNDRV_MINOR_HWDEPS,
-                                       idx % SNDRV_MINOR_HWDEPS,
-                                       hwdep->name);
+                           hwdep->card->number, hwdep->device, hwdep->name);
        }
        up(&register_mutex);
 }
@@ -493,9 +487,8 @@ static int __init alsa_hwdep_init(void)
 {
        struct snd_info_entry *entry;
 
-       memset(snd_hwdep_devices, 0, sizeof(snd_hwdep_devices));
        if ((entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL)) != NULL) {
-               entry->c.text.read_size = 512;
+               entry->c.text.read_size = PAGE_SIZE;
                entry->c.text.read = snd_hwdep_proc_read;
                if (snd_info_register(entry) < 0) {
                        snd_info_free_entry(entry);
index 2dd6bf9..2d7a420 100644 (file)
@@ -41,12 +41,13 @@ MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_MIXER);
 
 static int snd_mixer_oss_open(struct inode *inode, struct file *file)
 {
-       int cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode));
        struct snd_card *card;
        struct snd_mixer_oss_file *fmixer;
        int err;
 
-       if ((card = snd_cards[cardnum]) == NULL)
+       card = snd_lookup_oss_minor_data(iminor(inode),
+                                        SNDRV_OSS_DEVICE_TYPE_MIXER);
+       if (card == NULL)
                return -ENODEV;
        if (card->mixer_oss == NULL)
                return -ENODEV;
@@ -1286,7 +1287,7 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd)
                sprintf(name, "mixer%i%i", card->number, 0);
                if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER,
                                                   card, 0,
-                                                  &snd_mixer_oss_f_ops,
+                                                  &snd_mixer_oss_f_ops, card,
                                                   name)) < 0) {
                        snd_printk(KERN_ERR "unable to register OSS mixer device %i:%i\n",
                                   card->number, 0);
index 947bf08..2ae283c 100644 (file)
@@ -1834,9 +1834,6 @@ static int snd_task_name(struct task_struct *task, char *name, size_t size)
 
 static int snd_pcm_oss_open(struct inode *inode, struct file *file)
 {
-       int minor = iminor(inode);
-       int cardnum = SNDRV_MINOR_OSS_CARD(minor);
-       int device;
        int err;
        char task_name[32];
        struct snd_pcm *pcm;
@@ -1845,11 +1842,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
        int nonblock;
        wait_queue_t wait;
 
-       snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO);
-       device = SNDRV_MINOR_OSS_DEVICE(minor) == SNDRV_MINOR_OSS_PCM1 ?
-               adsp_map[cardnum] : dsp_map[cardnum];
-
-       pcm = snd_pcm_devices[(cardnum * SNDRV_PCM_DEVICES) + device];
+       pcm = snd_lookup_oss_minor_data(iminor(inode),
+                                       SNDRV_OSS_DEVICE_TYPE_PCM);
        if (pcm == NULL) {
                err = -ENODEV;
                goto __error1;
@@ -1890,7 +1884,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
        down(&pcm->open_mutex);
        while (1) {
                err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
-                                           minor, psetup, csetup);
+                                           iminor(inode), psetup, csetup);
                if (err >= 0)
                        break;
                if (err == -EAGAIN) {
@@ -2450,7 +2444,7 @@ static void register_oss_dsp(struct snd_pcm *pcm, int index)
        sprintf(name, "dsp%i%i", pcm->card->number, pcm->device);
        if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
                                    pcm->card, index, &snd_pcm_oss_f_reg,
-                                   name) < 0) {
+                                   pcm, name) < 0) {
                snd_printk(KERN_ERR "unable to register OSS PCM device %i:%i\n",
                           pcm->card->number, pcm->device);
        }
index 2bc5f69..95036c8 100644 (file)
@@ -33,7 +33,7 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Abramo Bagnara <abramo@alsa-proj
 MODULE_DESCRIPTION("Midlevel PCM code for ALSA.");
 MODULE_LICENSE("GPL");
 
-struct snd_pcm *snd_pcm_devices[SNDRV_CARDS * SNDRV_PCM_DEVICES];
+static LIST_HEAD(snd_pcm_devices);
 static LIST_HEAD(snd_pcm_notify_list);
 static DECLARE_MUTEX(register_mutex);
 
@@ -43,13 +43,23 @@ static int snd_pcm_dev_register(struct snd_device *device);
 static int snd_pcm_dev_disconnect(struct snd_device *device);
 static int snd_pcm_dev_unregister(struct snd_device *device);
 
+static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device)
+{
+       struct list_head *p;
+       struct snd_pcm *pcm;
+
+       list_for_each(p, &snd_pcm_devices) {
+               pcm = list_entry(p, struct snd_pcm, list);
+               if (pcm->card == card && pcm->device == device)
+                       return pcm;
+       }
+       return NULL;
+}
+
 static int snd_pcm_control_ioctl(struct snd_card *card,
                                 struct snd_ctl_file *control,
                                 unsigned int cmd, unsigned long arg)
 {
-       unsigned int tmp;
-
-       tmp = card->number * SNDRV_PCM_DEVICES;
        switch (cmd) {
        case SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE:
                {
@@ -57,14 +67,16 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
 
                        if (get_user(device, (int __user *)arg))
                                return -EFAULT;
+                       down(&register_mutex);
                        device = device < 0 ? 0 : device + 1;
                        while (device < SNDRV_PCM_DEVICES) {
-                               if (snd_pcm_devices[tmp + device])
+                               if (snd_pcm_search(card, device))
                                        break;
                                device++;
                        }
                        if (device == SNDRV_PCM_DEVICES)
                                device = -1;
+                       up(&register_mutex);
                        if (put_user(device, (int __user *)arg))
                                return -EFAULT;
                        return 0;
@@ -77,31 +89,44 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
                        struct snd_pcm *pcm;
                        struct snd_pcm_str *pstr;
                        struct snd_pcm_substream *substream;
+                       int err;
+
                        info = (struct snd_pcm_info __user *)arg;
                        if (get_user(device, &info->device))
                                return -EFAULT;
-                       if (device >= SNDRV_PCM_DEVICES)
-                               return -ENXIO;
-                       pcm = snd_pcm_devices[tmp + device];
-                       if (pcm == NULL)
-                               return -ENXIO;
                        if (get_user(stream, &info->stream))
                                return -EFAULT;
                        if (stream < 0 || stream > 1)
                                return -EINVAL;
-                       pstr = &pcm->streams[stream];
-                       if (pstr->substream_count == 0)
-                               return -ENOENT;
                        if (get_user(subdevice, &info->subdevice))
                                return -EFAULT;
-                       if (subdevice >= pstr->substream_count)
-                               return -ENXIO;
-                       for (substream = pstr->substream; substream; substream = substream->next)
+                       down(&register_mutex);
+                       pcm = snd_pcm_search(card, device);
+                       if (pcm == NULL) {
+                               err = -ENXIO;
+                               goto _error;
+                       }
+                       pstr = &pcm->streams[stream];
+                       if (pstr->substream_count == 0) {
+                               err = -ENOENT;
+                               goto _error;
+                       }
+                       if (subdevice >= pstr->substream_count) {
+                               err = -ENXIO;
+                               goto _error;
+                       }
+                       for (substream = pstr->substream; substream;
+                            substream = substream->next)
                                if (substream->number == (int)subdevice)
                                        break;
-                       if (substream == NULL)
-                               return -ENXIO;
-                       return snd_pcm_info_user(substream, info);
+                       if (substream == NULL) {
+                               err = -ENXIO;
+                               goto _error;
+                       }
+                       err = snd_pcm_info_user(substream, info);
+               _error:
+                       up(&register_mutex);
+                       return err;
                }
        case SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE:
                {
@@ -865,8 +890,7 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream)
 
 static int snd_pcm_dev_register(struct snd_device *device)
 {
-       int idx, cidx, err;
-       unsigned short minor;
+       int cidx, err;
        struct snd_pcm_substream *substream;
        struct list_head *list;
        char str[16];
@@ -874,12 +898,11 @@ static int snd_pcm_dev_register(struct snd_device *device)
 
        snd_assert(pcm != NULL && device != NULL, return -ENXIO);
        down(&register_mutex);
-       idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device;
-       if (snd_pcm_devices[idx]) {
+       if (snd_pcm_search(pcm->card, pcm->device)) {
                up(&register_mutex);
                return -EBUSY;
        }
-       snd_pcm_devices[idx] = pcm;
+       list_add_tail(&pcm->list, &snd_pcm_devices);
        for (cidx = 0; cidx < 2; cidx++) {
                int devtype = -1;
                if (pcm->streams[cidx].substream == NULL)
@@ -887,20 +910,19 @@ static int snd_pcm_dev_register(struct snd_device *device)
                switch (cidx) {
                case SNDRV_PCM_STREAM_PLAYBACK:
                        sprintf(str, "pcmC%iD%ip", pcm->card->number, pcm->device);
-                       minor = SNDRV_MINOR_PCM_PLAYBACK + idx;
                        devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK;
                        break;
                case SNDRV_PCM_STREAM_CAPTURE:
                        sprintf(str, "pcmC%iD%ic", pcm->card->number, pcm->device);
-                       minor = SNDRV_MINOR_PCM_CAPTURE + idx;
                        devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE;
                        break;
                }
                if ((err = snd_register_device(devtype, pcm->card,
                                               pcm->device,
-                                              &snd_pcm_f_ops[cidx], str)) < 0)
+                                              &snd_pcm_f_ops[cidx],
+                                              pcm, str)) < 0)
                {
-                       snd_pcm_devices[idx] = NULL;
+                       list_del(&pcm->list);
                        up(&register_mutex);
                        return err;
                }
@@ -921,11 +943,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
        struct snd_pcm *pcm = device->device_data;
        struct list_head *list;
        struct snd_pcm_substream *substream;
-       int idx, cidx;
+       int cidx;
 
        down(&register_mutex);
-       idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device;
-       snd_pcm_devices[idx] = NULL;
+       list_del_init(&pcm->list);
        for (cidx = 0; cidx < 2; cidx++)
                for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
                        if (substream->runtime)
@@ -941,15 +962,14 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
 
 static int snd_pcm_dev_unregister(struct snd_device *device)
 {
-       int idx, cidx, devtype;
+       int cidx, devtype;
        struct snd_pcm_substream *substream;
        struct list_head *list;
        struct snd_pcm *pcm = device->device_data;
 
        snd_assert(pcm != NULL, return -ENXIO);
        down(&register_mutex);
-       idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device;
-       snd_pcm_devices[idx] = NULL;
+       list_del(&pcm->list);
        for (cidx = 0; cidx < 2; cidx++) {
                devtype = -1;
                switch (cidx) {
@@ -975,24 +995,19 @@ static int snd_pcm_dev_unregister(struct snd_device *device)
 
 int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
 {
-       int idx;
+       struct list_head *p;
 
        snd_assert(notify != NULL && notify->n_register != NULL && notify->n_unregister != NULL, return -EINVAL);
        down(&register_mutex);
        if (nfree) {
                list_del(&notify->list);
-               for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) {
-                       if (snd_pcm_devices[idx] == NULL)
-                               continue;
-                       notify->n_unregister(snd_pcm_devices[idx]);
-               }
+               list_for_each(p, &snd_pcm_devices)
+                       notify->n_unregister(list_entry(p,
+                                                       struct snd_pcm, list));
        } else {
                list_add_tail(&notify->list, &snd_pcm_notify_list);
-               for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) {
-                       if (snd_pcm_devices[idx] == NULL)
-                               continue;
-                       notify->n_register(snd_pcm_devices[idx]);
-               }
+               list_for_each(p, &snd_pcm_devices)
+                       notify->n_register(list_entry(p, struct snd_pcm, list));
        }
        up(&register_mutex);
        return 0;
@@ -1005,16 +1020,14 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
 static void snd_pcm_proc_read(struct snd_info_entry *entry,
                              struct snd_info_buffer *buffer)
 {
-       int idx;
+       struct list_head *p;
        struct snd_pcm *pcm;
 
        down(&register_mutex);
-       for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) {
-               pcm = snd_pcm_devices[idx];
-               if (pcm == NULL)
-                       continue;
-               snd_iprintf(buffer, "%02i-%02i: %s : %s", idx / SNDRV_PCM_DEVICES,
-                           idx % SNDRV_PCM_DEVICES, pcm->id, pcm->name);
+       list_for_each(p, &snd_pcm_devices) {
+               pcm = list_entry(p, struct snd_pcm, list);
+               snd_iprintf(buffer, "%02i-%02i: %s : %s",
+                           pcm->card->number, pcm->device, pcm->id, pcm->name);
                if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
                        snd_iprintf(buffer, " : playback %i",
                                    pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count);
@@ -1063,7 +1076,6 @@ static void __exit alsa_pcm_exit(void)
 module_init(alsa_pcm_init)
 module_exit(alsa_pcm_exit)
 
-EXPORT_SYMBOL(snd_pcm_devices);
 EXPORT_SYMBOL(snd_pcm_new);
 EXPORT_SYMBOL(snd_pcm_new_stream);
 EXPORT_SYMBOL(snd_pcm_notify);
index bb40c01..9010306 100644 (file)
@@ -62,6 +62,7 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
                                      struct snd_pcm_hw_params_old __user * _oparams);
 static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
                                      struct snd_pcm_hw_params_old __user * _oparams);
+static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream);
 
 /*
  *
@@ -1554,7 +1555,8 @@ static struct file *snd_pcm_file_fd(int fd)
 {
        struct file *file;
        struct inode *inode;
-       unsigned short minor;
+       unsigned int minor;
+
        file = fget(fd);
        if (!file)
                return NULL;
@@ -1565,8 +1567,8 @@ static struct file *snd_pcm_file_fd(int fd)
                return NULL;
        }
        minor = iminor(inode);
-       if (minor >= 256 || 
-           minor % SNDRV_MINOR_DEVICES < SNDRV_MINOR_PCM_PLAYBACK) {
+       if (!snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_PLAYBACK) &&
+           !snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_CAPTURE)) {
                fput(file);
                return NULL;
        }
@@ -2071,18 +2073,30 @@ static int snd_pcm_open_file(struct file *file,
        return 0;
 }
 
-static int snd_pcm_open(struct inode *inode, struct file *file)
+static int snd_pcm_playback_open(struct inode *inode, struct file *file)
+{
+       struct snd_pcm *pcm;
+
+       pcm = snd_lookup_minor_data(iminor(inode),
+                                   SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
+       return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
+}
+
+static int snd_pcm_capture_open(struct inode *inode, struct file *file)
 {
-       int cardnum = SNDRV_MINOR_CARD(iminor(inode));
-       int device = SNDRV_MINOR_DEVICE(iminor(inode));
-       int err;
        struct snd_pcm *pcm;
+
+       pcm = snd_lookup_minor_data(iminor(inode),
+                                   SNDRV_DEVICE_TYPE_PCM_CAPTURE);
+       return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
+}
+
+static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
+{
+       int err;
        struct snd_pcm_file *pcm_file;
        wait_queue_t wait;
 
-       if (device < SNDRV_MINOR_PCM_PLAYBACK || device >= SNDRV_MINOR_DEVICES)
-               return -ENXIO;
-       pcm = snd_pcm_devices[(cardnum * SNDRV_PCM_DEVICES) + (device % SNDRV_MINOR_PCMS)];
        if (pcm == NULL) {
                err = -ENODEV;
                goto __error1;
@@ -2098,7 +2112,7 @@ static int snd_pcm_open(struct inode *inode, struct file *file)
        add_wait_queue(&pcm->open_wait, &wait);
        down(&pcm->open_mutex);
        while (1) {
-               err = snd_pcm_open_file(file, pcm, device >= SNDRV_MINOR_PCM_CAPTURE ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK, &pcm_file);
+               err = snd_pcm_open_file(file, pcm, stream, &pcm_file);
                if (err >= 0)
                        break;
                if (err == -EAGAIN) {
@@ -3375,7 +3389,7 @@ struct file_operations snd_pcm_f_ops[2] = {
                .owner =                THIS_MODULE,
                .write =                snd_pcm_write,
                .writev =               snd_pcm_writev,
-               .open =                 snd_pcm_open,
+               .open =                 snd_pcm_playback_open,
                .release =              snd_pcm_release,
                .poll =                 snd_pcm_playback_poll,
                .unlocked_ioctl =       snd_pcm_playback_ioctl,
@@ -3387,7 +3401,7 @@ struct file_operations snd_pcm_f_ops[2] = {
                .owner =                THIS_MODULE,
                .read =                 snd_pcm_read,
                .readv =                snd_pcm_readv,
-               .open =                 snd_pcm_open,
+               .open =                 snd_pcm_capture_open,
                .release =              snd_pcm_release,
                .poll =                 snd_pcm_capture_poll,
                .unlocked_ioctl =       snd_pcm_capture_ioctl,
index 7ac77e5..e6ee0d8 100644 (file)
@@ -56,10 +56,22 @@ static int snd_rawmidi_dev_register(struct snd_device *device);
 static int snd_rawmidi_dev_disconnect(struct snd_device *device);
 static int snd_rawmidi_dev_unregister(struct snd_device *device);
 
-static struct snd_rawmidi *snd_rawmidi_devices[SNDRV_CARDS * SNDRV_RAWMIDI_DEVICES];
-
+static LIST_HEAD(snd_rawmidi_devices);
 static DECLARE_MUTEX(register_mutex);
 
+static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device)
+{
+       struct list_head *p;
+       struct snd_rawmidi *rawmidi;
+
+       list_for_each(p, &snd_rawmidi_devices) {
+               rawmidi = list_entry(p, struct snd_rawmidi, list);
+               if (rawmidi->card == card && rawmidi->device == device)
+                       return rawmidi;
+       }
+       return NULL;
+}
+
 static inline unsigned short snd_rawmidi_file_flags(struct file *file)
 {
        switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
@@ -214,7 +226,7 @@ int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream)
        return 0;
 }
 
-int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice,
+int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice,
                            int mode, struct snd_rawmidi_file * rfile)
 {
        struct snd_rawmidi *rmidi;
@@ -225,7 +237,9 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice,
 
        if (rfile)
                rfile->input = rfile->output = NULL;
-       rmidi = snd_rawmidi_devices[(cardnum * SNDRV_RAWMIDI_DEVICES) + device];
+       down(&register_mutex);
+       rmidi = snd_rawmidi_search(card, device);
+       up(&register_mutex);
        if (rmidi == NULL) {
                err = -ENODEV;
                goto __error1;
@@ -368,9 +382,8 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice,
 static int snd_rawmidi_open(struct inode *inode, struct file *file)
 {
        int maj = imajor(inode);
-       int cardnum;
        struct snd_card *card;
-       int device, subdevice;
+       int subdevice;
        unsigned short fflags;
        int err;
        struct snd_rawmidi *rmidi;
@@ -380,27 +393,18 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
        struct snd_ctl_file *kctl;
 
        if (maj == snd_major) {
-               cardnum = SNDRV_MINOR_CARD(iminor(inode));
-               cardnum %= SNDRV_CARDS;
-               device = SNDRV_MINOR_DEVICE(iminor(inode)) - SNDRV_MINOR_RAWMIDI;
-               device %= SNDRV_MINOR_RAWMIDIS;
+               rmidi = snd_lookup_minor_data(iminor(inode),
+                                             SNDRV_DEVICE_TYPE_RAWMIDI);
 #ifdef CONFIG_SND_OSSEMUL
        } else if (maj == SOUND_MAJOR) {
-               cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode));
-               cardnum %= SNDRV_CARDS;
-               device = SNDRV_MINOR_OSS_DEVICE(iminor(inode)) == SNDRV_MINOR_OSS_MIDI ?
-                       midi_map[cardnum] : amidi_map[cardnum];
+               rmidi = snd_lookup_oss_minor_data(iminor(inode),
+                                                 SNDRV_OSS_DEVICE_TYPE_MIDI);
 #endif
        } else
                return -ENXIO;
 
-       rmidi = snd_rawmidi_devices[(cardnum * SNDRV_RAWMIDI_DEVICES) + device];
        if (rmidi == NULL)
                return -ENODEV;
-#ifdef CONFIG_SND_OSSEMUL
-       if (maj == SOUND_MAJOR && !rmidi->ossreg)
-               return -ENXIO;
-#endif
        if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) 
                return -EINVAL;         /* invalid combination */
        card = rmidi->card;
@@ -430,7 +434,8 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
                        }
                }
                up_read(&card->controls_rwsem);
-               err = snd_rawmidi_kernel_open(cardnum, device, subdevice, fflags, rawmidi_file);
+               err = snd_rawmidi_kernel_open(rmidi->card, rmidi->device,
+                                             subdevice, fflags, rawmidi_file);
                if (err >= 0)
                        break;
                if (err == -EAGAIN) {
@@ -570,9 +575,10 @@ int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info
        struct snd_rawmidi_str *pstr;
        struct snd_rawmidi_substream *substream;
        struct list_head *list;
-       if (info->device >= SNDRV_RAWMIDI_DEVICES)
-               return -ENXIO;
-       rmidi = snd_rawmidi_devices[card->number * SNDRV_RAWMIDI_DEVICES + info->device];
+
+       down(&register_mutex);
+       rmidi = snd_rawmidi_search(card, info->device);
+       up(&register_mutex);
        if (!rmidi)
                return -ENXIO;
        if (info->stream < 0 || info->stream > 1)
@@ -803,9 +809,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
                                     unsigned long arg)
 {
        void __user *argp = (void __user *)arg;
-       unsigned int tmp;
 
-       tmp = card->number * SNDRV_RAWMIDI_DEVICES;
        switch (cmd) {
        case SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE:
        {
@@ -813,14 +817,16 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
                
                if (get_user(device, (int __user *)argp))
                        return -EFAULT;
+               down(&register_mutex);
                device = device < 0 ? 0 : device + 1;
                while (device < SNDRV_RAWMIDI_DEVICES) {
-                       if (snd_rawmidi_devices[tmp + device])
+                       if (snd_rawmidi_search(card, device))
                                break;
                        device++;
                }
                if (device == SNDRV_RAWMIDI_DEVICES)
                        device = -1;
+               up(&register_mutex);
                if (put_user(device, (int __user *)argp))
                        return -EFAULT;
                return 0;
@@ -1493,7 +1499,7 @@ static void snd_rawmidi_dev_seq_free(struct snd_seq_device *device)
 
 static int snd_rawmidi_dev_register(struct snd_device *device)
 {
-       int idx, err;
+       int err;
        struct snd_info_entry *entry;
        char name[16];
        struct snd_rawmidi *rmidi = device->device_data;
@@ -1501,25 +1507,24 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
        if (rmidi->device >= SNDRV_RAWMIDI_DEVICES)
                return -ENOMEM;
        down(&register_mutex);
-       idx = (rmidi->card->number * SNDRV_RAWMIDI_DEVICES) + rmidi->device;
-       if (snd_rawmidi_devices[idx] != NULL) {
+       if (snd_rawmidi_search(rmidi->card, rmidi->device)) {
                up(&register_mutex);
                return -EBUSY;
        }
-       snd_rawmidi_devices[idx] = rmidi;
+       list_add_tail(&rmidi->list, &snd_rawmidi_devices);
        sprintf(name, "midiC%iD%i", rmidi->card->number, rmidi->device);
        if ((err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI,
                                       rmidi->card, rmidi->device,
-                                      &snd_rawmidi_f_ops, name)) < 0) {
+                                      &snd_rawmidi_f_ops, rmidi, name)) < 0) {
                snd_printk(KERN_ERR "unable to register rawmidi device %i:%i\n", rmidi->card->number, rmidi->device);
-               snd_rawmidi_devices[idx] = NULL;
+               list_del(&rmidi->list);
                up(&register_mutex);
                return err;
        }
        if (rmidi->ops && rmidi->ops->dev_register &&
            (err = rmidi->ops->dev_register(rmidi)) < 0) {
                snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);
-               snd_rawmidi_devices[idx] = NULL;
+               list_del(&rmidi->list);
                up(&register_mutex);
                return err;
        }
@@ -1527,8 +1532,8 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
        rmidi->ossreg = 0;
        if ((int)rmidi->device == midi_map[rmidi->card->number]) {
                if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI,
-                                           rmidi->card, 0,
-                                           &snd_rawmidi_f_ops, name) < 0) {
+                                           rmidi->card, 0, &snd_rawmidi_f_ops,
+                                           rmidi, name) < 0) {
                        snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 0);
                } else {
                        rmidi->ossreg++;
@@ -1539,8 +1544,8 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
        }
        if ((int)rmidi->device == amidi_map[rmidi->card->number]) {
                if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI,
-                                           rmidi->card, 1,
-                                           &snd_rawmidi_f_ops, name) < 0) {
+                                           rmidi->card, 1, &snd_rawmidi_f_ops,
+                                           rmidi, name) < 0) {
                        snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 1);
                } else {
                        rmidi->ossreg++;
@@ -1576,24 +1581,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
 static int snd_rawmidi_dev_disconnect(struct snd_device *device)
 {
        struct snd_rawmidi *rmidi = device->device_data;
-       int idx;
 
        down(&register_mutex);
-       idx = (rmidi->card->number * SNDRV_RAWMIDI_DEVICES) + rmidi->device;
-       snd_rawmidi_devices[idx] = NULL;
+       list_del_init(&rmidi->list);
        up(&register_mutex);
        return 0;
 }
 
 static int snd_rawmidi_dev_unregister(struct snd_device *device)
 {
-       int idx;
        struct snd_rawmidi *rmidi = device->device_data;
 
        snd_assert(rmidi != NULL, return -ENXIO);
        down(&register_mutex);
-       idx = (rmidi->card->number * SNDRV_RAWMIDI_DEVICES) + rmidi->device;
-       snd_rawmidi_devices[idx] = NULL;
+       list_del(&rmidi->list);
        if (rmidi->proc_entry) {
                snd_info_unregister(rmidi->proc_entry);
                rmidi->proc_entry = NULL;
index 61c0a41..4b51ab5 100644 (file)
@@ -225,7 +225,7 @@ register_device(void)
        down(&register_mutex);
        if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER,
                                          NULL, 0,
-                                         &seq_oss_f_ops,
+                                         &seq_oss_f_ops, NULL,
                                          SNDRV_SEQ_OSS_DEVNAME)) < 0) {
                snd_printk(KERN_ERR "can't register device seq\n");
                up(&register_mutex);
@@ -233,7 +233,7 @@ register_device(void)
        }
        if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC,
                                          NULL, 0,
-                                         &seq_oss_f_ops,
+                                         &seq_oss_f_ops, NULL,
                                          SNDRV_SEQ_OSS_DEVNAME)) < 0) {
                snd_printk(KERN_ERR "can't register device music\n");
                snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0);
index 087fdf3..c8bd37e 100644 (file)
@@ -2531,7 +2531,7 @@ int __init snd_sequencer_device_init(void)
                return -ERESTARTSYS;
 
        if ((err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0,
-                                      &snd_seq_f_ops, "seq")) < 0) {
+                                      &snd_seq_f_ops, NULL, "seq")) < 0) {
                up(&register_mutex);
                return err;
        }
index f88d2e3..0a65eb2 100644 (file)
@@ -183,7 +183,10 @@ static int midisynth_subscribe(void *private_data, struct snd_seq_port_subscribe
        struct snd_rawmidi_params params;
 
        /* open midi port */
-       if ((err = snd_rawmidi_kernel_open(msynth->card->number, msynth->device, msynth->subdevice, SNDRV_RAWMIDI_LFLG_INPUT, &msynth->input_rfile)) < 0) {
+       if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device,
+                                          msynth->subdevice,
+                                          SNDRV_RAWMIDI_LFLG_INPUT,
+                                          &msynth->input_rfile)) < 0) {
                snd_printd("midi input open failed!!!\n");
                return err;
        }
@@ -221,7 +224,10 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info
        struct snd_rawmidi_params params;
 
        /* open midi port */
-       if ((err = snd_rawmidi_kernel_open(msynth->card->number, msynth->device, msynth->subdevice, SNDRV_RAWMIDI_LFLG_OUTPUT, &msynth->output_rfile)) < 0) {
+       if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device,
+                                          msynth->subdevice,
+                                          SNDRV_RAWMIDI_LFLG_OUTPUT,
+                                          &msynth->output_rfile)) < 0) {
                snd_printd("midi output open failed!!!\n");
                return err;
        }
index a509f49..1e5eca5 100644 (file)
@@ -60,7 +60,6 @@ MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
 int snd_ecards_limit;
 
 static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
-
 static DECLARE_MUTEX(sound_mutex);
 
 extern struct class *sound_class;
@@ -107,6 +106,31 @@ static void snd_request_other(int minor)
 
 #endif                         /* request_module support */
 
+/**
+ * snd_lookup_minor_data - get user data of a registered device
+ * @minor: the minor number
+ * @type: device type (SNDRV_DEVICE_TYPE_XXX)
+ *
+ * Checks that a minor device with the specified type is registered, and returns
+ * its user data pointer.
+ */
+void *snd_lookup_minor_data(unsigned int minor, int type)
+{
+       struct snd_minor *mreg;
+       void *private_data;
+
+       if (minor > ARRAY_SIZE(snd_minors))
+               return NULL;
+       down(&sound_mutex);
+       mreg = snd_minors[minor];
+       if (mreg && mreg->type == type)
+               private_data = mreg->private_data;
+       else
+               private_data = NULL;
+       up(&sound_mutex);
+       return private_data;
+}
+
 static int snd_open(struct inode *inode, struct file *file)
 {
        int minor = iminor(inode);
@@ -183,6 +207,7 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)
  * @card: the card instance
  * @dev: the device index
  * @f_ops: the file operations
+ * @private_data: user pointer for f_ops->open()
  * @name: the device file name
  *
  * 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)
  * Retrurns zero if successful, or a negative error code on failure.
  */
 int snd_register_device(int type, struct snd_card *card, int dev,
-                       struct file_operations *f_ops, const char *name)
+                       struct file_operations *f_ops, void *private_data,
+                       const char *name)
 {
        int minor = snd_kernel_minor(type, card, dev);
        struct snd_minor *preg;
@@ -207,6 +233,7 @@ int snd_register_device(int type, struct snd_card *card, int dev,
        preg->card = card ? card->number : -1;
        preg->device = dev;
        preg->f_ops = f_ops;
+       preg->private_data = private_data;
        strcpy(preg->name, name);
        down(&sound_mutex);
        if (snd_minors[minor]) {
@@ -238,13 +265,18 @@ int snd_register_device(int type, struct snd_card *card, int dev,
  */
 int snd_unregister_device(int type, struct snd_card *card, int dev)
 {
-       int minor = snd_kernel_minor(type, card, dev);
+       int cardnum, minor;
        struct snd_minor *mptr;
 
-       if (minor < 0)
-               return minor;
+       cardnum = card ? card->number : -1;
        down(&sound_mutex);
-       if ((mptr = snd_minors[minor]) == NULL) {
+       for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor)
+               if ((mptr = snd_minors[minor]) != NULL &&
+                   mptr->type == type &&
+                   mptr->card == cardnum &&
+                   mptr->device == dev)
+                       break;
+       if (minor == ARRAY_SIZE(snd_minors)) {
                up(&sound_mutex);
                return -EINVAL;
        }
@@ -392,9 +424,11 @@ EXPORT_SYMBOL(snd_request_card);
 #endif
 EXPORT_SYMBOL(snd_register_device);
 EXPORT_SYMBOL(snd_unregister_device);
+EXPORT_SYMBOL(snd_lookup_minor_data);
 #if defined(CONFIG_SND_OSSEMUL)
 EXPORT_SYMBOL(snd_register_oss_device);
 EXPORT_SYMBOL(snd_unregister_oss_device);
+EXPORT_SYMBOL(snd_lookup_oss_minor_data);
 #endif
   /* memory.c */
 EXPORT_SYMBOL(copy_to_user_fromio);
index afbfd8d..b9e89ca 100644 (file)
 #define SNDRV_OSS_MINORS 128
 
 static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS];
-
 static DECLARE_MUTEX(sound_oss_mutex);
 
+void *snd_lookup_oss_minor_data(unsigned int minor, int type)
+{
+       struct snd_minor *mreg;
+       void *private_data;
+
+       if (minor > ARRAY_SIZE(snd_oss_minors))
+               return NULL;
+       down(&sound_oss_mutex);
+       mreg = snd_oss_minors[minor];
+       if (mreg && mreg->type == type)
+               private_data = mreg->private_data;
+       else
+               private_data = NULL;
+       up(&sound_oss_mutex);
+       return private_data;
+}
+
 static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
 {
        int minor;
@@ -78,7 +94,8 @@ static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
 }
 
 int snd_register_oss_device(int type, struct snd_card *card, int dev,
-                           struct file_operations *f_ops, const char *name)
+                           struct file_operations *f_ops, void *private_data,
+                           const char *name)
 {
        int minor = snd_oss_kernel_minor(type, card, dev);
        int minor_unit;
@@ -97,6 +114,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
        preg->card = card ? card->number : -1;
        preg->device = dev;
        preg->f_ops = f_ops;
+       preg->private_data = private_data;
        down(&sound_oss_mutex);
        snd_oss_minors[minor] = preg;
        minor_unit = SNDRV_MINOR_OSS_DEVICE(minor);
@@ -121,6 +139,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
                                                          carddev);
                if (register2 != track2)
                        goto __end;
+               snd_oss_minors[track2] = preg;
        }
        up(&sound_oss_mutex);
        return 0;
@@ -163,8 +182,10 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
                track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1);
                break;
        }
-       if (track2 >= 0)
+       if (track2 >= 0) {
                unregister_sound_special(track2);
+               snd_oss_minors[track2] = NULL;
+       }
        snd_oss_minors[minor] = NULL;
        up(&sound_oss_mutex);
        kfree(mptr);
index a7bcb04..c62dbac 100644 (file)
@@ -1952,8 +1952,8 @@ static int __init alsa_timer_init(void)
        if ((err = snd_timer_register_system()) < 0)
                snd_printk(KERN_ERR "unable to register system timer (%i)\n",
                           err);
-       if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER,
-                                      NULL, 0, &snd_timer_f_ops, "timer")) < 0)
+       if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0,
+                                      &snd_timer_f_ops, NULL, "timer")) < 0)
                snd_printk(KERN_ERR "unable to register timer device (%i)\n",
                           err);
        return 0;