Linux_ALSA聲卡驅(qū)動開發(fā)實(shí)踐(課堂PPT)_第1頁
Linux_ALSA聲卡驅(qū)動開發(fā)實(shí)踐(課堂PPT)_第2頁
Linux_ALSA聲卡驅(qū)動開發(fā)實(shí)踐(課堂PPT)_第3頁
Linux_ALSA聲卡驅(qū)動開發(fā)實(shí)踐(課堂PPT)_第4頁
Linux_ALSA聲卡驅(qū)動開發(fā)實(shí)踐(課堂PPT)_第5頁
已閱讀5頁,還剩15頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、1Linux ALSA聲卡驅(qū)動開發(fā)最佳實(shí)踐本實(shí)踐是在Linux 基礎(chǔ)培訓(xùn)(2)-驅(qū)動開發(fā)最佳實(shí)踐基礎(chǔ)上進(jìn)行的2目 錄一、ALSA架構(gòu)簡介二、最佳實(shí)踐的目標(biāo)、目的、方法三、具體步驟四、總結(jié)3目 錄一、一、ALSA架構(gòu)簡介架構(gòu)簡介二、最佳實(shí)踐的目標(biāo)、目的、方法三、具體步驟四、總結(jié)4一、ALSA架構(gòu)簡介 ALSA架構(gòu)特點(diǎn)支持多種聲卡設(shè)備模塊化的內(nèi)核驅(qū)動程序支持SMP和多線程提供應(yīng)用程序開發(fā)庫兼容OSS應(yīng)用程序開發(fā)5一、 ALSA架構(gòu)簡介ALSA是Advanced Linux Sound Architecture,高級Linux聲音架構(gòu)的簡稱,它在Linux操作系統(tǒng)上提供了音頻和MIDI(Musica

2、l Instrument Digital Interface,音樂設(shè)備數(shù)字化接口)的支持。它包含API 庫和工具、內(nèi)核驅(qū)動集合, 對 Linux 聲音進(jìn)行支持。 ALSA 包含一系列內(nèi)核驅(qū)動對不同的聲卡進(jìn)行支持,還提供了 libasound 的 API 庫。用這些進(jìn)行寫程序不需要打開設(shè)備等操作,所以編程人員在寫程序的時(shí)候不會被底層的東西困擾。ALSA自帶的應(yīng)用程序是alsa-utils工具包,包括aplay、alsamixer等。aplay用于在ASLA上播放音頻。alsamixer用于改變音頻信號的音量。alsa-lib是用戶空間的函數(shù)庫,提供了libasound.so給應(yīng)用程序使用,應(yīng)用程

3、序應(yīng)包含頭文件asoundlib.h。這個(gè)庫通過提供封裝函數(shù)(ALSA-API),使ALSA應(yīng)用程序編寫起來更容易。alsa-lib中有control,timer,dmix,pcm等,都是以插件(plugin)的形式存在的。alsa-lib通過硬件訪問層的系統(tǒng)調(diào)用與內(nèi)核層進(jìn)行交互。alsa-driver是音頻設(shè)備的alsa內(nèi)核部分的驅(qū)動。集成在內(nèi)核里面,大多是以模塊的方式存在??煞譃槿龑印?(1)最底層是硬件操控層,負(fù)責(zé)實(shí)現(xiàn)硬件操縱訪問的功能,這也是聲卡驅(qū)動程序中用戶需實(shí)現(xiàn)的主要部分; (2)中間層是ASLA驅(qū)動的核心部分,它由各種功能的音頻設(shè)備組件構(gòu)成,為用戶提供了一些預(yù)定義組件(如PCM、

4、AC97、音序器和控制器等),另外用戶也可以自行定義設(shè)備組件; (3)驅(qū)動的最上層是聲卡對象描述層,它是聲卡硬件的抽象描述,內(nèi)核通過這些描述可以得知該聲卡硬件的功能、設(shè)備組件和操作方法等。6一、 ALSA架構(gòu)簡介這是另一個(gè)ASLA架構(gòu)圖。與上一個(gè)圖大同小異。從內(nèi)核driver層、lib層到應(yīng)用層勾畫出了彼此之間的關(guān)系。圖中左下角OSS相關(guān)部分是為了兼容OSS驅(qū)動模型而存在的。不是本實(shí)踐的相關(guān)部分。7一、 ALSA架構(gòu)簡介左圖是從代碼的角度體現(xiàn)了alsa-lib和alsa-driver及hardware的交互關(guān)系。用戶層的alsa-lib通過操作alsa-driver創(chuàng)建的設(shè)備文件/dev/sn

