home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / drivers / sound / sound_switch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-18  |  10.6 KB  |  529 lines

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