LinuxALSA声卡驱动原理分析-设备打开过程和数据流程

合集下载

Linux系统中用ALSA驱动声卡流程详解

Linux系统中用ALSA驱动声卡流程详解

Linux系统中用ALSA驱动声卡流程详解一、什么是ALSAAdvanced Linux Sound Architecture 的简称为 ALSA ,译成中文的意思是 Linux 高级声音体系(这是我直译的,可能译的不对)。

一谈到体系就有点范围就太大了,所以ALSA不仅仅是包括对声卡的支持和驱动。

ALSA具有如下特征:1、对所有音频接口的高效支持,从普通用户的声卡到专业级别多路音频设备。

2、声卡驱动完全模块化设计。

3、SMP and thread-safe design。

4、开发库(alsa-lib)为程序设计提供了简单、方便,并且拥有有高级的效果和功能。

5、支持旧版本的OSS API 结口,能为大多数的OSS应用程序提供兼容。

OSS是一个商业性的驱动,OSS有一个简装本的代码已经移入内核和ALSA,其中alsa-oss就是。

OSS公司据说目前已经并不存在了。

我们没有必要用OSS 公司提供的商业版本。

用ALSA和OSS简装版足够。

二、关于硬件驱动驱动的必备基础1、如何查看硬件芯片在Linux操作系统中,所有的硬件都是以芯片组来区分的,品牌并不是最重要的。

硬件最重要的标识是芯片组。

所以您在讨论区求助的时候,只说硬件品牌,而不提供芯片组,大家是帮助不了您的,切记。

我们查看硬件的芯片组是的命令是 lspci -v 或者是dmesg,由于dmesg输出的信息不太多,不够直观。

所以经常用的还是lspci -v 。

也可以用lshal 获取。

最方便的还是lspci -v。

初学者还是用 lspci -v 更好一点。

我们运行lspci -v 后,如果查看声卡芯片组,发会现有类似下面的一段:2、系统内核版本[root@localhost beinan]# uname -r -m -p -i2.6.11-1.1369_FC4 i686 i686 i386上面的表示的是系统的内核版本,处理器架构等。

提示:如果您自己编译内核,还要安装kernel-devel (或 kernel-source),这个是在系统光盘或者映像文件中有带。

ALSA声卡驱动详解解析

ALSA声卡驱动详解解析

DAPM是Dynamic Audio Power Management的缩写,直译过来就是动态音频电源管理的意思,DAPM是为了使基于linux的移动设备上的音频子系统,在任何时候都工作在最小功耗状态下。

DAPM对用户空间的应用程序来说是透明的,所有与电源相关的开关都在ASoc core中完成。

用户空间的应用程序无需对代码做出修改,也无需重新编译,DAPM根据当前激活的音频流(playback/capture)和声卡中的mixer等的配置来决定那些音频控件的电源开关被打开或关闭。

/******************************************************************************************* **********/声明:本博内容均由/droidphone原创,转载请注明出处,谢谢!/******************************************************************************************* **********/DAPM控件是由普通的soc音频控件演变而来的,所以本章的内容我们先从普通的soc音频控件开始。

snd_kcontrol_new结构在正式讨论DAPM之前,我们需要先搞清楚ASoc中的一个重要的概念:kcontrol,不熟悉的读者需要浏览一下我之前的文章:Linux ALSA声卡驱动之四:Control设备的创建。

通常,一个kcontrol代表着一个mixer(混音器),或者是一个mux(多路开关),又或者是一个音量控制器等等。

从上述文章中我们知道,定义一个kcontrol主要就是定义一个snd_kcontrol_new 结构,为了方便讨论,这里再次给出它的定义:[cpp]view plaincopystruct snd_kcontrol_new {snd_ctl_elem_iface_t iface; /* interface identifier * /unsigned int device; /* device/client number * /unsigned int subdevice; /* subdevice (substream) number */const unsigned char *name; /* ASCII name of item */ unsigned int index; /* index of item */unsigned int access; /* access rights */unsigned int count; /* count of same elements */snd_kcontrol_info_t *info;snd_kcontrol_get_t *get;snd_kcontrol_put_t *put;union {1snd_kcontrol_tlv_rw_t *c;const unsigned int *p;} tlv;unsigned long private_value;};回到Linux ALSA声卡驱动之四:Control设备的创建中,我们知道,对于每个控件,我们需要定义一个和他对应的snd_kcontrol_new结构,这些snd_kcontrol_new结构会在声卡的初始化阶段,通过snd_soc_add_codec_controls函数注册到系统中,用户空间就可以通过amixer或alsamixer等工具查看和设定这些控件的状态。

使用最新ALSA驱动解决UbuntuLinuxIntel集成声卡问题Solrex

使用最新ALSA驱动解决UbuntuLinuxIntel集成声卡问题Solrex

使用最新ALSA驱动解决UbuntuLinuxIntel集成声卡问题Solrex使用最新 ALSA 驱动解决 Ubuntu Linux Intel 集成声卡问题目前用户所抱怨的Ubuntu 系列的声卡问题,基本上归结为几类:一,找不到声音设备;二,不发声;三,耳机和音箱同时发声;四、话筒没声。

大部分这种问题都是由笔记本上 Intel 集成声卡驱动引起的,关于这个问题的具体描述和解决方案,可以查看下面两个页面:BUG:SOLUTION:其实大部分问题都可以通过自己动手编译安装最新ALSA 驱动解决,解决方法上面两个链接中已经解释得很清楚了,我这里介绍一下我的思路:第一,查看ALSA 版本,如果最新,就不用重新安装了,仔细查看一下配置吧。

$ alsactl -v如果打印出: alsactl version 1.0.20,那么 ALSA 已经是最新了。

第二,在 ALSA 官方网站上,下载最新的 ALSA 驱动,怎么解压我就不说了吧。

$ wget ftp://ftp.alsa-/pub/driver/alsa-driver-1.0.20.tar.bz2$ wget ftp://ftp.alsa-/pub/lib/alsa-lib-1.0.20.tar.bz2$ wget ftp://ftp.alsa-/pub/utils/alsa-utils-1.0.20.tar.bz2第三,查看自己的内核版本和声卡解码芯片是否被支持。

查看支持的内核版本$ less alsa-driver-1.0.15/SUPPORTED_KERNELS查看自己声卡解码芯片(如果系统不能识别声卡,可能无法由下面两个查到,那么查看你电脑配置单吧)$ tail -2 /proc/asound/oss/sndstat或$ head -1/proc/asound/card0/codec#0比如我的 DELL D630 就显示的是下面这个Codec: SigmaTel STAC9205在alsa-driver-1.0.20/sound/Documentation/ALSA-Configuration.txt 中查找自己声卡解码芯片对应的model 名字,比如我的 STAC9205 对应的就是:STAC9205/9254ref Reference boarddell-m42 Dell (unknown)dell-m43 Dell Precisiondell-m44 Dell Inspiron如果存在对应的 model,恭喜你可以继续安装了。

