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

上传人:sccc 文档编号:4842443 上传时间:2023-05-18 格式:DOC 页数:12 大小:58.50KB
返回 下载 相关 举报
Linux ALSA声卡驱动之一:声卡的创建.doc_第1页
第1页 / 共12页
Linux ALSA声卡驱动之一:声卡的创建.doc_第2页
第2页 / 共12页
Linux ALSA声卡驱动之一:声卡的创建.doc_第3页
第3页 / 共12页
Linux ALSA声卡驱动之一:声卡的创建.doc_第4页
第4页 / 共12页
Linux ALSA声卡驱动之一:声卡的创建.doc_第5页
第5页 / 共12页
点击查看更多>>
资源描述

《Linux ALSA声卡驱动之一:声卡的创建.doc》由会员分享,可在线阅读,更多相关《Linux ALSA声卡驱动之一:声卡的创建.doc(12页珍藏版)》请在三一办公上搜索。

1、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.hc-sharpview plaincopy/*mainstructureforsoundc

2、ard*/structsnd_cardintnumber;/*numberofsoundcard(indextosnd_cards)*/charid16;/*idstringofthiscard*/chardriver16;/*drivername*/charshortname32;/*shortnameofthissoundcard*/charlongname80;/*nameofthissoundcard*/charmixername80;/*mixername*/charcomponents128;/*cardcomponentsdelimitedwithspace*/structmod

3、ule*module;/*top-levelmodule*/void*private_data;/*privatedataforsoundcard*/void(*private_free)(structsnd_card*card);/*callbackforfreeingofprivatedata*/structlist_headdevices;/*devices*/unsignedintlast_numid;/*lastusednumericID*/structrw_semaphorecontrols_rwsem;/*controlslistlock*/rwlock_tctl_files_r

4、wlock;/*ctl_fileslistlock*/intcontrols_count;/*countofallcontrols*/intuser_ctl_count;/*countofallusercontrols*/structlist_headcontrols;/*allcontrolsforthiscard*/structlist_headctl_files;/*activecontrolfiles*/structsnd_info_entry*proc_root;/*rootforsoundcardspecificfiles*/structsnd_info_entry*proc_id

5、;/*thecardid*/structproc_dir_entry*proc_root_link;/*numberlinktorealid*/structlist_headfiles_list;/*allfilesassociatedtothiscard*/structsnd_shutdown_f_ops*s_f_ops;/*fileoperaTIonsintheshutdownstate*/spinlock_tfiles_lock;/*lockthefilesforthiscard*/intshutdown;/*thiscardisgoingdown*/intfree_on_last_cl

6、ose;/*freeincontextoffile_release*/wait_queue_head_tshutdown_sleep;structdevice*dev;/*deviceassignedtothiscard*/#ifndefCONFIG_SYSFS_DEPRECATEDstructdevice*card_dev;/*cardXobjectforsysfs*/#endif#ifdefCONFIG_PMunsignedintpower_state;/*powerstate*/structmutexpower_lock;/*powerlock*/wait_queue_head_tpow

7、er_sleep;#endif#ifdefined(CONFIG_SND_MIXER_OSS)|defined(CONFIG_SND_MIXER_OSS_MODULE)structsnd_mixer_oss*mixer_oss;intmixer_oss_change_count;#endif;struct list_head devices 记录该声卡下所有逻辑设备的链表struct list_head controls 记录该声卡下所有的控制单元的链表void *private_data 声卡的私有数据,可以在创建声卡时通过参数指定数据的大小2. 声卡的建立流程2.1.1. 第一步,创建sn

