ALSA driver学习

本文详细介绍了ALSA内核驱动中的核心文件,包括初始化、注册声卡和设备、结构定义、关键函数以及初始化流程,重点讲解了card、device和pcm的相关数据结构和功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

核心文件

sound/core/sound.c:alsa driver,用于初始化,注册字符设备等

sound/core/init.c:提供一些card相关的API

sound/core/device.c:提供一些device相关的API

sound/core/pcm.c:初始化pcm相关的设备节点,提供一些pcm相关的API

card相关

数据结构

struct snd_card:alsa声卡结构

int number:声卡编号

char id[16]:声卡的标识名称

void *private_data:保存是有数据

struct list_head devices:记录该声卡下所有逻辑设备的链表(按照类型的数字从小到大排列)

struct list_head controls :记录该声卡下所有的控制单元的链表

关键函数

snd_card_new:创建一个新的声卡结构

snd_card_free:释放一个声卡结构

snd_card_register:注册声卡设备,将其注册到静态结构:static struct snd_card *snd_cards[SNDRV_CARDS];

snd_device_initialize:将设备注册到声卡下

snd_card_file_add:将文件连接到声卡目录下

snd_register_device:将声卡挂载的设备添加到kernel,并且保存到:static struct snd_minor *snd_minors[SNDRV_OS_MINORS];

snd_unregister_device:释放已注册的device
device相关

数据结构

struct snd_device:声卡设备结构体

struct list_head list:用于向snd_card注册

struct snd_card *card:设备所属声卡

enum snd_device_type type:设备类型

void *device_data:私有数据,如snd_pcm

struct snd_device_ops *ops:回调函数,用于注册和释放

关键函数

snd_device_new:将device注册到card的链表

snd_device_register_all:将card的所有所属设备,进行注册(通过device的dev_register)
pcm相关

每个pcm类型的设备,作为一个device挂在到card的device链表;每个pcm设备的stream向内核注册一个device(一般是2个)

数据结构

struct snd_pcm:pcm设备结构

struct snd_card *card:所属声卡

int device:该pcm是声卡下的第几个pcm,第一个pcm设备从0开始

char id[64]:pcm设备的标志名称

struct snd_pcm_str streams[2]:该数组中的两个元素指向两个snd_pcm_str结构,分别代表playback stream和capture stream。snd_pcm_str中的substream字段,指向snd_pcm_substream结构snd_pcm_substream是pcm中间层的核心,绝大部分任务都是在substream中处理,尤其是他的ops(snd_pcm_ops)字段,许多user空间的应用程序通过alsa-lib对驱动程序的请求都是由该结构中的函数处理

struct snd_pcm_hardware:PCM硬件参数结构(播放录音分开),open后保存在runtime->hw

struct snd_pcm_ops:pcm的操作函数集(播放录音分开)。通过snd_pcm_set_ops进行设置

struct snd_pcm_runtime:pcm信息库。保存在substream->runtime,snd_pcm_runtime该substream的一些重要的软件和硬件运行环境和参数

struct snd_pcm_hardware hw:保存pcm硬件参数,open时设置。

unsigned char *dma_area:DMA缓冲区虚拟地址

dma_addr_t dma_addr:DMA缓冲区物理地址,仅当缓冲区是线性缓冲区时才指定此字段

size_t dma_bytes:DMA缓冲区长度,单位字节

struct snd_pcm_mmap_status *status:运行状态。可以通过runtime->status->hw_ptr获取当前的DMA硬件指针。

struct snd_pcm_mmap_control *control:控制状态。DMA 应用程序指针可以通过 runtime->control 引用

void *private_data:指向用户私有数据结构

struct snd_pcm_substream:子流结构体,保存在stream->substream

struct snd_pcm_str:流结构,保存在pcm->streams

关键函数

snd_pcm_new:将pcm注册到card的链表

snd_pcm_new_stream:向pcm设备添加一个stream

snd_pcm_set_ops:设置pcm的操作函数集

callback函数

snd_xxx_open:打开pcm设备回调函数,在打开pcm设备时被调用。函数中会设置substream->hw

snd_xxx_close:关闭pcm设备回调函数,在关闭pcm设备时被调用。

snd_xxx_hw_params:设置pcm硬件参数回调函数,在pcm ioct/prepare等多处被调用

snd_xxx_hw_free:释放pcm硬件参数回调函数,在pcm ioct/close等多处被调用

snd_xxx_prepare:正式开始数据传送之前会调用该函数,该函数通常会完成dma操作的必要准备工作

snd_xxx_trigger:数据传送的开始,暂停,恢复和停止时,该函数会被调用,该函数通常触发DMA

snd_xxx_pointer:该函数返回传送数据的当前位置

中断函数

snd_pcm_period_elapsed:PCM中间层更新指针位置和计算缓冲区可用空间
control相关

数据结构

struct snd_kcontrol_new:创建前用于声明control组件

snd_ctl_elem_iface_t iface:指出了control的类型,alsa定义了几种类型(SNDDRV_CTL_ELEM_IFACE_XXX),常用的类型是MIXER,当然也可以定义属于全局的CARD类型,也可以定义属于某类设备的类型,例如HWDEP,PCMRAWMIDI,TIMER等,这时需要在device和subdevice字段中指出卡的设备逻辑编号

const unsigned char *name:是该control的名字,从ALSA 0.9.x开始,control的名字是变得比较重要,因为control的作用是按名字来归类的

unsigned int index:用于保存该control的在该卡中的编号。如果声卡中有不止一个codec,每个codec中有相同名字的control,这时我们可以通过index来区分这些controls。当index为0时,则可以忽略这种区分策略

unsigned int access:包含了该control的访问类型。每一个bit代表一种访问类型,这些访问类型可以多个“或”运算组合在一起。

unsigned int count:相同control组件的数量

snd_kcontrol_info_t *info:回调函数,获取control信息

snd_kcontrol_get_t *get:回调函数,获取control的值

snd_kcontrol_put_t *put:回调函数,设置control的值

union {

snd_kcontrol_tlv_rw_t *c;

const unsigned int *p;

} tlv:该control提供元数据(metadata)。用于control数值与DB值转换。tlv

unsigned long private_value:包含了一个任意的长整数类型值。该值可以通过info,get,put这几个回调函数访问。你可以自己决定如何使用该字段,例如可以把它拆分成多个位域,又或者是一个指针,指向某一个数据结构。

metadata:用于control数值与DB值转换

DECLARE_TLV_DB_SCALE:第一个参数为名称,第二个参数为最小值,第三个参数为步长,第四个参数为最小时是否mute

DECLARE_TLV_DB_LINEAR:第一个参数为名称,第二个参数为最小值,第三个参数为最大值,第四个参数为最小时是否mute

struct snd_kcontrol:创建后的control组件

关键函数

snd_ctl_new1:创建control组件

snd_ctl_add:将control注册到card

snd_ctl_notify:通知用户层control值发生变化

初始化流程

sound.c

1.注册声卡的字符设备,其他模块通过其为device注册节点文件(snd_register_device)。注册之后的设备保存到static struct snd_minor *snd_minors[SNDRV_OS_MINORS],上层应用调用snd_open时,通过其进行索引并替换对应的ops函数。

2.调用snd_info_init,创建asound目录

pcm.c

1.调用snd_ctl_register_ioctl创建pcm扩展的ioctl 命令

2.调用snd_pcm_proc_init创建proc的pcm节点文件

参考资料

Writing an ALSA Driver

Linux ALSA声卡驱动

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值