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

📄 pcm.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
static void snd_pcm_tick_timer_func(unsigned long data){	snd_pcm_substream_t *substream = (snd_pcm_substream_t*) data;	snd_pcm_tick_elapsed(substream);}int snd_pcm_open_substream(snd_pcm_t *pcm, int stream,			   snd_pcm_substream_t **rsubstream){	snd_pcm_str_t * pstr;	snd_pcm_substream_t * substream;	snd_pcm_runtime_t * runtime;	snd_ctl_file_t *kctl;	snd_card_t *card;	struct list_head *list;	int prefer_subdevice = -1;	size_t size;	snd_assert(rsubstream != NULL, return -EINVAL);	*rsubstream = NULL;	snd_assert(pcm != NULL, return -ENXIO);	pstr = &pcm->streams[stream];	if (pstr->substream == NULL)		return -ENODEV;	card = pcm->card;	down_read(&card->controls_rwsem);	list_for_each(list, &card->ctl_files) {		kctl = snd_ctl_file(list);		if (kctl->pid == current->pid) {			prefer_subdevice = kctl->prefer_pcm_subdevice;			break;		}	}	up_read(&card->controls_rwsem);	if (pstr->substream_count == 0)		return -ENODEV;	switch (stream) {	case SNDRV_PCM_STREAM_PLAYBACK:		if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) {			for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next) {				if (SUBSTREAM_BUSY(substream))					return -EAGAIN;			}		}		break;	case SNDRV_PCM_STREAM_CAPTURE:		if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) {			for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next) {				if (SUBSTREAM_BUSY(substream))					return -EAGAIN;			}		}		break;	default:		return -EINVAL;	}	if (prefer_subdevice >= 0) {		for (substream = pstr->substream; substream; substream = substream->next)			if (!SUBSTREAM_BUSY(substream) && substream->number == prefer_subdevice)				goto __ok;	}	for (substream = pstr->substream; substream; substream = substream->next)		if (!SUBSTREAM_BUSY(substream))			break;      __ok:	if (substream == NULL)		return -EAGAIN;	runtime = kcalloc(1, sizeof(*runtime), GFP_KERNEL);	if (runtime == NULL)		return -ENOMEM;	size = PAGE_ALIGN(sizeof(snd_pcm_mmap_status_t));	runtime->status = snd_malloc_pages(size, GFP_KERNEL);	if (runtime->status == NULL) {		kfree(runtime);		return -ENOMEM;	}	memset((void*)runtime->status, 0, size);	size = PAGE_ALIGN(sizeof(snd_pcm_mmap_control_t));	runtime->control = snd_malloc_pages(size, GFP_KERNEL);	if (runtime->control == NULL) {		snd_free_pages((void*)runtime->status, PAGE_ALIGN(sizeof(snd_pcm_mmap_status_t)));		kfree(runtime);		return -ENOMEM;	}	memset((void*)runtime->control, 0, size);	init_waitqueue_head(&runtime->sleep);	atomic_set(&runtime->mmap_count, 0);	init_timer(&runtime->tick_timer);	runtime->tick_timer.function = snd_pcm_tick_timer_func;	runtime->tick_timer.data = (unsigned long) substream;	runtime->status->state = SNDRV_PCM_STATE_OPEN;	substream->runtime = runtime;	substream->private_data = pcm->private_data;	pstr->substream_opened++;	*rsubstream = substream;	return 0;}void snd_pcm_release_substream(snd_pcm_substream_t *substream){	snd_pcm_runtime_t * runtime;	substream->file = NULL;	runtime = substream->runtime;	snd_assert(runtime != NULL, return);	if (runtime->private_free != NULL)		runtime->private_free(runtime);	snd_free_pages((void*)runtime->status, PAGE_ALIGN(sizeof(snd_pcm_mmap_status_t)));	snd_free_pages((void*)runtime->control, PAGE_ALIGN(sizeof(snd_pcm_mmap_control_t)));	if (runtime->hw_constraints.rules)		kfree(runtime->hw_constraints.rules);	kfree(runtime);	substream->runtime = NULL;	substream->pstr->substream_opened--;}static int snd_pcm_dev_register(snd_device_t *device){	int idx, cidx, err;	unsigned short minor;	snd_pcm_substream_t *substream;	struct list_head *list;	char str[16];	snd_pcm_t *pcm = device->device_data;	snd_assert(pcm != NULL && device != NULL, return -ENXIO);	down(&register_mutex);	idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device;	if (snd_pcm_devices[idx]) {		up(&register_mutex);		return -EBUSY;	}	snd_pcm_devices[idx] = pcm;	for (cidx = 0; cidx < 2; cidx++) {		int devtype = -1;		if (pcm->streams[cidx].substream == NULL)			continue;		switch (cidx) {		case SNDRV_PCM_STREAM_PLAYBACK:			sprintf(str, "pcmC%iD%ip", pcm->card->number, pcm->device);			minor = SNDRV_MINOR_PCM_PLAYBACK + idx;			devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK;			break;		case SNDRV_PCM_STREAM_CAPTURE:			sprintf(str, "pcmC%iD%ic", pcm->card->number, pcm->device);			minor = SNDRV_MINOR_PCM_CAPTURE + idx;			devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE;			break;		}		if ((err = snd_register_device(devtype, pcm->card, pcm->device, pcm->streams[cidx].reg, str)) < 0) {			snd_pcm_devices[idx] = NULL;			up(&register_mutex);			return err;		}		for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)			snd_pcm_timer_init(substream);	}	list_for_each(list, &snd_pcm_notify_list) {		snd_pcm_notify_t *notify;		notify = list_entry(list, snd_pcm_notify_t, list);		notify->n_register(pcm);	}	up(&register_mutex);	return 0;}static int snd_pcm_dev_disconnect(snd_device_t *device){	snd_pcm_t *pcm = device->device_data;	struct list_head *list;	snd_pcm_substream_t *substream;	int idx, cidx;	down(&register_mutex);	idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device;	snd_pcm_devices[idx] = NULL;	for (cidx = 0; cidx < 2; cidx++)		for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)			if (substream->runtime)				substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;	list_for_each(list, &snd_pcm_notify_list) {		snd_pcm_notify_t *notify;		notify = list_entry(list, snd_pcm_notify_t, list);		notify->n_disconnect(pcm);	}	up(&register_mutex);	return 0;}static int snd_pcm_dev_unregister(snd_device_t *device){	int idx, cidx, devtype;	snd_pcm_substream_t *substream;	struct list_head *list;	snd_pcm_t *pcm = device->device_data;	snd_assert(pcm != NULL, return -ENXIO);	down(&register_mutex);	idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device;	snd_pcm_devices[idx] = NULL;	for (cidx = 0; cidx < 2; cidx++) {		devtype = -1;		switch (cidx) {		case SNDRV_PCM_STREAM_PLAYBACK:			devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK;			break;		case SNDRV_PCM_STREAM_CAPTURE:			devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE;			break;		}		snd_unregister_device(devtype, pcm->card, pcm->device);		for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)			snd_pcm_timer_done(substream);	}	list_for_each(list, &snd_pcm_notify_list) {		snd_pcm_notify_t *notify;		notify = list_entry(list, snd_pcm_notify_t, list);		notify->n_unregister(pcm);	}	up(&register_mutex);	return snd_pcm_free(pcm);}int snd_pcm_notify(snd_pcm_notify_t *notify, int nfree){	int idx;	snd_assert(notify != NULL && notify->n_register != NULL && notify->n_unregister != NULL, return -EINVAL);	down(&register_mutex);	if (nfree) {		list_del(&notify->list);		for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) {			if (snd_pcm_devices[idx] == NULL)				continue;			notify->n_unregister(snd_pcm_devices[idx]);		}	} else {		list_add_tail(&notify->list, &snd_pcm_notify_list);		for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) {			if (snd_pcm_devices[idx] == NULL)				continue;			notify->n_register(snd_pcm_devices[idx]);		}	}	up(&register_mutex);	return 0;}/* *  Info interface */static void snd_pcm_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer){	int idx;	snd_pcm_t *pcm;	down(&register_mutex);	for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) {		pcm = snd_pcm_devices[idx];		if (pcm == NULL)			continue;		snd_iprintf(buffer, "%02i-%02i: %s : %s", idx / SNDRV_PCM_DEVICES,			    idx % SNDRV_PCM_DEVICES, pcm->id, pcm->name);		if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)			snd_iprintf(buffer, " : playback %i", pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count);		if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream)			snd_iprintf(buffer, " : capture %i", pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count);		snd_iprintf(buffer, "\n");	}	up(&register_mutex);}/* *  ENTRY functions */static snd_info_entry_t *snd_pcm_proc_entry = NULL;static int __init alsa_pcm_init(void){	snd_info_entry_t *entry;	snd_ctl_register_ioctl(snd_pcm_control_ioctl);	if ((entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL)) != NULL) {		snd_info_set_text_ops(entry, NULL, SNDRV_CARDS * SNDRV_PCM_DEVICES * 128, snd_pcm_proc_read);		if (snd_info_register(entry) < 0) {			snd_info_free_entry(entry);			entry = NULL;		}	}	snd_pcm_proc_entry = entry;	return 0;}static void __exit alsa_pcm_exit(void){	snd_ctl_unregister_ioctl(snd_pcm_control_ioctl);	if (snd_pcm_proc_entry) {		snd_info_unregister(snd_pcm_proc_entry);		snd_pcm_proc_entry = NULL;	}}module_init(alsa_pcm_init)module_exit(alsa_pcm_exit)EXPORT_SYMBOL(snd_pcm_devices);EXPORT_SYMBOL(snd_pcm_new);EXPORT_SYMBOL(snd_pcm_new_stream);EXPORT_SYMBOL(snd_pcm_notify);EXPORT_SYMBOL(snd_pcm_open_substream);EXPORT_SYMBOL(snd_pcm_release_substream);EXPORT_SYMBOL(snd_pcm_format_name);EXPORT_SYMBOL(snd_pcm_subformat_name);  /* pcm_native.c */EXPORT_SYMBOL(snd_pcm_link_rwlock);EXPORT_SYMBOL(snd_pcm_start);#ifdef CONFIG_PMEXPORT_SYMBOL(snd_pcm_suspend);EXPORT_SYMBOL(snd_pcm_suspend_all);#endifEXPORT_SYMBOL(snd_pcm_kernel_playback_ioctl);EXPORT_SYMBOL(snd_pcm_kernel_capture_ioctl);EXPORT_SYMBOL(snd_pcm_kernel_ioctl);EXPORT_SYMBOL(snd_pcm_open);EXPORT_SYMBOL(snd_pcm_release);EXPORT_SYMBOL(snd_pcm_playback_poll);EXPORT_SYMBOL(snd_pcm_capture_poll);EXPORT_SYMBOL(snd_pcm_mmap_data);#if SNDRV_PCM_INFO_MMAP_IOMEMEXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);#endif /* pcm_misc.c */EXPORT_SYMBOL(snd_pcm_format_signed);EXPORT_SYMBOL(snd_pcm_format_unsigned);EXPORT_SYMBOL(snd_pcm_format_linear);EXPORT_SYMBOL(snd_pcm_format_little_endian);EXPORT_SYMBOL(snd_pcm_format_big_endian);EXPORT_SYMBOL(snd_pcm_format_width);EXPORT_SYMBOL(snd_pcm_format_physical_width);EXPORT_SYMBOL(snd_pcm_format_size);EXPORT_SYMBOL(snd_pcm_format_silence_64);EXPORT_SYMBOL(snd_pcm_format_set_silence);EXPORT_SYMBOL(snd_pcm_build_linear_format);EXPORT_SYMBOL(snd_pcm_limit_hw_rates);

⌨️ 快捷键说明

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