Linux_ALSA声卡驱动原理分析

Linux_ALSA声卡驱动原理分析

11/12/2011
三、准备工作
4. 流程图结构说明 (1) 图示为函数的调用关系,向下为同一级调用,向右为函数内部的子函数调用。 (2) 绿色文字函数名(如function2)表示该函数是调用流程中比较关键的点。 (3) 红底白字的函数名(如function…)表示和其它层(如app和lib、lib和driver、alsa-driver和device-driver)的接口 函数或kernel的回调函数。 (4) 蓝色双虚线为函数实参等形式的输出值或函数返回值(如sun_function…有输出值到function1)。
11/12/2011
目录
一、导读 二、ALSA架构简介 三、准备工作 四、设备打开过程和数据流程 i. 整体分析 ii. 设备驱动程序insmod流程图 iii. 应用程序主流程图 iv. 声卡打开流程图 v. 数据写入流程图 五、ALSA其它形式的数据写入方法流程图
11/12/2011
三、准备工作
11/12/2011
目录
一、导读 二、ALSA架构简介 三、准备工作 四、设备打开过程和数据流程 i. 整体分析 ii. 设备驱动程序insmod流程图 iii. 应用程序主流程图 iv. 声卡打开流程图 v. 数据写入流程图 五、ALSA其它形式的数据写入方法流程图
11/12/2011
一、导 读
主函数()
function1()
sub_function1() function2() ......() sun_functionnction...()
function...()
11/12/2011
目录
一、导读 二、ALSA架构简介 三、准备工作 四、设备打开过程和数据流程 i. 整体分析 ii. 设备驱动程序insmod流程图 iii. 应用程序主流程图 iv. 声卡打开流程图 v. 数据写入流程图 五、ALSA其它形式的数据写入方法流程图

alsa 原理

alsa 原理

alsa 原理ALSA原理解析什么是ALSA?ALSA(Advanced Linux Sound Architecture)是Linux操作系统中的一种音频处理架构。

它提供了一种标准的音频设备驱动程序接口,用于操作和控制音频设备,如声卡、麦克风、扬声器等。

ALSA的组成部分ALSA由以下几个主要的组成部分组成:1.音频设备驱动程序:负责与硬件之间的通信,将音频设备的输入输出转换为数字信号,并通过内核提供的接口向应用程序提供访问。

2.音频库:提供高级的音频操作接口,为应用程序提供简化的音频处理功能。

3.控制工具:用于配置和控制音频设备的命令行工具,如alsactl和amixer。

ALSA的工作原理ALSA的工作原理可以简单概括为以下几个步骤:1.设备检测:当系统启动或插入音频设备时,ALSA会进行设备检测,并加载相应的设备驱动程序。

2.设备配置:ALSA会自动对音频设备进行配置,包括设定采样率、位深度、声道数等参数。

3.应用程序访问:应用程序通过调用ALSA提供的API接口来访问音频设备。

应用程序可以使用ALSA提供的库函数来进行音频采集、播放、混音等操作。

4.数据传输:ALSA通过DMA(Direct Memory Access)技术将音频数据从内存传输到音频设备,或者从音频设备传输到内存。

5.数据处理:音频数据在传输过程中,可以经过一系列的处理,例如音频编码、解码、混音等。

6.音量控制:ALSA提供了音量控制接口,应用程序可以通过调用API来调整音频设备的输入和输出音量。

7.音频事件处理:ALSA可以捕捉音频设备发出的事件,并通过回调函数通知应用程序。

例如,当音频设备的状态发生变化时,应用程序可以接收到相应的通知。

总结通过以上解析,我们了解了ALSA的基本原理和工作流程。

ALSA提供了一个标准的音频处理框架,使应用程序能够方便地访问和控制音频设备。

它的底层驱动程序负责和硬件进行通信,而高级的音频库则提供了简化和抽象的接口,方便应用程序进行音频处理。

Linux ALSA声卡驱动详细分析

Linux ALSA声卡驱动详细分析

1.Linux ALSA声卡驱动之一:ALSA架构简介一. 概述ALSA是Advanced Linux Sound Architecture 的缩写,目前已经成为了linux的主流音频体系结构,想了解更多的关于ALSA的这一开源项目的信息和知识,请查看以下网址:/。

在内核设备驱动层,ALSA提供了alsa-driver,同时在应用层,ALSA为我们提供了alsa-lib,应用程序只要调用alsa-lib提供的API,即可以完成对底层音频硬件的控制。

图 1.1 alsa的软件体系结构由图1.1可以看出,用户空间的alsa-lib对应用程序提供统一的API接口,这样可以隐藏了驱动层的实现细节,简化了应用程序的实现难度。

内核空间中,alsa-soc其实是对alsa-driver的进一步封装,他针对嵌入式设备提供了一些列增强的功能。

本系列博文仅对嵌入式系统中的alsa-driver和alsa-soc进行讨论。

二. ALSA设备文件结构我们从alsa在linux中的设备文件结构开始我们的alsa之旅. 看看我的电脑中的alsa驱动的设备文件结构:$ cd /dev/snd$ ls -lcrw-rw----+ 1 root audio 116, 8 2011-02-23 21:38 controlC0crw-rw----+ 1 root audio 116, 4 2011-02-23 21:38 midiC0D0crw-rw----+ 1 root audio 116, 7 2011-02-23 21:39 pcmC0D0ccrw-rw----+ 1 root audio 116, 6 2011-02-23 21:56 pcmC0D0pcrw-rw----+ 1 root audio 116, 7 2011-02-23 21:39 pcmC0D1ccrw-rw----+ 1 root audio 116, 5 2011-02-23 21:38 pcmC0D1pcrw-rw----+ 1 root audio 116, 3 2011-02-23 21:38 seqcrw-rw----+ 1 root audio 116, 2 2011-02-23 21:38 timer$我们可以看到以下设备文件:∙controlC0 --> 用于声卡的控制,例如通道选择,混音,麦克风的控制等∙midiC0D0 --> 用于播放midi音频∙pcmC0D0c --〉用于录音的pcm设备∙pcmC0D0p --〉用于播放的pcm设备∙seq --〉音序器∙timer --〉定时器其中,C0D0代表的是声卡0中的设备0,pcmC0D0c最后一个c代表capture,pcmC0D0p最后一个p代表playback,这些都是alsa-driver中的命名规则。

Linux--ALSA

Linux--ALSA

Linux ALSA 声卡驱动的分析一、ALSA && OSS在linux系统中,先后出现了音频设备的两种主要框架:OSS和ALSA.针对不同的数字音频子系统,出现了几种微处理器或DSP与音频器件间用于数字转换的接口。

1.1 音频设备的硬件接口:(1)PCM接口。

(2)IIS(I2S)接口。

(3)AC97接口。

