宋 剛
(重慶城市管理職業(yè)學(xué)院,重慶 401331)
ALSA聲卡驅(qū)動(dòng)程序設(shè)計(jì)
宋剛
(重慶城市管理職業(yè)學(xué)院,重慶401331)
文章介紹了Linux 操作系統(tǒng)中負(fù)責(zé)聲音處理的ALSA音頻子系統(tǒng),以及它包含的聲卡驅(qū)動(dòng)程序和編程步驟。通過(guò)對(duì)聲卡設(shè)備的驅(qū)動(dòng)程序?qū)嵗治?,文章總結(jié)出ALSA聲卡設(shè)備驅(qū)動(dòng)的通用編程框架。
ALSA;驅(qū)動(dòng)程序;音頻子系統(tǒng)
高級(jí)Linux聲音架構(gòu)(Advanced Linux Sound Architecture, ALSA)是Linux操作系統(tǒng)內(nèi)核中,用來(lái)為聲音設(shè)備提供編程輔助和硬件驅(qū)動(dòng)的子系統(tǒng)。如圖1所示,它包含兩個(gè)組成部分,一個(gè)是在用戶空間中用來(lái)簡(jiǎn)化編程的ALSA-Lib函數(shù)庫(kù)。功能是用戶請(qǐng)求轉(zhuǎn)換為對(duì)內(nèi)核空間中設(shè)備字符文件的調(diào)用。另外一個(gè)是在內(nèi)核空間中負(fù)責(zé)硬件控制的驅(qū)動(dòng)程序。它通過(guò)對(duì)設(shè)備字符設(shè)備的注冊(cè)與回調(diào),實(shí)現(xiàn)ALSA驅(qū)動(dòng)核心(core.c, pcm.c)。核心再通過(guò)回調(diào)具體聲卡的ALSA驅(qū)動(dòng),實(shí)現(xiàn)對(duì)聲卡硬件的操作。
圖1 ALSA音頻驅(qū)動(dòng)結(jié)構(gòu)層次
文章通過(guò)一個(gè)只包含話音采集功能的PCI總線聲卡,來(lái)描述內(nèi)核中ALSA驅(qū)動(dòng)程序的調(diào)用步驟和編程框架。具體可分為聲卡記錄的創(chuàng)建,PCM設(shè)備的創(chuàng)建,PCM操作函數(shù)的建立3個(gè)部分。
這里假設(shè)聲卡的Linux內(nèi)核模塊(Module)框架和PCI總線結(jié)構(gòu)初始化已經(jīng)完成。這兩部分通用結(jié)構(gòu)可由《Linux設(shè)備驅(qū)動(dòng)程序》一書(shū)中詳細(xì)給出,本文只關(guān)注書(shū)中欠缺的ALSA驅(qū)動(dòng)部分。
2.1聲卡記錄的創(chuàng)建
聲卡記錄是整個(gè)驅(qū)動(dòng)的核心,所有與聲卡相關(guān)的數(shù)據(jù)結(jié)構(gòu)和控制代碼都保存在聲卡記錄名下。它的具體結(jié)構(gòu)定義在include/sound/core.h,由函數(shù)snd_card_create()來(lái)創(chuàng)建和初始化,如圖2所示。
圖2 聲卡的創(chuàng)建
idx:聲卡的編號(hào),如為1,則由系統(tǒng)自動(dòng)分配。
xid:聲卡標(biāo)識(shí)符,如為NULL,則以snd_card的shortname或longname代替。
0:聲卡私有數(shù)據(jù)區(qū)大小。
card_ret:返回所創(chuàng)建的聲卡實(shí)例的指針。
2.2設(shè)置驅(qū)動(dòng)名和設(shè)備號(hào)等信息(見(jiàn)圖3)
圖3 設(shè)置驅(qū)動(dòng)程序信息
圖3創(chuàng)建了聲卡驅(qū)動(dòng)程序名,還有聲卡的短描述符和長(zhǎng)描述符,以及使用的PCI總線信息。因?yàn)橛脩艨臻g編程時(shí)ALSA-LIB需要明確調(diào)用的聲卡名稱,所以聲卡的命名必須具備關(guān)鍵字特性。
2.3聲卡的私有數(shù)據(jù)注冊(cè)為一個(gè)低階設(shè)備
這樣做的目的在于當(dāng)聲卡被注銷時(shí),芯片私有數(shù)據(jù)所占用的內(nèi)存可以隨著聲卡的注銷被自動(dòng)地釋放。如圖4所示,私有數(shù)據(jù)為空。
圖4 將專有數(shù)據(jù)注冊(cè)為一個(gè)低階設(shè)備
2.4聲卡的注冊(cè)和注銷(見(jiàn)圖5)
圖5 向ALSA注冊(cè)聲卡
注冊(cè)成功會(huì)生產(chǎn)色卡的設(shè)備文件,一般是dev/snd/ pcmCxxDxxp,pcmCxxDxxc,供用戶空間中的ALSALib庫(kù)調(diào)用。如果注冊(cè)失敗,可通過(guò)snd_card_free函數(shù)釋放聲卡所占有的所有資源。
通常一塊聲卡包含多個(gè)功能設(shè)備,如PCM,Control,Mixer,MIDI等。為便于學(xué)習(xí),這里只討論聲卡中必須擁有的PCM設(shè)備。在ALSA驅(qū)動(dòng)框架中,每塊聲卡最多可以包含4個(gè)PCM設(shè)備。PCM設(shè)備由一個(gè)Playback stream和一個(gè)Capture stream組成,每個(gè)Stream又由一個(gè)或多個(gè)Substreams組成。
3.1聲卡中采集PCM設(shè)備硬件描述信息(見(jiàn)圖6)
圖6 采集卡硬件描述
該聲卡設(shè)備硬件為一簡(jiǎn)單話音采集卡。結(jié)構(gòu)體中定義了使用U8格式的PCM編碼,采樣率為8KHz,單聲道,緩存區(qū)大小為48頁(yè),每頁(yè)32個(gè)字節(jié)。
3.2創(chuàng)建PCM設(shè)備(見(jiàn)圖7)
圖7 PCM設(shè)備的創(chuàng)建
第三個(gè)參數(shù),表示聲卡第一個(gè)PCM設(shè)備,從0開(kāi)始計(jì)算。
第四個(gè)參數(shù),表示P C M設(shè)備有幾個(gè)回放子流substream,本例中為0。
第五個(gè)參數(shù)nr_subdevs,為PCM設(shè)備下采集子流數(shù)量。
3.3定義PCM設(shè)備操作函數(shù)(見(jiàn)圖8)
圖8 PCM操作函數(shù)定義
該采集卡中的PCM設(shè)備只有Capture stream。一般聲卡中PCM Playback stream的設(shè)計(jì)與之相似。函數(shù)參數(shù)中的my_pcm_ops是函數(shù)的操作結(jié)構(gòu)體地址,該操作函數(shù)集定義如圖9所示。
圖9 操作函數(shù)集
該函數(shù)操作集的操作需要使用snd_pcm_sucstream_ chip()來(lái)獲得操作指針。具體功能為:open(),在PCM子流打開(kāi)時(shí)分配相應(yīng)的資源;close(),在PCM之流關(guān)閉時(shí)釋放相應(yīng)的資源。
ioctl(),完成一些特殊的控制功能;hw_params(),完成硬件參數(shù)的設(shè)置,如數(shù)據(jù)格式、緩沖大小等;hw_ free(),用來(lái)釋放hw_params()函數(shù)占用的系統(tǒng)資源;prepare(),在PCM子流開(kāi)始傳輸數(shù)據(jù)前,需要完成的操作;trigger(),在PCM子流開(kāi)始、停止、暫停時(shí)被調(diào)用;pointer(),給出當(dāng)前PCM之流緩沖區(qū)地址;copy(),提供內(nèi)存空間管理需要的數(shù)據(jù)拷貝功能。下一步是編寫(xiě)單個(gè)函數(shù)的實(shí)現(xiàn),如圖10所示。
圖10 操作函數(shù)實(shí)現(xiàn)
3.4 為操作函數(shù)預(yù)分配緩沖空間(見(jiàn)圖11)
圖11 分配DMA緩沖數(shù)據(jù)區(qū)
需要注意的是對(duì)緩沖空間的數(shù)據(jù)填充一定要采用DMA方式存取,否則數(shù)據(jù)的接收有可能產(chǎn)生中斷現(xiàn)象。
3.5PCM子流中斷的處理
最后是添加中斷處理函數(shù)。中斷處理的作用是當(dāng)緩沖區(qū)傳輸完成、硬件復(fù)位、總線操作的時(shí)候通知PCM中間層。可以通過(guò)調(diào)用函數(shù)snd_pcm_period_elapsed()來(lái)通知。中斷請(qǐng)求代碼為 snd_pcm_period_elapsed(my_ dev->ss)。
本文介紹了一個(gè)簡(jiǎn)單的聲卡設(shè)備的ALSA驅(qū)動(dòng)編制流程,詳細(xì)地討論了ALSA架構(gòu)中驅(qū)動(dòng)程序的架構(gòu)與編程框架。以此為基礎(chǔ)設(shè)計(jì)的Linux平臺(tái)多路話音采集卡ALSA驅(qū)動(dòng)程序已用于實(shí)踐教學(xué)中。從學(xué)習(xí)效果反饋上看,該驅(qū)動(dòng)框架對(duì)ALSA架構(gòu)音頻驅(qū)動(dòng)的學(xué)習(xí)和深入研究具備一定的指導(dǎo)意義。
[1]ALSA development team.ALSA開(kāi)源項(xiàng)目[EB/OL].(2016-09-15)[2013-10-31].http://www.alsa-project.org/.
[2]TAKASHI IWAI.Writing an ALSA Driver[EB/OL].(2016-09-10)[2005-02-10].http://www.alsa-project.org/~tiwai/writing-an-alsa-driver/.
[3]科波特.Linux設(shè)備驅(qū)動(dòng)程序[M].3版.魏永明,耿岳,鐘書(shū)毅,譯.北京:中國(guó)電力出版社,2006.
Design of ALSA sound card driver
Song Gang
(Chongqing City Management College, Chongqing 401331, China)
This article described the audio subsystem which is responsible for the ALSA sound processing in Linux operating system,sound card drivers and programming steps contained in it. By the analysis of sound device driver instance, the common programming framework of ALSA device driver was summed up in this paper.
ALSA; driver; audio subsystem
宋剛(1975— ),男,四川資中,??疲瑢?shí)驗(yàn)師;研究方向:計(jì)算機(jī)操作系統(tǒng)。