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;
  60 
  61   for (l = 0; l < 256, s[l]; l++);      /*
  62                                          * l=strlen(s);
  63                                          */
  64 
  65   if (status_len + l >= 4000)
  66     return 0;
  67 
  68   memcpy (&status_buf[status_len], s, l);
  69   status_len += l;
  70 
  71   return 1;
  72 }
  73 
  74 static int
  75 put_status_int (unsigned int val, int radix)
     /* [previous][next][first][last][top][bottom][index][help] */
  76 {
  77   int             l, v;
  78 
  79   static char     hx[] = "0123456789abcdef";
  80   char            buf[11];
  81 
  82   if (!val)
  83     return put_status ("0");
  84 
  85   l = 0;
  86   buf[10] = 0;
  87 
  88   while (val)
  89     {
  90       v = val % radix;
  91       val = val / radix;
  92 
  93       buf[9 - l] = hx[v];
  94       l++;
  95     }
  96 
  97   if (status_len + l >= 4000)
  98     return 0;
  99 
 100   memcpy (&status_buf[status_len], &buf[10 - l], l);
 101   status_len += l;
 102 
 103   return 1;
 104 }
 105 
 106 static void
 107 init_status (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 108 {
 109   /*
 110    * Write the status information to the status_buf and update status_len.
 111    * There is a limit of 4000 bytes for the data.
 112    */
 113 
 114   int             i;
 115 
 116   status_ptr = 0;
 117 
 118 #ifdef SOUND_UNAME_A
 119   put_status ("VoxWare Sound Driver:" SOUND_VERSION_STRING
 120               " (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY ",\n"
 121               SOUND_UNAME_A ")"
 122               "\n");
 123 #else
 124   put_status ("VoxWare Sound Driver:" SOUND_VERSION_STRING
 125               " (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY "@"
 126               SOUND_CONFIG_HOST "." SOUND_CONFIG_DOMAIN ")"
 127               "\n");
 128 #endif
 129 
 130   if (!put_status ("Config options: "))
 131     return;
 132   if (!put_status_int (SELECTED_SOUND_OPTIONS, 16))
 133     return;
 134 
 135   if (!put_status ("\n\nInstalled drivers: \n"))
 136     return;
 137 
 138   for (i = 0; i < (num_sound_drivers - 1); i++)
 139     {
 140       if (!put_status ("Type "))
 141         return;
 142       if (!put_status_int (sound_drivers[i].card_type, 10))
 143         return;
 144       if (!put_status (": "))
 145         return;
 146       if (!put_status (sound_drivers[i].name))
 147         return;
 148 
 149       if (!put_status ("\n"))
 150         return;
 151     }
 152 
 153   if (!put_status ("\n\nCard config: \n"))
 154     return;
 155 
 156   for (i = 0; i < (num_sound_cards - 1); i++)
 157     {
 158       int             drv;
 159 
 160       if (!snd_installed_cards[i].enabled)
 161         if (!put_status ("("))
 162           return;
 163 
 164       /*
 165        * if (!put_status_int(snd_installed_cards[i].card_type, 10)) return;
 166        * if (!put_status (": ")) return;
 167        */
 168 
 169       if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) != -1)
 170         if (!put_status (sound_drivers[drv].name))
 171           return;
 172 
 173       if (!put_status (" at 0x"))
 174         return;
 175       if (!put_status_int (snd_installed_cards[i].config.io_base, 16))
 176         return;
 177       if (!put_status (" irq "))
 178         return;
 179       if (!put_status_int (snd_installed_cards[i].config.irq, 10))
 180         return;
 181       if (!put_status (" drq "))
 182         return;
 183       if (!put_status_int (snd_installed_cards[i].config.dma, 10))
 184         return;
 185 
 186       if (!snd_installed_cards[i].enabled)
 187         if (!put_status (")"))
 188           return;
 189 
 190       if (!put_status ("\n"))
 191         return;
 192     }
 193 
 194 #ifdef EXCLUDE_AUDIO
 195   if (!put_status ("\nAudio devices: NOT ENABLED IN CONFIG\n"))
 196     return;
 197 #else
 198   if (!put_status ("\nAudio devices:\n"))
 199     return;
 200 
 201   for (i = 0; i < num_audiodevs; i++)
 202     {
 203       if (!put_status_int (i, 10))
 204         return;
 205       if (!put_status (": "))
 206         return;
 207       if (!put_status (audio_devs[i]->name))
 208         return;
 209       if (!put_status ("\n"))
 210         return;
 211     }
 212 #endif
 213 
 214 #ifdef EXCLUDE_SEQUENCER
 215   if (!put_status ("\nSynth devices: NOT ENABLED IN CONFIG\n"))
 216     return;
 217 #else
 218   if (!put_status ("\nSynth devices:\n"))
 219     return;
 220 
 221   for (i = 0; i < num_synths; i++)
 222     {
 223       if (!put_status_int (i, 10))
 224         return;
 225       if (!put_status (": "))
 226         return;
 227       if (!put_status (synth_devs[i]->info->name))
 228         return;
 229       if (!put_status ("\n"))
 230         return;
 231     }
 232 #endif
 233 
 234 #ifdef EXCLUDE_MIDI
 235   if (!put_status ("\nMidi devices: NOT ENABLED IN CONFIG\n"))
 236     return;
 237 #else
 238   if (!put_status ("\nMidi devices:\n"))
 239     return;
 240 
 241   for (i = 0; i < num_midis; i++)
 242     {
 243       if (!put_status_int (i, 10))
 244         return;
 245       if (!put_status (": "))
 246         return;
 247       if (!put_status (midi_devs[i]->info.name))
 248         return;
 249       if (!put_status ("\n"))
 250         return;
 251     }
 252 #endif
 253 
 254   if (!put_status ("\nTimers:\n"))
 255     return;
 256 
 257   for (i = 0; i < num_sound_timers; i++)
 258     {
 259       if (!put_status_int (i, 10))
 260         return;
 261       if (!put_status (": "))
 262         return;
 263       if (!put_status (sound_timer_devs[i]->info.name))
 264         return;
 265       if (!put_status ("\n"))
 266         return;
 267     }
 268 
 269   if (!put_status ("\nMixers:\n"))
 270     return;
 271 
 272   for (i = 0; i < num_mixers; i++)
 273     {
 274       if (!put_status_int (i, 10))
 275         return;
 276       if (!put_status (": "))
 277         return;
 278       if (!put_status (mixer_devs[i]->name))
 279         return;
 280       if (!put_status ("\n"))
 281         return;
 282     }
 283 }
 284 
 285 static int
 286 read_status (snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 287 {
 288   /*
 289    * Return at most 'count' bytes from the status_buf.
 290    */
 291   int             l, c;
 292 
 293   l = count;
 294   c = status_len - status_ptr;
 295 
 296   if (l > c)
 297     l = c;
 298   if (l <= 0)
 299     return 0;
 300 
 301   COPY_TO_USER (buf, 0, &status_buf[status_ptr], l);
 302   status_ptr += l;
 303 
 304   return l;
 305 }
 306 
 307 int
 308 sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 309 {
 310   DEB (printk ("sound_read_sw(dev=%d, count=%d)\n", dev, count));
 311 
 312   switch (dev & 0x0f)
 313     {
 314     case SND_DEV_STATUS:
 315       return read_status (buf, count);
 316       break;
 317 
 318     case SND_DEV_DSP:
 319     case SND_DEV_DSP16:
 320     case SND_DEV_AUDIO:
 321       return audio_read (dev, file, buf, count);
 322       break;
 323 
 324     case SND_DEV_SEQ:
 325     case SND_DEV_SEQ2:
 326       return sequencer_read (dev, file, buf, count);
 327       break;
 328 
 329 #ifndef EXCLUDE_MIDI
 330     case SND_DEV_MIDIN:
 331       return MIDIbuf_read (dev, file, buf, count);
 332 #endif
 333 
 334     default:
 335       printk ("Sound: Undefined minor device %d\n", dev);
 336     }
 337 
 338   return RET_ERROR (EPERM);
 339 }
 340 
 341 int
 342 sound_write_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 343 {
 344 
 345   DEB (printk ("sound_write_sw(dev=%d, count=%d)\n", dev, count));
 346 
 347   switch (dev & 0x0f)
 348     {
 349 
 350     case SND_DEV_SEQ:
 351     case SND_DEV_SEQ2:
 352       return sequencer_write (dev, file, buf, count);
 353       break;
 354 
 355     case SND_DEV_DSP:
 356     case SND_DEV_DSP16:
 357     case SND_DEV_AUDIO:
 358       return audio_write (dev, file, buf, count);
 359       break;
 360 
 361 #ifndef EXCLUDE_MIDI
 362     case SND_DEV_MIDIN:
 363       return MIDIbuf_write (dev, file, buf, count);
 364 #endif
 365 
 366     default:
 367       return RET_ERROR (EPERM);
 368     }
 369 
 370   return count;
 371 }
 372 
 373 int
 374 sound_open_sw (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 375 {
 376   int             retval;
 377 
 378   DEB (printk ("sound_open_sw(dev=%d) : usecount=%d\n", dev, sbc_devices[dev].usecount));
 379 
 380   if ((dev >= SND_NDEVS) || (dev < 0))
 381     {
 382       printk ("Invalid minor device %d\n", dev);
 383       return RET_ERROR (ENXIO);
 384     }
 385 
 386   switch (dev & 0x0f)
 387     {
 388     case SND_DEV_STATUS:
 389       if (status_busy)
 390         return RET_ERROR (EBUSY);
 391       status_busy = 1;
 392       if ((status_buf = (char *) KERNEL_MALLOC (4000)) == NULL)
 393         return RET_ERROR (EIO);
 394       status_len = status_ptr = 0;
 395       init_status ();
 396       break;
 397 
 398     case SND_DEV_CTL:
 399       return 0;
 400       break;
 401 
 402     case SND_DEV_SEQ:
 403     case SND_DEV_SEQ2:
 404       if ((retval = sequencer_open (dev, file)) < 0)
 405         return retval;
 406       break;
 407 
 408 #ifndef EXCLUDE_MIDI
 409     case SND_DEV_MIDIN:
 410       if ((retval = MIDIbuf_open (dev, file)) < 0)
 411         return retval;
 412       break;
 413 #endif
 414 
 415     case SND_DEV_DSP:
 416     case SND_DEV_DSP16:
 417     case SND_DEV_AUDIO:
 418       if ((retval = audio_open (dev, file)) < 0)
 419         return retval;
 420       break;
 421 
 422     default:
 423       printk ("Invalid minor device %d\n", dev);
 424       return RET_ERROR (ENXIO);
 425     }
 426 
 427   sbc_devices[dev].usecount++;
 428   in_use++;
 429 
 430   return 0;
 431 }
 432 
 433 void
 434 sound_release_sw (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 435 {
 436 
 437   DEB (printk ("sound_release_sw(dev=%d)\n", dev));
 438 
 439   switch (dev & 0x0f)
 440     {
 441     case SND_DEV_STATUS:
 442       if (status_buf)
 443         KERNEL_FREE (status_buf);
 444       status_buf = NULL;
 445       status_busy = 0;
 446       break;
 447 
 448     case SND_DEV_CTL:
 449       break;
 450 
 451     case SND_DEV_SEQ:
 452     case SND_DEV_SEQ2:
 453       sequencer_release (dev, file);
 454       break;
 455 
 456 #ifndef EXCLUDE_MIDI
 457     case SND_DEV_MIDIN:
 458       MIDIbuf_release (dev, file);
 459       break;
 460 #endif
 461 
 462     case SND_DEV_DSP:
 463     case SND_DEV_DSP16:
 464     case SND_DEV_AUDIO:
 465       audio_release (dev, file);
 466       break;
 467 
 468     default:
 469       printk ("Sound error: Releasing unknown device 0x%02x\n", dev);
 470     }
 471 
 472   sbc_devices[dev].usecount--;
 473   in_use--;
 474 }
 475 
 476 int
 477 sound_ioctl_sw (int dev, struct fileinfo *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 478                 unsigned int cmd, unsigned long arg)
 479 {
 480   DEB (printk ("sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
 481 
 482   if (((cmd >> 8) & 0xff) == 'M' && num_mixers > 0)     /* Mixer ioctl */
 483     if ((dev & 0x0f) != SND_DEV_CTL)
 484       {
 485         int             dtype = dev & 0x0f;
 486         int             mixdev;
 487 
 488         switch (dtype)
 489           {
 490           case SND_DEV_DSP:
 491           case SND_DEV_DSP16:
 492           case SND_DEV_AUDIO:
 493             mixdev = audio_devs[dev >> 4]->mixer_dev;
 494             if (mixdev < 0 || mixdev >= num_mixers)
 495               return RET_ERROR (ENXIO);
 496             return mixer_devs[mixdev]->ioctl (mixdev, cmd, arg);
 497             break;
 498 
 499           default:
 500             return mixer_devs[0]->ioctl (0, cmd, arg);
 501           }
 502       }
 503 
 504   switch (dev & 0x0f)
 505     {
 506 
 507     case SND_DEV_CTL:
 508 
 509       if (!num_mixers)
 510         return RET_ERROR (ENXIO);
 511 
 512       dev = dev >> 4;
 513 
 514       if (dev >= num_mixers)
 515         return RET_ERROR (ENXIO);
 516 
 517       return mixer_devs[dev]->ioctl (dev, cmd, arg);
 518       break;
 519 
 520     case SND_DEV_SEQ:
 521     case SND_DEV_SEQ2:
 522       return sequencer_ioctl (dev, file, cmd, arg);
 523       break;
 524 
 525     case SND_DEV_DSP:
 526     case SND_DEV_DSP16:
 527     case SND_DEV_AUDIO:
 528       return audio_ioctl (dev, file, cmd, arg);
 529       break;
 530 
 531 #ifndef EXCLUDE_MIDI
 532     case SND_DEV_MIDIN:
 533       return MIDIbuf_ioctl (dev, file, cmd, arg);
 534       break;
 535 #endif
 536 
 537     default:
 538       return RET_ERROR (EPERM);
 539       break;
 540     }
 541 
 542   return RET_ERROR (EPERM);
 543 }
 544 
 545 #endif

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