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

📄 pcm_oss.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	runtime->oss.subdivision = 1;	/* disable SUBDIVIDE */#endif	// printk("space: bytes = %i, periods = %i, fragstotal = %i, fragsize = %i\n", info.bytes, info.periods, info.fragstotal, info.fragsize);	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 * _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;	if (runtime->oss.buffer)		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;				spin_lock_irq(&runtime->lock);		if (snd_pcm_running(substream))			snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);		spin_unlock_irq(&runtime->lock);		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);	}	snd_magic_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 = snd_magic_kcalloc(snd_pcm_oss_file_t, 0, 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) {			snd_pcm_oss_release_file(pcm_oss_file);			return err;		}		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);			return err;		}		if ((err = psubstream->ops->open(psubstream)) < 0) {			snd_pcm_oss_release_file(pcm_oss_file);			return err;		}		err = snd_pcm_hw_constraints_complete(psubstream);		if (err < 0) {			snd_printd("snd_pcm_hw_constraint_complete failed\n");			snd_pcm_oss_release_file(pcm_oss_file);			return err;		}		psubstream->ffile = file;		snd_pcm_oss_init_substream(psubstream, psetup, minor);	}	if (csubstream != NULL) {		csubstream->oss.file = pcm_oss_file;		err = snd_pcm_hw_constraints_init(csubstream);		if (err < 0) {			snd_printd("snd_pcm_hw_constraint_init failed\n");			snd_pcm_oss_release_file(pcm_oss_file);			return err;		}		if ((err = csubstream->ops->open(csubstream)) < 0) {			snd_pcm_oss_release_file(pcm_oss_file);			return err;		}		err = snd_pcm_hw_constraints_complete(csubstream);		if (err < 0) {			snd_printd("snd_pcm_hw_constraint_complete failed\n");			snd_pcm_oss_release_file(pcm_oss_file);			return err;		}		csubstream->ffile = file;		snd_pcm_oss_init_substream(csubstream, csetup, minor);	}	file->private_data = pcm_oss_file;	*rpcm_oss_file = pcm_oss_file;	return 0;}static int snd_pcm_oss_open(struct inode *inode, struct file *file){	int minor = minor(inode->i_rdev);	int cardnum = SNDRV_MINOR_OSS_CARD(minor);	int device;	int err;	char task_name[32];	snd_pcm_t *pcm;	snd_pcm_oss_file_t *pcm_oss_file;	snd_pcm_oss_setup_t *psetup = NULL, *csetup = NULL;	int nonblock;	wait_queue_t wait;	snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO);	device = SNDRV_MINOR_OSS_DEVICE(minor) == SNDRV_MINOR_OSS_PCM1 ?		snd_adsp_map[cardnum] : snd_dsp_map[cardnum];#ifdef LINUX_2_2	MOD_INC_USE_COUNT;#endif	pcm = snd_pcm_devices[(cardnum * SNDRV_PCM_DEVICES) + device];	if (pcm == NULL) {		err = -ENODEV;		goto __error1;	}	if (!try_inc_mod_count(pcm->card->module)) {		err = -EFAULT;		goto __error1;	}	if (snd_task_name(current, task_name, sizeof(task_name)) < 0) {		err = -EFAULT;		goto __error1;	}	if (file->f_mode & FMODE_WRITE)		psetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, task_name);	if (file->f_mode & FMODE_READ)		csetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, task_name);	nonblock = !!(file->f_flags & O_NONBLOCK);	if (psetup && !psetup->disable) {		if (psetup->nonblock)			nonblock = 1;		else if (psetup->block)			nonblock = 0;		else if (!nonblock)			nonblock = snd_nonblock_open;	} else if (csetup && !csetup->disable) {		if (csetup->nonblock)			nonblock = 1;		else if (csetup->block)			nonblock = 0;		else if (!nonblock)			nonblock = snd_nonblock_open;	}	init_waitqueue_entry(&wait, current);	add_wait_queue(&pcm->open_wait, &wait);	while (1) {		down(&pcm->open_mutex);		err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,					    minor, psetup, csetup);		if (err >= 0)			break;		up(&pcm->open_mutex);		if (err == -EAGAIN) {			if (nonblock) {				err = -EBUSY;				break;			}		} else			break;		set_current_state(TASK_INTERRUPTIBLE);		schedule();		if (signal_pending(current)) {			err = -ERESTARTSYS;			break;		}	}	set_current_state(TASK_RUNNING);	remove_wait_queue(&pcm->open_wait, &wait);	if (err < 0)		goto __error;	up(&pcm->open_mutex);	return err;      __error:      	dec_mod_count(pcm->card->module);      __error1:#ifdef LINUX_2_2	MOD_DEC_USE_COUNT;#endif	return err;}static int snd_pcm_oss_release(struct inode *inode, struct file *file){	snd_pcm_t *pcm;	snd_pcm_substream_t *substream;	snd_pcm_oss_file_t *pcm_oss_file;	pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO);	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];	if (substream == NULL)		substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];	snd_assert(substream != NULL, return -ENXIO);	pcm = substream->pcm;	snd_pcm_oss_sync(pcm_oss_file);	down(&pcm->open_mutex);	snd_pcm_oss_release_file(pcm_oss_file);	up(&pcm->open_mutex);	wake_up(&pcm->open_wait);	dec_mod_count(pcm->card->module);#ifdef LINUX_2_2	MOD_DEC_USE_COUNT;#endif	return 0;}static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file,                             unsigned int cmd, unsigned long arg){	snd_pcm_oss_file_t *pcm_oss_file;	int res;	pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO);	if (cmd == OSS_GETVERSION)		return put_user(SNDRV_OSS_VERSION, (int *)arg) ? -EFAULT : 0;#if defined(CONFIG_SND_MIXER_OSS) || (defined(MODULE) && defined(CONFIG_SND_MIXER_OSS_MODULE))	if (((cmd >> 8) & 0xff) == 'M')	{	/* mixer ioctl - for OSS compatibility */		snd_pcm_substream_t *substream;		int idx;		for (idx = 0; idx < 2; ++idx) {			substream = pcm_oss_file->streams[idx];			if (substream != NULL)				break;		}		snd_assert(substream != NULL, return -ENXIO);		return snd_mixer_oss_ioctl_card(substream->pcm->card, cmd, arg);	}#endif	if (((cmd >> 8) & 0xff) != 'P')		return -EINVAL;	switch (cmd) {	case SNDCTL_DSP_RESET:		return snd_pcm_oss_reset(pcm_oss_file);	case SNDCTL_DSP_SYNC:		return snd_pcm_oss_sync(pcm_oss_file);	case SNDCTL_DSP_SPEED:		if (get_user(res, (int *)arg))			return -EFAULT;		if ((res = snd_pcm_oss_set_rate(pcm_oss_file, res))<0)			return res;		return put_user(res, (int *)arg) ? -EFAULT : 0;	case SOUND_PCM_READ_RATE:		res = snd_pcm_oss_get_rate(pcm_oss_file);		if (res < 0)			return res;		return put_user(res, (int *)arg) ? -EFAULT : 0;	case SNDCTL_DSP_STEREO:		if (get_user(res, (int *)arg))			return -EFAULT;		res = res > 0 ? 2 : 1;		if ((res = snd_pcm_oss_set_channels(pcm_oss_file, res)) < 0)			return res;		return put_user(--res, (int *)arg) ? -EFAULT : 0;	case SNDCTL_DSP_GETBLKSIZE:		res = snd_pcm_oss_get_block_size(pcm_oss_file);		if (res < 0)			return res;		return put_user(res, (int *)arg) ? -EFAULT : 0;	case SNDCTL_DSP_SETFMT:		if (get_user(res, (int *)arg))			return -EFAULT;		res = snd_pcm_oss_set_format(pcm_oss_file, res);		if (res < 0)			return res;		return put_user(res, (int *)arg) ? -EFAULT : 0;	case SOUND_PCM_READ_BITS:		res = snd_pcm_oss_get_format(pcm_oss_file);		if (res < 0)			return res;		return put_user(res, (int *)arg) ? -EFAULT : 0;	case SNDCTL_DSP_CHANNELS:		if (get_user(res, (int *)arg))			return -EFAULT;		res = snd_pcm_oss_set_channels(pcm_oss_file, res);		if (res < 0)			return res;		return put_user(res, (int *)arg) ? -EFAULT : 0;	case SOUND_PCM_READ_CHANNELS:		res = snd_pcm_oss_get_channels(pcm_oss_file);		if (res < 0)			return res;		return put_user(res, (int *)arg) ? -EFAULT : 0;	case SOUND_PCM_WRITE_FILTER:	case SOUND_PCM_READ_FILTER:		return -EIO;	case SNDCTL_DSP_POST:	/* to do */		return 0;	case SNDCTL_DSP_SUBDIVIDE:		if (get_user(res, (int *)arg))			return -EFAULT;		res = snd_pcm_oss_set_subdivide(pcm_oss_file, res);		if (res < 0)			return res;		return put_user(res, (int *)arg) ? -EFAULT : 0;	case SNDCTL_DSP_SETFRAGMENT:		if (get_user(res, (int *)arg))			return -EFAULT;		return snd_pcm_oss_set_fragment(pcm_oss_file, res);	case SNDCTL_DSP_GETFMTS:		res = snd_pcm_oss_get_formats(pcm_oss_file);		if (res < 0)			return res;		return put_user(res, (int *)arg) ? -EFAULT : 0;	case SNDCTL_DSP_GETOSPACE:	case SNDCTL_DSP_GETISPACE:		return snd_pcm_oss_get_space(pcm_oss_file,			cmd == SNDCTL_DSP_GETISPACE ?				SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK,			(struct audio_buf_info *) arg);	case SNDCTL_DSP_NONBLOCK:		return snd_pcm_oss_nonblock(file);	case SNDCTL_DSP_GETCAPS:		res = snd_pcm_oss_get_caps(pcm_oss_file);		if (res < 0)			return res;		return put_user(res, (int *)arg) ? -EFAULT : 0;	case SNDCTL_DSP_GETTRIGGER:		res = snd_pcm_oss_get_trigger(pcm_oss_file);		if (res < 0)			return res;		return put_user(res, (int *)arg) ? -EFAULT : 0;	case SNDCTL_DSP_SETTRIGGER:		if (get_user(res, (int *)arg))

⌨️ 快捷键说明

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