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

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