Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / sound / core / sound_oss.c
index de39d21..9055c6d 100644 (file)
 #include <sound/minors.h>
 #include <sound/info.h>
 #include <linux/sound.h>
+#include <linux/mutex.h>
 
-#define SNDRV_OS_MINORS                256
+#define SNDRV_OSS_MINORS 128
 
-static struct list_head snd_oss_minors_hash[SNDRV_CARDS];
+static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS];
+static DEFINE_MUTEX(sound_oss_mutex);
 
-static DECLARE_MUTEX(sound_oss_mutex);
-
-static snd_minor_t *snd_oss_minor_search(int minor)
+void *snd_lookup_oss_minor_data(unsigned int minor, int type)
 {
-       struct list_head *list;
-       snd_minor_t *mptr;
+       struct snd_minor *mreg;
+       void *private_data;
 
-       list_for_each(list, &snd_oss_minors_hash[SNDRV_MINOR_OSS_CARD(minor)]) {
-               mptr = list_entry(list, snd_minor_t, list);
-               if (mptr->number == minor)
-                       return mptr;
-       }
-       return NULL;
+       if (minor >= ARRAY_SIZE(snd_oss_minors))
+               return NULL;
+       mutex_lock(&sound_oss_mutex);
+       mreg = snd_oss_minors[minor];
+       if (mreg && mreg->type == type)
+               private_data = mreg->private_data;
+       else
+               private_data = NULL;
+       mutex_unlock(&sound_oss_mutex);
+       return private_data;
 }
 
-static int snd_oss_kernel_minor(int type, snd_card_t * card, int dev)
+static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
 {
        int minor;
 
@@ -86,29 +90,36 @@ static int snd_oss_kernel_minor(int type, snd_card_t * card, int dev)
        default:
                return -EINVAL;
        }
-       snd_assert(minor >= 0 && minor < SNDRV_OS_MINORS, return -EINVAL);
+       snd_assert(minor >= 0 && minor < SNDRV_OSS_MINORS, return -EINVAL);
        return minor;
 }
 
-int snd_register_oss_device(int type, snd_card_t * card, int dev, snd_minor_t * reg, const char *name)
+int snd_register_oss_device(int type, struct snd_card *card, int dev,
+                           const struct file_operations *f_ops, void *private_data,
+                           const char *name)
 {
        int minor = snd_oss_kernel_minor(type, card, dev);
        int minor_unit;
-       snd_minor_t *preg;
+       struct snd_minor *preg;
        int cidx = SNDRV_MINOR_OSS_CARD(minor);
        int track2 = -1;
        int register1 = -1, register2 = -1;
+       struct device *carddev = NULL;
 
+       if (card && card->number >= 8)
+               return 0; /* ignore silently */
        if (minor < 0)
                return minor;
-       preg = (snd_minor_t *)kmalloc(sizeof(snd_minor_t), GFP_KERNEL);
+       preg = kmalloc(sizeof(struct snd_minor), GFP_KERNEL);
        if (preg == NULL)
                return -ENOMEM;
-       *preg = *reg;
-       preg->number = minor;
+       preg->type = type;
+       preg->card = card ? card->number : -1;
        preg->device = dev;
-       down(&sound_oss_mutex);
-       list_add_tail(&preg->list, &snd_oss_minors_hash[cidx]);
+       preg->f_ops = f_ops;
+       preg->private_data = private_data;
+       mutex_lock(&sound_oss_mutex);
+       snd_oss_minors[minor] = preg;
        minor_unit = SNDRV_MINOR_OSS_DEVICE(minor);
        switch (minor_unit) {
        case SNDRV_MINOR_OSS_PCM:
@@ -121,15 +132,19 @@ int snd_register_oss_device(int type, snd_card_t * card, int dev, snd_minor_t *
                track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1);
                break;
        }
-       register1 = register_sound_special(reg->f_ops, minor);
+       if (card)
+               carddev = card->dev;
+       register1 = register_sound_special_device(f_ops, minor, carddev);
        if (register1 != minor)
                goto __end;
        if (track2 >= 0) {
-               register2 = register_sound_special(reg->f_ops, track2);
+               register2 = register_sound_special_device(f_ops, track2,
+                                                         carddev);
                if (register2 != track2)
                        goto __end;
+               snd_oss_minors[track2] = preg;
        }
-       up(&sound_oss_mutex);
+       mutex_unlock(&sound_oss_mutex);
        return 0;
 
       __end:
@@ -137,25 +152,27 @@ int snd_register_oss_device(int type, snd_card_t * card, int dev, snd_minor_t *
                unregister_sound_special(register2);
        if (register1 >= 0)
                unregister_sound_special(register1);
-       list_del(&preg->list);
-       up(&sound_oss_mutex);
+       snd_oss_minors[minor] = NULL;
+       mutex_unlock(&sound_oss_mutex);
        kfree(preg);
        return -EBUSY;
 }
 
-int snd_unregister_oss_device(int type, snd_card_t * card, int dev)
+int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
 {
        int minor = snd_oss_kernel_minor(type, card, dev);
        int cidx = SNDRV_MINOR_OSS_CARD(minor);
        int track2 = -1;
-       snd_minor_t *mptr;
+       struct snd_minor *mptr;
 
+       if (card && card->number >= 8)
+               return 0;
        if (minor < 0)
                return minor;
-       down(&sound_oss_mutex);
-       mptr = snd_oss_minor_search(minor);
+       mutex_lock(&sound_oss_mutex);
+       mptr = snd_oss_minors[minor];
        if (mptr == NULL) {
-               up(&sound_oss_mutex);
+               mutex_unlock(&sound_oss_mutex);
                return -ENOENT;
        }
        unregister_sound_special(minor);
@@ -170,10 +187,12 @@ int snd_unregister_oss_device(int type, snd_card_t * card, int dev)
                track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1);
                break;
        }
