数据流:
声卡设备的主设备号为:
文件core.h中
#define CONFIG_SND_MAJOR 116
文件sound.c中
static int major = CONFIG_SND_MAJOR;
这个主设备号关联一个上层的 file_operations,snd_fops。
在文件sound.c中:
static int __init alsa_sound_init(void)
{
snd_major = major;
snd_ecards_limit = cards_limit;
if (register_chrdev(major, "alsa", &snd_fops)) { //注册主设备号116并关联文件操作函数集snd_fops。
snd_printk(KERN_ERR "unable to register native major device number %d\n", major);
return -EIO;
}
。。。。。。
return 0;
}
声卡设备都是字符设备,都有自己的文件操作函数集,在设备节点创建时这些操作函数集
被包装成结构体snd_minor,根据其此设备号存放在结构体数组
static struct snd_minor *snd_minors[SNDRV_OS_MINORS];中。
结构体snd_minor的原型如下:
struct snd_minor {
int type; /* SNDRV_DEVICE_TYPE_XXX */
int card; /* card number */
int device; /* device number */
const struct file_operations *f_ops; /* file operations */
void *private_data; /* private data for f_ops->open */
struct device *dev; /* device for sysfs */
};
声卡设备节点的创建和文件操作函数的包装都是调用函数函数snd_register_device()来实现的。
static inline int snd_register_device(int type, struct snd_card *card, int dev,
const struct file_operations *f_ops,
void *private_data,
const char *name )
{
return snd_register_device_for_dev(type, card, dev, f_ops, private_data, name,snd_card_get_device_link(card));
}
int snd_register_device_for_dev( int type, struct snd_card *card, int dev,
const struct file_operations *f_ops,
void *private_data,
const char *name, struct device *device )
{
int minor;
struct snd_minor *preg;
preg = kmalloc(sizeof *preg, GFP_KERNEL);
preg->type = type;
preg->card = card ? card->number : -1;
preg->device = dev;
preg->f_ops = f_ops;
preg->private_data = private_data;
mutex_lock(&sound_mutex);
minor = snd_kernel_minor(type, card, dev);
snd_minors[minor] = preg; //将文件操作函数集f_ops包装成结构体preg放到结构体数组snd_minors[]中
//创建名为name的设备节点。
preg->dev = device_create(sound_class, device, MKDEV(major, minor), private_data, "%s", name);
。。。。。。
}
在声卡uda1341的声卡体系中总共创建了四个设备节点:
"timer","controlC%i", "pcmC%iD%ip","pcmC%iD%ic"
分别代表定时器,控制,播放流,录音流。
定时器:
在文件timer.c中
static int __init alsa_timer_init(void)
{
。。。。。。
//创建名为"timer"的设备节点,其关联的文件操作函数集为snd_timer_f_ops。
if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0,
&snd_timer_f_ops, NULL, "timer")) < 0)
snd_printk(KERN_ERR "unable to register timer device (%i)\n", err);
。。。。。。
}
文件uda134x.c中实现了一个重要函数
uda134x_soc_probe(struct platform_device *pdev)
在该函数中调用函数了snd_soc_init_card(socdev)
这个函数最终会调用如下函数:
int snd_device_register_all(struct snd_card *card)
{
struct snd_device *dev;
list_for_each_entry(dev, &card->devices, list) { //将创建剩余三个设备节点
if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) {
if ((err = dev->ops->dev_register(dev)) < 0)
return err;
dev->state = SNDRV_DEV_REGISTERED;
}
}
return 0;
}
这些snd_device 何时被添加到card->devices上的,在上一篇日志中已有论述。
控制:
在文件control.c中实现函数
static int snd_ctl_dev_register(struct snd_device *device)
{
struct snd_card *card = device->device_data;
int err, cardnum;
char name[16];
。。。。。。
cardnum = card->number;
//创建名为"controlC%i"的设备节点,关联文件操作函数集snd_ctl_f_ops
sprintf(name, "controlC%i", cardnum);
if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,
&snd_ctl_f_ops, card, name)) < 0)
return err;
。。。。。。
}
播放流 和 录音流:
static int snd_pcm_dev_register(struct snd_device *device)
{
int cidx, err;
struct snd_pcm_substream *substream;
struct snd_pcm_notify *notify;
char str[16];
struct snd_pcm *pcm = device->device_data;
struct device *dev;
。。。。。。
for (cidx = 0; cidx < 2; cidx++) { //有播放流和录音流所以是两次循环
switch (cidx) {
case SNDRV_PCM_STREAM_PLAYBACK:
sprintf(str, "pcmC%iD%ip", pcm->card->number, pcm->device); //设备节点名为"pcmC%iD%ip"
devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK;
break;
case SNDRV_PCM_STREAM_CAPTURE:
sprintf(str, "pcmC%iD%ic", pcm->card->number, pcm->device); //设备节点名为"pcmC%iD%ic"
devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE;
break;
}
。。。。。。
//创建设备节点,关联的文件操作函数集snd_pcm_f_ops[cidx]。
err = snd_register_device_for_dev(devtype, pcm->card, pcm->device,&snd_pcm_f_ops[cidx],
pcm, str, dev);
。。。。。。
for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
snd_pcm_timer_init(substream); //初始化每一个子流与定时器相关的部分。
}
。。。。。。。
}
转自:http://chxxxyg.blog.163.com/blog/static/15028119320107983813906/