在CD,MD,MP3随身听多采用IIS接口,移动电话会采用PCM接口,具有音频功能的PDA则多使用和PC一样的AC97编码格式。

1.2 linux OSS音频设备驱动OSS标准中有两个最基本的音频设备:mixer(混音器)和dsp(数字信号处理器)。

在声卡的硬件电路中,mixer是一个很重要的组成部分,它的作用是将多个信号组合或者叠加在一起,对于不同的声卡来说,其混音器的作用可能各不相同。

在OSS驱动中,/dev/mixer设备文件时应用程序对mixer进行操作的软件接口。

1.2.1 OSS用户空间编程(dsp编程)对OSS驱动声卡的编程使用linux文件接口函数,dsp接口的操作一般包括如下几个步骤(1)打开设备文件/dev/dsp。

(2)如果有需要,设置缓冲区大小。

(3)设置声道(channel)数量。

根据硬件设备和驱动程序的具体情况,可以设置为单声道或者立体声。

(4)设置采样格式和采样频率。

(5)读写/dev/dsp实现播放和录音。

1.3 linux ALSA音频设备驱动1.3.1 ALSA的主要特点.(1)支持多种声卡设备。

(2)模块化的内核驱动程序。

(3)支持SMP和多线程。

(4)提供应用开发函数库(alsa-lib)以简化应用程序开发。

(5)支持OSS API,兼容OSS应用程序。

ALSA系统包括驱动包alsa-driver,开发包alsa-libs,开发板插件alsa-libplugins,设置管理工具包alsa-utils,其他声音相关处理小程序包alsa-tools,特殊音频固件支持包alsa-firmware,OSS接口兼容模拟层工具alsa-oss,其中只有驱动包是必需的。

linux ALSA 声卡驱动之ALSA(Asoc)架构

linux ALSA 声卡驱动之ALSA(Asoc)架构

1.ASoC的由来ASoC--ALSA System on Chip <ALSA与芯片相关的部分>,是建立在标准ALSA驱动层上,为了更好的支持嵌入式处理器和移动设备中的音频Codec的一套软件体系。

在ASoC之前,内核对于SoC中的音频已经有部分的支持,不过有一些局限性:. Codec驱动与SoC CPU的底层耦合过于紧密,这种不理想会导致代码的重复,例如,wm8731的驱动,linux中有分别针对4个平台的驱动代码。

. 音频事件没有标准的方法来通知用户,例如耳机、麦克风的插拔和检测,这些事件在移动设备中是非常普通的,而且通常都需要特定的于机器的代码进行重新对音频路径进行配置。

. 当进行播放或录音时,驱动会让整个codec处于上电状态,这对于pc没问题,但对于移动设备来说,这意味着浪费大量的电量。

同时也不支持通过改变采样率和偏置电流来达到省电的目的。

ASoC正式为解决这些问题提出的,目前已经被整合到内核代码树中:sound/soc. ASoC 不能单独存在,他只是建立在标准ALSA驱动上,它必须和标准的ALSA驱动框架相结合才能工作2.硬件架构通常,就像软件领域里的抽象和重用一样,嵌入式设备的音频系统可以被划分为板载硬件(Machine)、Soc(platform)、Codec三大部分,如下图:. Machine 是指某一款机器,可以说是某款设备,由此可以看出Machine是不可重用的,每个Machine上的硬件实现可能都不一样,CPU不一样,Codec不一样,音频的输入,输出设备也是不一样,Machine为CPU、Codec、输入输出设备提供了一个载体。

. Platforn 一般是指某一个SoC平台,比如pxaxxx, s3cxxxx, omapxxx等,与音频相关的通常包含该SoC中的时钟、DMA、I2S、PCM等,只要指定了SoC,那么我们就可以认为它会有一个对应的platform,它只与SoC相关,与Machine无关,这样我们就可以把platform 抽象出来,使得同一款SoC不做改动就可以在不同的Machine中。

Linux ALSA声卡驱动之一:声卡的创建

Linux ALSA声卡驱动之一:声卡的创建

Linux ALSA声卡驱动之一:声卡的创建1. struct snd_card1.1. snd_card是什么snd_card可以说是整个ALSA音频驱动最顶层的一个结构,整个声卡的软件逻辑结构开始于该结构,几乎所有与声音相关的逻辑设备都是在snd_card的管理之下,声卡驱动的第一个动作通常就是创建一个snd_card结构体。

正因为如此,本节中,我们也从struct cnd_card 开始吧。