8、d_card的一个实例c-sharpview plaincopystructsnd_card*card;interr;.err=snd_card_create(index,id,THIS_MODULE,0,index 一个整数值,该声卡的编号id 字符串,声卡的标识符第四个参数 该参数决定在创建snd_card实例时,需要同时额外分配的私有数据的大小,该数据的指针最终会赋值给snd_card的private_data数据成员card 返回所创建的snd_card实例的指针2.1.2. 第二步,创建声卡的芯片专用数据声卡的专用数据主要用于存放该声卡的一些资源信息,例如中断资源、io资源、dma资

9、源等。可以有两种创建方法:通过上一步中snd_card_create()中的第四个参数,让snd_card_create自己创建c-sharpview plaincopy/structmychip用于保存专用数据err=snd_card_create(index,id,THIS_MODULE,sizeof(structmychip),/从private_data中取出structmychip*chip=card-private_data;自己创建:c-sharpview plaincopystructmychipstructsnd_card*card;.;structsnd_card*card

10、;structmychip*chip;chip=kzalloc(sizeof(*chip),GFP_KERNEL);.err=snd_card_create(indexdev,iddev,THIS_MODULE,0,/专用数据记录snd_card实例chip-card=card;.然后,把芯片的专有数据注册为声卡的一个低阶设备:c-sharpview plaincopystaTIcintsnd_mychip_dev_free(structsnd_device*device)returnsnd_mychip_free(device-device_data);staTIcstructsnd_dev

11、ice_opsops=.dev_free=snd_mychip_dev_free,;.snd_device_new(card,SNDRV_DEV_LOWLEVEL,chip,注册为低阶设备主要是为了当声卡被注销时,芯片专用数据所占用的内存可以被自动地释放。2.1.3. 第三步,设置Driver的ID和名字c-sharpview plaincopystrcpy(card-driver,MyChip);strcpy(card-shortname,MyOwnChip123);sprintf(card-longname,%sat0x%lxirq%i,card-shortname,chip-ioport

12、,chip-irq);snd_card的driver字段保存着芯片的ID字符串,user空间的alsa-lib会使用到该字符串,所以必须要保证该ID的唯一性。shortname字段更多地用于打印信息,longname字段则会出现在/proc/asound/cards中。2.1.4. 第四步,创建声卡的功能部件(逻辑设备),例如PCM,Mixer,MIDI等这时候可以创建声卡的各种功能部件了,还记得开头的snd_card结构体的devices字段吗?每一种部件的创建最终会调用snd_device_new()来生成一个snd_device实例,并把该实例链接到snd_card的devices链表中

13、。通常,alsa-driver的已经提供了一些常用的部件的创建函数,而不必直接调用snd_device_new(),比如:PCM - snd_pcm_new()RAWMIDI - snd_rawmidi_new()CONTROL - snd_ctl_create()TIMER - snd_timer_new()INFO - snd_card_proc_new()JACK - snd_jack_new()2.1.5. 第五步,注册声卡c-sharpview plaincopyerr=snd_card_register(card);if(errarm/pxa2xx-ac97.c的部分代码贴上来:c

14、ppview plaincopystaticint_devinitpxa2xx_ac97_probe(structplatform_device*dev)structsnd_card*card;structsnd_ac97_bus*ac97_bus;structsnd_ac97_templateac97_template;intret;pxa2xx_audio_ops_t*pdata=dev-dev.platform_data;if(dev-id=0)dev_err(ret=-ENXIO;gotoerr_dev;/(1)/ret=snd_card_create(SNDRV_DEFAULT_ID

15、X1,SNDRV_DEFAULT_STR1,THIS_MODULE,0,if(retdev=/(3)/strncpy(card-driver,dev-dev.driver-name,sizeof(card-driver);/(4)/ret=pxa2xx_pcm_new(card,if(ret)gotoerr;/(2)/ret=pxa2xx_ac97_hw_probe(dev);if(ret)gotoerr;/(4)/ret=snd_ac97_bus(card,0,if(ret)gotoerr_remove;memset(ret=snd_ac97_mixer(ac97_bus,if(ret)go

16、toerr_remove;/(3)/snprintf(card-shortname,sizeof(card-shortname),%s,snd_ac97_get_short_name(pxa2xx_ac97_ac97);snprintf(card-longname,sizeof(card-longname),%s(%s),dev-dev.driver-name,card-mixername);if(pdatasnd_ac97_dev_add_pdata(ac97_bus-codec0,pdata-codec_pdata0);snd_card_set_dev(card,/(5)/ret=snd_

17、card_register(card);if(ret=0)platform_set_drvdata(dev,card);return0;err_remove:pxa2xx_ac97_hw_remove(dev);err:if(card)snd_card_free(card);err_dev:returnret;staticint_devexitpxa2xx_ac97_remove(structplatform_device*dev)structsnd_card*card=platform_get_drvdata(dev);if(card)snd_card_free(card);platform

18、_set_drvdata(dev,NULL);pxa2xx_ac97_hw_remove(dev);return0;staticstructplatform_driverpxa2xx_ac97_driver=.probe=pxa2xx_ac97_probe,.remove=_devexit_p(pxa2xx_ac97_remove),.driver=.name=pxa2xx-ac97,.owner=THIS_MODULE,#ifdefCONFIG_PM.pm=#endif,;staticint_initpxa2xx_ac97_init(void)returnplatform_driver_re

19、gister(staticvoid_exitpxa2xx_ac97_exit(void)platform_driver_unregister(module_init(pxa2xx_ac97_init);module_exit(pxa2xx_ac97_exit);MODULE_AUTHOR(NicolasPitre);MODULE_DESCRIPTION(AC97driverfortheIntelPXA2xxchip);驱动程序通常由probe回调函数开始,对一下2.1中的步骤,是否有相似之处?经过以上的创建步骤之后,声卡的逻辑结构如下图所示:图 2.2.1 声卡的软件逻辑结构下面的章节里我们分

20、别讨论一下snd_card_create()和snd_card_register()这两个函数。3. snd_card_create()snd_card_create()在/sound/core/init.c中定义。cppview plaincopy/*snd_card_create-createandinitializeasoundcardstructure*idx:cardindex(address)0.(SNDRV_CARDS-1)*xid:cardidentification(ASCIIstring)*module:toplevelmoduleforlocking*extra_size

21、:allocatethisextrasizeafterthemainsoundcardstructure*card_ret:thepointertostorethecreatedcardinstance*Createsandinitializesasoundcardstructure.*Thefunctionallocatessnd_cardinstanceviakzallocwiththegiven*spaceforthedrivertousefreely.Theallocatedstructisstored*inthegivencard_retpointer.*Returnszeroifs

22、uccessfuloranegativeerrorcode.*/intsnd_card_create(intidx,constchar*xid,structmodule*module,intextra_size,structsnd_card*card_ret)首先,根据extra_size参数的大小分配内存,该内存区可以作为芯片的专有数据使用(见前面的介绍):c-sharpview plaincopycard=kzalloc(sizeof(*card)+extra_size,GFP_KERNEL);if(!card)return-ENOMEM;拷贝声卡的ID字符串:c-sharpview pl

23、aincopyif(xid)strlcpy(card-id,xid,sizeof(card-id);如果传入的声卡编号为-1,自动分配一个索引编号:c-sharpview plaincopyif(idxif(module_slot_match(module,idx2)idx=idx2;break;if(idxif(!slotsidx2|!*slotsidx2)idx=idx2;break;初始化snd_card结构中必要的字段:c-sharpview plaincopycard-number=idx;card-module=module;INIT_LIST_HEAD(init_rwsem(rw

24、lock_init(INIT_LIST_HEAD(INIT_LIST_HEAD(spin_lock_init(INIT_LIST_HEAD(init_waitqueue_head(#ifdefCONFIG_PMmutex_init(init_waitqueue_head(#endif建立逻辑设备:Controlc-sharpview plaincopy/*thecontrolinterfacecannotbeaccessedfromtheuserspaceuntil*/*snd_cards_bitmaskandsnd_cardsaresetwithsnd_card_register*/err=

25、snd_ctl_create(card);建立proc文件中的info节点:通常就是/proc/asound/card0c-sharpview plaincopyerr=snd_info_card_create(card);把第一步分配的内存指针放入private_data字段中:c-sharpview plaincopyif(extra_size0)card-private_data=(char*)card+sizeof(structsnd_card);4. snd_card_register()snd_card_create()在/sound/core/init.c中定义。c-sharpv

26、iew plaincopy/*snd_card_register-registerthesoundcard*card:soundcardstructure*Thisfunctionregistersallthedevicesassignedtothesoundcard.*Untilcallingthis,theALSAcontrolinterfaceisblockedfromthe*externalaccesses.Thus,youshouldcallthisfunctionattheend*oftheinitializationofthecard.*Returnszerootherwisea

27、negativeerrorcodeiftheregistrainfailed.*/intsnd_card_register(structsnd_card*card)首先,创建sysfs下的设备:c-sharpview plaincopyif(!card-card_dev)card-card_dev=device_create(sound_class,card-dev,MKDEV(0,0),card,card%i,card-number);if(IS_ERR(card-card_dev)card-card_dev=NULL;其中,sound_class是在/sound/sound_core.c中

28、创建的:c-sharpview plaincopystaticchar*sound_devnode(structdevice*dev,mode_t*mode)if(MAJOR(dev-devt)=SOUND_MAJOR)returnNULL;returnkasprintf(GFP_KERNEL,snd/%s,dev_name(dev);staticint_initinit_soundcore(void)intrc;rc=init_oss_soundcore();if(rc)returnrc;sound_class=class_create(THIS_MODULE,sound);if(IS_ER

29、R(sound_class)cleanup_oss_soundcore();returnPTR_ERR(sound_class);sound_class-devnode=sound_devnode;return0;由此可见,声卡的class将会出现在文件系统的/sys/class/sound/下面,并且,sound_devnode()也决定了相应的设备节点也将会出现在/dev/snd/下面。接下来的步骤,通过snd_device_register_all()注册所有挂在该声卡下的逻辑设备,snd_device_register_all()实际上是通过snd_card的devices链表,遍历所有的snd_device,并且调用snd_device的ops-dev_register()来实现各自设备的注册的。c-sharpview plaincopyif(err=snd_device_register_all(card)0)returnerr;最后就是建立一些相应的proc和sysfs下的文件或属性节点,代码就不贴了。至此,整个声卡完成了建立过程。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 建筑/施工/环境 > 农业报告


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号