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

📄 pcm_oss.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
			return err;		}		if ((err = psubstream->ops->open(psubstream)) < 0) {			snd_pcm_oss_release_file(pcm_oss_file);			return err;		}		psubstream->ffile = file;		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;		}		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;		}		csubstream->ffile = file;		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;		}		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_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++)		name[idx] = task->comm[idx];	name[idx] = '\0';	return 0;}static int snd_pcm_oss_open(struct inode *inode, struct file *file){	int minor = iminor(inode);	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 ?		adsp_map[cardnum] : dsp_map[cardnum];	pcm = snd_pcm_devices[(cardnum * SNDRV_PCM_DEVICES) + device];	if (pcm == NULL) {		err = -ENODEV;		goto __error1;	}	err = snd_card_file_add(pcm->card, file);	if (err < 0)		goto __error1;	if (!try_module_get(pcm->card->module)) {		err = -EFAULT;		goto __error2;	}	if (snd_task_name(current, task_name, sizeof(task_name)) < 0) {		err = -EFAULT;		goto __error;	}	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 (csetup && !csetup->disable) {		if (csetup->nonblock)			nonblock = 1;		else if (csetup->block)			nonblock = 0;	}	if (!nonblock)		nonblock = nonblock_open;	init_waitqueue_entry(&wait, current);	add_wait_queue(&pcm->open_wait, &wait);	down(&pcm->open_mutex);	while (1) {		err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,					    minor, psetup, csetup);		if (err >= 0)			break;		if (err == -EAGAIN) {			if (nonblock) {				err = -EBUSY;				break;			}		} else			break;		set_current_state(TASK_INTERRUPTIBLE);		up(&pcm->open_mutex);		schedule();		down(&pcm->open_mutex);		if (signal_pending(current)) {			err = -ERESTARTSYS;			break;		}	}	remove_wait_queue(&pcm->open_wait, &wait);	up(&pcm->open_mutex);	if (err < 0)		goto __error;	return err;      __error:     	module_put(pcm->card->module);      __error2:      	snd_card_file_remove(pcm->card, file);      __error1:	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 = file->private_data;	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);	module_put(pcm->card->module);	snd_card_file_remove(pcm->card, file);	return 0;}static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg){	snd_pcm_oss_file_t *pcm_oss_file;	int __user *p = (int __user *)arg;	int res;	pcm_oss_file = file->private_data;	if (cmd == OSS_GETVERSION)		return put_user(SNDRV_OSS_VERSION, p);	if (cmd == OSS_ALSAEMULVER)		return put_user(1, p);#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;#ifdef OSS_DEBUG	printk("pcm_oss: ioctl = 0x%x\n", cmd);#endif	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, p))			return -EFAULT;		if ((res = snd_pcm_oss_set_rate(pcm_oss_file, res))<0)			return res;		return put_user(res, p);	case SOUND_PCM_READ_RATE:		res = snd_pcm_oss_get_rate(pcm_oss_file);		if (res < 0)			return res;		return put_user(res, p);	case SNDCTL_DSP_STEREO:		if (get_user(res, p))			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, p);	case SNDCTL_DSP_GETBLKSIZE:		res = snd_pcm_oss_get_block_size(pcm_oss_file);		if (res < 0)			return res;		return put_user(res, p);	case SNDCTL_DSP_SETFMT:		if (get_user(res, p))			return -EFAULT;		res = snd_pcm_oss_set_format(pcm_oss_file, res);		if (res < 0)			return res;		return put_user(res, p);	case SOUND_PCM_READ_BITS:		res = snd_pcm_oss_get_format(pcm_oss_file);		if (res < 0)			return res;		return put_user(res, p);	case SNDCTL_DSP_CHANNELS:		if (get_user(res, p))			return -EFAULT;		res = snd_pcm_oss_set_channels(pcm_oss_file, res);		if (res < 0)			return res;		return put_user(res, p);	case SOUND_PCM_READ_CHANNELS:		res = snd_pcm_oss_get_channels(pcm_oss_file);		if (res < 0)			return res;		return put_user(res, p);	case SOUND_PCM_WRITE_FILTER:	case SOUND_PCM_READ_FILTER:		return -EIO;	case SNDCTL_DSP_POST:		return snd_pcm_oss_post(pcm_oss_file);	case SNDCTL_DSP_SUBDIVIDE:		if (get_user(res, p))			return -EFAULT;		res = snd_pcm_oss_set_subdivide(pcm_oss_file, res);		if (res < 0)			return res;		return put_user(res, p);	case SNDCTL_DSP_SETFRAGMENT:		if (get_user(res, p))			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, p);	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 __user *) 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, p);	case SNDCTL_DSP_GETTRIGGER:		res = snd_pcm_oss_get_trigger(pcm_oss_file);		if (res < 0)			return res;		return put_user(res, p);	case SNDCTL_DSP_SETTRIGGER:		if (get_user(res, p))			return -EFAULT;		return snd_pcm_oss_set_trigger(pcm_oss_file, res);	case SNDCTL_DSP_GETIPTR:	case SNDCTL_DSP_GETOPTR:		return snd_pcm_oss_get_ptr(pcm_oss_file,			cmd == SNDCTL_DSP_GETIPTR ?				SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK,			(struct count_info __user *) arg);	case SNDCTL_DSP_MAPINBUF:	case SNDCTL_DSP_MAPOUTBUF:		return snd_pcm_oss_get_mapbuf(pcm_oss_file,			cmd == SNDCTL_DSP_MAPINBUF ?				SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK,			(struct buffmem_desc __user *) arg);	case SNDCTL_DSP_SETSYNCRO:		/* stop DMA now.. */		return 0;	case SNDCTL_DSP_SETDUPLEX:		if (snd_pcm_oss_get_caps(pcm_oss_file) & DSP_CAP_DUPLEX)			return 0;		return -EIO;	case SNDCTL_DSP_GETODELAY:		res = snd_pcm_oss_get_odelay(pcm_oss_file);		if (res < 0) {			/* it's for sure, some broken apps don't check for error codes */			put_user(0, p);			return res;		}		return put_user(res, p);	case SNDCTL_DSP_PROFILE:		return 0;	/* silently ignore */	default:		snd_printd("pcm_oss: unknown command = 0x%x\n", cmd);	}	return -EINVAL;}#ifdef CONFIG_COMPAT/* all compatible */#define snd_pcm_oss_ioctl_compat	snd_pcm_oss_ioctl#else#define snd_pcm_oss_ioctl_compat	NULL#endifstatic ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset){	snd_pcm_oss_file_t *pcm_oss_file;	snd_pcm_substream_t *substream;	pcm_oss_file = file->private_data;	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];	if (substream == NULL)		return -ENXIO;#ifndef OSS_DEBUG	return snd_pcm_oss_read1(substream, buf, count);#else	{		ssize_t res = snd_pcm_oss_read1(substream, buf, count);		printk("pcm_oss: read %li bytes (returned %li bytes)\n", (long)count, (long)res);		return res;	}#endif}static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size_t count, loff_t *offset){	snd_pcm_oss_file_t *pcm_oss_file;	snd_pcm_substream_t *substream;	long result;	pcm_oss_file = file->private_data;	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];	if (substream == NULL)		return -ENXIO;	up(&file->f_dentry->d_inode->i_sem);	result = snd_pcm_oss_write1(substream, buf, count);	down(&file->f_dentry->d_inode->i_sem);#ifdef OSS_DEBUG	printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result);#endif	return result;}static int snd_pcm_oss_playback_ready(snd_pcm_substream_t *substream){	snd_pcm_runtime_t *runtime = substream->runtime;	if (atomic_read(&runtime->mmap_count))		return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt;	else		return snd_pcm_playback_avail(runtime) >= runtime->oss.period_frames;}static int snd_pcm_oss_capture_ready(snd_pcm_substream_t *substream){	snd_pcm_runtime_t *runtime = substream->runtime;	if (atomic_read(&runtime->mmap_count))		return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt;	else		return snd_pcm_capture_avail(runtime) >= runtime->oss.period_frames;}static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait){	snd_pcm_oss_file_t *pcm_oss_file;	unsigned int mask;	snd_pcm_substream_t *psubstream = NULL, *csubstream = NULL;		pcm_oss_file = file->private_data;	psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];	csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];	mask = 0;	if (psubstream != NULL) {		snd_pcm_runtime_t *runtime = psubstream->runtime;		poll_wait(file, &runtime->sleep, wait);		snd_pcm_stream_lock_irq(psubstream);		if (runtime->status->state != SNDRV_PCM_STATE_DRAINING &&		    (runtime->status->state != SNDRV_PCM_STATE_RUNNING ||		     snd_pcm_oss_playback_ready(psubstream)))			mask |= POLLOUT | POLLWRNORM;		snd_pcm_stream_unlock_irq(psubstream);	}	if (csubstream != NULL) {		snd_pcm_runtime_t *runtime = csubstream->runtime;		enum sndrv_pcm_state ostate;		poll_wait(file, &runtime->sleep, wait);		snd_pcm_stream_lock_irq(csubstream);		if ((ostate = runtime->status->state) != SNDRV_PCM_STATE_RUNNING ||		    snd_pcm_oss_capture_ready(csubstream))			mask |= POLLIN | POLLRDNORM;		snd_pcm_stream_unlock_irq(csubstream);		if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) {			snd_pcm_oss_file_t ofile;			memset(&ofile, 0, sizeof(ofile));			ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];			runtime->oss.trigger = 0;			snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT);		}	}	return mask;}static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area){	snd_pcm_oss_file_t *pcm_oss_file;	snd_pcm_substream_t *substream = NULL;	snd_pcm_runtime_t *runtime;	int err;#ifdef OSS_DEBUG	printk("pcm_oss: mmap begin\n");#endif	pcm_oss_file = file->private_data;	switch ((area->vm_flags 

⌨️ 快捷键说明

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