编写一个 ALSA 驱动
Takashi lwai
原帖地址:http://blog.chinaunix.net/u1/49088/showart_1006023.html
非常感谢作者的翻译。
编写一个 ALSA 驱动
(by Takashi Iwai)
0.3.6 版本
翻译: creator sz111@126.com
翻译这篇文章主要是为了学习 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()
s nd_BUG()
17. 致谢
前言
这篇文章主要介绍如何写一个 ALSA ( Advanced Linux Sound Architecture ) (http://www.alsa-project.org) 驱动 . 这篇文档主要针对 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 驱动中,它是空的 : )