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     }
 391 
 392   return -EPERM;
 393 }
 394 
 395 int
 396 sound_open_sw (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 397 {
 398   int             retval;
 399 
 400   DEB (printk ("sound_open_sw(dev=%d)\n", dev));
 401 
 402   if ((dev >= SND_NDEVS) || (dev < 0))
 403     {
 404       printk ("Invalid minor device %d\n", dev);
 405       return -ENXIO;
 406     }
 407 
 408   switch (dev & 0x0f)
 409     {
 410     case SND_DEV_STATUS:
 411       if (status_busy)
 412         return -EBUSY;
 413       status_busy = 1;
 414       if ((status_buf = (char *) kmalloc (4000, GFP_KERNEL)) == NULL)
 415         return -EIO;
 416       status_len = status_ptr = 0;
 417       init_status ();
 418       break;
 419 
 420     case SND_DEV_CTL:
 421       return 0;
 422       break;
 423 
 424 #ifdef CONFIG_SEQUENCER
 425     case SND_DEV_SEQ:
 426     case SND_DEV_SEQ2:
 427       if ((retval = sequencer_open (dev, file)) < 0)
 428         return retval;
 429       break;
 430 #endif
 431 
 432 #ifdef CONFIG_MIDI
 433     case SND_DEV_MIDIN:
 434       if ((retval = MIDIbuf_open (dev, file)) < 0)
 435         return retval;
 436       break;
 437 #endif
 438 
 439 #ifdef CONFIG_AUDIO
 440     case SND_DEV_DSP:
 441     case SND_DEV_DSP16:
 442     case SND_DEV_AUDIO:
 443       if ((retval = audio_open (dev, file)) < 0)
 444         return retval;
 445       break;
 446 #endif
 447 
 448     default:
 449       printk ("Invalid minor device %d\n", dev);
 450       return -ENXIO;
 451     }
 452 
 453   in_use++;
 454 
 455   return 0;
 456 }
 457 
 458 void
 459 sound_release_sw (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 460 {
 461 
 462   DEB (printk ("sound_release_sw(dev=%d)\n", dev));
 463 
 464   switch (dev & 0x0f)
 465     {
 466     case SND_DEV_STATUS:
 467       if (status_buf)
 468         kfree (status_buf);
 469       status_buf = NULL;
 470       status_busy = 0;
 471       break;
 472 
 473     case SND_DEV_CTL:
 474       break;
 475 
 476 #ifdef CONFIG_SEQUENCER
 477     case SND_DEV_SEQ:
 478     case SND_DEV_SEQ2:
 479       sequencer_release (dev, file);
 480       break;
 481 #endif
 482 
 483 #ifdef CONFIG_MIDI
 484     case SND_DEV_MIDIN:
 485       MIDIbuf_release (dev, file);
 486       break;
 487 #endif
 488 
 489 #ifdef CONFIG_AUDIO
 490     case SND_DEV_DSP:
 491     case SND_DEV_DSP16:
 492     case SND_DEV_AUDIO:
 493       audio_release (dev, file);
 494       break;
 495 #endif
 496 
 497     default:
 498       printk ("Sound error: Releasing unknown device 0x%02x\n", dev);
 499     }
 500   in_use--;
 501 }
 502 
 503 int
 504 sound_ioctl_sw (int dev, struct fileinfo *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 505                 unsigned int cmd, caddr_t arg)
 506 {
 507   DEB (printk ("sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
 508 
 509   if (((cmd >> 8) & 0xff) == 'M' && num_mixers > 0)     /* Mixer ioctl */
 510     if ((dev & 0x0f) != SND_DEV_CTL)
 511       {
 512         int             dtype = dev & 0x0f;
 513         int             mixdev;
 514 
 515         switch (dtype)
 516           {
 517 #ifdef CONFIG_AUDIO
 518           case SND_DEV_DSP:
 519           case SND_DEV_DSP16:
 520           case SND_DEV_AUDIO:
 521             mixdev = audio_devs[dev >> 4]->mixer_dev;
 522             if (mixdev < 0 || mixdev >= num_mixers)
 523               return -ENXIO;
 524             return mixer_devs[mixdev]->ioctl (mixdev, cmd, arg);
 525             break;
 526 #endif
 527 
 528           default:
 529             return mixer_devs[0]->ioctl (0, cmd, arg);
 530           }
 531       }
 532 
 533   switch (dev & 0x0f)
 534     {
 535 
 536     case SND_DEV_CTL:
 537 
 538       if (!num_mixers)
 539         return -ENXIO;
 540 
 541       dev = dev >> 4;
 542 
 543       if (dev >= num_mixers)
 544         return -ENXIO;
 545 
 546       return mixer_devs[dev]->ioctl (dev, cmd, arg);
 547       break;
 548 
 549 #ifdef CONFIG_SEQUENCER
 550     case SND_DEV_SEQ:
 551     case SND_DEV_SEQ2:
 552       return sequencer_ioctl (dev, file, cmd, arg);
 553       break;
 554 #endif
 555 
 556 #ifdef CONFIG_AUDIO
 557     case SND_DEV_DSP:
 558     case SND_DEV_DSP16:
 559     case SND_DEV_AUDIO:
 560       return audio_ioctl (dev, file, cmd, arg);
 561       break;
 562 #endif
 563 
 564 #ifdef CONFIG_MIDI
 565     case SND_DEV_MIDIN:
 566       return MIDIbuf_ioctl (dev, file, cmd, arg);
 567       break;
 568 #endif
 569 
 570     }
 571 
 572   return -EPERM;
 573 }

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