一.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注冊到內核中