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

📄 pcm.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  Digital Audio (PCM) abstract layer *  Copyright (c) by Jaroslav Kysela <perex@perex.cz> * * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA * */#include <sound/driver.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/time.h>#include <linux/mutex.h>#include <sound/core.h>#include <sound/minors.h>#include <sound/pcm.h>#include <sound/control.h>#include <sound/info.h>MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Abramo Bagnara <abramo@alsa-project.org>");MODULE_DESCRIPTION("Midlevel PCM code for ALSA.");MODULE_LICENSE("GPL");static LIST_HEAD(snd_pcm_devices);static LIST_HEAD(snd_pcm_notify_list);static DEFINE_MUTEX(register_mutex);static int snd_pcm_free(struct snd_pcm *pcm);static int snd_pcm_dev_free(struct snd_device *device);static int snd_pcm_dev_register(struct snd_device *device);static int snd_pcm_dev_disconnect(struct snd_device *device);static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device){	struct snd_pcm *pcm;	list_for_each_entry(pcm, &snd_pcm_devices, list) {		if (pcm->card == card && pcm->device == device)			return pcm;	}	return NULL;}static int snd_pcm_control_ioctl(struct snd_card *card,				 struct snd_ctl_file *control,				 unsigned int cmd, unsigned long arg){	switch (cmd) {	case SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE:		{			int device;			if (get_user(device, (int __user *)arg))				return -EFAULT;			mutex_lock(&register_mutex);			device = device < 0 ? 0 : device + 1;			while (device < SNDRV_PCM_DEVICES) {				if (snd_pcm_search(card, device))					break;				device++;			}			if (device == SNDRV_PCM_DEVICES)				device = -1;			mutex_unlock(&register_mutex);			if (put_user(device, (int __user *)arg))				return -EFAULT;			return 0;		}	case SNDRV_CTL_IOCTL_PCM_INFO:		{			struct snd_pcm_info __user *info;			unsigned int device, subdevice;			int stream;			struct snd_pcm *pcm;			struct snd_pcm_str *pstr;			struct snd_pcm_substream *substream;			int err;			info = (struct snd_pcm_info __user *)arg;			if (get_user(device, &info->device))				return -EFAULT;			if (get_user(stream, &info->stream))				return -EFAULT;			if (stream < 0 || stream > 1)				return -EINVAL;			if (get_user(subdevice, &info->subdevice))				return -EFAULT;			mutex_lock(&register_mutex);			pcm = snd_pcm_search(card, device);			if (pcm == NULL) {				err = -ENXIO;				goto _error;			}			pstr = &pcm->streams[stream];			if (pstr->substream_count == 0) {				err = -ENOENT;				goto _error;			}			if (subdevice >= pstr->substream_count) {				err = -ENXIO;				goto _error;			}			for (substream = pstr->substream; substream;			     substream = substream->next)				if (substream->number == (int)subdevice)					break;			if (substream == NULL) {				err = -ENXIO;				goto _error;			}			err = snd_pcm_info_user(substream, info);		_error:			mutex_unlock(&register_mutex);			return err;		}	case SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE:		{			int val;						if (get_user(val, (int __user *)arg))				return -EFAULT;			control->prefer_pcm_subdevice = val;			return 0;		}	}	return -ENOIOCTLCMD;}#ifdef CONFIG_SND_VERBOSE_PROCFS#define STATE(v) [SNDRV_PCM_STATE_##v] = #v#define STREAM(v) [SNDRV_PCM_STREAM_##v] = #v#define READY(v) [SNDRV_PCM_READY_##v] = #v#define XRUN(v) [SNDRV_PCM_XRUN_##v] = #v#define SILENCE(v) [SNDRV_PCM_SILENCE_##v] = #v#define TSTAMP(v) [SNDRV_PCM_TSTAMP_##v] = #v#define ACCESS(v) [SNDRV_PCM_ACCESS_##v] = #v#define START(v) [SNDRV_PCM_START_##v] = #v#define FORMAT(v) [SNDRV_PCM_FORMAT_##v] = #v#define SUBFORMAT(v) [SNDRV_PCM_SUBFORMAT_##v] = #v static char *snd_pcm_format_names[] = {	FORMAT(S8),	FORMAT(U8),	FORMAT(S16_LE),	FORMAT(S16_BE),	FORMAT(U16_LE),	FORMAT(U16_BE),	FORMAT(S24_LE),	FORMAT(S24_BE),	FORMAT(U24_LE),	FORMAT(U24_BE),	FORMAT(S32_LE),	FORMAT(S32_BE),	FORMAT(U32_LE),	FORMAT(U32_BE),	FORMAT(FLOAT_LE),	FORMAT(FLOAT_BE),	FORMAT(FLOAT64_LE),	FORMAT(FLOAT64_BE),	FORMAT(IEC958_SUBFRAME_LE),	FORMAT(IEC958_SUBFRAME_BE),	FORMAT(MU_LAW),	FORMAT(A_LAW),	FORMAT(IMA_ADPCM),	FORMAT(MPEG),	FORMAT(GSM),	FORMAT(SPECIAL),	FORMAT(S24_3LE),	FORMAT(S24_3BE),	FORMAT(U24_3LE),	FORMAT(U24_3BE),	FORMAT(S20_3LE),	FORMAT(S20_3BE),	FORMAT(U20_3LE),	FORMAT(U20_3BE),	FORMAT(S18_3LE),	FORMAT(S18_3BE),	FORMAT(U18_3LE),	FORMAT(U18_3BE),};static const char *snd_pcm_format_name(snd_pcm_format_t format){	return snd_pcm_format_names[format];}static char *snd_pcm_stream_names[] = {	STREAM(PLAYBACK),	STREAM(CAPTURE),};static char *snd_pcm_state_names[] = {	STATE(OPEN),	STATE(SETUP),	STATE(PREPARED),	STATE(RUNNING),	STATE(XRUN),	STATE(DRAINING),	STATE(PAUSED),	STATE(SUSPENDED),};static char *snd_pcm_access_names[] = {	ACCESS(MMAP_INTERLEAVED), 	ACCESS(MMAP_NONINTERLEAVED),	ACCESS(MMAP_COMPLEX),	ACCESS(RW_INTERLEAVED),	ACCESS(RW_NONINTERLEAVED),};static char *snd_pcm_subformat_names[] = {	SUBFORMAT(STD), };static char *snd_pcm_tstamp_mode_names[] = {	TSTAMP(NONE),	TSTAMP(MMAP),};static const char *snd_pcm_stream_name(int stream){	snd_assert(stream <= SNDRV_PCM_STREAM_LAST, return NULL);	return snd_pcm_stream_names[stream];}static const char *snd_pcm_access_name(snd_pcm_access_t access){	return snd_pcm_access_names[access];}static const char *snd_pcm_subformat_name(snd_pcm_subformat_t subformat){	return snd_pcm_subformat_names[subformat];}static const char *snd_pcm_tstamp_mode_name(int mode){	snd_assert(mode <= SNDRV_PCM_TSTAMP_LAST, return NULL);	return snd_pcm_tstamp_mode_names[mode];}static const char *snd_pcm_state_name(snd_pcm_state_t state){	return snd_pcm_state_names[state];}#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)#include <linux/soundcard.h>static const char *snd_pcm_oss_format_name(int format){	switch (format) {	case AFMT_MU_LAW:		return "MU_LAW";	case AFMT_A_LAW:		return "A_LAW";	case AFMT_IMA_ADPCM:		return "IMA_ADPCM";	case AFMT_U8:		return "U8";	case AFMT_S16_LE:		return "S16_LE";	case AFMT_S16_BE:		return "S16_BE";	case AFMT_S8:		return "S8";	case AFMT_U16_LE:		return "U16_LE";	case AFMT_U16_BE:		return "U16_BE";	case AFMT_MPEG:		return "MPEG";	default:		return "unknown";	}}#endifstatic void snd_pcm_proc_info_read(struct snd_pcm_substream *substream,				   struct snd_info_buffer *buffer){	struct snd_pcm_info *info;	int err;	if (! substream)		return;	info = kmalloc(sizeof(*info), GFP_KERNEL);	if (! info) {		printk(KERN_DEBUG "snd_pcm_proc_info_read: cannot malloc\n");		return;	}	err = snd_pcm_info(substream, info);	if (err < 0) {		snd_iprintf(buffer, "error %d\n", err);		kfree(info);		return;	}	snd_iprintf(buffer, "card: %d\n", info->card);	snd_iprintf(buffer, "device: %d\n", info->device);	snd_iprintf(buffer, "subdevice: %d\n", info->subdevice);	snd_iprintf(buffer, "stream: %s\n", snd_pcm_stream_name(info->stream));	snd_iprintf(buffer, "id: %s\n", info->id);	snd_iprintf(buffer, "name: %s\n", info->name);	snd_iprintf(buffer, "subname: %s\n", info->subname);	snd_iprintf(buffer, "class: %d\n", info->dev_class);	snd_iprintf(buffer, "subclass: %d\n", info->dev_subclass);	snd_iprintf(buffer, "subdevices_count: %d\n", info->subdevices_count);	snd_iprintf(buffer, "subdevices_avail: %d\n", info->subdevices_avail);	kfree(info);}static void snd_pcm_stream_proc_info_read(struct snd_info_entry *entry,					  struct snd_info_buffer *buffer){	snd_pcm_proc_info_read(((struct snd_pcm_str *)entry->private_data)->substream,			       buffer);}static void snd_pcm_substream_proc_info_read(struct snd_info_entry *entry,					     struct snd_info_buffer *buffer){	snd_pcm_proc_info_read((struct snd_pcm_substream *)entry->private_data,			       buffer);}static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,						  struct snd_info_buffer *buffer){	struct snd_pcm_substream *substream = entry->private_data;	struct snd_pcm_runtime *runtime = substream->runtime;	if (!runtime) {		snd_iprintf(buffer, "closed\n");		return;	}	if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {		snd_iprintf(buffer, "no setup\n");		return;	}	snd_iprintf(buffer, "access: %s\n", snd_pcm_access_name(runtime->access));	snd_iprintf(buffer, "format: %s\n", snd_pcm_format_name(runtime->format));	snd_iprintf(buffer, "subformat: %s\n", snd_pcm_subformat_name(runtime->subformat));	snd_iprintf(buffer, "channels: %u\n", runtime->channels);		snd_iprintf(buffer, "rate: %u (%u/%u)\n", runtime->rate, runtime->rate_num, runtime->rate_den);		snd_iprintf(buffer, "period_size: %lu\n", runtime->period_size);		snd_iprintf(buffer, "buffer_size: %lu\n", runtime->buffer_size);		snd_iprintf(buffer, "tick_time: %u\n", runtime->tick_time);#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)	if (substream->oss.oss) {		snd_iprintf(buffer, "OSS format: %s\n", snd_pcm_oss_format_name(runtime->oss.format));		snd_iprintf(buffer, "OSS channels: %u\n", runtime->oss.channels);			snd_iprintf(buffer, "OSS rate: %u\n", runtime->oss.rate);		snd_iprintf(buffer, "OSS period bytes: %lu\n", (unsigned long)runtime->oss.period_bytes);		snd_iprintf(buffer, "OSS periods: %u\n", runtime->oss.periods);		snd_iprintf(buffer, "OSS period frames: %lu\n", (unsigned long)runtime->oss.period_frames);	}#endif}static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,						  struct snd_info_buffer *buffer)

⌨️ 快捷键说明

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