root/sound/sound_core.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. init_oss_soundcore
  2. cleanup_oss_soundcore
  3. sound_devnode
  4. init_soundcore
  5. cleanup_soundcore
  6. __sound_insert_unit
  7. __sound_remove_unit
  8. sound_insert_unit
  9. sound_remove_unit
  10. register_sound_special_device
  11. register_sound_special
  12. register_sound_mixer
  13. register_sound_dsp
  14. unregister_sound_special
  15. unregister_sound_mixer
  16. unregister_sound_dsp
  17. __look_for_unit
  18. soundcore_open
  19. cleanup_oss_soundcore
  20. init_oss_soundcore

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *      Sound core.  This file is composed of two parts.  sound_class
   4  *      which is common to both OSS and ALSA and OSS sound core which
   5  *      is used OSS or emulation of it.
   6  */
   7 
   8 /*
   9  * First, the common part.
  10  */
  11 #include <linux/module.h>
  12 #include <linux/device.h>
  13 #include <linux/err.h>
  14 #include <linux/kdev_t.h>
  15 #include <linux/major.h>
  16 #include <sound/core.h>
  17 
  18 #ifdef CONFIG_SOUND_OSS_CORE
  19 static int __init init_oss_soundcore(void);
  20 static void cleanup_oss_soundcore(void);
  21 #else
  22 static inline int init_oss_soundcore(void)      { return 0; }
  23 static inline void cleanup_oss_soundcore(void)  { }
  24 #endif
  25 
  26 struct class *sound_class;
  27 EXPORT_SYMBOL(sound_class);
  28 
  29 MODULE_DESCRIPTION("Core sound module");
  30 MODULE_AUTHOR("Alan Cox");
  31 MODULE_LICENSE("GPL");
  32 
  33 static char *sound_devnode(struct device *dev, umode_t *mode)
  34 {
  35         if (MAJOR(dev->devt) == SOUND_MAJOR)
  36                 return NULL;
  37         return kasprintf(GFP_KERNEL, "snd/%s", dev_name(dev));
  38 }
  39 
  40 static int __init init_soundcore(void)
  41 {
  42         int rc;
  43 
  44         rc = init_oss_soundcore();
  45         if (rc)
  46                 return rc;
  47 
  48         sound_class = class_create(THIS_MODULE, "sound");
  49         if (IS_ERR(sound_class)) {
  50                 cleanup_oss_soundcore();
  51                 return PTR_ERR(sound_class);
  52         }
  53 
  54         sound_class->devnode = sound_devnode;
  55 
  56         return 0;
  57 }
  58 
  59 static void __exit cleanup_soundcore(void)
  60 {
  61         cleanup_oss_soundcore();
  62         class_destroy(sound_class);
  63 }
  64 
  65 subsys_initcall(init_soundcore);
  66 module_exit(cleanup_soundcore);
  67 
  68 
  69 #ifdef CONFIG_SOUND_OSS_CORE
  70 /*
  71  *      OSS sound core handling. Breaks out sound functions to submodules
  72  *      
  73  *      Author:         Alan Cox <alan@lxorguk.ukuu.org.uk>
  74  *
  75  *      Fixes:
  76  *
  77  *                         --------------------
  78  * 
  79  *      Top level handler for the sound subsystem. Various devices can
  80  *      plug into this. The fact they don't all go via OSS doesn't mean 
  81  *      they don't have to implement the OSS API. There is a lot of logic
  82  *      to keeping much of the OSS weight out of the code in a compatibility
  83  *      module, but it's up to the driver to rember to load it...
  84  *
  85  *      The code provides a set of functions for registration of devices
  86  *      by type. This is done rather than providing a single call so that
  87  *      we can hide any future changes in the internals (eg when we go to
  88  *      32bit dev_t) from the modules and their interface.
  89  *
  90  *      Secondly we need to allocate the dsp, dsp16 and audio devices as
  91  *      one. Thus we misuse the chains a bit to simplify this.
  92  *
  93  *      Thirdly to make it more fun and for 2.3.x and above we do all
  94  *      of this using fine grained locking.
  95  *
  96  *      FIXME: we have to resolve modules and fine grained load/unload
  97  *      locking at some point in 2.3.x.
  98  */
  99 
 100 #include <linux/init.h>
 101 #include <linux/slab.h>
 102 #include <linux/types.h>
 103 #include <linux/kernel.h>
 104 #include <linux/sound.h>
 105 #include <linux/kmod.h>
 106 
 107 #define SOUND_STEP 16
 108 
 109 struct sound_unit
 110 {
 111         int unit_minor;
 112         const struct file_operations *unit_fops;
 113         struct sound_unit *next;
 114         char name[32];
 115 };
 116 
 117 /*
 118  * By default, OSS sound_core claims full legacy minor range (0-255)
 119  * of SOUND_MAJOR to trap open attempts to any sound minor and
 120  * requests modules using custom sound-slot/service-* module aliases.
 121  * The only benefit of doing this is allowing use of custom module
 122  * aliases instead of the standard char-major-* ones.  This behavior
 123  * prevents alternative OSS implementation and is scheduled to be
 124  * removed.
 125  *
 126  * CONFIG_SOUND_OSS_CORE_PRECLAIM and soundcore.preclaim_oss kernel
 127  * parameter are added to allow distros and developers to try and
 128  * switch to alternative implementations without needing to rebuild
 129  * the kernel in the meantime.  If preclaim_oss is non-zero, the
 130  * kernel will behave the same as before.  All SOUND_MAJOR minors are
 131  * preclaimed and the custom module aliases along with standard chrdev
 132  * ones are emitted if a missing device is opened.  If preclaim_oss is
 133  * zero, sound_core only grabs what's actually in use and for missing
 134  * devices only the standard chrdev aliases are requested.
 135  *
 136  * All these clutters are scheduled to be removed along with
 137  * sound-slot/service-* module aliases.
 138  */
 139 #ifdef CONFIG_SOUND_OSS_CORE_PRECLAIM
 140 static int preclaim_oss = 1;
 141 #else
 142 static int preclaim_oss = 0;
 143 #endif
 144 
 145 module_param(preclaim_oss, int, 0444);
 146 
 147 static int soundcore_open(struct inode *, struct file *);
 148 
 149 static const struct file_operations soundcore_fops =
 150 {
 151         /* We must have an owner or the module locking fails */
 152         .owner  = THIS_MODULE,
 153         .open   = soundcore_open,
 154         .llseek = noop_llseek,
 155 };
 156 
 157 /*
 158  *      Low level list operator. Scan the ordered list, find a hole and
 159  *      join into it. Called with the lock asserted
 160  */
 161 
 162 static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list, const struct file_operations *fops, int index, int low, int top)
 163 {
 164         int n=low;
 165 
 166         if (index < 0) {        /* first free */
 167 
 168                 while (*list && (*list)->unit_minor<n)
 169                         list=&((*list)->next);
 170 
 171                 while(n<top)
 172                 {
 173                         /* Found a hole ? */
 174                         if(*list==NULL || (*list)->unit_minor>n)
 175                                 break;
 176                         list=&((*list)->next);
 177                         n+=SOUND_STEP;
 178                 }
 179 
 180                 if(n>=top)
 181                         return -ENOENT;
 182         } else {
 183                 n = low+(index*16);
 184                 while (*list) {
 185                         if ((*list)->unit_minor==n)
 186                                 return -EBUSY;
 187                         if ((*list)->unit_minor>n)
 188                                 break;
 189                         list=&((*list)->next);
 190                 }
 191         }       
 192                 
 193         /*
 194          *      Fill it in
 195          */
 196          
 197         s->unit_minor=n;
 198         s->unit_fops=fops;
 199         
 200         /*
 201          *      Link it
 202          */
 203          
 204         s->next=*list;
 205         *list=s;
 206         
 207         
 208         return n;
 209 }
 210 
 211 /*
 212  *      Remove a node from the chain. Called with the lock asserted
 213  */
 214  
 215 static struct sound_unit *__sound_remove_unit(struct sound_unit **list, int unit)
 216 {
 217         while(*list)
 218         {
 219                 struct sound_unit *p=*list;
 220                 if(p->unit_minor==unit)
 221                 {
 222                         *list=p->next;
 223                         return p;
 224                 }
 225                 list=&(p->next);
 226         }
 227         printk(KERN_ERR "Sound device %d went missing!\n", unit);
 228         return NULL;
 229 }
 230 
 231 /*
 232  *      This lock guards the sound loader list.
 233  */
 234 
 235 static DEFINE_SPINLOCK(sound_loader_lock);
 236 
 237 /*
 238  *      Allocate the controlling structure and add it to the sound driver
 239  *      list. Acquires locks as needed
 240  */
 241 
 242 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)
 243 {
 244         struct sound_unit *s = kmalloc(sizeof(*s), GFP_KERNEL);
 245         int r;
 246 
 247         if (!s)
 248                 return -ENOMEM;
 249 
 250         spin_lock(&sound_loader_lock);
 251 retry:
 252         r = __sound_insert_unit(s, list, fops, index, low, top);
 253         spin_unlock(&sound_loader_lock);
 254         
 255         if (r < 0)
 256                 goto fail;
 257         else if (r < SOUND_STEP)
 258                 sprintf(s->name, "sound/%s", name);
 259         else
 260                 sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP);
 261 
 262         if (!preclaim_oss) {
 263                 /*
 264                  * Something else might have grabbed the minor.  If
 265                  * first free slot is requested, rescan with @low set
 266                  * to the next unit; otherwise, -EBUSY.
 267                  */
 268                 r = __register_chrdev(SOUND_MAJOR, s->unit_minor, 1, s->name,
 269                                       &soundcore_fops);
 270                 if (r < 0) {
 271                         spin_lock(&sound_loader_lock);
 272                         __sound_remove_unit(list, s->unit_minor);
 273                         if (index < 0) {
 274                                 low = s->unit_minor + SOUND_STEP;
 275                                 goto retry;
 276                         }
 277                         spin_unlock(&sound_loader_lock);
 278                         r = -EBUSY;
 279                         goto fail;
 280                 }
 281         }
 282 
 283         device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor),
 284                       NULL, "%s", s->name+6);
 285         return s->unit_minor;
 286 
 287 fail:
 288         kfree(s);
 289         return r;
 290 }
 291 
 292 /*
 293  *      Remove a unit. Acquires locks as needed. The drivers MUST have
 294  *      completed the removal before their file operations become
 295  *      invalid.
 296  */
 297         
 298 static void sound_remove_unit(struct sound_unit **list, int unit)
 299 {
 300         struct sound_unit *p;
 301 
 302         spin_lock(&sound_loader_lock);
 303         p = __sound_remove_unit(list, unit);
 304         spin_unlock(&sound_loader_lock);
 305         if (p) {
 306                 if (!preclaim_oss)
 307                         __unregister_chrdev(SOUND_MAJOR, p->unit_minor, 1,
 308                                             p->name);
 309                 device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor));
 310                 kfree(p);
 311         }
 312 }
 313 
 314 /*
 315  *      Allocations
 316  *
 317  *      0       *16             Mixers
 318  *      1       *8              Sequencers
 319  *      2       *16             Midi
 320  *      3       *16             DSP
 321  *      4       *16             SunDSP
 322  *      5       *16             DSP16
 323  *      6       --              sndstat (obsolete)
 324  *      7       *16             unused
 325  *      8       --              alternate sequencer (see above)
 326  *      9       *16             raw synthesizer access
 327  *      10      *16             unused
 328  *      11      *16             unused
 329  *      12      *16             unused
 330  *      13      *16             unused
 331  *      14      *16             unused
 332  *      15      *16             unused
 333  */
 334 
 335 static struct sound_unit *chains[SOUND_STEP];
 336 
 337 /**
 338  *      register_sound_special_device - register a special sound node
 339  *      @fops: File operations for the driver
 340  *      @unit: Unit number to allocate
 341  *      @dev: device pointer
 342  *
 343  *      Allocate a special sound device by minor number from the sound
 344  *      subsystem.
 345  *
 346  *      Return: The allocated number is returned on success. On failure,
 347  *      a negative error code is returned.
 348  */
 349  
 350 int register_sound_special_device(const struct file_operations *fops, int unit,
 351                                   struct device *dev)
 352 {
 353         const int chain = unit % SOUND_STEP;
 354         int max_unit = 256;
 355         const char *name;
 356         char _name[16];
 357 
 358         switch (chain) {
 359             case 0:
 360                 name = "mixer";
 361                 break;
 362             case 1:
 363                 name = "sequencer";
 364                 if (unit >= SOUND_STEP)
 365                         goto __unknown;
 366                 max_unit = unit + 1;
 367                 break;
 368             case 2:
 369                 name = "midi";
 370                 break;
 371             case 3:
 372                 name = "dsp";
 373                 break;
 374             case 4:
 375                 name = "audio";
 376                 break;
 377             case 5:
 378                 name = "dspW";
 379                 break;
 380             case 8:
 381                 name = "sequencer2";
 382                 if (unit >= SOUND_STEP)
 383                         goto __unknown;
 384                 max_unit = unit + 1;
 385                 break;
 386             case 9:
 387                 name = "dmmidi";
 388                 break;
 389             case 10:
 390                 name = "dmfm";
 391                 break;
 392             case 12:
 393                 name = "adsp";
 394                 break;
 395             case 13:
 396                 name = "amidi";
 397                 break;
 398             case 14:
 399                 name = "admmidi";
 400                 break;
 401             default:
 402                 {
 403                     __unknown:
 404                         sprintf(_name, "unknown%d", chain);
 405                         if (unit >= SOUND_STEP)
 406                                 strcat(_name, "-");
 407                         name = _name;
 408                 }
 409                 break;
 410         }
 411         return sound_insert_unit(&chains[chain], fops, -1, unit, max_unit,
 412                                  name, 0600, dev);
 413 }
 414  
 415 EXPORT_SYMBOL(register_sound_special_device);
 416 
 417 int register_sound_special(const struct file_operations *fops, int unit)
 418 {
 419         return register_sound_special_device(fops, unit, NULL);
 420 }
 421 
 422 EXPORT_SYMBOL(register_sound_special);
 423 
 424 /**
 425  *      register_sound_mixer - register a mixer device
 426  *      @fops: File operations for the driver
 427  *      @dev: Unit number to allocate
 428  *
 429  *      Allocate a mixer device. Unit is the number of the mixer requested.
 430  *      Pass -1 to request the next free mixer unit.
 431  *
 432  *      Return: On success, the allocated number is returned. On failure,
 433  *      a negative error code is returned.
 434  */
 435 
 436 int register_sound_mixer(const struct file_operations *fops, int dev)
 437 {
 438         return sound_insert_unit(&chains[0], fops, dev, 0, 128,
 439                                  "mixer", 0600, NULL);
 440 }
 441 
 442 EXPORT_SYMBOL(register_sound_mixer);
 443 
 444 /*
 445  *      DSP's are registered as a triple. Register only one and cheat
 446  *      in open - see below.
 447  */
 448  
 449 /**
 450  *      register_sound_dsp - register a DSP device
 451  *      @fops: File operations for the driver
 452  *      @dev: Unit number to allocate
 453  *
 454  *      Allocate a DSP device. Unit is the number of the DSP requested.
 455  *      Pass -1 to request the next free DSP unit.
 456  *
 457  *      This function allocates both the audio and dsp device entries together
 458  *      and will always allocate them as a matching pair - eg dsp3/audio3
 459  *
 460  *      Return: On success, the allocated number is returned. On failure,
 461  *      a negative error code is returned.
 462  */
 463 
 464 int register_sound_dsp(const struct file_operations *fops, int dev)
 465 {
 466         return sound_insert_unit(&chains[3], fops, dev, 3, 131,
 467                                  "dsp", 0600, NULL);
 468 }
 469 
 470 EXPORT_SYMBOL(register_sound_dsp);
 471 
 472 /**
 473  *      unregister_sound_special - unregister a special sound device
 474  *      @unit: unit number to allocate
 475  *
 476  *      Release a sound device that was allocated with
 477  *      register_sound_special(). The unit passed is the return value from
 478  *      the register function.
 479  */
 480 
 481 
 482 void unregister_sound_special(int unit)
 483 {
 484         sound_remove_unit(&chains[unit % SOUND_STEP], unit);
 485 }
 486  
 487 EXPORT_SYMBOL(unregister_sound_special);
 488 
 489 /**
 490  *      unregister_sound_mixer - unregister a mixer
 491  *      @unit: unit number to allocate
 492  *
 493  *      Release a sound device that was allocated with register_sound_mixer().
 494  *      The unit passed is the return value from the register function.
 495  */
 496 
 497 void unregister_sound_mixer(int unit)
 498 {
 499         sound_remove_unit(&chains[0], unit);
 500 }
 501 
 502 EXPORT_SYMBOL(unregister_sound_mixer);
 503 
 504 /**
 505  *      unregister_sound_dsp - unregister a DSP device
 506  *      @unit: unit number to allocate
 507  *
 508  *      Release a sound device that was allocated with register_sound_dsp().
 509  *      The unit passed is the return value from the register function.
 510  *
 511  *      Both of the allocated units are released together automatically.
 512  */
 513 
 514 void unregister_sound_dsp(int unit)
 515 {
 516         sound_remove_unit(&chains[3], unit);
 517 }
 518 
 519 
 520 EXPORT_SYMBOL(unregister_sound_dsp);
 521 
 522 static struct sound_unit *__look_for_unit(int chain, int unit)
 523 {
 524         struct sound_unit *s;
 525         
 526         s=chains[chain];
 527         while(s && s->unit_minor <= unit)
 528         {
 529                 if(s->unit_minor==unit)
 530                         return s;
 531                 s=s->next;
 532         }
 533         return NULL;
 534 }
 535 
 536 static int soundcore_open(struct inode *inode, struct file *file)
 537 {
 538         int chain;
 539         int unit = iminor(inode);
 540         struct sound_unit *s;
 541         const struct file_operations *new_fops = NULL;
 542 
 543         chain=unit&0x0F;
 544         if(chain==4 || chain==5)        /* dsp/audio/dsp16 */
 545         {
 546                 unit&=0xF0;
 547                 unit|=3;
 548                 chain=3;
 549         }
 550         
 551         spin_lock(&sound_loader_lock);
 552         s = __look_for_unit(chain, unit);
 553         if (s)
 554                 new_fops = fops_get(s->unit_fops);
 555         if (preclaim_oss && !new_fops) {
 556                 spin_unlock(&sound_loader_lock);
 557 
 558                 /*
 559                  *  Please, don't change this order or code.
 560                  *  For ALSA slot means soundcard and OSS emulation code
 561                  *  comes as add-on modules which aren't depend on
 562                  *  ALSA toplevel modules for soundcards, thus we need
 563                  *  load them at first.   [Jaroslav Kysela <perex@jcu.cz>]
 564                  */
 565                 request_module("sound-slot-%i", unit>>4);
 566                 request_module("sound-service-%i-%i", unit>>4, chain);
 567 
 568                 /*
 569                  * sound-slot/service-* module aliases are scheduled
 570                  * for removal in favor of the standard char-major-*
 571                  * module aliases.  For the time being, generate both
 572                  * the legacy and standard module aliases to ease
 573                  * transition.
 574                  */
 575                 if (request_module("char-major-%d-%d", SOUND_MAJOR, unit) > 0)
 576                         request_module("char-major-%d", SOUND_MAJOR);
 577 
 578                 spin_lock(&sound_loader_lock);
 579                 s = __look_for_unit(chain, unit);
 580                 if (s)
 581                         new_fops = fops_get(s->unit_fops);
 582         }
 583         spin_unlock(&sound_loader_lock);
 584         if (new_fops) {
 585                 /*
 586                  * We rely upon the fact that we can't be unloaded while the
 587                  * subdriver is there.
 588                  */
 589                 int err = 0;
 590                 replace_fops(file, new_fops);
 591 
 592                 if (file->f_op->open)
 593                         err = file->f_op->open(inode,file);
 594 
 595                 return err;
 596         }
 597         return -ENODEV;
 598 }
 599 
 600 MODULE_ALIAS_CHARDEV_MAJOR(SOUND_MAJOR);
 601 
 602 static void cleanup_oss_soundcore(void)
 603 {
 604         /* We have nothing to really do here - we know the lists must be
 605            empty */
 606         unregister_chrdev(SOUND_MAJOR, "sound");
 607 }
 608 
 609 static int __init init_oss_soundcore(void)
 610 {
 611         if (preclaim_oss &&
 612             register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops) < 0) {
 613                 printk(KERN_ERR "soundcore: sound device already in use.\n");
 614                 return -EBUSY;
 615         }
 616 
 617         return 0;
 618 }
 619 
 620 #endif /* CONFIG_SOUND_OSS_CORE */

/* [<][>][^][v][top][bottom][index][help] */