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        device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor),
 174                      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                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 *      unregister_sound_special - unregister a special sound device
 370 *      @unit: unit number to allocate
 371 *
 372 *      Release a sound device that was allocated with
 373 *      register_sound_special(). The unit passed is the return value from
 374 *      the register function.
 375 */
 376
 377
 378void unregister_sound_special(int unit)
 379{
 380        sound_remove_unit(&chains[unit % SOUND_STEP], unit);
 381}
 382 
 383EXPORT_SYMBOL(unregister_sound_special);
 384
 385/**
 386 *      unregister_sound_mixer - unregister a mixer
 387 *      @unit: unit number to allocate
 388 *
 389 *      Release a sound device that was allocated with register_sound_mixer().
 390 *      The unit passed is the return value from the register function.
 391 */
 392
 393void unregister_sound_mixer(int unit)
 394{
 395        sound_remove_unit(&chains[0], unit);
 396}
 397
 398EXPORT_SYMBOL(unregister_sound_mixer);
 399
 400/**
 401 *      unregister_sound_midi - unregister a midi device
 402 *      @unit: unit number to allocate
 403 *
 404 *      Release a sound device that was allocated with register_sound_midi().
 405 *      The unit passed is the return value from the register function.
 406 */
 407
 408void unregister_sound_midi(int unit)
 409{
 410        return sound_remove_unit(&chains[2], unit);
 411}
 412
 413EXPORT_SYMBOL(unregister_sound_midi);
 414
 415/**
 416 *      unregister_sound_dsp - unregister a DSP device
 417 *      @unit: unit number to allocate
 418 *
 419 *      Release a sound device that was allocated with register_sound_dsp().
 420 *      The unit passed is the return value from the register function.
 421 *
 422 *      Both of the allocated units are released together automatically.
 423 */
 424
 425void unregister_sound_dsp(int unit)
 426{
 427        return sound_remove_unit(&chains[3], unit);
 428}
 429
 430
 431EXPORT_SYMBOL(unregister_sound_dsp);
 432
 433/*
 434 *      Now our file operations
 435 */
 436
 437static int soundcore_open(struct inode *, struct file *);
 438
 439static const struct file_operations soundcore_fops=
 440{
 441        /* We must have an owner or the module locking fails */
 442        .owner  = THIS_MODULE,
 443        .open   = soundcore_open,
 444};
 445
 446static struct sound_unit *__look_for_unit(int chain, int unit)
 447{
 448        struct sound_unit *s;
 449        
 450        s=chains[chain];
 451        while(s && s->unit_minor <= unit)
 452        {
 453                if(s->unit_minor==unit)
 454                        return s;
 455                s=s->next;
 456        }
 457        return NULL;
 458}
 459
 460int soundcore_open(struct inode *inode, struct file *file)
 461{
 462        int chain;
 463        int unit = iminor(inode);
 464        struct sound_unit *s;
 465        const struct file_operations *new_fops = NULL;
 466
 467        chain=unit&0x0F;
 468        if(chain==4 || chain==5)        /* dsp/audio/dsp16 */
 469        {
 470                unit&=0xF0;
 471                unit|=3;
 472                chain=3;
 473        }
 474        
 475        spin_lock(&sound_loader_lock);
 476        s = __look_for_unit(chain, unit);
 477        if (s)
 478                new_fops = fops_get(s->unit_fops);
 479        if (!new_fops) {
 480                spin_unlock(&sound_loader_lock);
 481                /*
 482                 *  Please, don't change this order or code.
 483                 *  For ALSA slot means soundcard and OSS emulation code
 484                 *  comes as add-on modules which aren't depend on
 485                 *  ALSA toplevel modules for soundcards, thus we need
 486                 *  load them at first.   [Jaroslav Kysela <perex@jcu.cz>]
 487                 */
 488                request_module("sound-slot-%i", unit>>4);
 489                request_module("sound-service-%i-%i", unit>>4, chain);
 490                spin_lock(&sound_loader_lock);
 491                s = __look_for_unit(chain, unit);
 492                if (s)
 493                        new_fops = fops_get(s->unit_fops);
 494        }
 495        if (new_fops) {
 496                /*
 497                 * We rely upon the fact that we can't be unloaded while the
 498                 * subdriver is there, so if ->open() is successful we can
 499                 * safely drop the reference counter and if it is not we can
 500                 * revert to old ->f_op. Ugly, indeed, but that's the cost of
 501                 * switching ->f_op in the first place.
 502                 */
 503                int err = 0;
 504                const struct file_operations *old_fops = file->f_op;
 505                file->f_op = new_fops;
 506                spin_unlock(&sound_loader_lock);
 507                if(file->f_op->open)
 508                        err = file->f_op->open(inode,file);
 509                if (err) {
 510                        fops_put(file->f_op);
 511                        file->f_op = fops_get(old_fops);
 512                }
 513                fops_put(old_fops);
 514                return err;
 515        }
 516        spin_unlock(&sound_loader_lock);
 517        return -ENODEV;
 518}
 519
 520MODULE_DESCRIPTION("Core sound module");
 521MODULE_AUTHOR("Alan Cox");
 522MODULE_LICENSE("GPL");
 523MODULE_ALIAS_CHARDEV_MAJOR(SOUND_MAJOR);
 524
 525static void __exit cleanup_soundcore(void)
 526{
 527        /* We have nothing to really do here - we know the lists must be
 528           empty */
 529        unregister_chrdev(SOUND_MAJOR, "sound");
 530        class_destroy(sound_class);
 531}
 532
 533static int __init init_soundcore(void)
 534{
 535        if (register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops)==-1) {
 536                printk(KERN_ERR "soundcore: sound device already in use.\n");
 537                return -EBUSY;
 538        }
 539        sound_class = class_create(THIS_MODULE, "sound");
 540        if (IS_ERR(sound_class))
 541                return PTR_ERR(sound_class);
 542
 543        return 0;
 544}
 545
 546module_init(init_soundcore);
 547module_exit(cleanup_soundcore);
 548