Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Sound core.  This file is composed of two parts.  sound_class
0004  *  which is common to both OSS and ALSA and OSS sound core which
0005  *  is used OSS or emulation of it.
0006  */
0007 
0008 /*
0009  * First, the common part.
0010  */
0011 #include <linux/module.h>
0012 #include <linux/device.h>
0013 #include <linux/err.h>
0014 #include <linux/kdev_t.h>
0015 #include <linux/major.h>
0016 #include <sound/core.h>
0017 
0018 #ifdef CONFIG_SOUND_OSS_CORE
0019 static int __init init_oss_soundcore(void);
0020 static void cleanup_oss_soundcore(void);
0021 #else
0022 static inline int init_oss_soundcore(void)  { return 0; }
0023 static inline void cleanup_oss_soundcore(void)  { }
0024 #endif
0025 
0026 struct class *sound_class;
0027 EXPORT_SYMBOL(sound_class);
0028 
0029 MODULE_DESCRIPTION("Core sound module");
0030 MODULE_AUTHOR("Alan Cox");
0031 MODULE_LICENSE("GPL");
0032 
0033 static char *sound_devnode(struct device *dev, umode_t *mode)
0034 {
0035     if (MAJOR(dev->devt) == SOUND_MAJOR)
0036         return NULL;
0037     return kasprintf(GFP_KERNEL, "snd/%s", dev_name(dev));
0038 }
0039 
0040 static int __init init_soundcore(void)
0041 {
0042     int rc;
0043 
0044     rc = init_oss_soundcore();
0045     if (rc)
0046         return rc;
0047 
0048     sound_class = class_create(THIS_MODULE, "sound");
0049     if (IS_ERR(sound_class)) {
0050         cleanup_oss_soundcore();
0051         return PTR_ERR(sound_class);
0052     }
0053 
0054     sound_class->devnode = sound_devnode;
0055 
0056     return 0;
0057 }
0058 
0059 static void __exit cleanup_soundcore(void)
0060 {
0061     cleanup_oss_soundcore();
0062     class_destroy(sound_class);
0063 }
0064 
0065 subsys_initcall(init_soundcore);
0066 module_exit(cleanup_soundcore);
0067 
0068 
0069 #ifdef CONFIG_SOUND_OSS_CORE
0070 /*
0071  *  OSS sound core handling. Breaks out sound functions to submodules
0072  *  
0073  *  Author:     Alan Cox <alan@lxorguk.ukuu.org.uk>
0074  *
0075  *  Fixes:
0076  *
0077  *                         --------------------
0078  * 
0079  *  Top level handler for the sound subsystem. Various devices can
0080  *  plug into this. The fact they don't all go via OSS doesn't mean 
0081  *  they don't have to implement the OSS API. There is a lot of logic
0082  *  to keeping much of the OSS weight out of the code in a compatibility
0083  *  module, but it's up to the driver to rember to load it...
0084  *
0085  *  The code provides a set of functions for registration of devices
0086  *  by type. This is done rather than providing a single call so that
0087  *  we can hide any future changes in the internals (eg when we go to
0088  *  32bit dev_t) from the modules and their interface.
0089  *
0090  *  Secondly we need to allocate the dsp, dsp16 and audio devices as
0091  *  one. Thus we misuse the chains a bit to simplify this.
0092  *
0093  *  Thirdly to make it more fun and for 2.3.x and above we do all
0094  *  of this using fine grained locking.
0095  *
0096  *  FIXME: we have to resolve modules and fine grained load/unload
0097  *  locking at some point in 2.3.x.
0098  */
0099 
0100 #include <linux/init.h>
0101 #include <linux/slab.h>
0102 #include <linux/types.h>
0103 #include <linux/kernel.h>
0104 #include <linux/sound.h>
0105 #include <linux/kmod.h>
0106 
0107 #define SOUND_STEP 16
0108 
0109 struct sound_unit
0110 {
0111     int unit_minor;
0112     const struct file_operations *unit_fops;
0113     struct sound_unit *next;
0114     char name[32];
0115 };
0116 
0117 /*
0118  * By default, OSS sound_core claims full legacy minor range (0-255)
0119  * of SOUND_MAJOR to trap open attempts to any sound minor and
0120  * requests modules using custom sound-slot/service-* module aliases.
0121  * The only benefit of doing this is allowing use of custom module
0122  * aliases instead of the standard char-major-* ones.  This behavior
0123  * prevents alternative OSS implementation and is scheduled to be
0124  * removed.
0125  *
0126  * CONFIG_SOUND_OSS_CORE_PRECLAIM and soundcore.preclaim_oss kernel
0127  * parameter are added to allow distros and developers to try and
0128  * switch to alternative implementations without needing to rebuild
0129  * the kernel in the meantime.  If preclaim_oss is non-zero, the
0130  * kernel will behave the same as before.  All SOUND_MAJOR minors are
0131  * preclaimed and the custom module aliases along with standard chrdev
0132  * ones are emitted if a missing device is opened.  If preclaim_oss is
0133  * zero, sound_core only grabs what's actually in use and for missing
0134  * devices only the standard chrdev aliases are requested.
0135  *
0136  * All these clutters are scheduled to be removed along with
0137  * sound-slot/service-* module aliases.
0138  */
0139 static int preclaim_oss = IS_ENABLED(CONFIG_SOUND_OSS_CORE_PRECLAIM);
0140 
0141 module_param(preclaim_oss, int, 0444);
0142 
0143 static int soundcore_open(struct inode *, struct file *);
0144 
0145 static const struct file_operations soundcore_fops =
0146 {
0147     /* We must have an owner or the module locking fails */
0148     .owner  = THIS_MODULE,
0149     .open   = soundcore_open,
0150     .llseek = noop_llseek,
0151 };
0152 
0153 /*
0154  *  Low level list operator. Scan the ordered list, find a hole and
0155  *  join into it. Called with the lock asserted
0156  */
0157 
0158 static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list, const struct file_operations *fops, int index, int low, int top)
0159 {
0160     int n=low;
0161 
0162     if (index < 0) {    /* first free */
0163 
0164         while (*list && (*list)->unit_minor<n)
0165             list=&((*list)->next);
0166 
0167         while(n<top)
0168         {
0169             /* Found a hole ? */
0170             if(*list==NULL || (*list)->unit_minor>n)
0171                 break;
0172             list=&((*list)->next);
0173             n+=SOUND_STEP;
0174         }
0175 
0176         if(n>=top)
0177             return -ENOENT;
0178     } else {
0179         n = low+(index*16);
0180         while (*list) {
0181             if ((*list)->unit_minor==n)
0182                 return -EBUSY;
0183             if ((*list)->unit_minor>n)
0184                 break;
0185             list=&((*list)->next);
0186         }
0187     }   
0188         
0189     /*
0190      *  Fill it in
0191      */
0192      
0193     s->unit_minor=n;
0194     s->unit_fops=fops;
0195     
0196     /*
0197      *  Link it
0198      */
0199      
0200     s->next=*list;
0201     *list=s;
0202     
0203     
0204     return n;
0205 }
0206 
0207 /*
0208  *  Remove a node from the chain. Called with the lock asserted
0209  */
0210  
0211 static struct sound_unit *__sound_remove_unit(struct sound_unit **list, int unit)
0212 {
0213     while(*list)
0214     {
0215         struct sound_unit *p=*list;
0216         if(p->unit_minor==unit)
0217         {
0218             *list=p->next;
0219             return p;
0220         }
0221         list=&(p->next);
0222     }
0223     printk(KERN_ERR "Sound device %d went missing!\n", unit);
0224     return NULL;
0225 }
0226 
0227 /*
0228  *  This lock guards the sound loader list.
0229  */
0230 
0231 static DEFINE_SPINLOCK(sound_loader_lock);
0232 
0233 /*
0234  *  Allocate the controlling structure and add it to the sound driver
0235  *  list. Acquires locks as needed
0236  */
0237 
0238 static int sound_insert_unit(struct sound_unit **list, const struct file_operations *fops, int index, int low, int top, const char *name, umode_t mode, struct device *dev)
0239 {
0240     struct sound_unit *s = kmalloc(sizeof(*s), GFP_KERNEL);
0241     int r;
0242 
0243     if (!s)
0244         return -ENOMEM;
0245 
0246     spin_lock(&sound_loader_lock);
0247 retry:
0248     r = __sound_insert_unit(s, list, fops, index, low, top);
0249     spin_unlock(&sound_loader_lock);
0250     
0251     if (r < 0)
0252         goto fail;
0253     else if (r < SOUND_STEP)
0254         sprintf(s->name, "sound/%s", name);
0255     else
0256         sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP);
0257 
0258     if (!preclaim_oss) {
0259         /*
0260          * Something else might have grabbed the minor.  If
0261          * first free slot is requested, rescan with @low set
0262          * to the next unit; otherwise, -EBUSY.
0263          */
0264         r = __register_chrdev(SOUND_MAJOR, s->unit_minor, 1, s->name,
0265                       &soundcore_fops);
0266         if (r < 0) {
0267             spin_lock(&sound_loader_lock);
0268             __sound_remove_unit(list, s->unit_minor);
0269             if (index < 0) {
0270                 low = s->unit_minor + SOUND_STEP;
0271                 goto retry;
0272             }
0273             spin_unlock(&sound_loader_lock);
0274             r = -EBUSY;
0275             goto fail;
0276         }
0277     }
0278 
0279     device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor),
0280               NULL, "%s", s->name+6);
0281     return s->unit_minor;
0282 
0283 fail:
0284     kfree(s);
0285     return r;
0286 }
0287 
0288 /*
0289  *  Remove a unit. Acquires locks as needed. The drivers MUST have
0290  *  completed the removal before their file operations become
0291  *  invalid.
0292  */
0293     
0294 static void sound_remove_unit(struct sound_unit **list, int unit)
0295 {
0296     struct sound_unit *p;
0297 
0298     spin_lock(&sound_loader_lock);
0299     p = __sound_remove_unit(list, unit);
0300     spin_unlock(&sound_loader_lock);
0301     if (p) {
0302         if (!preclaim_oss)
0303             __unregister_chrdev(SOUND_MAJOR, p->unit_minor, 1,
0304                         p->name);
0305         device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor));
0306         kfree(p);
0307     }
0308 }
0309 
0310 /*
0311  *  Allocations
0312  *
0313  *  0   *16     Mixers
0314  *  1   *8      Sequencers
0315  *  2   *16     Midi
0316  *  3   *16     DSP
0317  *  4   *16     SunDSP
0318  *  5   *16     DSP16
0319  *  6   --      sndstat (obsolete)
0320  *  7   *16     unused
0321  *  8   --      alternate sequencer (see above)
0322  *  9   *16     raw synthesizer access
0323  *  10  *16     unused
0324  *  11  *16     unused
0325  *  12  *16     unused
0326  *  13  *16     unused
0327  *  14  *16     unused
0328  *  15  *16     unused
0329  */
0330 
0331 static struct sound_unit *chains[SOUND_STEP];
0332 
0333 /**
0334  *  register_sound_special_device - register a special sound node
0335  *  @fops: File operations for the driver
0336  *  @unit: Unit number to allocate
0337  *      @dev: device pointer
0338  *
0339  *  Allocate a special sound device by minor number from the sound
0340  *  subsystem.
0341  *
0342  *  Return: The allocated number is returned on success. On failure,
0343  *  a negative error code is returned.
0344  */
0345  
0346 int register_sound_special_device(const struct file_operations *fops, int unit,
0347                   struct device *dev)
0348 {
0349     const int chain = unit % SOUND_STEP;
0350     int max_unit = 256;
0351     const char *name;
0352     char _name[16];
0353 
0354     switch (chain) {
0355         case 0:
0356         name = "mixer";
0357         break;
0358         case 1:
0359         name = "sequencer";
0360         if (unit >= SOUND_STEP)
0361             goto __unknown;
0362         max_unit = unit + 1;
0363         break;
0364         case 2:
0365         name = "midi";
0366         break;
0367         case 3:
0368         name = "dsp";
0369         break;
0370         case 4:
0371         name = "audio";
0372         break;
0373         case 5:
0374         name = "dspW";
0375         break;
0376         case 8:
0377         name = "sequencer2";
0378         if (unit >= SOUND_STEP)
0379             goto __unknown;
0380         max_unit = unit + 1;
0381         break;
0382         case 9:
0383         name = "dmmidi";
0384         break;
0385         case 10:
0386         name = "dmfm";
0387         break;
0388         case 12:
0389         name = "adsp";
0390         break;
0391         case 13:
0392         name = "amidi";
0393         break;
0394         case 14:
0395         name = "admmidi";
0396         break;
0397         default:
0398             {
0399             __unknown:
0400             sprintf(_name, "unknown%d", chain);
0401                 if (unit >= SOUND_STEP)
0402                     strcat(_name, "-");
0403                 name = _name;
0404         }
0405         break;
0406     }
0407     return sound_insert_unit(&chains[chain], fops, -1, unit, max_unit,
0408                  name, 0600, dev);
0409 }
0410  
0411 EXPORT_SYMBOL(register_sound_special_device);
0412 
0413 int register_sound_special(const struct file_operations *fops, int unit)
0414 {
0415     return register_sound_special_device(fops, unit, NULL);
0416 }
0417 
0418 EXPORT_SYMBOL(register_sound_special);
0419 
0420 /**
0421  *  register_sound_mixer - register a mixer device
0422  *  @fops: File operations for the driver
0423  *  @dev: Unit number to allocate
0424  *
0425  *  Allocate a mixer device. Unit is the number of the mixer requested.
0426  *  Pass -1 to request the next free mixer unit.
0427  *
0428  *  Return: On success, the allocated number is returned. On failure,
0429  *  a negative error code is returned.
0430  */
0431 
0432 int register_sound_mixer(const struct file_operations *fops, int dev)
0433 {
0434     return sound_insert_unit(&chains[0], fops, dev, 0, 128,
0435                  "mixer", 0600, NULL);
0436 }
0437 
0438 EXPORT_SYMBOL(register_sound_mixer);
0439 
0440 /*
0441  *  DSP's are registered as a triple. Register only one and cheat
0442  *  in open - see below.
0443  */
0444  
0445 /**
0446  *  register_sound_dsp - register a DSP device
0447  *  @fops: File operations for the driver
0448  *  @dev: Unit number to allocate
0449  *
0450  *  Allocate a DSP device. Unit is the number of the DSP requested.
0451  *  Pass -1 to request the next free DSP unit.
0452  *
0453  *  This function allocates both the audio and dsp device entries together
0454  *  and will always allocate them as a matching pair - eg dsp3/audio3
0455  *
0456  *  Return: On success, the allocated number is returned. On failure,
0457  *  a negative error code is returned.
0458  */
0459 
0460 int register_sound_dsp(const struct file_operations *fops, int dev)
0461 {
0462     return sound_insert_unit(&chains[3], fops, dev, 3, 131,
0463                  "dsp", 0600, NULL);
0464 }
0465 
0466 EXPORT_SYMBOL(register_sound_dsp);
0467 
0468 /**
0469  *  unregister_sound_special - unregister a special sound device
0470  *  @unit: unit number to allocate
0471  *
0472  *  Release a sound device that was allocated with
0473  *  register_sound_special(). The unit passed is the return value from
0474  *  the register function.
0475  */
0476 
0477 
0478 void unregister_sound_special(int unit)
0479 {
0480     sound_remove_unit(&chains[unit % SOUND_STEP], unit);
0481 }
0482  
0483 EXPORT_SYMBOL(unregister_sound_special);
0484 
0485 /**
0486  *  unregister_sound_mixer - unregister a mixer
0487  *  @unit: unit number to allocate
0488  *
0489  *  Release a sound device that was allocated with register_sound_mixer().
0490  *  The unit passed is the return value from the register function.
0491  */
0492 
0493 void unregister_sound_mixer(int unit)
0494 {
0495     sound_remove_unit(&chains[0], unit);
0496 }
0497 
0498 EXPORT_SYMBOL(unregister_sound_mixer);
0499 
0500 /**
0501  *  unregister_sound_dsp - unregister a DSP device
0502  *  @unit: unit number to allocate
0503  *
0504  *  Release a sound device that was allocated with register_sound_dsp().
0505  *  The unit passed is the return value from the register function.
0506  *
0507  *  Both of the allocated units are released together automatically.
0508  */
0509 
0510 void unregister_sound_dsp(int unit)
0511 {
0512     sound_remove_unit(&chains[3], unit);
0513 }
0514 
0515 
0516 EXPORT_SYMBOL(unregister_sound_dsp);
0517 
0518 static struct sound_unit *__look_for_unit(int chain, int unit)
0519 {
0520     struct sound_unit *s;
0521     
0522     s=chains[chain];
0523     while(s && s->unit_minor <= unit)
0524     {
0525         if(s->unit_minor==unit)
0526             return s;
0527         s=s->next;
0528     }
0529     return NULL;
0530 }
0531 
0532 static int soundcore_open(struct inode *inode, struct file *file)
0533 {
0534     int chain;
0535     int unit = iminor(inode);
0536     struct sound_unit *s;
0537     const struct file_operations *new_fops = NULL;
0538 
0539     chain=unit&0x0F;
0540     if(chain==4 || chain==5)    /* dsp/audio/dsp16 */
0541     {
0542         unit&=0xF0;
0543         unit|=3;
0544         chain=3;
0545     }
0546     
0547     spin_lock(&sound_loader_lock);
0548     s = __look_for_unit(chain, unit);
0549     if (s)
0550         new_fops = fops_get(s->unit_fops);
0551     if (preclaim_oss && !new_fops) {
0552         spin_unlock(&sound_loader_lock);
0553 
0554         /*
0555          *  Please, don't change this order or code.
0556          *  For ALSA slot means soundcard and OSS emulation code
0557          *  comes as add-on modules which aren't depend on
0558          *  ALSA toplevel modules for soundcards, thus we need
0559          *  load them at first.   [Jaroslav Kysela <perex@jcu.cz>]
0560          */
0561         request_module("sound-slot-%i", unit>>4);
0562         request_module("sound-service-%i-%i", unit>>4, chain);
0563 
0564         /*
0565          * sound-slot/service-* module aliases are scheduled
0566          * for removal in favor of the standard char-major-*
0567          * module aliases.  For the time being, generate both
0568          * the legacy and standard module aliases to ease
0569          * transition.
0570          */
0571         if (request_module("char-major-%d-%d", SOUND_MAJOR, unit) > 0)
0572             request_module("char-major-%d", SOUND_MAJOR);
0573 
0574         spin_lock(&sound_loader_lock);
0575         s = __look_for_unit(chain, unit);
0576         if (s)
0577             new_fops = fops_get(s->unit_fops);
0578     }
0579     spin_unlock(&sound_loader_lock);
0580 
0581     if (!new_fops)
0582         return -ENODEV;
0583 
0584     /*
0585      * We rely upon the fact that we can't be unloaded while the
0586      * subdriver is there.
0587      */
0588     replace_fops(file, new_fops);
0589 
0590     if (!file->f_op->open)
0591         return -ENODEV;
0592 
0593     return file->f_op->open(inode, file);
0594 }
0595 
0596 MODULE_ALIAS_CHARDEV_MAJOR(SOUND_MAJOR);
0597 
0598 static void cleanup_oss_soundcore(void)
0599 {
0600     /* We have nothing to really do here - we know the lists must be
0601        empty */
0602     unregister_chrdev(SOUND_MAJOR, "sound");
0603 }
0604 
0605 static int __init init_oss_soundcore(void)
0606 {
0607     if (preclaim_oss &&
0608         register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops) < 0) {
0609         printk(KERN_ERR "soundcore: sound device already in use.\n");
0610         return -EBUSY;
0611     }
0612 
0613     return 0;
0614 }
0615 
0616 #endif /* CONFIG_SOUND_OSS_CORE */