5、d/pcmC0D0p等對內(nèi)核層進(jìn)行訪問。內(nèi)核層的alsa-drivier驅(qū)動再經(jīng)由sound core對硬件聲卡芯片進(jìn)行訪問。從而實(shí)現(xiàn)了 appalsa-libalsa-driverhardware的操作。圖中右上角OSS相關(guān)部分是為了兼容OSS驅(qū)動模型而存在的。不是本實(shí)踐的相關(guān)部分。8目 錄一、ALSA架構(gòu)簡介二、最佳實(shí)踐的目標(biāo)、目的、方法二、最佳實(shí)踐的目標(biāo)、目的、方法三、具體步驟四、總結(jié)9二、最佳實(shí)踐的目標(biāo)、目的、方法在alsa的整體架構(gòu)中,alsa-driver的硬件操控層,負(fù)責(zé)實(shí)現(xiàn)硬件操縱訪問,這也是聲卡驅(qū)動程序中用戶需實(shí)現(xiàn)的主要部分。我們要實(shí)現(xiàn)的是針對特定聲卡芯片ens1371的控制

6、在這里把它叫做device-driver(設(shè)備驅(qū)動), alsa-driver的其它部分叫做alsa-driver(alsa驅(qū)動)。user spacekernel space app 1app nALSA應(yīng)用程序alsa-libpcmdmixcontroltimeralsa-driveralsa內(nèi)核APIdevice-driverhardwareens1371ALSA整體架構(gòu)10目 錄一、ALSA架構(gòu)簡介二、最佳實(shí)踐的目標(biāo)、目的、方法三、具體步驟三、具體步驟四、總結(jié)11三、具體步驟1. 準(zhǔn)備工作。 (1) 使用alsa自帶的aplay工具或其它應(yīng)用程序播放音頻,測試開發(fā)環(huán)境是否能夠正常播放音

7、頻。如果不能播放,可以用alsamixer等工具查看音量是否被靜音了。總之,如果正常環(huán)境如果都不能播放音頻,那我們后續(xù)的工作也就不能檢驗(yàn)正確與否了。 aplay工具shell中命令如下: # apt-get install alsa-utils /初次使用安裝alsa-utils工具,以后直接執(zhí)行下一步就可以了。 # aplay /opt/test_files/pcm.wav /aplay后面的文件路徑根據(jù)自己的實(shí)際情況填寫。紅色文字表示shell中輸入的命令。 alsamixer工具shell中命令如下: # apt-get install alsa-utils /初次使用安裝alsa-ut

8、ils工具,以后直接執(zhí)行下一步就可以了。 # alsamixer。alsamixer中,、 方向鍵可以調(diào)整焦點(diǎn),、方向鍵可以調(diào)整音量,esc鍵退出。也可以用數(shù)字或+、-鍵調(diào)整音量。 (2) 檢查使用的PC的聲卡是否是ENS1371,shell中命令如下: # lspci |grep “1371” ENS1371聲卡會顯示類似如下字樣 #02:02.0 Multimedia audio controller: Ensoniq ES1371 AudioPCI-97 (rev 02) 如果不是ENS1371,下文可作為參考根據(jù)自己的實(shí)際情況進(jìn)行。12三、具體步驟1. 準(zhǔn)備工作。 (2) 新建工作目錄

9、如alsa-ens1371-dev-driver,在工作目錄中新建文件ens1371-playback.c。 (3) 制作makefile。新建文件Makefile。參照Linux 基礎(chǔ)培訓(xùn)(2)-驅(qū)動開發(fā)最佳實(shí)踐-1.pptx第5頁編寫Makefile。Makefile內(nèi)容如下:2. 查看內(nèi)核linux-source-2.6.26/sound/pci/ens1371.c的代碼,內(nèi)容如下:即在定義宏CHIP1371的基礎(chǔ)上,使用ens1370.c。ifneq ($(KERNELRELEASE),)obj-m := ens1371-playback.oelseKBUILD := /lib/mod

