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 handler
   5  */
   6 /*
   7  * Copyright by Hannu Savolainen 1993-1996
   8  *
   9  * Redistribution and use in source and binary forms, with or without
  10  * modification, are permitted provided that the following conditions are
  11  * met: 1. Redistributions of source code must retain the above copyright
  12  * notice, this list of conditions and the following disclaimer. 2.
  13  * Redistributions in binary form must reproduce the above copyright notice,
  14  * this list of conditions and the following disclaimer in the documentation
  15  * and/or other materials provided with the distribution.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
  18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  */
  29 #include <linux/config.h>
  30 
  31 
  32 #include "sound_config.h"
  33 
  34 struct sbc_device
  35   {
  36     int             usecount;
  37   };
  38 
  39 static int      in_use = 0;     /* Total # of open devices */
  40 
  41 /*
  42  * /dev/sndstatus -device
  43  */
  44 static char    *status_buf = NULL;
  45 static int      status_len, status_ptr;
  46 static int      status_busy = 0;
  47 
  48 static int
  49 put_status (char *s)
     /* [previous][next][first][last][top][bottom][index][help] */
  50 {
  51   int             l = strnlen (s, 256);
  52 
  53   if (status_len + l >= 4000)
  54     return 0;
  55 
  56   memcpy (&status_buf[status_len], s, l);
  57   status_len += l;
  58 
  59   return 1;
  60 }
  61 
  62 static int
  63 put_status_int (unsigned int val, int radix)
     /* [previous][next][first][last][top][bottom][index][help] */
  64 {
  65   int             l, v;
  66 
  67   static char     hx[] = "0123456789abcdef";
  68   char            buf[11];
  69 
  70   if (!val)
  71     return put_status ("0");
  72 
  73   l = 0;
  74   buf[10] = 0;
  75 
  76   while (val)
  77     {
  78       v = val % radix;
  79       val = val / radix;
  80 
  81       buf[9 - l] = hx[v];
  82       l++;
  83     }
  84 
  85   if (status_len + l >= 4000)
  86     return 0;
  87 
  88   memcpy (&status_buf[status_len], &buf[10 - l], l);
  89   status_len += l;
  90 
  91   return 1;
  92 }
  93 
  94 static void
  95 init_status (void)
     /* [previous][next][first][last][top][bottom][index][help] */
  96 {
  97   /*
  98    * Write the status information to the status_buf and update status_len.
  99    * There is a limit of 4000 bytes for the data.
 100    */
 101 
 102   int             i;
 103 
 104   status_ptr = 0;
 105 
 106 #ifdef SOUND_UNAME_A
 107   put_status ("Sound Driver:" SOUND_VERSION_STRING
 108               " (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY ",\n"
 109               SOUND_UNAME_A ")"
 110               "\n");
 111 #else
 112   put_status ("Sound Driver:" SOUND_VERSION_STRING
 113               " (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY "@"
 114               SOUND_CONFIG_HOST "." SOUND_CONFIG_DOMAIN ")"
 115               "\n");
 116 #endif
 117 
 118   if (!put_status ("Config options: "))
 119     return;
 120   if (!put_status_int (SELECTED_SOUND_OPTIONS, 16))
 121     return;
 122 
 123   if (!put_status ("\n\nInstalled drivers: \n"))
 124     return;
 125 
 126   for (i = 0; i < num_sound_drivers; i++)
 127     if (sound_drivers[i].card_type != 0)
 128       {
 129         if (!put_status ("Type "))
 130           return;
 131         if (!put_status_int (sound_drivers[i].card_type, 10))
 132           return;
 133         if (!put_status (": "))
 134           return;
 135         if (!put_status (sound_drivers[i].name))
 136           return;
 137 
 138         if (!put_status ("\n"))
 139           return;
 140       }
 141 
 142   if (!put_status ("\n\nCard config: \n"))
 143     return;
 144 
 145   for (i = 0; i < num_sound_cards; i++)
 146     if (snd_installed_cards[i].card_type != 0)
 147       {
 148         int             drv, tmp;
 149 
 150         if (!snd_installed_cards[i].enabled)
 151           if (!put_status ("("))
 152             return;
 153 
 154         /*
 155          * if (!put_status_int(snd_installed_cards[i].card_type, 10)) return;
 156          * if (!put_status (": ")) return;
 157          */
 158 
 159         if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) != -1)
 160           if (!put_status (sound_drivers[drv].name))
 161             return;
 162 
 163         if (!put_status (" at 0x"))
 164           return;
 165         if (!put_status_int (snd_installed_cards[i].config.io_base, 16))
 166           return;
 167 
 168         if (!put_status (" irq "))
 169           return;
 170         tmp = snd_installed_cards[i].config.irq;
 171         if (tmp < 0)
 172           tmp = -tmp;
 173         if (!put_status_int (tmp, 10))
 174           return;
 175 
 176         if (snd_installed_cards[i].config.dma != -1)
 177           {
 178             if (!put_status (" drq "))
 179               return;
 180             if (!put_status_int (snd_installed_cards[i].config.dma, 10))
 181               return;
 182             if (snd_installed_cards[i].config.dma2 != -1)
 183               {
 184                 if (!put_status (","))
 185                   return;
 186                 if (!put_status_int (snd_installed_cards[i].config.dma2, 10))
 187                   return;
 188               }
 189           }
 190 
 191         if (!snd_installed_cards[i].enabled)
 192           if (!put_status (")"))
 193             return;
 194 
 195         if (!put_status ("\n"))
 196           return;
 197       }
 198 
 199   if (!sound_started)
 200     {
 201       put_status ("\n\n***** Sound driver not started *****\n\n");
 202       return;
 203     }
 204 
 205 #ifndef CONFIG_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 #ifndef CONFIG_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 #ifndef CONFIG_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 (char *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, char *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 #ifdef CONFIG_AUDIO
 335     case SND_DEV_DSP:
 336     case SND_DEV_DSP16:
 337     case SND_DEV_AUDIO:
 338       return audio_read (dev, file, buf, count);
 339       break;
 340 #endif
 341 
 342 #ifdef CONFIG_SEQUENCER
 343     case SND_DEV_SEQ:
 344     case SND_DEV_SEQ2:
 345       return sequencer_read (dev, file, buf, count);
 346       break;
 347 #endif
 348 
 349 #ifdef CONFIG_MIDI
 350     case SND_DEV_MIDIN:
 351       return MIDIbuf_read (dev, file, buf, count);
 352 #endif
 353 
 354     default:
 355       printk ("Sound: Undefined minor device %d\n", dev);
 356     }
 357 
 358   return -EPERM;
 359 }
 360 
 361 int
 362 sound_write_sw (int dev, struct fileinfo *file, const char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 363 {
 364 
 365   DEB (printk ("sound_write_sw(dev=%d, count=%d)\n", dev, count));
 366 
 367   switch (dev & 0x0f)
 368     {
 369 
 370 #ifdef CONFIG_SEQUENCER
 371     case SND_DEV_SEQ:
 372     case SND_DEV_SEQ2:
 373       return sequencer_write (dev, file, buf, count);
 374       break;
 375 #endif
 376 
 377 #ifdef CONFIG_AUDIO
 378     case SND_DEV_DSP:
 379     case SND_DEV_DSP16:
 380     case SND_DEV_AUDIO:
 381       return audio_write (dev, file, buf, count);
 382       break;
 383 #endif
 384 
 385 #ifdef CONFIG_MIDI
 386     case SND_DEV_MIDIN:
 387       return MIDIbuf_write (dev, file, buf, count);
 388 #endif
 389 
 390     default:
 391       return -EPERM;
 392     }
 393 
 394   return count;
 395 }
 396 
 397 int
 398 sound_open_sw (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 399 {
 400   int             retval;
 401 
 402   DEB (printk ("sound_open_sw(dev=%d)\n", dev));
 403 
 404   if ((dev >= SND_NDEVS) || (dev < 0))
 405     {
 406       printk ("Invalid minor device %d\n", dev);
 407       return -ENXIO;
 408     }
 409 
 410   switch (dev & 0x0f)
 411     {
 412     case SND_DEV_STATUS:
 413       if (status_busy)
 414         return -EBUSY;
 415       status_busy = 1;
 416       if ((status_buf = (char *) kmalloc (4000, GFP_KERNEL)) == NULL)
 417         return -EIO;
 418       status_len = status_ptr = 0;
 419       init_status ();
 420       break;
 421 
 422     case SND_DEV_CTL:
 423       return 0;
 424       break;
 425 
 426 #ifdef CONFIG_SEQUENCER
 427     case SND_DEV_SEQ:
 428     case SND_DEV_SEQ2:
 429       if ((retval = sequencer_open (dev, file)) < 0)
 430         return retval;
 431       break;
 432 #endif
 433 
 434 #ifdef CONFIG_MIDI
 435     case SND_DEV_MIDIN:
 436       if ((retval = MIDIbuf_open (dev, file)) < 0)
 437         return retval;
 438       break;
 439 #endif
 440 
 441 #ifdef CONFIG_AUDIO
 442     case SND_DEV_DSP:
 443     case SND_DEV_DSP16:
 444     case SND_DEV_AUDIO:
 445       if ((retval = audio_open (dev, file)) < 0)
 446         return retval;
 447       break;
 448 #endif
 449 
 450     default:
 451       printk ("Invalid minor device %d\n", dev);
 452       return -ENXIO;
 453     }
 454 
 455   in_use++;
 456 
 457   return 0;
 458 }
 459 
 460 void
 461 sound_release_sw (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 462 {
 463 
 464   DEB (printk ("sound_release_sw(dev=%d)\n", dev));
 465 
 466   switch (dev & 0x0f)
 467     {
 468     case SND_DEV_STATUS:
 469       if (status_buf)
 470         kfree (status_buf);
 471       status_buf = NULL;
 472       status_busy = 0;
 473       break;
 474 
 475     case SND_DEV_CTL:
 476       break;
 477 
 478 #ifdef CONFIG_SEQUENCER
 479     case SND_DEV_SEQ:
 480     case SND_DEV_SEQ2:
 481       sequencer_release (dev, file);
 482       break;
 483 #endif
 484 
 485 #ifdef CONFIG_MIDI
 486     case SND_DEV_MIDIN:
 487       MIDIbuf_release (dev, file);
 488       break;
 489 #endif
 490 
 491 #ifdef CONFIG_AUDIO
 492     case SND_DEV_DSP:
 493     case SND_DEV_DSP16:
 494     case SND_DEV_AUDIO:
 495       audio_release (dev, file);
 496       break;
 497 #endif
 498 
 499     default:
 500       printk ("Sound error: Releasing unknown device 0x%02x\n", dev);
 501     }
 502   in_use--;
 503 }
 504 
 505 int
 506 sound_ioctl_sw (int dev, struct fileinfo *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 507                 unsigned int cmd, caddr_t arg)
 508 {
 509   DEB (printk ("sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
 510 
 511   if (((cmd >> 8) & 0xff) == 'M' && num_mixers > 0)     /* Mixer ioctl */
 512     if ((dev & 0x0f) != SND_DEV_CTL)
 513       {
 514         int             dtype = dev & 0x0f;
 515         int             mixdev;
 516 
 517         switch (dtype)
 518           {
 519 #ifdef CONFIG_AUDIO
 520           case SND_DEV_DSP:
 521           case SND_DEV_DSP16:
 522           case SND_DEV_AUDIO:
 523             mixdev = audio_devs[dev >> 4]->mixer_dev;
 524             if (mixdev < 0 || mixdev >= num_mixers)
 525               return -ENXIO;
 526             return mixer_devs[mixdev]->ioctl (mixdev, cmd, arg);
 527             break;
 528 #endif
 529 
 530           default:
 531             return mixer_devs[0]->ioctl (0, cmd, arg);
 532           }
 533       }
 534 
 535   switch (dev & 0x0f)
 536     {
 537 
 538     case SND_DEV_CTL:
 539 
 540       if (!num_mixers)
 541         return -ENXIO;
 542 
 543       dev = dev >> 4;
 544 
 545       if (dev >= num_mixers)
 546         return -ENXIO;
 547 
 548       return mixer_devs[dev]->ioctl (dev, cmd, arg);
 549       break;
 550 
 551 #ifdef CONFIG_SEQUENCER
 552     case SND_DEV_SEQ:
 553     case SND_DEV_SEQ2:
 554       return sequencer_ioctl (dev, file, cmd, arg);
 555       break;
 556 #endif
 557 
 558 #ifdef CONFIG_AUDIO
 559     case SND_DEV_DSP:
 560     case SND_DEV_DSP16:
 561     case SND_DEV_AUDIO:
 562       return audio_ioctl (dev, file, cmd, arg);
 563       break;
 564 #endif
 565 
 566 #ifdef CONFIG_MIDI
 567     case SND_DEV_MIDIN:
 568       return MIDIbuf_ioctl (dev, file, cmd, arg);
 569       break;
 570 #endif
 571 
 572     default:
 573       return -EPERM;
 574       break;
 575     }
 576 
 577   return -EPERM;
 578 }

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