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