10、ules/uname -r/buildmodules:make -C $(KBUILD) M=$(shell pwd) modulesclean:rm -f *.o * core .depend .*.cmd *.ko *.mod.c *.order *.symversrm -rf .tmp_versionsendif#define CHIP1371#include ens1370.c“13三、具體步驟3. 抽取ens1370.c(位于linux-source-2.6.26/sound/pci)中Linux通用驅(qū)動程序核心,添加到ens1371-playback.c中并make,測試??梢韵忍?/p>

11、加框架,再向框架中逐步添加函數(shù)。可以打印適當(dāng)?shù)膌og信息,不會影響ens1371的流程。Linux通用驅(qū)動程序代碼如下:4.根據(jù)ens1370.c的代碼,向init和exit中添加實(shí)現(xiàn)函數(shù)。根據(jù)調(diào)用關(guān)系實(shí)現(xiàn)一個(gè)被調(diào)用函數(shù)的最小化定義(如下頁圖中的snd_audiopci_probe()和snd_audiopci_remove()),以填充調(diào)用函數(shù),并將無關(guān)部分注釋掉,減輕代碼量。注意注釋無關(guān)部分時(shí)需要注意,有些不能確定有沒有用,可以先留著,另外,除了函數(shù)外,其他部分的最好用注釋,不要直接刪除,以便在后面檢查是否刪除了有用的部分。 定義最小化的函數(shù)后,代碼是可以編譯,并可以加載到內(nèi)核的,再逐步添

12、寫被調(diào)用函數(shù),以此類推,直到所有的調(diào)用關(guān)系全部被添加進(jìn)代碼。如向init和exit中添加實(shí)現(xiàn)函數(shù):#define CHIP1371#include #define ENS1371_DEBUG#ifdef ENS1371_DEBUG#define FUNC_LOG() printk(KERN_ERR “FUNC_LOG: %d%s()n, _LINE_, _FUNCTION_)#endifstatic int _init alsa_card_ens137x_init(void) FUNC_LOG();static void _exit alsa_card_ens137x_exit(void) F

13、UNC_LOG();module_init(alsa_card_ens137x_init)module_exit(alsa_card_ens137x_exit)14#define CHIP1371#include #include #define ENS1371_DEBUG#ifdef ENS1371_DEBUG#define FUNC_LOG() printk(KERN_ERR FUNC_LOG: %d:%s()n, _LINE_, _FUNCTION_)#endif#define DRIVER_NAME ENS1371“static struct pci_device_id snd_aud

14、iopci_ids = /#ifdef CHIP1370/ 0 x1274, 0 x5000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, ,/* ES1370 */#endif#ifdef CHIP1371 0 x1274, 0 x1371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, ,/* ES1371 */ 0 x1274, 0 x5880, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, ,/* ES1373 - CT5880 */ 0 x1102, 0 x8938, PCI_ANY_ID, PCI_ANY_ID, 0,

15、0, 0, ,/* Ectiva EV1938 */#endif 0, ;static int _devinit snd_audiopci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)FUNC_LOG();return 0;static void _devexit snd_audiopci_remove(struct pci_dev *pci)FUNC_LOG();static struct pci_driver driver = .name = DRIVER_NAME,.id_table = snd_audiop

16、ci_ids,.probe = snd_audiopci_probe,.remove = _devexit_p(snd_audiopci_remove),#ifdef CONFIG_PM/.suspend = snd_ensoniq_suspend,/.resume = snd_ensoniq_resume,#endif;static int _init alsa_card_ens137x_init(void)FUNC_LOG();return pci_register_driver(&driver);static void _exit alsa_card_ens137x_exit(v

17、oid)FUNC_LOG();pci_unregister_driver(&driver);module_init(alsa_card_ens137x_init)module_exit(alsa_card_ens137x_exit)三、具體步驟15三、具體步驟5. make、insmod、rmmod 驅(qū)動模塊示例:注意insmod ens1371-playback.ko前,要先卸載系統(tǒng)中原有的ens1371模塊snd_ens1371。否則,在定義了DRIVER_NAME后,insmod時(shí)就會出錯(cuò)。圖中,紅色是shell中輸入的命令,黃色是系統(tǒng)打印的信息,而綠色是我們的模塊打印的log。

