root/drivers/sound/sound_switch.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. put_status
  2. put_status_int
  3. init_status
  4. read_status
  5. sound_read_sw
  6. sound_write_sw
  7. sound_open_sw
  8. sound_release_sw
  9. sound_ioctl_sw

   1 /*
   2  * sound/sound_switch.c
   3  *
   4  * The system call switch
   5  *
   6  * Copyright by Hannu Savolainen 1993
   7  *
   8  * Redistribution and use in source and binary forms, with or without
   9  * modification, are permitted provided that the following conditions are
  10  * met: 1. Redistributions of source code must retain the above copyright
  11  * notice, this list of conditions and the following disclaimer. 2.
  12  * Redistributions in binary form must reproduce the above copyright notice,
  13  * this list of conditions and the following disclaimer in the documentation
  14  * and/or other materials provided with the distribution.
  15  *
  16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
  17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  23  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26  * SUCH DAMAGE.
  27  *
  28  */
  29 
  30 #include "sound_config.h"
  31 
  32 #ifdef CONFIGURE_SOUNDCARD
  33 
  34 struct sbc_device
  35   {
  36     int             usecount;
  37   };
  38 
  39 static struct sbc_device sbc_devices[SND_NDEVS] =
  40 {
  41   {0}};
  42 
  43 static int      in_use = 0;     /*
  44 
  45 
  46                                  * *  * * Total # of open device files
  47                                  * (excluding * * * minor 0)   */
  48 
  49 /*
  50  * /dev/sndstatus -device
  51  */
  52 static char    *status_buf = NULL;
  53 static int      status_len, status_ptr;
  54 static int      status_busy = 0;
  55 
  56 static int
  57 put_status (char *s)
     /* [previous][next][first][last][top][bottom][index][help] */
  58 {
  59   int             l = strnlen (s, 256);
  60 
  61   if (status_len + l >= 4000)
  62     return 0;
  63 
  64   memcpy (&status_buf[status_len], s, l);
  65   status_len += l;
  66 
  67   return 1;
  68 }
  69 
  70 static int
  71 put_status_int (unsigned int val, int radix)
     /* [previous][next][first][last][top][bottom][index][help] */
  72 {
  73   int             l, v;
  74 
  75   static char     hx[] = "0123456789abcdef";
  76   char            buf[11];
  77 
  78   if (!val)
  79     return put_status ("0");
  80 
  81   l = 0;
  82   buf[10] = 0;
  83 
  84   while (val)
  85     {
  86       v = val % radix;
  87       val = val / radix;
  88 
  89       buf[9 - l] = hx[v];
  90       l++;
  91     }
  92 
  93   if (status_len + l >= 4000)
  94     return 0;
  95 
  96   memcpy (&status_buf[status_len], &buf[10 - l], l);
  97   status_len += l;
  98 
  99   return 1;
 100 }
 101 
 102 static void
 103 init_status (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 104 {
 105   /*
 106    * Write the status information to the status_buf and update status_len.
 107    * There is a limit of 4000 bytes for the data.
 108    */
 109 
 110   int             i;
 111 
 112   status_ptr = 0;
 113 
 114 #ifdef SOUND_UNAME_A
 115   put_status ("VoxWare Sound Driver:" SOUND_VERSION_STRING
 116               " (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY ",\n"
 117               SOUND_UNAME_A ")"
 118               "\n");
 119 #else
 120   put_status ("VoxWare Sound Driver:" SOUND_VERSION_STRING
 121               " (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY "@"
 122               SOUND_CONFIG_HOST "." SOUND_CONFIG_DOMAIN ")"
 123               "\n");
 124 #endif
 125 
 126   if (!put_status ("Config options: "))
 127     return;
 128   if (!put_status_int (SELECTED_SOUND_OPTIONS, 16))
 129     return;
 130 
 131   if (!put_status ("\n\nInstalled drivers: \n"))
 132     return;
 133 
 134   for (i = 0; i < (num_sound_drivers - 1); i++)
 135     {
 136       if (!put_status ("Type "))
 137         return;
 138       if (!put_status_int (sound_drivers[i].card_type, 10))
 139         return;
 140       if (!put_status (": "))
 141         return;
 142       if (!put_status (sound_drivers[i].name))
 143         return;
 144 
 145       if (!put_status ("\n"))
 146         return;
 147     }
 148 
 149   if (!put_status ("\n\nCard config: \n"))
 150     return;
 151 
 152   for (i = 0; i < (num_sound_cards - 1); i++)
 153     {
 154       int             drv, tmp;
 155 
 156       if (!snd_installed_cards[i].enabled)
 157         if (!put_status ("("))
 158           return;
 159 
 160       /*
 161        * if (!put_status_int(snd_installed_cards[i].card_type, 10)) return;
 162        * if (!put_status (": ")) return;
 163        */
 164 
 165       if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) != -1)
 166         if (!put_status (sound_drivers[drv].name))
 167           return;
 168 
 169       if (!put_status (" at 0x"))
 170         return;
 171       if (!put_status_int (snd_installed_cards[i].config.io_base, 16))
 172         return;
 173 
 174       if (!put_status (" irq "))
 175         return;
 176       tmp = snd_installed_cards[i].config.irq;
 177       if (tmp < 0)
 178         tmp = -tmp;
 179       if (!put_status_int (tmp, 10))
 180         return;
 181 
 182       if (snd_installed_cards[i].config.dma != -1)
 183         {
 184           if (!put_status (" drq "))
 185             return;
 186           if (!put_status_int (snd_installed_cards[i].config.dma, 10))
 187             return;
 188           if (snd_installed_cards[i].config.dma2 != -1)
 189             {
 190               if (!put_status (","))
 191                 return;
 192               if (!put_status_int (snd_installed_cards[i].config.dma2, 10))
 193                 return;
 194             }
 195         }
 196 
 197       if (!snd_installed_cards[i].enabled)
 198         if (!put_status (")"))
 199           return;
 200 
 201       if (!put_status ("\n"))
 202         return;
 203     }
 204 
 205 #ifdef EXCLUDE_AUDIO
 206   if (!put_status ("\nAudio devices: NOT ENABLED IN CONFIG\n"))
 207     return;
 208 #else
 209   if (!put_status ("\nAudio devices:\n"))
 210     return;
 211 
 212   for (i = 0; i < num_audiodevs; i++)
 213     {
 214       if (!put_status_int (i, 10))
 215         return;
 216       if (!put_status (": "))
 217         return;
 218       if (!put_status (audio_devs[i]->name))
 219         return;
 220 
 221       if (audio_devs[i]->flags & DMA_DUPLEX)
 222         if (!put_status (" (DUPLEX)"))
 223           return;
 224 
 225       if (!put_status ("\n"))
 226         return;
 227     }
 228 #endif
 229 
 230 #ifdef EXCLUDE_SEQUENCER
 231   if (!put_status ("\nSynth devices: NOT ENABLED IN CONFIG\n"))
 232     return;
 233 #else
 234   if (!put_status ("\nSynth devices:\n"))
 235     return;
 236 
 237   for (i = 0; i < num_synths; i++)
 238     {
 239       if (!put_status_int (i, 10))
 240         return;
 241       if (!put_status (": "))
 242         return;
 243       if (!put_status (synth_devs[i]->info->name))
 244         return;
 245       if (!put_status ("\n"))
 246         return;
 247     }
 248 #endif
 249 
 250 #ifdef EXCLUDE_MIDI
 251   if (!put_status ("\nMidi devices: NOT ENABLED IN CONFIG\n"))
 252     return;
 253 #else
 254   if (!put_status ("\nMidi devices:\n"))
 255     return;
 256 
 257   for (i = 0; i < num_midis; i++)
 258     {
 259       if (!put_status_int (i, 10))
 260         return;
 261       if (!put_status (": "))
 262         return;
 263       if (!put_status (midi_devs[i]->info.name))
 264         return;
 265       if (!put_status ("\n"))
 266         return;
 267     }
 268 #endif
 269 
 270   if (!put_status ("\nTimers:\n"))
 271     return;
 272 
 273   for (i = 0; i < num_sound_timers; i++)
 274     {
 275       if (!put_status_int (i, 10))
 276         return;
 277       if (!put_status (": "))
 278         return;
 279       if (!put_status (sound_timer_devs[i]->info.name))
 280         return;
 281       if (!put_status ("\n"))
 282         return;
 283     }
 284 
 285   if (!put_status ("\nMixers:\n"))
 286     return;
 287 
 288   for (i = 0; i < num_mixers; i++)
 289     {
 290       if (!put_status_int (i, 10))
 291         return;
 292       if (!put_status (": "))
 293         return;
 294       if (!put_status (mixer_devs[i]->name))
 295         return;
 296       if (!put_status ("\n"))
 297         return;
 298     }
 299 }
 300 
 301 static int
 302 read_status (snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 303 {
 304   /*
 305    * Return at most 'count' bytes from the status_buf.
 306    */
 307   int             l, c;
 308 
 309   l = count;
 310   c = status_len - status_ptr;
 311 
 312   if (l > c)
 313     l = c;
 314   if (l <= 0)
 315     return 0;
 316 
 317   memcpy_tofs (&((buf)[0]), &status_buf[status_ptr], l);
 318   status_ptr += l;
 319 
 320   return l;
 321 }
 322 
 323 int
 324 sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 325 {
 326   DEB (printk ("sound_read_sw(dev=%d, count=%d)\n", dev, count));
 327 
 328   switch (dev & 0x0f)
 329     {
 330     case SND_DEV_STATUS:
 331       return read_status (buf, count);
 332       break;
 333 
 334     case SND_DEV_DSP:
 335     case SND_DEV_DSP16:
 336     case SND_DEV_AUDIO:
 337       return audio_read (dev, file, buf, count);
 338       break;
 339 
 340     case SND_DEV_SEQ:
 341     case SND_DEV_SEQ2:
 342       return sequencer_read (dev, file, buf, count);
 343       break;
 344 
 345 #ifndef EXCLUDE_MIDI
 346     case SND_DEV_MIDIN:
 347       return MIDIbuf_read (dev, file, buf, count);
 348 #endif
 349 
 350     default:
 351       printk ("Sound: Undefined minor device %d\n", dev);
 352     }
 353 
 354   return -EPERM;
 355 }
 356 
 357 int
 358 sound_write_sw (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 359 {
 360 
 361   DEB (printk ("sound_write_sw(dev=%d, count=%d)\n", dev, count));
 362 
 363   switch (dev & 0x0f)
 364     {
 365 
 366     case SND_DEV_SEQ:
 367     case SND_DEV_SEQ2:
 368       return sequencer_write (dev, file, buf, count);
 369       break;
 370 
 371     case SND_DEV_DSP:
 372     case SND_DEV_DSP16:
 373     case SND_DEV_AUDIO:
 374       return audio_write (dev, file, buf, count);
 375       break;
 376 
 377 #ifndef EXCLUDE_MIDI
 378     case SND_DEV_MIDIN:
 379       return MIDIbuf_write (dev, file, buf, count);
 380 #endif
 381 
 382     default:
 383       return -EPERM;
 384     }
 385 
 386   return count;
 387 }
 388 
 389 int
 390 sound_open_sw (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 391 {
 392   int             retval;
 393 
 394   DEB (printk ("sound_open_sw(dev=%d) : usecount=%d\n", dev, sbc_devices[dev].usecount));
 395 
 396   if ((dev >= SND_NDEVS) || (dev < 0))
 397     {
 398       printk ("Invalid minor device %d\n", dev);
 399       return -ENXIO;
 400     }
 401 
 402   switch (dev & 0x0f)
 403     {
 404     case SND_DEV_STATUS:
 405       if (status_busy)
 406         return -EBUSY;
 407       status_busy = 1;
 408       if ((status_buf = (char *) kmalloc (4000, GFP_KERNEL)) == NULL)
 409         return -EIO;
 410       status_len = status_ptr = 0;
 411       init_status ();
 412       break;
 413 
 414     case SND_DEV_CTL:
 415       return 0;
 416       break;
 417 
 418     case SND_DEV_SEQ:
 419     case SND_DEV_SEQ2:
 420       if ((retval = sequencer_open (dev, file)) < 0)
 421         return retval;
 422       break;
 423 
 424 #ifndef EXCLUDE_MIDI
 425     case SND_DEV_MIDIN:
 426       if ((retval = MIDIbuf_open (dev, file)) < 0)
 427         return retval;
 428       break;
 429 #endif
 430 
 431     case SND_DEV_DSP:
 432     case SND_DEV_DSP16:
 433     case SND_DEV_AUDIO:
 434       if ((retval = audio_open (dev, file)) < 0)
 435         return retval;
 436       break;
 437 
 438     default:
 439       printk ("Invalid minor device %d\n", dev);
 440       return -ENXIO;
 441     }
 442 
 443   sbc_devices[dev].usecount++;
 444   in_use++;
 445 
 446   return 0;
 447 }
 448 
 449 void
 450 sound_release_sw (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 451 {
 452 
 453   DEB (printk ("sound_release_sw(dev=%d)\n", dev));
 454 
 455   switch (dev & 0x0f)
 456     {
 457     case SND_DEV_STATUS:
 458       if (status_buf)
 459         kfree (status_buf);
 460       status_buf = NULL;
 461       status_busy = 0;
 462       break;
 463 
 464     case SND_DEV_CTL:
 465       break;
 466 
 467     case SND_DEV_SEQ:
 468     case SND_DEV_SEQ2:
 469       sequencer_release (dev, file);
 470       break;
 471 
 472 #ifndef EXCLUDE_MIDI
 473     case SND_DEV_MIDIN:
 474       MIDIbuf_release (dev, file);
 475       break;
 476 #endif
 477 
 478     case SND_DEV_DSP:
 479     case SND_DEV_DSP16:
 480     case SND_DEV_AUDIO:
 481       audio_release (dev, file);
 482       break;
 483 
 484     default:
 485       printk ("Sound error: Releasing unknown device 0x%02x\n", dev);
 486     }
 487 
 488   sbc_devices[dev].usecount--;
 489   in_use--;
 490 }
 491 
 492 int
 493 sound_ioctl_sw (int dev, struct fileinfo *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 494                 unsigned int cmd, ioctl_arg arg)
 495 {
 496   DEB (printk ("sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
 497 
 498   if (((cmd >> 8) & 0xff) == 'M' && num_mixers > 0)     /* Mixer ioctl */
 499     if ((dev & 0x0f) != SND_DEV_CTL)
 500       {
 501         int             dtype = dev & 0x0f;
 502         int             mixdev;
 503 
 504         switch (dtype)
 505           {
 506           case SND_DEV_DSP:
 507           case SND_DEV_DSP16:
 508           case SND_DEV_AUDIO:
 509             mixdev = audio_devs[dev >> 4]->mixer_dev;
 510             if (mixdev < 0 || mixdev >= num_mixers)
 511               return -ENXIO;
 512             return mixer_devs[mixdev]->ioctl (mixdev, cmd, arg);
 513             break;
 514 
 515           default:
 516             return mixer_devs[0]->ioctl (0, cmd, arg);
 517           }
 518       }
 519 
 520   switch (dev & 0x0f)
 521     {
 522 
 523     case SND_DEV_CTL:
 524 
 525       if (!num_mixers)
 526         return -ENXIO;
 527 
 528       dev = dev >> 4;
 529 
 530       if (dev >= num_mixers)
 531         return -ENXIO;
 532 
 533       return mixer_devs[dev]->ioctl (dev, cmd, arg);
 534       break;
 535 
 536     case SND_DEV_SEQ:
 537     case SND_DEV_SEQ2:
 538       return sequencer_ioctl (dev, file, cmd, arg);
 539       break;
 540 
 541     case SND_DEV_DSP:
 542     case SND_DEV_DSP16:
 543     case SND_DEV_AUDIO:
 544       return audio_ioctl (dev, file, cmd, arg);
 545       break;
 546 
 547 #ifndef EXCLUDE_MIDI
 548     case SND_DEV_MIDIN:
 549       return MIDIbuf_ioctl (dev, file, cmd, arg);
 550       break;
 551 #endif
 552 
 553     default:
 554       return -EPERM;
 555       break;
 556     }
 557 
 558   return -EPERM;
 559 }
 560 
 561 #endif

/* [previous][next][first][last][top][bottom][index][help] */