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

📄 pcm_oss.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
static int snd_pcm_oss_nonblock(struct file * file){	file->f_flags |= O_NONBLOCK;	return 0;}static int snd_pcm_oss_get_caps1(snd_pcm_substream_t *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	{		snd_pcm_runtime_t *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(snd_pcm_oss_file_t *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++) {		snd_pcm_substream_t *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(snd_pcm_substream_t *substream, snd_pcm_uframes_t hw_ptr){	snd_pcm_runtime_t *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(snd_pcm_oss_file_t *pcm_oss_file, int trigger){	snd_pcm_runtime_t *runtime;	snd_pcm_substream_t *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_playback_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_capture_ioctl(csubstream, cmd, NULL);		if (err < 0)			return err;	} _skip2:	return 0;}static int snd_pcm_oss_get_trigger(snd_pcm_oss_file_t *pcm_oss_file){	snd_pcm_substream_t *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(snd_pcm_oss_file_t *pcm_oss_file){	snd_pcm_substream_t *substream;	snd_pcm_runtime_t *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_playback_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(snd_pcm_oss_file_t *pcm_oss_file, int stream, struct count_info __user * _info){		snd_pcm_substream_t *substream;	snd_pcm_runtime_t *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) {			snd_pcm_oss_setup_t *setup = substream->oss.setup;			if (setup && 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(snd_pcm_oss_file_t *pcm_oss_file, int stream, struct audio_buf_info __user *_info){	snd_pcm_substream_t *substream;	snd_pcm_runtime_t *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(snd_pcm_oss_file_t *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 snd_pcm_oss_setup_t *snd_pcm_oss_look_for_setup(snd_pcm_t *pcm, int stream, const char *task_name){	const char *ptr, *ptrl;	snd_pcm_oss_setup_t *setup;	down(&pcm->streams[stream].oss.setup_mutex);	for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) {		if (!strcmp(setup->task_name, task_name)) {			up(&pcm->streams[stream].oss.setup_mutex);			return setup;		}	}	ptr = ptrl = task_name;	while (*ptr) {		if (*ptr == '/')			ptrl = ptr + 1;		ptr++;	}	if (ptrl == task_name) {		goto __not_found;		return NULL;	}	for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) {		if (!strcmp(setup->task_name, ptrl)) {			up(&pcm->streams[stream].oss.setup_mutex);			return setup;		}	}      __not_found:	up(&pcm->streams[stream].oss.setup_mutex);	return NULL;}static void snd_pcm_oss_init_substream(snd_pcm_substream_t *substream,				       snd_pcm_oss_setup_t *setup,				       int minor){	snd_pcm_runtime_t *runtime;	substream->oss.oss = 1;	substream->oss.setup = setup;	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;}static void snd_pcm_oss_release_substream(snd_pcm_substream_t *substream){	snd_pcm_runtime_t *runtime;	runtime = substream->runtime;	vfree(runtime->oss.buffer);	snd_pcm_oss_plugin_clear(substream);	substream->oss.file = NULL;	substream->oss.oss = 0;}static int snd_pcm_oss_release_file(snd_pcm_oss_file_t *pcm_oss_file){	int cidx;	snd_assert(pcm_oss_file != NULL, return -ENXIO);	for (cidx = 0; cidx < 2; ++cidx) {		snd_pcm_substream_t *substream = pcm_oss_file->streams[cidx];		snd_pcm_runtime_t *runtime;		if (substream == NULL)			continue;		runtime = substream->runtime;				snd_pcm_stream_lock_irq(substream);		if (snd_pcm_running(substream))			snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);		snd_pcm_stream_unlock_irq(substream);		if (substream->ffile != NULL) {			if (substream->ops->hw_free != NULL)				substream->ops->hw_free(substream);			substream->ops->close(substream);			substream->ffile = NULL;		}		snd_pcm_oss_release_substream(substream);		snd_pcm_release_substream(substream);	}	kfree(pcm_oss_file);	return 0;}static int snd_pcm_oss_open_file(struct file *file,				 snd_pcm_t *pcm,				 snd_pcm_oss_file_t **rpcm_oss_file,				 int minor,				 snd_pcm_oss_setup_t *psetup,				 snd_pcm_oss_setup_t *csetup){	int err = 0;	snd_pcm_oss_file_t *pcm_oss_file;	snd_pcm_substream_t *psubstream = NULL, *csubstream = NULL;	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;	if ((f_mode & FMODE_WRITE) && !(psetup && psetup->disable)) {		if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_PLAYBACK,					       &psubstream)) < 0) {			snd_pcm_oss_release_file(pcm_oss_file);			return err;		}		pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK] = psubstream;	}	if ((f_mode & FMODE_READ) && !(csetup && csetup->disable)) {		if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_CAPTURE, 					       &csubstream)) < 0) {			if (!(f_mode & FMODE_WRITE) || err != -ENODEV) {				snd_pcm_oss_release_file(pcm_oss_file);				return err;			} else {				csubstream = NULL;			}		}		pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE] = csubstream;	}		if (psubstream == NULL && csubstream == NULL) {		snd_pcm_oss_release_file(pcm_oss_file);		return -EINVAL;	}	if (psubstream != NULL) {		psubstream->oss.file = pcm_oss_file;		err = snd_pcm_hw_constraints_init(psubstream);		if (err < 0) {			snd_printd("snd_pcm_hw_constraint_init failed\n");			snd_pcm_oss_release_file(pcm_oss_file);

⌨️ 快捷键说明

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