sound core,就是sound 系统的架构层,先了解一下linux为驱动开发者提供了什么样的框架来编写音频驱动。代码路径是kernel/sound/sound_core.c
sound驱动是如何载入系统的,先看看是否有init 和probe,但是这个是core的驱动,core驱动一般的功能是在系统中注册对应的总线或者生成相关的文件夹,提供相应的match函数、注册、注销函数。因此,sound core 首先是先使得自己成为kernel的一部份:
subsys_initcall(init_soundcore);
这导致了内核启动会去执行 init_soundcore() 函数,init函数做了什么呢?
static int __init init_soundcore(void)
{
int rc;
rc = init_oss_soundcore(); /******(1)******/
if (rc)
return rc;
sound_class = class_create(THIS_MODULE, "sound"); /******(2)******/
if (IS_ERR(sound_class)) {
cleanup_oss_soundcore();
return PTR_ERR(sound_class);
}
sound_class->devnode = sound_devnode; /******(3)******/
return 0;
}
1. init还算比较简单,(1)调用了字符设备注册了sound 的字符设备
这里需要注意,只有使用OSS(Open Sound System)架构的时候才会去注册这个sound的字符设备,逻辑如下
static int __init init_oss_soundcore(void)
{
if (preclaim_oss &&
register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops) < 0) {
printk(KERN_ERR "soundcore: sound device already in use.\n");
return -EBUSY;
}
return 0;
}
#ifdef CONFIG_SOUND_OSS_CORE_PRECLAIM
static int preclaim_oss = 1;
#else
static int preclaim_oss = 0;
#endif
很不幸的是现在几乎不实用OSS架构,因为OSS 架构已经不那么OPEN了,而是开始收费,额~~ 所以嘛,大家都懂滴;转而使用ALSA(Advanced Linux Sound Architecture)架构了,所以目前的接触的项目中也没有注册sound 字符设备了。
$ cat /proc/devices | grep sound
没有任何信息。但是音频设备肯定是字符设备,在日后的某个地方将会被注册,让我们拭目以待。对字符设备,当然少不了file_operations啦,但是这里没有注册字符设备,这些operations 函数自然也没有被调用,但是可以简单看,培养一下架构思想 ,比如open函数,总的调用思路是:snd open ---》 根据次设备号找到snd设备的 open ---》执行snd设备的open
static int soundcore_open(struct inode *inode, struct file *file)
{
int chain;
int unit = iminor(inode);
struct sound_unit *s;
const struct file_operations *new_fops = NULL;
chain=unit&0x0F;
if(chain==4 || chain==5) /* dsp/audio/dsp16 */
{
unit&=0xF0;
unit|=3;
chain=3;
}
spin_lock(&sound_loader_lock);
s = __look_for_unit(chain, unit);
if (s)
new_fops = fops_get(s->unit_fops);
if (preclaim_oss && !new_fops) {
spin_unlock(&sound_loader_lock);
/*
* Please, don't change this order or code.
* For ALSA slot means soundcard and OSS emulation code
* comes as add-on modules which aren't depend on
* ALSA toplevel modules for soundcards, thus we need
* load them at first. [Jaroslav Kysela <perex@jcu.cz>]
*/
request_module("sound-slot-%i", unit>>4);
request_module("sound-service-%i-%i", unit>>4, chain);
/*
* sound-slot/service-* module aliases are scheduled
* for removal in favor of the standard char-major-*
* module aliases. For the time being, generate both
* the legacy and standard module aliases to ease
* transition.
*/
if (request_module("char-major-%d-%d", SOUND_MAJOR, unit) > 0)
request_module("char-major-%d", SOUND_MAJOR);
spin_lock(&sound_loader_lock);
s = __look_for_unit(chain, unit);
if (s)
new_fops = fops_get(s->unit_fops);
}
spin_unlock(&sound_loader_lock);
if (new_fops) {
/*
* We rely upon the fact that we can't be unloaded while the
* subdriver is there.
*/
int err = 0;
replace_fops(file, new_fops);
if (file->f_op->open)
err = file->f_op->open(inode,file);
return err;
}
return -ENODEV;
}
(2)创建了sound类,方便日后创建对应的设备节点,如下图
(3)的本意是用来获取sound设备标号的,但是这里应该没有使用他。
2. sound设备注册函数的罗列
从上图可以得知,提供了6个设备注册函数,对不同的设备有不同的注册接口。其中 midi,是(Musical Instrument Digital Interface,简称MIDI)是一个工业标准的电子通信协议.为电子乐器等演奏设备(如合成器)定义各种音符或弹奏码,容许电子乐器、电脑、手机或其它的舞台演出配备彼此连接,调整和同步,得以即时交换演奏数据。MIDI不发送声音,只发送像是音调和音乐强度的数据,音量,颤音和相位[1]等参数的控制信号,还有设置节奏的时钟信号。在不同的电脑上,输出的声音也因音源器不同而有差异。
其注册函数真正使用到的时候再做进一步分析,有注册函数肯定也有注销函数
好了,对于sound core,先看到这里,日后有补充还会继续添加。