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