⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audio.c

📁 <Linux1.0核心游记>电子书+书后源码+Linux1.0源码
💻 C
字号:
/* * sound/audio.c *  * Device file manager for /dev/audio *  * Copyright by Hannu Savolainen 1993 *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. 2. * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. *  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *  */#include "sound_config.h"#ifdef CONFIGURE_SOUNDCARD#ifndef EXCLUDE_AUDIO#include "ulaw.h"#define ON		1#define OFF		0static int      wr_buff_no[MAX_DSP_DEV];	/* != -1, if there is a						 * incomplete output block */static int      wr_buff_size[MAX_DSP_DEV], wr_buff_ptr[MAX_DSP_DEV];static int	audio_mode[MAX_DSP_DEV];#define		AM_NONE		0#define		AM_WRITE	1#define 	AM_READ		2static char    *wr_dma_buf[MAX_DSP_DEV];intaudio_open (int dev, struct fileinfo *file){  int             ret;  int		  bits;  int		  dev_type = dev & 0x0f;  int		  mode = file->mode & O_ACCMODE;  dev = dev >> 4;  if (dev_type == SND_DEV_DSP16)     bits = 16;  else     bits = 8;  if ((ret = DMAbuf_open (dev, mode)) < 0)    return ret;  if (DMAbuf_ioctl (dev, SNDCTL_DSP_SAMPLESIZE, bits, 1) != bits)    {      audio_release (dev, file);      return RET_ERROR (ENXIO);    }  wr_buff_no[dev] = -1;  audio_mode[dev] = AM_NONE;  return ret;}voidaudio_release (int dev, struct fileinfo *file){  int             mode;  dev = dev >> 4;  mode = file->mode & O_ACCMODE;  if (wr_buff_no[dev] >= 0)    {      DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);      wr_buff_no[dev] = -1;    }  DMAbuf_release (dev, mode);}#ifdef NO_INLINE_ASMstatic voidtranslate_bytes (const unsigned char *table, unsigned char *buff, unsigned long n){  unsigned long   i;  for (i = 0; i < n; ++i)    buff[i] = table[buff[i]];}#elseextern inline voidtranslate_bytes (const void *table, void *buff, unsigned long n){  __asm__ ("cld\n"	   "1:\tlodsb\n\t"	   "xlatb\n\t"	   "stosb\n\t"	   "loop 1b\n\t":	   :"b" ((long) table), "c" (n), "D" ((long) buff), "S" ((long) buff)	   :"bx", "cx", "di", "si", "ax");}#endifintaudio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count){  int             c, p, l;  int             err;  int		  dev_type = dev & 0x0f;  dev = dev >> 4;  p = 0;  c = count;  if (audio_mode[dev] == AM_READ)	/* Direction changed */  {      wr_buff_no[dev] = -1;  }  audio_mode[dev] = AM_WRITE;  if (!count)			/* Flush output */    {      if (wr_buff_no[dev] >= 0)	{	  DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);	  wr_buff_no[dev] = -1;	}      return 0;    }  while (c)    {				/* Perform output blocking */      if (wr_buff_no[dev] < 0)	/* There is no incomplete buffers */	{	  if ((wr_buff_no[dev] = DMAbuf_getwrbuffer (dev, &wr_dma_buf[dev], &wr_buff_size[dev])) < 0)	    return wr_buff_no[dev];	  wr_buff_ptr[dev] = 0;	}      l = c;      if (l > (wr_buff_size[dev] - wr_buff_ptr[dev]))	l = (wr_buff_size[dev] - wr_buff_ptr[dev]);      if (!dsp_devs[dev]->copy_from_user)	{			/* No device specific copy routine */	  COPY_FROM_USER (&wr_dma_buf[dev][wr_buff_ptr[dev]], buf, p, l);	}      else	dsp_devs[dev]->copy_from_user (dev,			       wr_dma_buf[dev], wr_buff_ptr[dev], buf, p, l);      /* Insert local processing here */      if (dev_type == SND_DEV_AUDIO)      {#ifdef linux      /* This just allows interrupts while the conversion is running */         __asm__ ("sti");#endif         translate_bytes (ulaw_dsp, &wr_dma_buf[dev][wr_buff_ptr[dev]], l);      }      c -= l;      p += l;      wr_buff_ptr[dev] += l;      if (wr_buff_ptr[dev] >= wr_buff_size[dev])	{	  if ((err = DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev])) < 0)	    return err;	  wr_buff_no[dev] = -1;	}    }  return count;}intaudio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count){  int             c, p, l;  char           *dmabuf;  int             buff_no;  int		  dev_type = dev & 0x0f;  dev = dev >> 4;  p = 0;  c = count;  if (audio_mode[dev] == AM_WRITE)  {      if (wr_buff_no[dev] >= 0)	{	  DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);	  wr_buff_no[dev] = -1;	}  }  audio_mode[dev] = AM_READ;  while (c)    {      if ((buff_no = DMAbuf_getrdbuffer (dev, &dmabuf, &l)) < 0)	return buff_no;      if (l > c)	l = c;      /* Insert any local processing here. */      if (dev_type == SND_DEV_AUDIO)      {#ifdef linux        /* This just allows interrupts while the conversion is running */        __asm__ ("sti");#endif        translate_bytes (dsp_ulaw, dmabuf, l);      }      COPY_TO_USER (buf, p, dmabuf, l);      DMAbuf_rmchars (dev, buff_no, l);      p += l;      c -= l;    }  return count - c;}intaudio_ioctl (int dev, struct fileinfo *file,	     unsigned int cmd, unsigned int arg){  int		  dev_type = dev & 0x0f;  dev = dev >> 4;  switch (cmd)    {    case SNDCTL_DSP_SYNC:      if (wr_buff_no[dev] >= 0)	{	  DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);	  wr_buff_no[dev] = -1;	}      return DMAbuf_ioctl (dev, cmd, arg, 0);      break;    case SNDCTL_DSP_POST:      if (wr_buff_no[dev] >= 0)	{	  DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);	  wr_buff_no[dev] = -1;	}      return 0;      break;    case SNDCTL_DSP_RESET:      wr_buff_no[dev] = -1;      return DMAbuf_ioctl (dev, cmd, arg, 0);      break;    default:      if (dev_type == SND_DEV_AUDIO)         return RET_ERROR (EIO);      return DMAbuf_ioctl (dev, cmd, arg, 0);    }}longaudio_init (long mem_start){  return mem_start;}#else/* Stub versions */intaudio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count){  return RET_ERROR (EIO);}intaudio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count){  return RET_ERROR (EIO);}intaudio_open (int dev, struct fileinfo *file)  {    return RET_ERROR (ENXIO);  }voidaudio_release (int dev, struct fileinfo *file)  {  };intaudio_ioctl (int dev, struct fileinfo *file,	     unsigned int cmd, unsigned int arg){  return RET_ERROR (EIO);}intaudio_lseek (int dev, struct fileinfo *file, off_t offset, int orig){  return RET_ERROR (EIO);}longaudio_init (long mem_start){  return mem_start;}#endif#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -