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

📄 pcm_oss.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			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 *) 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 *) 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, (int *)arg);			return res;		}		return put_user(res, (int *)arg) ? -EFAULT : 0;	case SNDCTL_DSP_PROFILE:		return 0;	/* silently ignore */	default:		snd_printd("pcm_oss: unknown command = 0x%x\n", cmd);	}	return -EINVAL;}static ssize_t snd_pcm_oss_read(struct file *file, char *buf, size_t count, loff_t *offset){	snd_pcm_oss_file_t *pcm_oss_file;	snd_pcm_substream_t *substream;	pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO);	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];	if (substream == NULL)		return -ENXIO;	return snd_pcm_oss_read1(substream, buf, count);}static ssize_t snd_pcm_oss_write(struct file *file, const char *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 = 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)		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);	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_ready(substream);}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_ready(substream);}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 = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return 0);	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;		spin_lock_irq(&runtime->lock);		poll_wait(file, &runtime->sleep, wait);		if (runtime->status->state != SNDRV_PCM_STATE_DRAINING &&		    (runtime->status->state != SNDRV_PCM_STATE_RUNNING ||		     snd_pcm_oss_playback_ready(psubstream)))			mask |= POLLOUT | POLLWRNORM;		spin_unlock_irq(&runtime->lock);	}	if (csubstream != NULL) {		snd_pcm_runtime_t *runtime = csubstream->runtime;		spin_lock_irq(&runtime->lock);		poll_wait(file, &runtime->sleep, wait);		if (runtime->status->state != SNDRV_PCM_STATE_RUNNING ||		    snd_pcm_oss_capture_ready(csubstream))			mask |= POLLIN | POLLRDNORM;		spin_unlock_irq(&runtime->lock);	}	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;	pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO);	switch ((area->vm_flags & (VM_READ | VM_WRITE))) {	case VM_READ | VM_WRITE:		substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];		if (substream)			break;		/* Fall through */	case VM_READ:		substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];		break;	case VM_WRITE:		substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];		break;	default:		return -EINVAL;	}	/* set VM_READ access as well to fix memset() routines that do	   reads before writes (to improve performance) */	area->vm_flags |= VM_READ;	if (substream == NULL)		return -ENXIO;	runtime = substream->runtime;	if (!(runtime->info & SNDRV_PCM_INFO_MMAP_VALID))		return -EIO;	if (runtime->info & SNDRV_PCM_INFO_INTERLEAVED)		runtime->access = SNDRV_PCM_ACCESS_MMAP_INTERLEAVED;	else		return -EIO;		if (runtime->oss.params) {		if ((err = snd_pcm_oss_change_params(substream)) < 0)			return err;	}	if (runtime->oss.plugin_first != NULL)		return -EIO;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 25)	if (area->vm_pgoff != 0)#else	if (area->vm_offset != 0)#endif		return -EINVAL;	err = snd_pcm_mmap_data(substream, file, area);	if (err < 0)		return err;	runtime->oss.mmap_bytes = area->vm_end - area->vm_start;	/* In mmap mode we never stop */	runtime->stop_threshold = runtime->boundary;	return 0;}/* *  /proc interface */static void snd_pcm_oss_proc_read(snd_info_entry_t *entry,				  snd_info_buffer_t * buffer){	snd_pcm_str_t *pstr = (snd_pcm_str_t *)entry->private_data;	snd_pcm_oss_setup_t *setup = pstr->oss.setup_list;	down(&pstr->oss.setup_mutex);	while (setup) {		snd_iprintf(buffer, "%s %u %u%s%s%s%s\n",			    setup->task_name,			    setup->periods,			    setup->period_size,			    setup->disable ? " disable" : "",			    setup->direct ? " direct" : "",			    setup->block ? " block" : "",			    setup->nonblock ? " non-block" : "");		setup = setup->next;	}	up(&pstr->oss.setup_mutex);}static void snd_pcm_oss_proc_free_setup_list(snd_pcm_str_t * pstr){	unsigned int idx;	snd_pcm_substream_t *substream;	snd_pcm_oss_setup_t *setup, *setupn;	for (idx = 0, substream = pstr->substream;	     idx < pstr->substream_count; idx++, substream = substream->next)		substream->oss.setup = NULL;	for (setup = pstr->oss.setup_list, pstr->oss.setup_list = NULL;	     setup; setup = setupn) {		setupn = setup->next;		kfree(setup->task_name);		kfree(setup);	}	pstr->oss.setup_list = NULL;}static void snd_pcm_oss_proc_write(snd_info_entry_t *entry,				   snd_info_buffer_t * buffer){	snd_pcm_str_t *pstr = (snd_pcm_str_t *)entry->private_data;	char line[512], str[32], task_name[32], *ptr;	int idx1;	snd_pcm_oss_setup_t *setup, *setup1, template;	while (!snd_info_get_line(buffer, line, sizeof(line))) {		down(&pstr->oss.setup_mutex);		memset(&template, 0, sizeof(template));		ptr = snd_info_get_str(task_name, line, sizeof(task_name));		if (!strcmp(task_name, "clear") || !strcmp(task_name, "erase")) {			snd_pcm_oss_proc_free_setup_list(pstr);			up(&pstr->oss.setup_mutex);			continue;		}		for (setup = pstr->oss.setup_list; setup; setup = setup->next) {			if (!strcmp(setup->task_name, task_name)) {				template = *setup;				break;			}		}		ptr = snd_info_get_str(str, ptr, sizeof(str));		template.periods = simple_strtoul(str, NULL, 10);		ptr = snd_info_get_str(str, ptr, sizeof(str));		template.period_size = simple_strtoul(str, NULL, 10);		for (idx1 = 31; idx1 >= 0; idx1--)			if (template.period_size & (1 << idx1))				break;		for (idx1--; idx1 >= 0; idx1--)			template.period_size &= ~(1 << idx1);		do {			ptr = snd_info_get_str(str, ptr, sizeof(str));			if (!strcmp(str, "disable")) {				template.disable = 1;			} else if (!strcmp(str, "direct")) {				template.direct = 1;			} else if (!strcmp(str, "block")) {				template.block = 1;			} else if (!strcmp(str, "non-block")) {				template.nonblock = 1;			}		} while (*str);		if (setup == NULL) {			setup = (snd_pcm_oss_setup_t *) kmalloc(sizeof(snd_pcm_oss_setup_t), GFP_KERNEL);			if (setup) {				if (pstr->oss.setup_list == NULL) {					pstr->oss.setup_list = setup;				} else {					for (setup1 = pstr->oss.setup_list; setup1->next; setup1 = setup1->next);					setup1->next = setup;				}				template.task_name = snd_kmalloc_strdup(task_name, GFP_KERNEL);			} else {				buffer->error = -ENOMEM;			}		}		if (setup)			*setup = template;		up(&pstr->oss.setup_mutex);	}}static void snd_pcm_oss_proc_init(snd_pcm_t *pcm){	int stream;	for (stream = 0; stream < 2; ++stream) {		snd_info_entry_t *entry;		snd_pcm_str_t *pstr = &pcm->streams[stream];		if (pstr->substream_count == 0)			continue;		if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) {			entry->content = SNDRV_INFO_CONTENT_TEXT;			entry->mode = S_IFREG | S_IRUGO | S_IWUSR;			entry->c.text.read_size = 8192;			entry->c.text.read = snd_pcm_oss_proc_read;			entry->c.text.write_size = 8192;			entry->c.text.write = snd_pcm_oss_proc_write;			entry->private_data = pstr;			if (snd_info_register(entry) < 0) {				snd_info_free_entry(entry);				entry = NULL;			}		}		pstr->oss.proc_entry = entry;	}}static void snd_pcm_oss_proc_done(snd_pcm_t *pcm){	int stream;	for (stream = 0; stream < 2; ++stream) {		snd_pcm_str_t *pstr = &pcm->streams[stream];		if (pstr->oss.proc_entry) {			snd_info_unregister(pstr->oss.proc_entry);			pstr->oss.proc_entry = NULL;			snd_pcm_oss_proc_free_setup_list(pstr);		}	}}/* *  ENTRY functions */static struct file_operations snd_pcm_oss_f_reg ={#ifndef LINUX_2_2	owner:		THIS_MODULE,#endif	read:		snd_pcm_oss_read,	write:		snd_pcm_oss_write,	open:		snd_pcm_oss_open,	release:	snd_pcm_oss_release,	poll:		snd_pcm_oss_poll,	ioctl:		snd_pcm_oss_ioctl,	mmap:		snd_pcm_oss_mmap,};static snd_minor_t snd_pcm_oss_reg ={	comment:	"digital audio",	f_ops:		&snd_pcm_oss_f_reg,};static void register_oss_dsp(unsigned short native_minor, snd_pcm_t *pcm, int index){	char name[128];	sprintf(name, "dsp%i%i", pcm->card->number, pcm->device);	if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,				    pcm->card, index, &snd_pcm_oss_reg,				    name) < 0) {		snd_printk("unable to register OSS PCM device %i:%i\n", pcm->card->number, pcm->device);	}}static int snd_pcm_oss_register_minor(unsigned short native_minor,				      snd_pcm_t * pcm){	pcm->oss.reg = 0;	if (snd_dsp_map[pcm->card->number] == pcm->device) {		char name[128];		int duplex;		register_oss_dsp(native_minor, pcm, 0);		duplex = (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count > 0 && 			      pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count && 			      !(pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX));		sprintf(name, "%s%s", pcm->name, duplex ? " (DUPLEX)" : "");		snd_oss_info_register(SNDRV_OSS_INFO_DEV_AUDIO,				      pcm->card->number,				      name);		pcm->oss.reg++;	}	if (snd_adsp_map[pcm->card->number] == pcm->device) {		register_oss_dsp(native_minor, pcm, 1);		pcm->oss.reg++;	}	if (pcm->oss.reg)		snd_pcm_oss_proc_init(pcm);	return 0;}static int snd_pcm_oss_unregister_minor(unsigned short native_minor,				        snd_pcm_t * pcm){	if (pcm->oss.reg) {		if (snd_dsp_map[pcm->card->number] == pcm->device) {			snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,						  pcm->card, 0);			snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->card->number);		}		if (snd_adsp_map[pcm->card->number] == pcm->device)			snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,						  pcm->card, 1);		pcm->oss.reg = 0;		snd_pcm_oss_proc_done(pcm);	}	return 0;}static snd_pcm_notify_t snd_pcm_oss_notify ={	n_register:	snd_pcm_oss_register_minor,	n_unregister:	snd_pcm_oss_unregister_minor,};static int __init alsa_pcm_oss_init(void){	int i;	int err;	if ((err = snd_pcm_notify(&snd_pcm_oss_notify, 0)) < 0)		return err;	/* check device map table */	for (i = 0; i < SNDRV_CARDS; i++) {		if (snd_dsp_map[i] < 0 || snd_dsp_map[i] >= SNDRV_PCM_DEVICES) {			snd_printk("invalid dsp_map[%d] = %d\n", i, snd_dsp_map[i]);			snd_dsp_map[i] = 0;		}		if (snd_adsp_map[i] < 0 || snd_adsp_map[i] >= SNDRV_PCM_DEVICES) {			snd_printk("invalid adsp_map[%d] = %d\n", i, snd_adsp_map[i]);			snd_adsp_map[i] = 1;		}	}	return 0;}static void __exit alsa_pcm_oss_exit(void){	snd_pcm_notify(&snd_pcm_oss_notify, 1);}module_init(alsa_pcm_oss_init)module_exit(alsa_pcm_oss_exit)

⌨️ 快捷键说明

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