1.2. snd_card的定义snd_card的定义位于改头文件中:include/sound/core.h[c-sharp] view plain copy/* main structure for soundcard */struct snd_card {int number; /* number of soundcard (index tosnd_cards) */char id[16]; /* id string of this card */char driver[16]; /* driver name */char shortname[32]; /* short name of this soundcard */char longname[80]; /* name of this soundcard */char mixername[80]; /* mixer name */char components[128]; /* card components delimited withspace */struct module *module; /* top-level module */void *private_data; /* private data for soundcard */void (*private_free) (struct snd_card *card); /* callback for freeing ofprivate data */struct list_head devices; /* devices */unsigned int last_numid; /* last used numeric ID */struct rw_semaphore controls_rwsem; /* controls list lock */rwlock_t ctl_files_rwlock; /* ctl_files list lock */int controls_count; /* count of all controls */。

Linux ALSA声卡驱动原理分析- 设备打开过程和数据流程

Linux ALSA声卡驱动原理分析- 设备打开过程和数据流程

1. ALSA-lib调试方法
alsa-utils中的aplay程序可以进行应用程序和lib库的调试。
操作如下:
(1) 复制alsa-utils和alsa-lib到linux文件系统下,如:
#cp -rf alsa-utils-1.0.16 /opt/
#cp -rf alsa-lib-1.0.16 /opt/
1. ALSA是Advanced Linux Sound Architecture,高 级Linux声音架构的简称,它在Linux操作系统上 提供了音频和MIDI(Musical Instrument Digital Interface,音乐设备数字化接口)的支持。它 包含API 库和工具、内核驱动集合, 对 Linux 声音进行支持。 ALSA 包含一系列内核驱动对 不同的声卡进行支持,还提供了 libasound 的 API 库。用这些进行写程序不需要打开设备等 操作,所以编程人员在写程序的时候不会被底 层的东西困扰。
三、准备工作
图中红色表示为在 shell中输入的命令, 具体命令要根据具体 环境自己修改。
跟踪代码时可以在 gdb中使用 bt(backtrace)指令跟 踪调用栈查看函数调 用关系。
2020/4/3
三、准备作
3. 生成alsa-lib文档 alsa-lib中可以用文档生成工具doxygen生成API及相关说明文档。在alsa-lib-1.0.16中依次执行如下: #cd /opt/alsa-lib-1.0.16 #cd doc #doxygen doxygen.cfg
ii.设备驱动程序insmod流程图
module_init(alsa_card_ens137x_init) alsa_card_ens137x_init() pci_register_driver(&driver)

Linux_ALSA声卡驱动开发实践

Linux_ALSA声卡驱动开发实践

atic void __devexit snd_audiopci_remove(struct pci_dev *pci) FUNC_LOG();
atic struct pci_driver driver = { .name = DRIVER_NAME, .id_table = snd_audiopci_ids, .probe = snd_audiopci_probe, .remove = __devexit_p(snd_audiopci_remove), fdef CONFIG_PM //.suspend = snd_ensoniq_suspend, //.resume = snd_ensoniq_resume, endif
6. 仿照snd_audiopci_probe()和 snd_audiopci_remove()的填充与 的填充与alsa_card_ens137x_init()和alsa_card_ens137x_exit()类 似,如此一级一级的填充下去,直至模块可以播放出声音 直至模块可以播放出声音。 对于snd_audiopci_probe()这样比较复杂的函数,要一 行一行的添加,边添加边调试。如遇到变量等应该在前面函数中赋值而还没有实现的部分 如遇到变量等应该在前面函数中赋值而还没有实现的部分,可以先用if宏等方法暂 时注释掉,如下页代码中的红色部分。添加的代码如下:
define DRIVER_NAME "ENS1371“ atic struct pci_device_id snd_audiopci_ids[] = { #ifdef CHIP1370 { 0x1274, 0x5000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, #endif fdef CHIP1371 { 0x1274, 0x1371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, { 0x1274, 0x5880, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, { 0x1102, 0x8938, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, endif { 0, }

ALSA声卡驱动详解

ALSA声卡驱动详解

ALSA声卡驱动详解1.ALSA声卡驱动中的DAPM详解之一:kcontrolDAPM是Dynamic Audio Power Management的缩写,直译过来就是动态音频电源管理的意思,DAPM是为了使基于linux的移动设备上的音频子系统,在任何时候都工作在最小功耗状态下。

DAPM对用户空间的应用程序来说是透明的,所有与电源相关的开关都在ASoc core中完成。

用户空间的应用程序无需对代码做出修改,也无需重新编译,DAPM根据当前激活的音频流(playback/capture)和声卡中的mixer等的配置来决定那些音频控件的电源开关被打开或关闭。

/******************************************************************************************* **********/声明:本博内容均由/droidphone原创,转载请注明出处,谢谢!/******************************************************************************************* **********/DAPM控件是由普通的soc音频控件演变而来的,所以本章的内容我们先从普通的soc音频控件开始。

snd_kcontrol_new结构在正式讨论DAPM之前,我们需要先搞清楚ASoc中的一个重要的概念:kcontrol,不熟悉的读者需要浏览一下我之前的文章:Linux ALSA声卡驱动之四:Control 设备的创建。

通常,一个kcontrol代表着一个mixer(混音器),或者是一个mux (多路开关),又或者是一个音量控制器等等。

从上述文章中我们知道,定义一个kcontrol主要就是定义一个snd_kcontrol_new结构,为了方便讨论,这里再次给出它的定义:[cpp] view plaincopystruct snd_kcontrol_new {snd_ctl_elem_iface_t iface; /* interface identifier * /unsigned int device; /* device/client number * /unsigned int subdevice; /* subdevice (substream) number */const unsigned char *name; /* ASCII name of item */unsigned int index; /* index of item */unsigned int access; /* access rights */unsigned int count; /* count of same elements */snd_kcontrol_info_t *info;snd_kcontrol_get_t *get;snd_kcontrol_put_t *put;union {snd_kcontrol_tlv_rw_t *c;2const unsigned int *p;} tlv;unsigned long private_value;};回到Linux ALSA声卡驱动之四:Control设备的创建中,我们知道,对于每个控件,我们需要定义一个和他对应的snd_kcontrol_new结构,这些snd_kcontrol_new结构会在声卡的初始化阶段,通过snd_soc_add_codec_controls函数注册到系统中,用户空间就可以通过amixer 或alsamixer等工具查看和设定这些控件的状态。

Linux ALSA声卡驱动原理分析- 设备打开过程和数据流程

Linux ALSA声卡驱动原理分析- 设备打开过程和数据流程

pci_enable_device()
snd_ensoniq_1371_mixer() snd_ac97_bus() snd_ac97_mixer()
snd_ensoniq_pcm()
pci_request_regions() pci_resource_start() request_irq() pci_set_master()
※红色文字表示shell中输入的命令,具体命令要根据具体环境自己修改。
alsa-utils-1.0.16和alsa-lib-1.0.16从网上下,也可以在光盘debian-506-source-DVD-1.iso中的pool/main/a/文件夹下找到。
(2). 复制音频文件,如复制test_files文件夹到/opt下,
(6). 通过gdb可以对alsa-utils的aplay和alsa-lib的libsound.so进行本地调试。
#gdb aplay
(gdb)set args /opt/test_files/pcm.wav
(gdb)b main
(gdb)r
1/5/2020
… … ... …
2. ALSA-lib调试方法示例。
i. 整体分析
四、设备打开过程和数据流程
ALSA应用程序
app 1
……
app n
ALSA-lib
control
timer
… pcm
dmix
ALSA-driver hardware
内核API 设备驱动
ens1371
user space kernel space
1. 声卡芯片的硬件驱动程序实际上是alsa-driver的 一部分,但是在本文档中,为了明示层次关系, 将这两个分开对待。将硬件驱动程序叫做 device-driver(设备驱动), alsa-driver的其它部 分叫做alsa-driver(alsa驱动)。

Linux操作系统声卡驱动的安装与配置

Linux操作系统声卡驱动的安装与配置

Linux操作系统声卡驱动的安装与配置
一般的声卡驱动是支持windows的,linux很少,所以安装声卡驱动很麻烦。

Linux下安装声卡驱动,用的是alsa,它就好像是万能的一样,可以支持很多类型的声卡,如:
;一个是alsa-lib;最后一个是alsa-untils。

安装步骤:
1、把前面的三个东西给解压出来,解压之后会产生文件夹,比如:文件夹——alsa-driver、alsa-lib、alsa-untils
2、打开终端,先进入alsa-driver文件夹,然后输入……
3、进入alsa-lib文件夹,然后输入的内容除了第2项中的第4小项不要之外,一切照旧。

4、进入alsa-untils文件夹,一切同第三项。

上面的都操作完之后接着就是修改系统文件了。

在/ect目录下有一个moudules.conf的文件,在里面加入:
以上那段内容里面有个snd-xxxx的,那个指的是声卡的设备名称。

查过之后,有一张表可以对照,如下:
根据自己的实际情况然后修改自己的把snd-xxxx改成相对应的名称。

好了保存重启,一般就OK了
第一次操作很麻烦,但习惯了会觉得那是一种乐趣的,至少我自己是这么觉得的。

注:如果是初次操作,需要修改到系统本身的一些东西的话,建议最好先备份,错了改过来就比较容易点,备份,其实就是复制一份同样的东西到另一个安全的地方。

Linux系统中用ALSA驱动声卡流程详解共10页文档

Linux系统中用ALSA驱动声卡流程详解共10页文档

Linux系统中用ALSA驱动声卡流程详解一、什么是ALSAAdvanced Linux Sound Architecture 的简称为 ALSA ,译成中文的意思是 Linux 高级声音体系(这是我直译的,可能译的不对)。

一谈到体系就有点范围就太大了,所以ALSA不仅仅是包括对声卡的支持和驱动。

ALSA具有如下特征:1、对所有音频接口的高效支持,从普通用户的声卡到专业级别多路音频设备。

2、声卡驱动完全模块化设计。

3、SMP and thread-safe design。

4、开发库(alsa-lib)为程序设计提供了简单、方便,并且拥有有高级的效果和功能。

5、支持旧版本的OSS API 结口,能为大多数的OSS应用程序提供兼容。

OSS是一个商业性的驱动,OSS有一个简装本的代码已经移入内核和ALSA,其中alsa-oss就是。

OSS公司据说目前已经并不存在了。

我们没有必要用OSS 公司提供的商业版本。

用ALSA和OSS简装版足够。

二、关于硬件驱动驱动的必备基础1、如何查看硬件芯片在Linux操作系统中,所有的硬件都是以芯片组来区分的,品牌并不是最重要的。

硬件最重要的标识是芯片组。

所以您在讨论区求助的时候,只说硬件品牌,而不提供芯片组,大家是帮助不了您的,切记。

我们查看硬件的芯片组是的命令是 lspci -v 或者是dmesg,由于dmesg输出的信息不太多,不够直观。

所以经常用的还是lspci -v 。

也可以用lshal 获取。

最方便的还是lspci -v。

初学者还是用 lspci -v 更好一点。

我们运行lspci -v 后,如果查看声卡芯片组,发会现有类似下面的一段:2、系统内核版本[root@localhost beinan]# uname -r -m -p -i2.6.11-1.1369_FC4 i686 i686 i386上面的表示的是系统的内核版本,处理器架构等。

提示:如果您自己编译内核,还要安装kernel-devel (或 kernel-source),这个是在系统光盘或者映像文件中有带。

linux alsa声卡驱动原理

linux alsa声卡驱动原理

linux alsa声卡驱动原理ALSA(Advanced Linux Sound Architecture)是Linux操作系统中的音频驱动架构,它提供了音频设备管理和音频处理的接口。

ALSA声卡驱动的原理主要包括以下几个方面:1. ALSA声卡驱动模块:ALSA声卡驱动是一个内核模块,它和硬件设备之间建立了通信桥梁。

在Linux系统启动时,会加载相应的声卡驱动模块,以识别声卡硬件,并提供对硬件设备的访问接口。

2. 设备和节点:ALSA声卡驱动将声卡硬件设备抽象为一个字符设备文件,称为设备节点,它位于/dev目录下。

通过打开和读写该设备节点,可以与声卡设备进行数据交互。

例如,可以通过设备节点将音频数据输出到声卡设备,或者从声卡设备读取音频数据。

3. PCM接口和声音采样:ALSA声卡驱动的主要功能是处理和传输音频数据。

它通过PCM(Pulse-code modulation)接口进行音频数据的输入和输出。

PCM 接口定义了采样率、通道数和采样位数等参数,通过这些参数来控制声卡设备的录音和播放功能。

声卡驱动会将音频数据从应用程序读取或传输到声卡设备,并在硬件上进行数字到模拟的转换或模拟到数字的转换。

4. 设备控制和配置:ALSA声卡驱动还提供了控制和配置音频设备的接口。

通过这些接口,可以设置音量、音效、混音等参数,以及获取设备的状态信息。

它还支持音频设备的热插拔,可以动态添加或移除声卡设备。

总的来说,ALSA声卡驱动是Linux系统中负责管理音频设备和处理音频数据的模块。

它提供了访问音频设备的接口,并通过PCM接口进行音频数据的输入和输出。

通过控制和配置接口,可以对音频设备进行各种参数的设置和控制。

alsa声卡dev_snd_pcmC0D0p的open打开流程

alsa声卡dev_snd_pcmC0D0p的open打开流程

alsa声卡/dev/snd/pcmC0D0p的open打开流程原文地址:/space.php?uid=20564848&do=blog&cuid=2116725 aplay.c==> main==> snd_pcm_open(&handle, pcm_name, stream, open_mode); // 打开一路pcm,刷新config配置如果是"default",同时type等于SND_CONFIG_TYPE_COMPOUND那么这里对应"empty"static const char *const build_in_pcms[] = {"adpcm", "alaw", "copy", "dmix", "file", "hooks", "hw", "ladspa", "lfloat","linear", "meter", "mulaw", "multi", "null", "empty", "plug", "rate", "route", "share","shm", "dsnoop", "dshare", "asym", "iec958", "softvol", "mmap_emul",NULL};_snd_pcm_empty_open和snd_pcm_open_named_slave==> snd_pcm_open_conf(pcmp, name, root, conf, stream, mode);==> open_func = snd_dlobj_cache_lookup(open_name);将获得lib库中_snd_pcm_empty_open函数所以open_func将等于_snd_pcm_empty_open_snd_pcm_empty_open_snd_pcm_asym_open_snd_pcm_plug_open_snd_pcm_softvol_open_snd_pcm_dmix_open_snd_pcm_hw_open==> snd_pcm_hw_open(pcmp, name, card, device, subdevice, stream,mode | (nonblock ? SND_PCM_NONBLOCK : 0),0, sync_ptr_ioctl);==> snd_ctl_hw_openfilename等于"/dev/snd/controlC0"==> snd_open_device(filename, fmode);ctl->ops = &snd_ctl_hw_ops;ctl->private_data = hw;ctl->poll_fd = fd;*handle = ctl;filename等于"/dev/snd/pcmC0D0p"==> fd = snd_open_device(filename, fmode);==> return snd_pcm_hw_open_fd(pcmp, name, fd, 0, sync_ptr_ioctl);==> snd_pcm_new(&pcm, SND_PCM_TYPE_HW, name, info.stream, mode);pcm->ops = &snd_pcm_hw_ops;pcm->fast_ops = &snd_pcm_hw_fast_ops;static int snd_pcm_hw_mmap_control(snd_pcm_t *pcm){snd_pcm_hw_t *hw = pcm->private_data;void *ptr;int err;if (hw->sync_ptr == NULL) { // 如果还没有mmap,那么执行mmap映射内核空间驱动使用的声音缓冲区ptr = mmap(NULL, page_align(sizeof(struct sndrv_pcm_mmap_control)),PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,hw->fd, SNDRV_PCM_MMAP_OFFSET_CONTROL);if (ptr == MAP_FAILED || ptr == NULL) {err = -errno;SYSMSG("control mmap failed");return err;}hw->mmap_control = ptr; // 声卡驱动头部填充了一个结构体sndrv_pcm_mmap_control,类似qvfb显示原理.// struct sndrv_pcm_mmap_control {// sndrv_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */// sndrv_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */// };} else {hw->mmap_control->avail_min = 1;}snd_pcm_set_appl_ptr(pcm, &hw->mmap_control->appl_ptr, hw->fd,SNDRV_PCM_MMAP_OFFSET_CONTROL);return 0;}snd_pcm_mmapswitch (i->type) {case SND_PCM_AREA_MMAP: // 表示为数据区分配驱动内存,在snd_pcm_hw_channel_info中设置了typeptr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, i->u.mmap.fd, i->u.mmap.offset);/*mmap==> snd_pcm_mmap_data==> snd_pcm_default_mmap// mmap the DMA buffer on RAMstatic int snd_pcm_default_mmap(struct snd_pcm_substream *substream,area->vm_ops = &snd_pcm_vm_ops_data; // vma操作函数,当应用程序向该area读写不存在的内存数据时,area->vm_private_data = substream; // 将执行snd_pcm_vm_ops_data中的fault// 函数snd_pcm_mmap_data_fault进一步以页为单位申请内存空间,所以如果用户程序需要64k,那么将执行16次,每次申请4k空间[luther.gliethttp].area->vm_flags |= VM_RESERVED;atomic_inc(&substream->mmap_count);return 0;}*/if (ptr == MAP_FAILED) {SYSERR("mmap failed");return -errno;}i->addr = ptr;==> snd_pcm_mmap_controlstatic int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,struct vm_area_struct *area){struct snd_pcm_runtime *runtime;long size;if (!(area->vm_flags & VM_READ))return -EINVAL;runtime = substream->runtime;size = area->vm_end - area->vm_start;if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)))return -EINVAL;area->vm_ops = &snd_pcm_vm_ops_control; // 当对( area->vm_start,area->vm_end)之间空间操作,发生area->vm_private_data = substream; // 缺页时,内核将调用该vm_ops方法来处理fault异常,area->vm_flags |= VM_RESERVED; // 进而执行snd_pcm_mmap_control_fault申请1个page空间return 0;}==> writei_func = snd_pcm_writei;==> playback(argv[optind++]);==> pcm_write(audiobuf, l);==> writei_func(handle, data, count);就是调用上面的snd_pcm_writei==> snd_pcm_writei==> _snd_pcm_writei==> pcm->fast_ops->writei(pcm->fast_op_arg, buffer, size);==> snd_pcm_plugin_writei==> snd_pcm_write_areas(pcm, areas, 0, size,snd_pcm_plugin_write_areas);==> avail = snd_pcm_avail_update(pcm); // 获取可用缓冲区位置偏移索引值==> func()就是snd_pcm_plugin_write_areas函数发送1024帧音频数据,一帧对应一次完整采样,比如stereo 立体声,24bits量化,那么这里一帧对应3*2字节数据,即一次完整采样所需空间[luther.gliethttp].==> plugin->write(pcm, areas, offset, frames,slave_areas, slave_offset, &slave_frames);即调用snd_pcm_linear_write_areas函数将areas中的frames频数据拷贝到slave_areas内存区==> pcm->fast_ops->mmap_commit(pcm->fast_op_arg, offset, frames);==> snd_pcm_dmix_mmap_commit==> snd_pcm_dmix_sync_area/** synchronize shm ring buffer with hardware*/static void snd_pcm_dmix_sync_area(snd_pcm_t *pcm)==> /* add sample areas here */src_areas = snd_pcm_mmap_areas(pcm);dst_areas = snd_pcm_mmap_areas(dmix->spcm); // 添加==> mix_areas(dmix, src_areas, dst_areas, appl_ptr, slave_appl_ptr, transfer);if (dmix->interleaved) { // 可以将缓冲中的音频数据填充到硬件中[luther.gliethttp]/** process all areas in one loop* it optimizes the memory accesses for this case*/do_mix_areas(size * channels,(unsigned char *)dst_areas[0].addr + sample_size * dst_ofs * channels,(unsigned char *)src_areas[0].addr + sample_size * src_ofs * channels,dmix->u.dmix.sum_buffer + dst_ofs * channels,sample_size,sample_size,sizeof(signed int));return;}==> do_mix_areas(size * channels,(unsigned char *)src_areas[0].addr + sample_size * src_ofs * channels,dmix->u.dmix.sum_buffer + dst_ofs * channels,sample_size,sample_size,sizeof(signed int));这里的do_mix_areas在i386中,使用下面完全用汇编实现的拷贝函数MIX_AREAS_32完成数据从src到dst的快速拷贝,每拷贝一次,声卡就会发出一点声音[luther.gliethttp]/** for plain i386, 32-bit version (24-bit resolution)*/static void MIX_AREAS_32(unsigned int size,volatile signed int *dst, signed int *src,volatile signed int *sum, size_t dst_step,size_t src_step, size_t sum_step)_snd_pcm_asym_open_snd_pcm_dmix_opensnd_pcm_plugin_avail_update==> snd_pcm_avail_update(slave);==> pcm->fast_ops->avail_update(pcm->fast_op_arg);==> snd_pcm_dmix_avail_update==> snd_pcm_mmap_playback_avail(pcm);alsa_sound_init#define CONFIG_SND_MAJOR 116 /* standard configuration */static int major = CONFIG_SND_MAJOR;module_init(alsa_sound_init)alsa_sound_init==> register_chrdev(major, "alsa", &snd_fops) // 主设备号为116的所有设备都为alsa设备,节点方法集为snd_fopsstatic const struct file_operations snd_fops = // alsa的设备名为pcmC0D1c或pcmC0D1p等[luther.gliethttp].{.owner = THIS_MODULE,.open = snd_open};snd_open==> __snd_open(inode, file);unsigned int minor = iminor(inode);mptr = snd_minors[minor];file->f_op = fops_get(mptr->f_ops);file->f_op->open(inode, file);const struct file_operations snd_pcm_f_ops[2] = {{ // alsa使用到的SNDRV_PCM_STREAM_PLAYBACK放音方法集[luther.gliethttp].owner = THIS_MODULE,.write = snd_pcm_write,.aio_write = snd_pcm_aio_write,.open = snd_pcm_playback_open,.release = snd_pcm_release,.poll = snd_pcm_playback_poll,.unlocked_ioctl = snd_pcm_playback_ioctl,.compat_ioctl = snd_pcm_ioctl_compat,.mmap = snd_pcm_mmap,.fasync = snd_pcm_fasync,.get_unmapped_area = dummy_get_unmapped_area,},{ // alsa使用到的SNDRV_PCM_STREAM_CAPTURE录音方法集[luther.gliethttp].owner = THIS_MODULE,.read = snd_pcm_read,.aio_read = snd_pcm_aio_read,.open = snd_pcm_capture_open,.release = snd_pcm_release,.poll = snd_pcm_capture_poll,.unlocked_ioctl = snd_pcm_capture_ioctl,.compat_ioctl = snd_pcm_ioctl_compat,.mmap = snd_pcm_mmap,.fasync = snd_pcm_fasync,.get_unmapped_area = dummy_get_unmapped_area,}};=========================================================================snd_intel8x0_probe==> snd_intel8x0_create==> request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_SHARED,card->shortname, chip)snd_intel8x0_interruptsnd_intel8x0_updatesnd_open==> snd_pcm_playback_open==> snd_pcm_open==> snd_pcm_open_file==> snd_pcm_open_substream==> substream->ops->open(substream)即snd_intel8x0_playback_ops.open==> snd_intel8x0_playback_open==> snd_intel8x0_pcm_openstatic int snd_intel8x0_pcm_open(struct snd_pcm_substream *substream, struct ichdev *ichdev) {struct intel8x0 *chip = snd_pcm_substream_chip(substream);struct snd_pcm_runtime *runtime = substream->runtime;int err;ichdev->substream = substream;runtime->hw = snd_intel8x0_stream; // 声卡配置硬件信息[luther.gliethttp]runtime->hw.rates = ichdev->pcm->rates;snd_pcm_limit_hw_rates(runtime);if (chip->device_type == DEVICE_SIS) {runtime->hw.buffer_bytes_max = 64*1024;runtime->hw.period_bytes_max = 64*1024;}if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) return err;runtime->private_data = ichdev;return 0;}ioctl(SNDRV_PCM_IOCTL_HW_PARAMS)==> snd_pcm_f_ops.unlocked_ioctl即:snd_pcm_playback_ioctl==> snd_pcm_playback_ioctl==> snd_pcm_playback_ioctl1==> snd_pcm_common_ioctl1case SNDRV_PCM_IOCTL_HW_PARAMS:return snd_pcm_hw_params_user(substream, arg);==> snd_pcm_hw_params_user==> snd_pcm_hw_params==> substream->ops->hw_params即snd_intel8x0_playback_ops.hw_params==> snd_intel8x0_hw_params==> snd_ac97_pcm_open(ichdev->pcm, params_rate(hw_params),params_channels(hw_params),ichdev->pcm->r[dbl].slots);ioctl(SNDRV_PCM_IOCTL_PREPARE)==> snd_pcm_playback_ioctl==> snd_pcm_playback_ioctl1==> snd_pcm_common_ioctl1==> snd_pcm_prepare // prepare the PCM substream to be triggerable==> snd_pcm_action_nonatomic(&snd_pcm_action_prepare,substream, f_flags);==> snd_pcm_action_single(ops, substream, state);ops->pre_action(substream, state);ops->do_action(substream, state);ops->post_action(substream, state);上面ops就是之前提到的snd_pcm_action_prepare==> snd_pcm_do_prepare调用snd_pcm_do_reset(substream, 0);复位substream->ops->prepare(substream);即snd_intel8x0_playback_ops.prepare==> snd_intel8x0_pcm_preparestatic int snd_intel8x0_pcm_prepare(struct snd_pcm_substream *substream){struct intel8x0 *chip = snd_pcm_substream_chip(substream);struct snd_pcm_runtime *runtime = substream->runtime;struct ichdev *ichdev = get_ichdev(substream);ichdev->physbuf = runtime->dma_addr; // dma缓冲区地址ichdev->size = snd_pcm_lib_buffer_bytes(substream); // 将帧缓冲大小转为字节空间大小[luther.gliethttp] ichdev->fragsize = snd_pcm_lib_period_bytes(substream);if (ichdev->ichd == ICHD_PCMOUT) {snd_intel8x0_setup_pcm_out(chip, runtime); // 为play模式设置ac97寄存器[luther.gliethttp]if (chip->device_type == DEVICE_INTEL_ICH4)ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1;}snd_intel8x0_setup_periods(chip, ichdev); // 设置PCI总线ac97的bank地址空间[luther.gliethttp] return 0;}==> snd_intel8x0_setup_pcm_outstatic void snd_intel8x0_setup_pcm_out(struct intel8x0 *chip,struct snd_pcm_runtime *runtime){unsigned int cnt;int dbl = runtime->rate > 48000;// 一共有如下几种设备:enum { DEVICE_INTEL, DEVICE_INTEL_ICH4, DEVICE_SIS, DEVICE_ALI, DEVICE_NFORCE };spin_lock_irq(&chip->reg_lock);switch (chip->device_type) {cnt = igetdword(chip, ICHREG(ALI_SCR));cnt &= ~ICH_ALI_SC_PCM_246_MASK;if (runtime->channels == 4 || dbl)cnt |= ICH_ALI_SC_PCM_4;else if (runtime->channels == 6)cnt |= ICH_ALI_SC_PCM_6;iputdword(chip, ICHREG(ALI_SCR), cnt);break;case DEVICE_SIS:cnt = igetdword(chip, ICHREG(GLOB_CNT));cnt &= ~ICH_SIS_PCM_246_MASK;if (runtime->channels == 4 || dbl)cnt |= ICH_SIS_PCM_4;else if (runtime->channels == 6)cnt |= ICH_SIS_PCM_6;iputdword(chip, ICHREG(GLOB_CNT), cnt);break;default:cnt = igetdword(chip, ICHREG(GLOB_CNT));cnt &= ~(ICH_PCM_246_MASK | ICH_PCM_20BIT);if (runtime->channels == 4 || dbl)cnt |= ICH_PCM_4;else if (runtime->channels == 6)cnt |= ICH_PCM_6;else if (runtime->channels == 8)cnt |= ICH_PCM_8;if (chip->device_type == DEVICE_NFORCE) {/* reset to 2ch once to keep the 6 channel data in alignment,* to start from Front Left always*/if (cnt & ICH_PCM_246_MASK) {iputdword(chip, ICHREG(GLOB_CNT), cnt & ~ICH_PCM_246_MASK);spin_unlock_irq(&chip->reg_lock);msleep(50); /* grrr... */spin_lock_irq(&chip->reg_lock);}} else if (chip->device_type == DEVICE_INTEL_ICH4) {if (runtime->sample_bits > 16)cnt |= ICH_PCM_20BIT;}iputdword(chip, ICHREG(GLOB_CNT), cnt);break;spin_unlock_irq(&chip->reg_lock);}ioctl(SNDRV_PCM_IOCTL_START)==> snd_pcm_playback_ioctl==> snd_pcm_playback_ioctl1==> snd_pcm_common_ioctl1==> snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, SNDRV_PCM_STATE_RUNNING); ==> snd_pcm_action_single // state等于SNDRV_PCM_STATE_RUNNINGstatic struct action_ops snd_pcm_action_start = {.pre_action = snd_pcm_pre_start,.do_action = snd_pcm_do_start,.undo_action = snd_pcm_undo_start,.post_action = snd_pcm_post_start};ops->pre_action(substream, state);ops->do_action(substream, state);ops->post_action(substream, state);上面ops就是之前提到的snd_pcm_action_start==> snd_pcm_do_start==> substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);即snd_intel8x0_playback_ops.trigger==> snd_intel8x0_pcm_trigger启动ac97数据传输以上都只是执行一次[luther.gliethttp]只要发送音频数据,就会执行该ioctl更新pointerioctl(SNDRV_PCM_IOCTL_HWSYNC)==> snd_pcm_playback_ioctl==> snd_pcm_playback_ioctl1==> snd_pcm_common_ioctl1==> snd_pcm_hwsynccase SNDRV_PCM_STATE_RUNNING:if ((err = snd_pcm_update_hw_ptr(substream)) < 0)break;==> snd_pcm_update_hw_ptr==> snd_pcm_update_hw_ptr_post==> snd_pcm_update_hw_ptr_pos==> substream->ops->pointer(substream);即snd_intel8x0_playback_ops.pointer==> snd_intel8x0_pcm_pointer // 更新dma缓冲区数据最后可用数据索引值[luther.gliethttp]。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

•三、准备工作
•四、设备打开过程和数据流程

i. 整体分析

ii. 设备驱动程序insmod流程图

iii. 应用程序主流程图

iv. 声卡打开流程图

v. 数据写入流程图
•五、ALSA其它形式的数据写入方法流程图
•三、准备工作

为了更有效的跟踪ALSA的流程,需要在开始前进行一些准备工作,这包括用户层ALSA-lib库的调试方法和文档生成
•目 录
•一、导读
•二、ALSA架构简介
•三、准备工作
•四、设备打开过程和数据流程

i. 整体分析

ii. 设备驱动程序insmod流程图

iii. 应用程序主流程图

iv. 声卡打开流程图

v. 数据写入流程图
•五、ALSA其它形式的数据写入方法流程图
•二、ALSA架构简介
1. ALSA是Advanced Linux Sound Architecture,高级 Linux声音架构的简称,它在Linux操作系统上提供 了音频和MIDI(Musical Instrument Digital Interface,音乐设备数字化接口)的支持。它包 含API 库和工具、内核驱动集合, 对 Linux 声音 进行支持。 ALSA 包含一系列内核驱动对不同的 声卡进行支持,还提供了 libasound 的 API 库。 用这些进行写程序不需要打开设备等操作,所以 编程人员在写程序的时候不会被底层的东西困扰 。

#cp -rf alsa-utils-1.0.16 /opt/

#cp -rf alsa-lib-1.0.16 /opt/

※红色文字表示shell中输入的命令,具体命令要根据具体环境自己修改。

alsa-utils-1.0.16和alsa-lib-1.0.16从网上下,也可以在光盘debian-506-source-DVD-1.iso中的pool/main/a/文件夹下找
• 本文主要针对ALSA声卡硬件驱动,从应用程序的角度展示了从用户层到内核层再 到硬件驱动程序控制声卡硬件的过程。主要包括insmod、声卡打开、数据写入三 个流程。rmmod和声卡关闭的流程与insmod、声卡打开类似,本文没有描述。 ALSA的其他部分如控制、录音等,不在本文叙述范围内。其中的insmod是系统初 始化时或手动加载,不需要具体的应用程序参与。具体到硬件,使用的是ENS1371 芯片,关于最小化的ENS1371芯片驱动程序,可以参考《 Linux ALSA声卡驱动开发 最佳实践.pptx》。
•五、ALSA其它形式的数据写入方法流程图
•目 录
•一、导读
•二、ALSA架构简介
•三、准备工作
•四、设备打开过程和数据流程

i. 整体分析

ii. 设备驱动程序insmod流程图

iii. 应用程序主流程图

iv. 声卡打开流程图

数据写入流程图
•五、ALSA其它形式的数据写入方法流程图
•一、导 读
2. ALSA自带的应用程序是alsa-utils工具包,包括 aplay、alsamixer等。aplay用于在ASLA上播放音 频。alsamixer用于改变音频信号的音量。
3. alsa-lib是用户空间的函数库,提供了libasound.so 给应用程序使用,应用程序应包含头文件 asoundlib.h。这个库通过提供封装函数(ALSA-API) ,使ALSA应用程序不需要涉及具体硬件,编写起 来更容易。alsa-lib中有control,timer,dmix, pcm等,都是以插件(plugin)的形式存在的。alsalib通过硬件访问层的系统调用与内核层进行交互 。
。alsa-driver的调试方法参见《Linux 基础培训(2)-驱动开发最佳实践-1.pptx》。对调用流程和数据流程进行分析时,这部
分内容起到辅助作用。
• 1. ALSA-lib调试方法
• alsa-utils中的aplay程序可以进行应用程序和lib库的调试。
• 操作如下:

(1) 复制alsa-utils和alsa-lib到linux文件系统下,如:
到。

(2). 复制音频文件,如复制test_files文件夹到/opt下,

#cp -rf test_files /opt/

(3). 在alsa-lib-1.0.16中依次执行如下:

#cd /opt/alsa-lib-1.0.16

#./configure

#make

#make install
7. (3)驱动的最上层是声卡对象描述层,它是声 卡硬件的抽象描述,内核通过这些描述可以得知 该声卡硬件的功能、设备组件和操作方法等。
•二、 ALSA架构简介
• 左图是从代码的角度体现了alsa-lib和alsa-driver
及hardware的交互关系。用户层的alsa-lib通过操
作alsa-driver创建的设备文件/dev/snd/pcmC0D0p

※系统需要安装gcc等工具。
等对内核层进行访问。内核层的alsa-drivier驱动
再经由sound core对硬件声卡芯片进行访问。从
而实现了

app alsa-lib alsa-driver hardware的操作

• 图中右上角OSS相关部分是为了兼容OSS驱动模型 而存在的。不是本实践的相关部分。
•目 录
•一、导读
•二、ALSA架构简介
4. alsa-driver是音频设备的alsa内核部分的驱动。集 成在内核里面,大多是以模块的方式存在。可分 为三层。
5. (1)最底层是硬件操控层,负责实现硬件操纵 访问的功能,这也是声卡驱动程序中用户需实现 的主要部分;
6. (2)中间层是ASLA驱动的核心部分,它由各种 功能的音频设备组件构成,为用户提供了一些预 定义组件(如PCM、AC97、音序器和控制器等) ,另外用户也可以自行定义设备组件;
LinuxALSA声卡驱动原 理分析-设备打开过程和
数据流程
2020年5月28日星期四
•目 录
•一、导读
•二、ALSA架构简介
•三、准备工作
•四、设备打开过程和数据流程

i. 整体分析

ii. 设备驱动程序insmod流程图

iii. 应用程序主流程图

iv. 声卡打开流程图

v. 数据写入流程图
相关文档
最新文档