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