1.xa0structxa0snd_card
1.1.xa0snd_card是什么
snd_card可以说是整个ALSA音频驱动最顶层的一个结构,整个声卡的软件逻辑结构开始于该结构,几乎所有与声音相关的逻辑设备都是在snd_card的管理之下,声卡驱动的第一个动作通常就是创建一个snd_card结构体。正因为如此,本节中,我们也从xa0structxa0cnd_card开始吧。
1.2.xa0snd_card的定义
snd_card的定义位于改头文件中:include/sound/core.h
/*xa0mainxa0structurexa0forxa0soundcardxa0*/
structxa0snd_cardxa0{
intxa0number;xa0/*xa0numberxa0ofxa0soundcardxa0(indexxa0to
snd_cards)xa0*/
charxa0id[16];xa0/*xa0idxa0stringxa0ofxa0thisxa0cardxa0*/
charxa0driver[16];xa0/*xa0driverxa0namexa0*/
charxa0shortname[32];xa0/*xa0shortxa0namexa0ofxa0thisxa0soundcardxa0*/
charxa0longname[80];xa0/*xa0namexa0ofxa0thisxa0soundcardxa0*/
charxa0mixername[80];xa0/*xa0mixerxa0namexa0*/
charxa0components[128];xa0/*xa0cardxa0componentsxa0delimitedxa0with
spacexa0*/
structxa0modulexa0*module;xa0/*xa0top-levelxa0modulexa0*/
voidxa0*private_data;xa0/*xa0privatexa0dataxa0forxa0soundcardxa0*/
voidxa0(*private_free)xa0(structxa0snd_cardxa0*card);xa0/*xa0callbackxa0forxa0freeingxa0of
privatexa0dataxa0*/
structxa0list_headxa0devices;xa0/*xa0devicesxa0*/
unsignedxa0intxa0last_numid;xa0/*xa0lastxa0usedxa0numericxa0IDxa0*/
structxa0rw_semaphorexa0controls_rwsem;xa0/*xa0controlsxa0listxa0lockxa0*/
rwlock_txa0ctl_files_rwlock;xa0/*xa0ctl_filesxa0listxa0lockxa0*/
intxa0controls_count;xa0/*xa0countxa0ofxa0allxa0controlsxa0*/
intxa0user_ctl_count;xa0/*xa0countxa0ofxa0allxa0userxa0controlsxa0*/
structxa0list_headxa0controls;xa0/*xa0allxa0controlsxa0forxa0thisxa0cardxa0*/
structxa0list_headxa0ctl_files;xa0/*xa0activexa0controlxa0filesxa0*/
structxa0snd_info_entryxa0*proc_root;xa0/*xa0rootxa0forxa0soundcardxa0specificxa0filesxa0*/
structxa0snd_info_entryxa0*proc_id;xa0/*xa0thexa0cardxa0idxa0*/
structxa0proc_dir_entryxa0*proc_root_link;xa0/*xa0numberxa0linkxa0toxa0realxa0idxa0*/
structxa0list_headxa0files_list;xa0/*xa0allxa0filesxa0associatedxa0toxa0thisxa0cardxa0*/
structxa0snd_shutdown_f_opsxa0*s_f_ops;xa0/*xa0filexa0operationsxa0inxa0thexa0shutdown
statexa0*/
spinlock_txa0files_lock;xa0/*xa0lockxa0thexa0filesxa0forxa0thisxa0cardxa0*/
intxa0shutdown;xa0/*xa0thisxa0cardxa0isxa0goingxa0downxa0*/
intxa0free_on_last_close;xa0/*xa0freexa0inxa0contextxa0ofxa0file_releasexa0*/
wait_queue_head_txa0shutdown_sleep;
structxa0devicexa0*dev;xa0/*xa0devicexa0assignedxa0toxa0thisxa0cardxa0*/
#ifndefxa0CONFIG_SYSFS_DEPRECATED
structxa0devicexa0*card_dev;xa0/*xa0cardXxa0objectxa0forxa0sysfsxa0*/
#endif
#ifdefxa0CONFIG_PM
unsignedxa0intxa0power_state;xa0/*xa0powerxa0statexa0*/
structxa0mutexxa0power_lock;xa0/*xa0powerxa0lockxa0*/
wait_queue_head_txa0power_sleep;
#endif
#ifxa0defined(CONFIG_SND_MIXER_OSS)xa0||xa0defined(CONFIG_SND_MIXER_OSS_MODULE)
structxa0snd_mixer_ossxa0*mixer_oss;
intxa0mixer_oss_change_count;
#endif
};
structxa0list_headxa0devicesxa0记录该声卡下所有逻辑设备的链表
structxa0list_headxa0controlsxa0记录该声卡下所有的控制单元的链表
voidxa0*private_dataxa0声卡的私有数据,可以在创建声卡时通过参数指定数据的大小
2.xa0声卡的建立流程
2.1.1.xa0第一步,创建snd_card的一个实例
structxa0snd_cardxa0*card;
intxa0err;
....
errxa0=xa0snd_card_create(index,xa0id,xa0THIS_MODULE,xa00,xa0&card);
indexxa0一个整数值,该声卡的编号
idxa0字符串,声卡的标识符
第四个参数xa0该参数决定在创建snd_card实例时,需要同时额外分配的私有数据的大小,该数据的指针最终会赋值给snd_card的private_data数据成员
cardxa0返回所创建的snd_card实例的指针
2.1.2.xa0第二步,创建声卡的芯片专用数据
声卡的专用数据主要用于存放该声卡的一些资源信息,例如中断资源、io资源、dma资源等。可以有两种创建方法:
通过上一步中snd_card_create()中的第四个参数,让snd_card_create自己创建
//xa0structxa0mychipxa0用于保存专用数据
errxa0=xa0snd_card_create(index,xa0id,xa0THIS_MODULE,
sizeof(structxa0mychip),xa0&card);
//xa0从private_data中取出
structxa0mychipxa0*chipxa0=xa0card->private_data;
自己创建:
structxa0mychipxa0{
structxa0snd_cardxa0*card;
....
};
structxa0snd_cardxa0*card;
structxa0mychipxa0*chip;
chipxa0=xa0kzalloc(sizeof(*chip),xa0GFP_KERNEL);
......
errxa0=xa0snd_card_create(index[dev],xa0id[dev],xa0THIS_MODULE,xa00,xa0&card);
//xa0专用数据记录snd_card实例
chip->cardxa0=xa0card;
.....
然后,把芯片的专有数据注册为声卡的一个低阶设备:
staticxa0intxa0snd_mychip_dev_free(structxa0snd_devicexa0*device)
{
returnxa0snd_mychip_free(device->device_data);
}
staticxa0structxa0snd_device_opsxa0opsxa0=xa0{
.dev_freexa0=xa0snd_mychip_dev_free,
};
....
snd_device_new(card,xa0SNDRV_DEV_LOWLEVEL,xa0chip,xa0&ops);
注册为低阶设备主要是为了当声卡被注销时,芯片专用数据所占用的内存可以被自动地释放。
2.1.3.xa0第三步,设置Driver的ID和名字
strcpy(card->driver,xa0"Myxa0Chip");
strcpy(card->shortname,xa0"Myxa0Ownxa0Chipxa0123");
sprintf(card->longname,xa0"%sxa0atxa00x%lxxa0irqxa0%i",
card->shortname,xa0chip->ioport,xa0chip->irq);
snd_card的driver字段保存着芯片的ID字符串,user空间的alsa-lib会使用到该字符串,所以必须要保证该ID的唯一性。shortname字段更多地用于打印信息,longname字段则会出现在/proc/asound/cards中。