18、另外,驅(qū)動模塊的單步調(diào)試可以參照Linux 基礎(chǔ)培訓(xùn)(2)-驅(qū)動開發(fā)最佳實(shí)踐-1.pptx。16三、具體步驟6. 仿照snd_audiopci_probe()和 snd_audiopci_remove()的填充與alsa_card_ens137x_init()和alsa_card_ens137x_exit()類似,如此一級一級的填充下去,直至模塊可以播放出聲音。 對于snd_audiopci_probe()這樣比較復(fù)雜的函數(shù),要一行一行的添加,邊添加邊調(diào)試。如遇到變量等應(yīng)該在前面函數(shù)中賦值而還沒有實(shí)現(xiàn)的部分,可以先用if宏等方法暫時(shí)注釋掉,如下頁代碼中的紅色部分。添加的代碼如下:#define

19、 CHIP1371#include #include #include #include #define ENS1371_DEBUG#ifdef ENS1371_DEBUG#define FUNC_LOG() printk(KERN_ERR FUNC_LOG: %d:%s()n, _LINE_, _FUNCTION_)#endif#define DRIVER_NAME ENS1371“static struct pci_device_id snd_audiopci_ids = ;static int indexSNDRV_CARDS = SNDRV_DEFAULT_IDX;/* Index 0

20、-MAX */static char *idSNDRV_CARDS = SNDRV_DEFAULT_STR;/* ID for this card */static int enableSNDRV_CARDS = SNDRV_DEFAULT_ENABLE_PNP;/* Enable switches */static int spdifSNDRV_CARDS;static int lineioSNDRV_CARDS;struct ensoniq ;MODULE_DEVICE_TABLE(pci, snd_audiopci_ids);static int _devinit snd_ensoniq

21、_1371_mixer(struct ensoniq *ensoniq, int has_spdif, int has_line)FUNC_LOG();return(0);static int _devinit snd_ensoniq_pcm(struct ensoniq * ensoniq, int device, struct snd_pcm * rpcm)FUNC_LOG();return 0;static int _devinit snd_ensoniq_create(struct snd_card *card, struct pci_dev *pci, struct ensoniq

22、* rensoniq)FUNC_LOG();return 0;17三、具體步驟6. 代碼續(xù):static int _devinit snd_audiopci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)static int dev;struct snd_card *card;struct ensoniq *ensoniq;int err, pcm_devs2;FUNC_LOG();if (dev = SNDRV_CARDS)return -ENODEV;if (!enabledev) dev+;return -EN

23、OENT;card = snd_card_new(indexdev, iddev, THIS_MODULE, 0);if (card = NULL)return -ENOMEM;if (err = snd_ensoniq_create(card, pci, &ensoniq) private_data = ensoniq;pcm_devs0 = 0; pcm_devs1 = 1;/#ifdef CHIP1370/if (err = snd_ensoniq_1370_mixer(ensoniq) 0) /snd_card_free(card);/return err;/#endif/#i

24、fdef CHIP1371if (err = snd_ensoniq_1371_mixer(ensoniq, spdifdev, lineiodev) 0) snd_card_free(card);return err;/#endifif (err = snd_ensoniq_pcm(ensoniq, 0, NULL) 0) snd_card_free(card);return err;/if (err = snd_ensoniq_pcm2(ensoniq, 1, NULL) 0) /snd_card_free(card);/return err;/if (err = snd_ensoniq_

25、midi(ensoniq, 0, NULL) driver, DRIVER_NAME);strcpy(card-shortname, Ensoniq AudioPCI);#ifdef ENS1371_RESERVEDsprintf(card-longname, %s %s at 0 x%lx, irq %i,card-shortname,card-driver,ensoniq-port,ensoniq-irq);#endifif (err = snd_card_register(card) 0) snd_card_free(card);return err;pci_set_drvdata(pc

26、i, card);dev+;return 0;static void _devexit snd_audiopci_remove(struct pci_dev *pci)FUNC_LOG();snd_card_free(pci_get_drvdata(pci);pci_set_drvdata(pci, NULL);static struct pci_driver driver = .name = DRIVER_NAME,.id_table = snd_audiopci_ids,.probe = snd_audiopci_probe,.remove = _devexit_p(snd_audiopci_remove),#ifdef CONFIG_PM/.suspend = snd_ensoniq_suspend,/.resume = snd_ensoniq_resume,#endif;static int _init alsa_card_ens137x_init(void)FUNC_LOG();return pci_register_driver(&driver);static void _exit alsa_card_ens137x_exit(void)FUNC_LOG();pci_un

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論