一.ALSA核心层注册流程分析
驱动目录:kernel-4.9/sound/core/sound.c
struct file_operations snd_fops =
{
.owner = THIS_MODULE,
.open = snd_open, (inode, file)
---->struct snd_minor *mptr = snd_minors[minor];
---->file->f_op = fops_get(mptr->f_ops);
---->file->f_op->open(inode, file);
.llseek = noop_llseek,
}
1.alsa_sound_init()
---->register_chrdev(major, "alsa", &snd_fops)
---->__register_chrdev(major, 0, 256, name, fops);
这里注册了256个cdev
驱动目录:kernel-4.9/sound/core/control.c
static const struct file_operations snd_ctl_f_ops =
{
.owner = THIS_MODULE,
.read = snd_ctl_read,
.open = snd_ctl_open,
.release = snd_ctl_release,
.llseek = no_llseek,
.poll = snd_ctl_poll,
.unlocked_ioctl = snd_ctl_ioctl,
.compat_ioctl = snd_ctl_ioctl_compat,
.fasync = snd_ctl_fasync,
};
snd_ctl_dev_register(struct snd_device *device)
---->sprintf(name, "controlC%i", cardnum);
---->snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,
&snd_ctl_f_ops, card, name)) < 0)
驱动目录:
kernel-4.9/sound/core/sound.c
kernel-4.9/sound/core/control.c
---->snd_register_device_for_dev(int type, struct snd_card *card, int dev,
struct file_operations *f_ops,
void *private_data,
char *name, struct device *device)
---->preg->type = type;
---->preg->card = card ? card->number : -1;
---->preg->device = dev;
---->preg->f_ops = f_ops;
---->preg->private_data = private_data;
---->snd_minors[minor] = preg;
---->device_create(sound_class, device, MKDEV(major,minor),private_data, "%s", name);//dev节点 /dev/sound/controlC0
2.snd_ctl_create(struct snd_card *card)
---->static struct snd_device_ops ops = {
.dev_free = snd_ctl_dev_free,
.dev_register =snd_ctl_dev_register,
.dev_disconnect = snd_ctl_dev_disconnect,
};
创建snd_card的一个实例snd_card_new
kernel-4.9/sound/core/device.c
---->snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops)
----> list_add(&dev->list, &card->devices)
然后通过snd_card_register注册到内核中:kernel-4.9/sound/core/init.c
3.snd_card_register (struct snd_card *card)
----> device_create(sound_class, card->dev, MKDEV(0, 0), card, "card%i", card->number);
//dev节点 /dev/sound/card0
---->snd_device_register_all(card)
---->list_for_each_entry(dev, &card->devices, list)
----> dev->ops->dev_register(dev)
----> init_info_for_card(card);// 建立一些相应的proc和sysfs下的文件或属性节点
4.如何要完成一个声卡驱动
如果要完成一个完整的声卡驱动,其应该满足3步曲,那就是申请、初始化和注册才能成功。
(1)创建snd_card的一个实例snd_card_new
(2)初始化结构体
(3)通过snd_card_register注册到内核中