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