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#ifdef CONFIG_SOUND_MSNDCLAS
 123extern int msnd_classic_init(void);
 124#endif
 125#ifdef CONFIG_SOUND_MSNDPIN
 126extern int msnd_pinnacle_init(void);
 127#endif
 128
 129/*
 130 * By default, OSS sound_core claims full legacy minor range (0-255)
 131 * of SOUND_MAJOR to trap open attempts to any sound minor and
 132 * requests modules using custom sound-slot/service-* module aliases.
 133 * The only benefit of doing this is allowing use of custom module
 134 * aliases instead of the standard char-major-* ones.  This behavior
 135 * prevents alternative OSS implementation and is scheduled to be
 136 * removed.
 137 *
 138 * CONFIG_SOUND_OSS_CORE_PRECLAIM and soundcore.preclaim_oss kernel
 139 * parameter are added to allow distros and developers to try and
 140 * switch to alternative implementations without needing to rebuild
 141 * the kernel in the meantime.  If preclaim_oss is non-zero, the
 142 * kernel will behave the same as before.  All SOUND_MAJOR minors are
 143 * preclaimed and the custom module aliases along with standard chrdev
 144 * ones are emitted if a missing device is opened.  If preclaim_oss is
 145 * zero, sound_core only grabs what's actually in use and for missing
 146 * devices only the standard chrdev aliases are requested.
 147 *
 148 * All these clutters are scheduled to be removed along with
 149 * sound-slot/service-* module aliases.
 150 */
 151#ifdef CONFIG_SOUND_OSS_CORE_PRECLAIM
 152static int preclaim_oss = 1;
 153#else
 154static int preclaim_oss = 0;
 155#endif
 156
 157module_param(preclaim_oss, int, 0444);
 158
 159static int soundcore_open(struct inode *, struct file *);
 160
 161static const struct file_operations soundcore_fops =
 162{
 163        /* We must have an owner or the module locking fails */
 164        .owner  = THIS_MODULE,
 165        .open   = soundcore_open,
 166        .llseek = noop_llseek,
 167};
 168
 169/*
 170 *      Low level list operator. Scan the ordered list, find a hole and
 171 *      join into it. Called with the lock asserted
 172 */
 173
 174static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list, const struct file_operations *fops, int index, int low, int top)
 175{
 176        int n=low;
 177
 178        if (index < 0) {        /* first free */
 179
 180                while (*list && (*list)->unit_minor<n)
 181                        list=&((*list)->next);
 182
 183                while(n<top)
 184                {
 185                        /* Found a hole ? */
 186                        if(*list==NULL || (*list)->unit_minor>n)
 187                                break;
 188                        list=&((*list)->next);
 189                        n+=SOUND_STEP;
 190                }
 191
 192                if(n>=top)
 193                        return -ENOENT;
 194        } else {
 195                n = low+(index*16);
 196                while (*list) {
 197                        if ((*list)->unit_minor==n)
 198                                return -EBUSY;
 199                        if ((*list)->unit_minor>n)
 200                                break;
 201                        list=&((*list)->next);
 202                }
 203        }       
 204                
 205        /*
 206         *      Fill it in
 207         */
 208         
 209        s->unit_minor=n;
 210        s->unit_fops=fops;
 211        
 212        /*
 213         *      Link it
 214         */
 215         
 216        s->next=*list;
 217        *list=s;
 218        
 219        
 220        return n;
 221}
 222
 223/*
 224 *      Remove a node from the chain. Called with the lock asserted
 225 */
 226 
 227static struct sound_unit *__sound_remove_unit(struct sound_unit **list, int unit)
 228{
 229        while(*list)
 230        {
 231                struct sound_unit *p=*list;
 232                if(p->unit_minor==unit)
 233                {
 234                        *list=p->next;
 235                        return p;
 236                }
 237                list=&(p->next);
 238        }
 239        printk(KERN_ERR "Sound device %d went missing!\n", unit);
 240        return NULL;
 241}
 242
 243/*
 244 *      This lock guards the sound loader list.
 245 */
 246
 247static DEFINE_SPINLOCK(sound_loader_lock);
 248
 249/*
 250 *      Allocate the controlling structure and add it to the sound driver
 251 *      list. Acquires locks as needed
 252 */
 253
 254static 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)
 255{
 256        struct sound_unit *s = kmalloc(sizeof(*s), GFP_KERNEL);
 257        int r;
 258
 259        if (!s)
 260                return -ENOMEM;
 261
 262        spin_lock(&sound_loader_lock);
 263retry:
 264        r = __sound_insert_unit(s, list, fops, index, low, top);
 265        spin_unlock(&sound_loader_lock);
 266        
 267        if (r < 0)
 268                goto fail;
 269        else if (r < SOUND_STEP)
 270                sprintf(s->name, "sound/%s", name);
 271        else
 272                sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP);
 273
 274        if (!preclaim_oss) {
 275                /*
 276                 * Something else might have grabbed the minor.  If
 277                 * first free slot is requested, rescan with @low set
 278                 * to the next unit; otherwise, -EBUSY.
 279                 */
 280                r = __register_chrdev(SOUND_MAJOR, s->unit_minor, 1, s->name,
 281                                      &soundcore_fops);
 282                if (r < 0) {
 283                        spin_lock(&sound_loader_lock);
 284                        __sound_remove_unit(list, s->unit_minor);
 285                        if (index < 0) {
 286                                low = s->unit_minor + SOUND_STEP;
 287                                goto retry;
 288                        }
 289                        spin_unlock(&sound_loader_lock);
 290                        return -EBUSY;
 291                }
 292        }
 293
 294        device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor),
 295                      NULL, "%s", s->name+6);
 296        return s->unit_minor;
 297
 298fail:
 299        kfree(s);
 300        return r;
 301}
 302
 303/*
 304 *      Remove a unit. Acquires locks as needed. The drivers MUST have
 305 *      completed the removal before their file operations become
 306 *      invalid.
 307 */
 308        
 309static void sound_remove_unit(struct sound_unit **list, int unit)
 310{
 311        struct sound_unit *p;
 312
 313        spin_lock(&sound_loader_lock);
 314        p = __sound_remove_unit(list, unit);
 315        spin_unlock(&sound_loader_lock);
 316        if (p) {
 317                if (!preclaim_oss)
 318                        __unregister_chrdev(SOUND_MAJOR, p->unit_minor, 1,
 319                                            p->name);
 320                device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor));
 321                kfree(p);
 322        }
 323}
 324
 325/*
 326 *      Allocations
 327 *
 328 *      0       *16             Mixers
 329 *      1       *8              Sequencers
 330 *      2       *16             Midi
 331 *      3       *16             DSP
 332 *      4       *16             SunDSP
 333 *      5       *16             DSP16
 334 *      6       --              sndstat (obsolete)
 335 *      7       *16             unused
 336 *      8       --              alternate sequencer (see above)
 337 *      9       *16             raw synthesizer access
 338 *      10      *16             unused
 339 *      11      *16             unused
 340 *      12      *16             unused
 341 *      13      *16             unused
 342 *      14      *16             unused
 343 *      15      *16             unused
 344 */
 345
 346static struct sound_unit *chains[SOUND_STEP];
 347
 348/**
 349 *      register_sound_special_device - register a special sound node
 350 *      @fops: File operations for the driver
 351 *      @unit: Unit number to allocate
 352 *      @dev: device pointer
 353 *
 354 *      Allocate a special sound device by minor number from the sound
 355 *      subsystem.
 356 *
 357 *      Return: The allocated number is returned on success. On failure,
 358 *      a negative error code is returned.
 359 */
 360 
 361int register_sound_special_device(const struct file_operations *fops, int unit,
 362                                  struct device *dev)
 363{
 364        const int chain = unit % SOUND_STEP;
 365        int max_unit = 256;
 366        const char *name;
 367        char _name[16];
 368
 369        switch (chain) {
 370            case 0:
 371                name = "mixer";
 372                break;
 373            case 1:
 374                name = "sequencer";
 375                if (unit >= SOUND_STEP)
 376                        goto __unknown;
 377                max_unit = unit + 1;
 378                break;
 379            case 2:
 380                name = "midi";
 381                break;
 382            case 3:
 383                name = "dsp";
 384                break;
 385            case 4:
 386                name = "audio";
 387                break;
 388            case 5:
 389                name = "dspW";
 390                break;
 391            case 8:
 392                name = "sequencer2";
 393                if (unit >= SOUND_STEP)
 394                        goto __unknown;
 395                max_unit = unit + 1;
 396                break;
 397            case 9:
 398                name = "dmmidi";
 399                break;
 400            case 10:
 401                name = "dmfm";
 402                break;
 403            case 12:
 404                name = "adsp";
 405                break;
 406            case 13:
 407                name = "amidi";
 408                break;
 409            case 14:
 410                name = "admmidi";
 411                break;
 412            default:
 413                {
 414                    __unknown:
 415                        sprintf(_name, "unknown%d", chain);
 416                        if (unit >= SOUND_STEP)
 417                                strcat(_name, "-");
 418                        name = _name;
 419                }
 420                break;
 421        }
 422        return sound_insert_unit(&chains[chain], fops, -1, unit, max_unit,
 423                                 name, 0600, dev);
 424}
 425 
 426EXPORT_SYMBOL(register_sound_special_device);
 427
 428int register_sound_special(const struct file_operations *fops, int unit)
 429{
 430        return register_sound_special_device(fops, unit, NULL);
 431}
 432
 433EXPORT_SYMBOL(register_sound_special);
 434
 435/**
 436 *      register_sound_mixer - register a mixer device
 437 *      @fops: File operations for the driver
 438 *      @dev: Unit number to allocate
 439 *
 440 *      Allocate a mixer device. Unit is the number of the mixer requested.
 441 *      Pass -1 to request the next free mixer unit.
 442 *
 443 *      Return: On success, the allocated number is returned. On failure,
 444 *      a negative error code is returned.
 445 */
 446
 447int register_sound_mixer(const struct file_operations *fops, int dev)
 448{
 449        return sound_insert_unit(&chains[0], fops, dev, 0, 128,
 450                                 "mixer", 0600, NULL);
 451}
 452
 453EXPORT_SYMBOL(register_sound_mixer);
 454
 455/**
 456 *      register_sound_midi - register a midi device
 457 *      @fops: File operations for the driver
 458 *      @dev: Unit number to allocate
 459 *
 460 *      Allocate a midi device. Unit is the number of the midi device requested.
 461 *      Pass -1 to request the next free midi unit.
 462 *
 463 *      Return: On success, the allocated number is returned. On failure,
 464 *      a negative error code is returned.
 465 */
 466
 467int register_sound_midi(const struct file_operations *fops, int dev)
 468{
 469        return sound_insert_unit(&chains[2], fops, dev, 2, 130,
 470                                 "midi", S_IRUSR | S_IWUSR, NULL);
 471}
 472
 473EXPORT_SYMBOL(register_sound_midi);
 474
 475/*
 476 *      DSP's are registered as a triple. Register only one and cheat
 477 *      in open - see below.
 478 */
 479 
 480/**
 481 *      register_sound_dsp - register a DSP device
 482 *      @fops: File operations for the driver
 483 *      @dev: Unit number to allocate
 484 *
 485 *      Allocate a DSP device. Unit is the number of the DSP requested.
 486 *      Pass -1 to request the next free DSP unit.
 487 *
 488 *      This function allocates both the audio and dsp device entries together
 489 *      and will always allocate them as a matching pair - eg dsp3/audio3
 490 *
 491 *      Return: On success, the allocated number is returned. On failure,
 492 *      a negative error code is returned.
 493 */
 494
 495int register_sound_dsp(const struct file_operations *fops, int dev)
 496{
 497        return sound_insert_unit(&chains[3], fops, dev, 3, 131,
 498                                 "dsp", 0600, NULL);
 499}
 500
 501EXPORT_SYMBOL(register_sound_dsp);
 502
 503/**
 504 *      unregister_sound_special - unregister a special sound device
 505 *      @unit: unit number to allocate
 506 *
 507 *      Release a sound device that was allocated with
 508 *      register_sound_special(). The unit passed is the return value from
 509 *      the register function.
 510 */
 511
 512
 513void unregister_sound_special(int unit)
 514{
 515        sound_remove_unit(&chains[unit % SOUND_STEP], unit);
 516}
 517 
 518EXPORT_SYMBOL(unregister_sound_special);
 519
 520/**
 521 *      unregister_sound_mixer - unregister a mixer
 522 *      @unit: unit number to allocate
 523 *
 524 *      Release a sound device that was allocated with register_sound_mixer().
 525 *      The unit passed is the return value from the register function.
 526 */
 527
 528void unregister_sound_mixer(int unit)
 529{
 530        sound_remove_unit(&chains[0], unit);
 531}
 532
 533EXPORT_SYMBOL(unregister_sound_mixer);
 534
 535/**
 536 *      unregister_sound_midi - unregister a midi device
 537 *      @unit: unit number to allocate
 538 *
 539 *      Release a sound device that was allocated with register_sound_midi().
 540 *      The unit passed is the return value from the register function.
 541 */
 542
 543void unregister_sound_midi(int unit)
 544{
 545        sound_remove_unit(&chains[2], unit);
 546}
 547
 548EXPORT_SYMBOL(unregister_sound_midi);
 549
 550/**
 551 *      unregister_sound_dsp - unregister a DSP device
 552 *      @unit: unit number to allocate
 553 *
 554 *      Release a sound device that was allocated with register_sound_dsp().
 555 *      The unit passed is the return value from the register function.
 556 *
 557 *      Both of the allocated units are released together automatically.
 558 */
 559
 560void unregister_sound_dsp(int unit)
 561{
 562        sound_remove_unit(&chains[3], unit);
 563}
 564
 565
 566EXPORT_SYMBOL(unregister_sound_dsp);
 567
 568static struct sound_unit *__look_for_unit(int chain, int unit)
 569{
 570        struct sound_unit *s;
 571        
 572        s=chains[chain];
 573        while(s && s->unit_minor <= unit)
 574        {
 575                if(s->unit_minor==unit)
 576                        return s;
 577                s=s->next;
 578        }
 579        return NULL;
 580}
 581
 582static int soundcore_open(struct inode *inode, struct file *file)
 583{
 584        int chain;
 585        int unit = iminor(inode);
 586        struct sound_unit *s;
 587        const struct file_operations *new_fops = NULL;
 588
 589        chain=unit&0x0F;
 590        if(chain==4 || chain==5)        /* dsp/audio/dsp16 */
 591        {
 592                unit&=0xF0;
 593                unit|=3;
 594                chain=3;
 595        }
 596        
 597        spin_lock(&sound_loader_lock);
 598        s = __look_for_unit(chain, unit);
 599        if (s)
 600                new_fops = fops_get(s->unit_fops);
 601        if (preclaim_oss && !new_fops) {
 602                spin_unlock(&sound_loader_lock);
 603
 604                /*
 605                 *  Please, don't change this order or code.
 606                 *  For ALSA slot means soundcard and OSS emulation code
 607                 *  comes as add-on modules which aren't depend on
 608                 *  ALSA toplevel modules for soundcards, thus we need
 609                 *  load them at first.   [Jaroslav Kysela <perex@jcu.cz>]
 610                 */
 611                request_module("sound-slot-%i", unit>>4);
 612                request_module("sound-service-%i-%i", unit>>4, chain);
 613
 614                /*
 615                 * sound-slot/service-* module aliases are scheduled
 616                 * for removal in favor of the standard char-major-*
 617                 * module aliases.  For the time being, generate both
 618                 * the legacy and standard module aliases to ease
 619                 * transition.
 620                 */
 621                if (request_module("char-major-%d-%d", SOUND_MAJOR, unit) > 0)
 622                        request_module("char-major-%d", SOUND_MAJOR);
 623
 624                spin_lock(&sound_loader_lock);
 625                s = __look_for_unit(chain, unit);
 626                if (s)
 627                        new_fops = fops_get(s->unit_fops);
 628        }
 629        spin_unlock(&sound_loader_lock);
 630        if (new_fops) {
 631                /*
 632                 * We rely upon the fact that we can't be unloaded while the
 633                 * subdriver is there.
 634                 */
 635                int err = 0;
 636                replace_fops(file, new_fops);
 637
 638                if (file->f_op->open)
 639                        err = file->f_op->open(inode,file);
 640
 641                return err;
 642        }
 643        return -ENODEV;
 644}
 645
 646MODULE_ALIAS_CHARDEV_MAJOR(SOUND_MAJOR);
 647
 648static void cleanup_oss_soundcore(void)
 649{
 650        /* We have nothing to really do here - we know the lists must be
 651           empty */
 652        unregister_chrdev(SOUND_MAJOR, "sound");
 653}
 654
 655static int __init init_oss_soundcore(void)
 656{
 657        if (preclaim_oss &&
 658            register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops) == -1) {
 659                printk(KERN_ERR "soundcore: sound device already in use.\n");
 660                return -EBUSY;
 661        }
 662
 663        return 0;
 664}
 665
 666#endif /* CONFIG_SOUND_OSS_CORE */
 667