ALSA声卡笔记1---ALSA驱动框架

1、声卡驱动程序sound.c

(1)入口函数里通过register_chrdev()函数注册file_operations 结构体

(2)file_operations 结构体,里面只有open函数,没有发现读写函数,可知open函数是起中转作用的函数,肯定会找到一个新的file_operations 结构体

ALSA声卡笔记1---ALSA驱动框架_第1张图片

(3)调用过程

  • 以minor变量保存传入节点inode结构体的次设备号
  • 以minor为下标在结构体数组中取出一项,让mptr指针指向此项
  • 表示取出mptr结构体指针里的file_operations 结构体
  • 调用file_operations 结构体里面的open函数

ALSA声卡笔记1---ALSA驱动框架_第2张图片

2、谁来设置snd_minors[]结构体数组

(1)谁来设置snd_minors[]结构体数组


函数里面有数组项snd_minors外,为了mdev或udev能自动创建设备节点,我们有class_create()函数创建类,下面创建设备device_create(),类在Sound_ core.c入口函数里面被创建,sound.c的入口函数里面注册字符设备函数,snd_register_device_for_dev()函数里面创建声卡逻辑设备时有device_create()


(2)snd_register_device_for_dev()函数被谁调用(有两路调用)

一路声卡设备的控制接口

ALSA声卡笔记1---ALSA驱动框架_第3张图片

另一路声卡设备的数据接口


两路分析之---第一路

3、第一路调用分析

(1)snd_register_device()被谁调用(Core.h)

ALSA声卡笔记1---ALSA驱动框架_第4张图片

(2)创建声卡设备的控制接口函数snd_ctl_dev_register()被谁调用(control.c)


ALSA声卡笔记1---ALSA驱动框架_第5张图片

(3)由上面可知函数snd_ctl_create()在init.c程序的


中被调用

(4)由可知创建一个snd_card结构体

两路分析之---第二路

4、第二路调用分析

(1)创建声卡设备的数据接口函数snd_pcm_dev_register()函数被谁调用(Pcm.c)

ALSA声卡笔记1---ALSA驱动框架_第6张图片

(2)创建一个新的PCM设备函数_snd_pcm_new()被谁调用


(3)snd_pcm_new()被谁调用

某个声卡的驱动程序

5、代码框架重新梳理(第1路)

(1)snd_card_create()函数(Init.c)


除了创建一个snd_card结构体外,还会调用snd_ctl_create()


这表示所有声卡里面,必定会有控制接口

(2)创建控制类的逻辑设备snd_ctl_create()函数

ALSA声卡笔记1---ALSA驱动框架_第7张图片

里snd_device_new()函数可以看出,对于同一个声卡,里面可能有多个逻辑设备,device应该就是逻辑设备的意思(有control、pcm等),参数SNDRV_DEV_CONTROL表示其类别,最终snd_ctl_dev_register()被调用

(3)snd_ctl_dev_register()函数

里面的snd_register_device()函数注册一个file_operations 结构体snd_ctl_f_ops

ALSA声卡笔记1---ALSA驱动框架_第8张图片

(4)snd_register_device()函数

ALSA声卡笔记1---ALSA驱动框架_第9张图片

(5)snd_register_device_for_dev()函数

填充结构体数组snd_minors[]


6、代码框架重新梳理(第2路)

(1)snd_pcm_new()调用


(2)_snd_pcm_new()调用  (创建播放流和录音流)

ALSA声卡笔记1---ALSA驱动框架_第10张图片

创建声卡的逻辑设备,这个逻辑设备最后会导致snd_pcm_dev_register()函数被调用


(3)snd_pcm_dev_register()函数


(4)snd_pcm_f_ops结构体数组,第0项表示播放,第1项表示录音,在Pcm.c里

7、创建设备节点的名字的取值(第1路)

(1)snd_register_device_for_dev()函数里的device_create()函数,其中“%s”来源于name,这个name是snd_register_device_for_dev()函数传进来的参数



(2)snd_register_device_for_dev()函数被 snd_register_device()函数调用,也就是snd_register_device_for_dev()函数里面的name参数是 snd_register_device()函数传过来的

ALSA声卡笔记1---ALSA驱动框架_第11张图片

(3)snd_register_device()函数 snd_ctl_dev_register()函数调用,由下面可以看出name参数根据可知为controlC%i,C表示Card声卡,其中i值来源于右边的cardnum,这个cardnum来源于snd_card结构体中的成员。而snd_card结构体来源于snd_device结构体的snd_card结构体。

ALSA声卡笔记1---ALSA驱动框架_第12张图片

8、创建设备节点的名字的取值(第2路)

(1)snd_register_device_for_dev()函数里的device_create()函数,其中“%s”来源于name,这个name是snd_register_device_for_dev()函数传进来的参数



(2)snd_register_device_for_dev()函数被snd_pcm_dev_register()函数调用


里面的str参数正是name参数,下面有pcmC%iD%ip和pcmC%iD%ic,C表示Card的意思,%i表示哪一个声卡,D表示哪一个声卡下的哪一个逻辑设备,p表示播放,c表示录音

ALSA声卡笔记1---ALSA驱动框架_第13张图片

9、总结(如何写alsa声卡驱动)

(1)构造snd_card结构体snd_card_create()构造snd_card结构体并自动创建控制接口。调用函数snd_ctrl_create

(2)初始化;如snd_pcm_new(),创建逻辑设备(播放设备或录音设备)

(3)注册 snd_card_register

ALSA声卡笔记1---ALSA驱动框架_第14张图片

你可能感兴趣的:(声卡)