编写一个ALSA驱动
Takashi lwai
编写一个ALSA驱动
(by Takashi Iwai)
0.3.6版本
翻译:creator
翻译这篇文章主要是为了学习ALSA驱动,因为感觉ALSA是Linux音频发展方向,所以下决心仔细看看,但是中文资料太少,就想翻译一份奉献给广大初学并且英文不好的朋友。不过自己的英文也非常不好,我也在努力学习中。
翻译的不好,有些地方也不准确,希望大家多提宝贵意见,共同维护这篇文档。
这篇文档主要描述如何写一个ALSA(Linux 高级声音体系 )驱动。
目录
前言
1.目录树架构
概述
内核
core/oss
core/ioctl32
core/seq
core/seq/oss
core/seq/instr
头文件
驱动
drviers/mpu401
drviers/opl3 和 opl4
i2c
i2c/l3
synth
pci
isa
arm,ppc,和sparc
usb
pcmcia
oss
2.PCI驱动的基本流程
概要
代码示例
构造器
1)检查并增加设备索引
2)创建一个声卡实例
3)创建一个主要部件
4)设定驱动ID和名字
5)创建其他部件,如:混音器(mixer),MIDI,等
6)注册声卡实例
7)设定PCI驱动数据,然后返回零。
析构器
头文件
3.管理声卡和部件
声卡实例
部件
chip相关数据
1.通过snd_card_new()分配
2.分配其他设备
注册和释放
4.PCI资源管理
代码示例
一些必须做的事情
资源分配
设备结构体的注册
PCI入口
5.PCM接口
概述
代码示例
构造器
析构器
PCM相关的运行时数据
硬件描述
PCM配置
DMA缓冲区信息
运行状态
私有数据
中断的回调函数
操作函数(回调函数)
open
close
ioctl
hw_params
hw_free
prepare
trigger
pointer
copy,silence
ack
page
中断向量
周期中断
高频率的时钟中断
调用snd_pcm_period_elapsed()
原子
约束
6.控制接口
概述
控制接口描述
控制接口名称
通用capture和playback
Tone控制
3D控制
MIC Boost
接口标识
回调函数
info
get
put
回调函数并不是原子的
构造器
更新通知
7.AC97解码器的API函数
概述
代码示例
构造器
回调函数
驱动中更新寄存器
调整时钟
Proc文件
多个解码器
8.MIDI(MPU401-UART)接口
概述
构造器
中断向量
9.Raw MIDI接口
概述
构造器
回调函数
open
close
输出子系统的trigger
输入子系统的trigger
drain
10.杂项设备
FM OPL3
硬件相关设备
IEC958(S/PDIF)
11.缓存和内存管理
缓存类型
附加硬件缓存
不相邻缓存
通过Vmalloc申请的缓存
12.Proc接口
13.电源管理
14.模块参数
15.如何把你的驱动加入到ALS代码中
概述
单一文件的驱动程序
多个文件的驱动程序
16.一些有用的函数
snd_printk()相关函数
snd_assert()
snd_BUG()
17.致谢
前言
这篇文章主要介绍如何写一个ALSA(Advanced Linux Sound Architecture)()驱动.这篇文档主要针对PCI声卡。假如是其他类似的设备,API函数可能会是不同的。尽管如此,至少ALSA内核的API是一样的。因此,这篇文章对于写其他类型的设备驱动同样有帮助。
本文的读者需要有足够的C语言的知识和基本的linux内核编程知识。本文不会去解释一些Linux内核编码的基本话题,也不会去详细介绍底层驱动的实现。它仅仅描述如何写一个基于ALSA的PCI声卡驱动。
假如你对0.5.x版本以前的ALSA驱动非常熟悉的话,你可以检查驱动文件,例如es1938.c或maestro3.c,那些是在0.5.x版本基础上而来的,你可以对比一下他们的差别。
这篇文档仍然是一个草稿,非常欢迎大家的反馈和指正。
第一章 文件目录结构
概述
有两种方式可以得到ALSA驱动程序。
一个是通过ALSA的ftp网站上下载,另外一个是2.6(或以后)Linux源码里面。为了保持两者的同步,ALSA驱动程序被分为两个源码树:alsa-kernel和alsa -drvier。前者完全包含在Linux2.6(或以后)内核树里面,这个源码树仅仅是为了保持2.6(或以后)内核的兼容。后者,ALSA驱动,包含了很多更细分的文件,为了在2.2和2.4内核上编译,配置,同时为了适应最新的内核API函数,和一些在开发中或尚在测试的附加功能。当他们那些功能完成并且工作稳定的时候最终会被移入到alsa 内核树中。
ALSA驱动的文件目录描述如下。 alsa-kernel和alsa-drvier几乎含有相同的文件架构,除了“core”目录和alsa-drvier目录树中被称为“acore”。
示例1-1.ALSA文件目录结构
sound
/core
/oss
/seq
/oss
/instr
/ioctl32
/include
/drivers
/mpu401
/opl3
/i2c
/l3
/synth
/emux
/pci
/(cards)
/isa
/(cards)
/arm
/ppc
/sparc
/usb
/pcmcia/(cards)
/oss
core目录
这个目录包含了中间层,ALSA的核心驱动。那些本地ALSA模块保持在这个目录里。一些子目录包含那些与内核配置相关的不同的模块。
core/oss
关于PCM和mixer的OSS模拟的模块保存在这个目录里面。Raw midi OSS模拟也被包含在ALSA rawmidi 代码中,因为它非常小。音序器代码被保存在core/seq/oss目录里面(如下)。
core/ioctl32
这个目录包含32bit-ioctl到64bit架构(如x86-64,ppc64,sparc64)的转换。对于32bit和alpha的架构,他们是不被编译的。
core/seq
这和它的子目录主要是关于ALSA的音序器。它包含了音序器的core和一些主要的音序器模块如:snd-seq-midi,snd-seq-virmidi等等。它们仅仅在内核配置中当CONFIG_SND_SEQUENCER被设定的时候才会被编译。
core/seq/oss
包含了OSS音序器的模拟的代码。
core/seq/instr
包含了一些音序器工具层的一些模块。
include目录
这里面放的是ALSA驱动程序开放给用户空间,或者被其他不同目录引用的共同头文件。一般来说,私有头文件不应该被放到此文件目录,但是你仍然会发现一些这样的文件,那是历史遗留问题了。
Drivers目录
这个目录包含了在不同架构的系统中的不同驱动共享的文件部分。它们是硬件无关的。例如:一个空的pcm驱动和一系列MIDI驱动会放在这个文件夹中。在子目录里面,会放一些不同的组件的代码,他们是根据不同的bus和cpu架构实现的。
drivers/mpu401
MPU401和MPU401-UART模块被放到这里。
drviers/opl3和opl4
OPL3和OPL4 FM-synth相关放到这里。
i2c目录
这里面包含了ALSA的i2c组件。
虽然Linux有个i2c的标准协议层,ALSA还是拥有它关于一些card的专用i2c代码,因为一些声卡仅仅需要一些简单的操作,而标准的i2c的API函数对此显得太过复杂了。
i2c/l3
这是ARM L3 i2c驱动的子目录
synth目录
它包含了synth(合成器)的中间层模块
到目前为止,仅仅在synth/emux目录下面有Emu8000/Tmu10k1 synth驱动。
pci目录
它和它的一些子目录文件负责PCI声卡和一些PCI BUS的上层card模块。
在pci目录下面保存着一些简单的驱动文件,而一些比较复杂的,同时包含多个程序文件的驱动会被放置在pci目录下面一个单独的子目录里面(如:emu10k1,ice1712)。
isa目录
它和它的一些子目录文件是处理ISA声卡的上层card模块。
arm,ppc,和sparc目录
这里放置一些和芯片架构相关的一些上层的card模块。
usb目录
这里包含一些USB-AUDIO驱动。在最新版本里面,已经把USB MIDI驱动也集成进USB-AUDIO驱动了。
pcmcia目录
PCMCIA卡,特别是PCCard驱动会放到这里。CardBus驱动将会放到pci目录里面,因为API函数和标准PCI卡上统一的。
oss目录
OSS/Lite源文件将被放置在linux2.6(或以后)版本的源码树中。(在ALSA驱动中,它是空的:)