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

📄 pcm_native.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 				  snd_pcm_hw_rule_mulkdiv, (void*) 8,				  SNDRV_PCM_HW_PARAM_PERIOD_BYTES, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);	if (err < 0)		return err;	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 				  snd_pcm_hw_rule_muldivk, (void*) 1000000,				  SNDRV_PCM_HW_PARAM_PERIOD_TIME, SNDRV_PCM_HW_PARAM_RATE, -1);	if (err < 0)		return err;	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 				  snd_pcm_hw_rule_mul, NULL,				  SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_PERIODS, -1);	if (err < 0)		return err;	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 				  snd_pcm_hw_rule_mulkdiv, (void*) 8,				  SNDRV_PCM_HW_PARAM_BUFFER_BYTES, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);	if (err < 0)		return err;	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 				  snd_pcm_hw_rule_muldivk, (void*) 1000000,				  SNDRV_PCM_HW_PARAM_BUFFER_TIME, SNDRV_PCM_HW_PARAM_RATE, -1);	if (err < 0)		return err;	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 				  snd_pcm_hw_rule_muldivk, (void*) 8,				  SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);	if (err < 0)		return err;	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 				  snd_pcm_hw_rule_muldivk, (void*) 8,				  SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);	if (err < 0)		return err;	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 				  snd_pcm_hw_rule_mulkdiv, (void*) 1000000,				  SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_RATE, -1);	if (err < 0)		return err;	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_TIME, 				  snd_pcm_hw_rule_mulkdiv, (void*) 1000000,				  SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_RATE, -1);	if (err < 0)		return err;	return 0;}int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream){	struct snd_pcm_runtime *runtime = substream->runtime;	struct snd_pcm_hardware *hw = &runtime->hw;	int err;	unsigned int mask = 0;        if (hw->info & SNDRV_PCM_INFO_INTERLEAVED)		mask |= 1 << SNDRV_PCM_ACCESS_RW_INTERLEAVED;        if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED)		mask |= 1 << SNDRV_PCM_ACCESS_RW_NONINTERLEAVED;	if (hw->info & SNDRV_PCM_INFO_MMAP) {		if (hw->info & SNDRV_PCM_INFO_INTERLEAVED)			mask |= 1 << SNDRV_PCM_ACCESS_MMAP_INTERLEAVED;		if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED)			mask |= 1 << SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED;		if (hw->info & SNDRV_PCM_INFO_COMPLEX)			mask |= 1 << SNDRV_PCM_ACCESS_MMAP_COMPLEX;	}	err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_ACCESS, mask);	snd_assert(err >= 0, return -EINVAL);	err = snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT, hw->formats);	snd_assert(err >= 0, return -EINVAL);	err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT, 1 << SNDRV_PCM_SUBFORMAT_STD);	snd_assert(err >= 0, return -EINVAL);	err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS,					   hw->channels_min, hw->channels_max);	snd_assert(err >= 0, return -EINVAL);	err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE,					   hw->rate_min, hw->rate_max);	snd_assert(err >= 0, return -EINVAL);	err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,					   hw->period_bytes_min, hw->period_bytes_max);	snd_assert(err >= 0, return -EINVAL);	err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIODS,					   hw->periods_min, hw->periods_max);	snd_assert(err >= 0, return -EINVAL);	err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,					   hw->period_bytes_min, hw->buffer_bytes_max);	snd_assert(err >= 0, return -EINVAL);	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 				  snd_pcm_hw_rule_buffer_bytes_max, substream,				  SNDRV_PCM_HW_PARAM_BUFFER_BYTES, -1);	if (err < 0)		return err;	/* FIXME: remove */	if (runtime->dma_bytes) {		err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 0, runtime->dma_bytes);		snd_assert(err >= 0, return -EINVAL);	}	if (!(hw->rates & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))) {		err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 					  snd_pcm_hw_rule_rate, hw,					  SNDRV_PCM_HW_PARAM_RATE, -1);		if (err < 0)			return err;	}	/* FIXME: this belong to lowlevel */	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_TICK_TIME,				     1000000 / HZ, 1000000 / HZ);	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);	return 0;}static void pcm_release_private(struct snd_pcm_substream *substream){	snd_pcm_unlink(substream);}void snd_pcm_release_substream(struct snd_pcm_substream *substream){	substream->ref_count--;	if (substream->ref_count > 0)		return;	snd_pcm_drop(substream);	if (substream->hw_opened) {		if (substream->ops->hw_free != NULL)			substream->ops->hw_free(substream);		substream->ops->close(substream);		substream->hw_opened = 0;	}	if (substream->pcm_release) {		substream->pcm_release(substream);		substream->pcm_release = NULL;	}	snd_pcm_detach_substream(substream);}EXPORT_SYMBOL(snd_pcm_release_substream);int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,			   struct file *file,			   struct snd_pcm_substream **rsubstream){	struct snd_pcm_substream *substream;	int err;	err = snd_pcm_attach_substream(pcm, stream, file, &substream);	if (err < 0)		return err;	if (substream->ref_count > 1) {		*rsubstream = substream;		return 0;	}	err = snd_pcm_hw_constraints_init(substream);	if (err < 0) {		snd_printd("snd_pcm_hw_constraints_init failed\n");		goto error;	}	if ((err = substream->ops->open(substream)) < 0)		goto error;	substream->hw_opened = 1;	err = snd_pcm_hw_constraints_complete(substream);	if (err < 0) {		snd_printd("snd_pcm_hw_constraints_complete failed\n");		goto error;	}	*rsubstream = substream;	return 0; error:	snd_pcm_release_substream(substream);	return err;}EXPORT_SYMBOL(snd_pcm_open_substream);static int snd_pcm_open_file(struct file *file,			     struct snd_pcm *pcm,			     int stream,			     struct snd_pcm_file **rpcm_file){	struct snd_pcm_file *pcm_file;	struct snd_pcm_substream *substream;	struct snd_pcm_str *str;	int err;	snd_assert(rpcm_file != NULL, return -EINVAL);	*rpcm_file = NULL;	err = snd_pcm_open_substream(pcm, stream, file, &substream);	if (err < 0)		return err;	pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);	if (pcm_file == NULL) {		snd_pcm_release_substream(substream);		return -ENOMEM;	}	pcm_file->substream = substream;	if (substream->ref_count == 1) {		str = substream->pstr;		substream->file = pcm_file;		substream->pcm_release = pcm_release_private;	}	file->private_data = pcm_file;	*rpcm_file = pcm_file;	return 0;}static int snd_pcm_playback_open(struct inode *inode, struct file *file){	struct snd_pcm *pcm;	pcm = snd_lookup_minor_data(iminor(inode),				    SNDRV_DEVICE_TYPE_PCM_PLAYBACK);	return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);}static int snd_pcm_capture_open(struct inode *inode, struct file *file){	struct snd_pcm *pcm;	pcm = snd_lookup_minor_data(iminor(inode),				    SNDRV_DEVICE_TYPE_PCM_CAPTURE);	return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);}static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream){	int err;	struct snd_pcm_file *pcm_file;	wait_queue_t wait;	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;	}	init_waitqueue_entry(&wait, current);	add_wait_queue(&pcm->open_wait, &wait);	mutex_lock(&pcm->open_mutex);	while (1) {		err = snd_pcm_open_file(file, pcm, stream, &pcm_file);		if (err >= 0)			break;		if (err == -EAGAIN) {			if (file->f_flags & O_NONBLOCK) {				err = -EBUSY;				break;			}		} else			break;		set_current_state(TASK_INTERRUPTIBLE);		mutex_unlock(&pcm->open_mutex);		schedule();		mutex_lock(&pcm->open_mutex);		if (signal_pending(current)) {			err = -ERESTARTSYS;			break;		}	}	remove_wait_queue(&pcm->open_wait, &wait);	mutex_unlock(&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_release(struct inode *inode, struct file *file){	struct snd_pcm *pcm;	struct snd_pcm_substream *substream;	struct snd_pcm_file *pcm_file;	pcm_file = file->private_data;	substream = pcm_file->substream;	snd_assert(substream != NULL, return -ENXIO);	pcm = substream->pcm;	fasync_helper(-1, file, 0, &substream->runtime->fasync);	mutex_lock(&pcm->open_mutex);	snd_pcm_release_substream(substream);	kfree(pcm_file);	mutex_unlock(&pcm->open_mutex);	wake_up(&pcm->open_wait);	module_put(pcm->card->module);	snd_card_file_remove(pcm->card, file);	return 0;}static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream,						 snd_pcm_uframes_t frames){	struct snd_pcm_runtime *runtime = substream->runtime;	snd_pcm_sframes_t appl_ptr;	snd_pcm_sframes_t ret;	snd_pcm_sframes_t hw_avail;	if (frames == 0)		return 0;	snd_pcm_stream_lock_irq(substream);	switch (runtime->status->state) {	case SNDRV_PCM_STATE_PREPARED:		break;	case SNDRV_PCM_STATE_DRAINING:	case SNDRV_PCM_STATE_RUNNING:		if (snd_pcm_update_hw_ptr(substream) >= 0)			break;		/* Fall through */	case SNDRV_PCM_STATE_XRUN:		ret = -EPIPE;		goto __end;	default:		ret = -EBADFD;		goto __end;	}	hw_avail = snd_pcm_playback_hw_avail(runtime);	if (hw_avail <= 0) {		ret = 0;		goto __end;	}	if (frames > (snd_pcm_uframes_t)hw_avail)		frames = hw_avail;	else		frames -= frames % runtime->xfer_align;	appl_ptr = runtime->control->appl_ptr - frames;	if (appl_ptr < 0)		appl_ptr += runtime->boundary;	runtime->control->appl_ptr = appl_ptr;	if (runtime->status->state == SNDRV_PCM_STATE_RUNNING &&	    runtime->sleep_min)		snd_pcm_tick_prepare(substream);	ret = frames; __end:	snd_pcm_stream_unlock_irq(substream);	return ret;}static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substream,						snd_pcm_uframes_t frames){	struct snd_pcm_runtime *runtime = substream->runtime;	snd_pcm_sframes_t appl_ptr;	snd_pcm_sframes_t ret;	snd_pcm_sframes_t hw_avail;	if (frames == 0)		return 0;	snd_pcm_stream_lock_irq(substream);	switch (runtime->status->state) {	case SNDRV_PCM_STATE_PREPARED:	case SNDRV_PCM_STATE_DRAINING:		break;	case SNDRV_PCM_STATE_RUNNING:		if (snd_pcm_update_hw_ptr(substream) >= 0)			break;		/* Fall through */	case SNDRV_PCM_STATE_XRUN:		ret = -EPIPE;		goto __end;	default:		ret = -EBADFD;		goto __end;	}	hw_avail = snd_pcm_capture_hw_avail(runtime);	if (hw_avail <= 0) {		ret = 0;		goto __end;	}	if (frames > (snd_pcm_uframes_t)hw_avail)		frames = hw_avail;	else		frames -= frames % runtime->xfer_align;	appl_ptr = runtime->control->appl_ptr - frames;	if (appl_ptr < 0)		appl_ptr += runtime->boundary;	runtime->control->appl_ptr = appl_ptr;	if (runtime->status->state == SNDRV_PCM_STATE_RUNNING &&	    runtime->sleep_min)		snd_pcm_tick_prepare(substream);	ret = frames; __end:	snd_pcm_stream_unlock_irq(substream);	return ret;}static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *substream,						  snd_pcm_uframes_t frames){	struct snd_pcm_runtime *runtime = substream->runtime;	snd_pcm_sframes_t appl_ptr;	snd_pcm_sframes_t ret;	snd_pcm_sframes_t avail;	if (frames == 0)		return 0;	snd_pcm_stream_lock_irq(substream);	switch (runtime->status->state) {	case SNDRV_PCM_STATE_PREPARED:	case SNDRV_PCM_STATE_PAUSED:		break;	case SNDRV_PCM_STATE_DRAINING:	case SNDRV_PCM_STATE_RUNNING:		if (snd_pcm_update_hw_ptr(substream) >= 0)			break;		/* Fall through */	case SNDRV_PCM_STATE_XRUN:		ret = -EPIPE;		goto __end;	default:		ret = -EBADFD;		goto __end;	}	avail = snd_pcm_playback_avail(runtime);	if (avail <= 0) {		ret = 0;		goto __end;	}	if (frames > (snd_pcm_uframes_t)avail)		frames = avail;	else		frames -= frames % runtime->xfer_align;	appl_ptr = runtime->control->appl_ptr + frames;	if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)		appl_ptr -= runtime->boundary;	runtime->control->appl_ptr = appl_ptr;	if (runtime->status->state == SNDRV_PCM_STATE_RUNNING &&	    runtime->sleep_min)		snd_pcm_tick_prepare(substream);	ret = frames; __end:	snd_pcm_stream_unlock_irq(substream);	return ret;}static snd_pcm_sframes_t snd_pcm_capture_forward(struct 

⌨️ 快捷键说明

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