-       if (track2 >= 0)
+       if (track2 >= 0) {
                unregister_sound_special(track2);
-       list_del(&mptr->list);
-       up(&sound_oss_mutex);
+               snd_oss_minors[track2] = NULL;
+       }
+       snd_oss_minors[minor] = NULL;
+       mutex_unlock(&sound_oss_mutex);
        kfree(mptr);
        return 0;
 }
@@ -184,36 +203,52 @@ int snd_unregister_oss_device(int type, snd_card_t * card, int dev)
 
 #ifdef CONFIG_PROC_FS
 
-static snd_info_entry_t *snd_minor_info_oss_entry = NULL;
+static struct snd_info_entry *snd_minor_info_oss_entry = NULL;
 
-static void snd_minor_info_oss_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+static const char *snd_oss_device_type_name(int type)
 {
-       int card, dev;
-       struct list_head *list;
-       snd_minor_t *mptr;
-
-       down(&sound_oss_mutex);
-       for (card = 0; card < SNDRV_CARDS; card++) {
-               list_for_each(list, &snd_oss_minors_hash[card]) {
-                       mptr = list_entry(list, snd_minor_t, list);
-                       dev = SNDRV_MINOR_OSS_DEVICE(mptr->number);
-                       if (dev != SNDRV_MINOR_OSS_SNDSTAT &&
-                           dev != SNDRV_MINOR_OSS_SEQUENCER &&
-                           dev != SNDRV_MINOR_OSS_MUSIC)
-                               snd_iprintf(buffer, "%3i: [%i-%2i]: %s\n", mptr->number, card, dev, mptr->comment);
-                       else
-                               snd_iprintf(buffer, "%3i:       : %s\n", mptr->number, mptr->comment);
-               }
+       switch (type) {
+       case SNDRV_OSS_DEVICE_TYPE_MIXER:
+               return "mixer";
+       case SNDRV_OSS_DEVICE_TYPE_SEQUENCER:
+       case SNDRV_OSS_DEVICE_TYPE_MUSIC:
+               return "sequencer";
+       case SNDRV_OSS_DEVICE_TYPE_PCM:
+               return "digital audio";
+       case SNDRV_OSS_DEVICE_TYPE_MIDI:
+               return "raw midi";
+       case SNDRV_OSS_DEVICE_TYPE_DMFM:
+               return "hardware dependent";
+       default:
+               return "?";
        }
-       up(&sound_oss_mutex);
 }
 
-#endif /* CONFIG_PROC_FS */
+static void snd_minor_info_oss_read(struct snd_info_entry *entry,
+                                   struct snd_info_buffer *buffer)
+{
+       int minor;
+       struct snd_minor *mptr;
+
+       mutex_lock(&sound_oss_mutex);
+       for (minor = 0; minor < SNDRV_OSS_MINORS; ++minor) {
+               if (!(mptr = snd_oss_minors[minor]))
+                       continue;
+               if (mptr->card >= 0)
+                       snd_iprintf(buffer, "%3i: [%i-%2i]: %s\n", minor,
+                                   mptr->card, mptr->device,
+                                   snd_oss_device_type_name(mptr->type));
+               else
+                       snd_iprintf(buffer, "%3i:       : %s\n", minor,
+                                   snd_oss_device_type_name(mptr->type));
+       }
+       mutex_unlock(&sound_oss_mutex);
+}
+
 
 int __init snd_minor_info_oss_init(void)
 {
-#ifdef CONFIG_PROC_FS
-       snd_info_entry_t *entry;
+       struct snd_info_entry *entry;
 
        entry = snd_info_create_module_entry(THIS_MODULE, "devices", snd_oss_root);
        if (entry) {
@@ -225,26 +260,15 @@ int __init snd_minor_info_oss_init(void)
                }
        }
        snd_minor_info_oss_entry = entry;
-#endif
        return 0;
 }
 
 int __exit snd_minor_info_oss_done(void)
 {
-#ifdef CONFIG_PROC_FS
        if (snd_minor_info_oss_entry)
                snd_info_unregister(snd_minor_info_oss_entry);
-#endif
-       return 0;
-}
-
-int __init snd_oss_init_module(void)
-{
-       int card;
-       
-       for (card = 0; card < SNDRV_CARDS; card++)
-               INIT_LIST_HEAD(&snd_oss_minors_hash[card]);
        return 0;
 }
+#endif /* CONFIG_PROC_FS */
 
 #endif /* CONFIG_SND_OSSEMUL */