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

📄 pcm_oss.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			return err;	}	return err;}static int snd_pcm_oss_nonblock(struct file * file){	file->f_flags |= O_NONBLOCK;	return 0;}static int snd_pcm_oss_get_caps1(struct snd_pcm_substream *substream, int res){	if (substream == NULL) {		res &= ~DSP_CAP_DUPLEX;		return res;	}#ifdef DSP_CAP_MULTI	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)		if (substream->pstr->substream_count > 1)			res |= DSP_CAP_MULTI;#endif	/* DSP_CAP_REALTIME is set all times: */	/* all ALSA drivers can return actual pointer in ring buffer */#if defined(DSP_CAP_REALTIME) && 0	{		struct snd_pcm_runtime *runtime = substream->runtime;		if (runtime->info & (SNDRV_PCM_INFO_BLOCK_TRANSFER|SNDRV_PCM_INFO_BATCH))			res &= ~DSP_CAP_REALTIME;	}#endif	return res;}static int snd_pcm_oss_get_caps(struct snd_pcm_oss_file *pcm_oss_file){	int result, idx;		result = DSP_CAP_TRIGGER | DSP_CAP_MMAP	| DSP_CAP_DUPLEX | DSP_CAP_REALTIME;	for (idx = 0; idx < 2; idx++) {		struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];		result = snd_pcm_oss_get_caps1(substream, result);	}	result |= 0x0001;	/* revision - same as SB AWE 64 */	return result;}static void snd_pcm_oss_simulate_fill(struct snd_pcm_substream *substream, snd_pcm_uframes_t hw_ptr){	struct snd_pcm_runtime *runtime = substream->runtime;	snd_pcm_uframes_t appl_ptr;	appl_ptr = hw_ptr + runtime->buffer_size;	appl_ptr %= runtime->boundary;	runtime->control->appl_ptr = appl_ptr;}static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int trigger){	struct snd_pcm_runtime *runtime;	struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;	int err, cmd;#ifdef OSS_DEBUG	printk("pcm_oss: trigger = 0x%x\n", trigger);#endif		psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];	csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];	if (psubstream) {		if ((err = snd_pcm_oss_make_ready(psubstream)) < 0)			return err;	}	if (csubstream) {		if ((err = snd_pcm_oss_make_ready(csubstream)) < 0)			return err;	}      	if (psubstream) {      		runtime = psubstream->runtime;		if (trigger & PCM_ENABLE_OUTPUT) {			if (runtime->oss.trigger)				goto _skip1;			if (atomic_read(&psubstream->runtime->mmap_count))				snd_pcm_oss_simulate_fill(psubstream, runtime->hw_ptr_interrupt);			runtime->oss.trigger = 1;			runtime->start_threshold = 1;			cmd = SNDRV_PCM_IOCTL_START;		} else {			if (!runtime->oss.trigger)				goto _skip1;			runtime->oss.trigger = 0;			runtime->start_threshold = runtime->boundary;			cmd = SNDRV_PCM_IOCTL_DROP;			runtime->oss.prepare = 1;		}		err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL);		if (err < 0)			return err;	} _skip1:	if (csubstream) {      		runtime = csubstream->runtime;		if (trigger & PCM_ENABLE_INPUT) {			if (runtime->oss.trigger)				goto _skip2;			runtime->oss.trigger = 1;			runtime->start_threshold = 1;			cmd = SNDRV_PCM_IOCTL_START;		} else {			if (!runtime->oss.trigger)				goto _skip2;			runtime->oss.trigger = 0;			runtime->start_threshold = runtime->boundary;			cmd = SNDRV_PCM_IOCTL_DROP;			runtime->oss.prepare = 1;		}		err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL);		if (err < 0)			return err;	} _skip2:	return 0;}static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file){	struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;	int result = 0;	psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];	csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];	if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger)		result |= PCM_ENABLE_OUTPUT;	if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger)		result |= PCM_ENABLE_INPUT;	return result;}static int snd_pcm_oss_get_odelay(struct snd_pcm_oss_file *pcm_oss_file){	struct snd_pcm_substream *substream;	struct snd_pcm_runtime *runtime;	snd_pcm_sframes_t delay;	int err;	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];	if (substream == NULL)		return -EINVAL;	if ((err = snd_pcm_oss_make_ready(substream)) < 0)		return err;	runtime = substream->runtime;	if (runtime->oss.params || runtime->oss.prepare)		return 0;	err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);	if (err == -EPIPE)		delay = 0;	/* hack for broken OSS applications */	else if (err < 0)		return err;	return snd_pcm_oss_bytes(substream, delay);}static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct count_info __user * _info){		struct snd_pcm_substream *substream;	struct snd_pcm_runtime *runtime;	snd_pcm_sframes_t delay;	int fixup;	struct count_info info;	int err;	if (_info == NULL)		return -EFAULT;	substream = pcm_oss_file->streams[stream];	if (substream == NULL)		return -EINVAL;	if ((err = snd_pcm_oss_make_ready(substream)) < 0)		return err;	runtime = substream->runtime;	if (runtime->oss.params || runtime->oss.prepare) {		memset(&info, 0, sizeof(info));		if (copy_to_user(_info, &info, sizeof(info)))			return -EFAULT;		return 0;	}	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {		err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);		if (err == -EPIPE || err == -ESTRPIPE || (! err && delay < 0)) {			err = 0;			delay = 0;			fixup = 0;		} else {			fixup = runtime->oss.buffer_used;		}	} else {		err = snd_pcm_oss_capture_position_fixup(substream, &delay);		fixup = -runtime->oss.buffer_used;	}	if (err < 0)		return err;	info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size);	if (atomic_read(&runtime->mmap_count)) {		snd_pcm_sframes_t n;		n = (delay = runtime->hw_ptr_interrupt) - runtime->oss.prev_hw_ptr_interrupt;		if (n < 0)			n += runtime->boundary;		info.blocks = n / runtime->period_size;		runtime->oss.prev_hw_ptr_interrupt = delay;		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)			snd_pcm_oss_simulate_fill(substream, delay);		info.bytes = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr) & INT_MAX;	} else {		delay = snd_pcm_oss_bytes(substream, delay);		if (stream == SNDRV_PCM_STREAM_PLAYBACK) {			if (substream->oss.setup.buggyptr)				info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;			else				info.blocks = (delay + fixup) / runtime->oss.period_bytes;			info.bytes = (runtime->oss.bytes - delay) & INT_MAX;		} else {			delay += fixup;			info.blocks = delay / runtime->oss.period_bytes;			info.bytes = (runtime->oss.bytes + delay) & INT_MAX;		}	}	if (copy_to_user(_info, &info, sizeof(info)))		return -EFAULT;	return 0;}static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct audio_buf_info __user *_info){	struct snd_pcm_substream *substream;	struct snd_pcm_runtime *runtime;	snd_pcm_sframes_t avail;	int fixup;	struct audio_buf_info info;	int err;	if (_info == NULL)		return -EFAULT;	substream = pcm_oss_file->streams[stream];	if (substream == NULL)		return -EINVAL;	runtime = substream->runtime;	if (runtime->oss.params &&	    (err = snd_pcm_oss_change_params(substream)) < 0)		return err;	info.fragsize = runtime->oss.period_bytes;	info.fragstotal = runtime->periods;	if (runtime->oss.prepare) {		if (stream == SNDRV_PCM_STREAM_PLAYBACK) {			info.bytes = runtime->oss.period_bytes * runtime->oss.periods;			info.fragments = runtime->oss.periods;		} else {			info.bytes = 0;			info.fragments = 0;		}	} else {		if (stream == SNDRV_PCM_STREAM_PLAYBACK) {			err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &avail);			if (err == -EPIPE || err == -ESTRPIPE || (! err && avail < 0)) {				avail = runtime->buffer_size;				err = 0;				fixup = 0;			} else {				avail = runtime->buffer_size - avail;				fixup = -runtime->oss.buffer_used;			}		} else {			err = snd_pcm_oss_capture_position_fixup(substream, &avail);			fixup = runtime->oss.buffer_used;		}		if (err < 0)			return err;		info.bytes = snd_pcm_oss_bytes(substream, avail) + fixup;		info.fragments = info.bytes / runtime->oss.period_bytes;	}#ifdef OSS_DEBUG	printk("pcm_oss: space: bytes = %i, fragments = %i, fragstotal = %i, fragsize = %i\n", info.bytes, info.fragments, info.fragstotal, info.fragsize);#endif	if (copy_to_user(_info, &info, sizeof(info)))		return -EFAULT;	return 0;}static int snd_pcm_oss_get_mapbuf(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct buffmem_desc __user * _info){	// it won't be probably implemented	// snd_printd("TODO: snd_pcm_oss_get_mapbuf\n");	return -EINVAL;}static const char *strip_task_path(const char *path){	const char *ptr, *ptrl = NULL;	for (ptr = path; *ptr; ptr++) {		if (*ptr == '/')			ptrl = ptr + 1;	}	return ptrl;}static void snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream,				      const char *task_name,				      struct snd_pcm_oss_setup *rsetup){	struct snd_pcm_oss_setup *setup;	mutex_lock(&pcm->streams[stream].oss.setup_mutex);	do {		for (setup = pcm->streams[stream].oss.setup_list; setup;		     setup = setup->next) {			if (!strcmp(setup->task_name, task_name))				goto out;		}	} while ((task_name = strip_task_path(task_name)) != NULL); out:	if (setup)		*rsetup = *setup;	mutex_unlock(&pcm->streams[stream].oss.setup_mutex);}static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream){	struct snd_pcm_runtime *runtime;	runtime = substream->runtime;	vfree(runtime->oss.buffer);	runtime->oss.buffer = NULL;#ifdef CONFIG_SND_PCM_OSS_PLUGINS	snd_pcm_oss_plugin_clear(substream);#endif	substream->oss.oss = 0;}static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,				       struct snd_pcm_oss_setup *setup,				       int minor){	struct snd_pcm_runtime *runtime;	substream->oss.oss = 1;	substream->oss.setup = *setup;	if (setup->nonblock)		substream->ffile->f_flags |= O_NONBLOCK;	else if (setup->block)		substream->ffile->f_flags &= ~O_NONBLOCK;	runtime = substream->runtime;	runtime->oss.params = 1;	runtime->oss.trigger = 1;	runtime->oss.rate = 8000;	switch (SNDRV_MINOR_OSS_DEVICE(minor)) {	case SNDRV_MINOR_OSS_PCM_8:		runtime->oss.format = AFMT_U8;		break;	case SNDRV_MINOR_OSS_PCM_16:		runtime->oss.format = AFMT_S16_LE;		break;	default:		runtime->oss.format = AFMT_MU_LAW;	}	runtime->oss.channels = 1;	runtime->oss.fragshift = 0;	runtime->oss.maxfrags = 0;	runtime->oss.subdivision = 0;	substream->pcm_release = snd_pcm_oss_release_substream;}static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file){	int cidx;	snd_assert(pcm_oss_file != NULL, return -ENXIO);	for (cidx = 0; cidx < 2; ++cidx) {		struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx];		if (substream)			snd_pcm_release_substream(substream);	}	kfree(pcm_oss_file);	return 0;}static int snd_pcm_oss_open_file(struct file *file,				 struct snd_pcm *pcm,				 struct snd_pcm_oss_file **rpcm_oss_file,				 int minor,				 struct snd_pcm_oss_setup *setup){	int idx, err;	struct snd_pcm_oss_file *pcm_oss_file;	struct snd_pcm_substream *substream;	unsigned int f_mode = file->f_mode;	snd_assert(rpcm_oss_file != NULL, return -EINVAL);	*rpcm_oss_file = NULL;	pcm_oss_file = kzalloc(sizeof(*pcm_oss_file), GFP_KERNEL);	if (pcm_oss_file == NULL)		return -ENOMEM;	if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) &&	    (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX))		f_mode = FMODE_WRITE;	for (idx = 0; idx < 2; idx++) {		if (setup[idx].disable)			continue;		if (! pcm->streams[idx].substream_count)			continue; /* no matching substream */		if (idx == SNDRV_PCM_STREAM_PLAYBACK) {			if (! (f_mode & FMODE_WRITE))				continue;		} else {			if (! (f_mode & FMODE_READ))				continue;		}		err = snd_pcm_open_substream(pcm, idx, file, &substream);		if (err < 0) {			snd_pcm_oss_release_file(pcm_oss_file);			return err;		}		pcm_oss_file->streams[idx] = substream;		substream->file = pcm_oss_file;		snd_pcm_oss_init_substream(substream, &setup[idx], minor);	}		if (!pcm_oss_file->streams[0] && !pcm_oss_file->streams[1]) {		snd_pcm_oss_release_file(pcm_oss_file);		return -EINVAL;	}	file->private_data = pcm_oss_file;	*rpcm_oss_file = pcm_oss_file;	return 0;}static int snd_task_name(struct task_struct *task, char *name, size_t size){	unsigned int idx;	snd_assert(task != NULL && name != NULL && size >= 2, return -EINVAL);	for (idx = 0; idx < sizeof(task->comm) && idx + 1 < size; idx++)

⌨️ 快捷键说明

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