LinuxALSA聲卡驅(qū)動之四:Control設(shè)備的創(chuàng)建_第1頁
LinuxALSA聲卡驅(qū)動之四:Control設(shè)備的創(chuàng)建_第2頁
LinuxALSA聲卡驅(qū)動之四:Control設(shè)備的創(chuàng)建_第3頁
LinuxALSA聲卡驅(qū)動之四:Control設(shè)備的創(chuàng)建_第4頁
LinuxALSA聲卡驅(qū)動之四:Control設(shè)備的創(chuàng)建_第5頁
已閱讀5頁,還剩8頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、Linux ALSA聲卡驅(qū)動之四:Co ntrol設(shè)備的創(chuàng)建Control 接口Control接口主要讓用戶空間的應(yīng)用程序(alsa-lib )可以訪問和控制音頻 codec芯片中的多路開關(guān),滑動控件等。對于Mixer (混 音)來說,Control接口顯得尤為重要,從 ALSA 0.9.x版本開始,所有的mixer工作都是通過 control接口的API來實現(xiàn)的。ALSA已經(jīng)為AC97定義了完整的控制接口模型,如果你的Codec芯片只支持AC97接 口,你可以不用關(guān)心本節(jié)的內(nèi)容。 定義了所有的Control API。如果你要為你的 codec實現(xiàn)自 己的controls,請在代碼中包含該頭文

2、件。Controls 的定義要自定義一個Control,我們首先要定義3各回調(diào)函數(shù):info,get和put。然 后,定義一個 snd_kcontrol_new 結(jié)構(gòu):c-sharp view pla in copy1. static struct sn d_kc on trol_ new my_c on trol _dev in itdata = 2. .iface = SNDRV_CTL_ELEMFACE_MIXER,3. .n ame = PCM Playback Switch,4. .in dex = 0,5. .access = SNDRV_CTL_ELEM_ACCESS_READW

3、RITE,6. .private_value = 0xffff,8.9.get = my_control_get,.put = my_control_put10. ;iface 字段指出了 control 的類型, alsa 定義了幾種類型(SNDDRV_CTL_ELEM_IFACE_X,常用的類型是 MIXER當(dāng)然也可以定義屬于 全局的CARD型,也可以定義屬于某類設(shè)備的類型,例如HWDEPPCMRAWMQTIMEF等,這時需要在device 和subdevice字段中指出卡的設(shè)備 邏輯編號。name字段是該control的名字,從 ALSA 0.9.x開始,control的名字是變得比 較

4、重要,因為control的作用是按名字來歸類的。ALSA已經(jīng)預(yù)定義了一些 control 的名字,我們再 Control Name 一節(jié)詳細討論。index 字段用于保存該 control 的在該卡中的編號。如果聲卡中有不止一個 codec,每個codec中有相同名字的control,這時我們可以通過index來區(qū)分 這些 controls 。當(dāng) index 為 0 時,則可以忽略這種區(qū)分策略。access 字段包含了該 control 的訪問類型。每一個 bit 代表一種訪問類型,這 些訪問類型可以多個“或”運算組合在一起。private_value 字段包含了一個任意的長整數(shù)類型值。該值可

5、以通過 info , get, put 這幾個回調(diào)函數(shù)訪問。你可以自己決定如何使用該字段,例如可以把 它拆分成多個位域,又或者是一個指針,指向某一個數(shù)據(jù)結(jié)構(gòu)。tlv 字段為該 control 提供元數(shù)據(jù)Control的名字control的名字需要遵循一些標(biāo)準(zhǔn),通??梢苑殖?3部分來定義control的名 字:源-方向-功能。* 源,可以理解為該 control的輸入端,alsa已經(jīng)預(yù)定義了一些常用的源,例如:Master,PCM, CD, Line 等等。* 方向,代表該 control的數(shù)據(jù)流向,例如: Playback, Capture, Bypass,Bypass Capture等等,也

6、可以不定義方向,這時表示該Control是雙向的(playback 禾口 capture )。* 功能,根據(jù)control的功能,可以是以下字符串:Switch,Volume,Route等等。也有一些命名上的特例:* 全局的 capture 和 playback Capture Source ,Capture Volume,Capture Switch,它們用于全局的 capture source , switch 禾口 volume。同理,Playback Volume ,Playback Switch,它們用于全局的輸出 switch 和volume。Ton e-c on troles音調(diào)

7、控制的開關(guān)和音量命名為:Tone Control - XXX,例如,Tone Control - Switch , Tone Control - Bass , Tone Control - Center。 3D controls3D 控件的命名規(guī)則:,3D Control - Switch , 3D Control -Center , 3D Control - Space。 Mic boost麥克風(fēng)音量加強控件命名為:Mic Boost或Mic Boost(6dB)。訪問標(biāo)志(ACCESS Flags)Access字段是一個bitmask,它保存了改control的訪問類型。默認(rèn)的訪問類 型是

8、:SNDDRV_CTL_ELEM_ACCESS_READW明該 control 支持讀和寫操 作。如果access字段沒有定義 (.access=0 ),此時也認(rèn)為是 READWRIT類 型。如果是一個只讀control ,access應(yīng)該設(shè)置為: SNDDRV_CTL_ELEM_ACCESS_RSAD我們不必定義 put回調(diào)函數(shù)。類似 地,如果是只寫control ,access應(yīng)該設(shè)置為: SNDDRV_CTL_ELEM_ACCESS_WRITE 我們不必定義 get 回調(diào)函數(shù)。如果control的值會頻繁地改變(例如:電平表),我們可以使用VOLATILE類型,這意味著該control會

9、在沒有通知的情況下改變,應(yīng)用程序應(yīng)該定時地查 詢該control的值?;卣{(diào)函數(shù)info回調(diào)函數(shù)info回調(diào)函數(shù)用于獲取control的詳細信息。它的主要工作就是填充通過參數(shù) 傳入的snd_ctl_elem_info對象,以下例子是一個具有單個元素的boolean型control 的 info 回調(diào):c-sharp view pla in copy1. static int sn d_myctl_m ono _i nfo(struct sn d_kc on trol *kc on trol,2. struct sn d_ctl_elem_i nfo *ui nfo)3. 4. ui nfo-ty

10、pe = SNDRV_CTL_ELEM_TYPE_BOOLEAN;5. uin fo-co unt = 1;6. ui nfo-value.i nteger.min = 0;7. uin fo-value.i nteger.max = 1;8. return 0;9. type字段指出該control的值類型,值類型可以是BOOLEAN, INTEGER, ENUMERATED, BYTES,IEC9和8INTEGER6之一。count 字段指出了改 control 中包含有多少個元素單元,比如,立體聲的音量control左右兩個聲道的音量值,它的count字段等于2。value字段是一個聯(lián)合

11、體(union) ,value的內(nèi) 容和control的類型有關(guān)。其 中,boolean和integer類型是相同的。ENUMERATED型有些特殊。它的value需要設(shè)定一個字符串和字符串的索引,請看以下例子:c-sharpview pla in copy1. static int sn d_myctl_e num _i nfo(struct sn d_kc on trol *kc on trol,2. struct sn d_ctl_elem_i nfo *ui nfo)3. 4. static char *texts4 = 5. First, Second, Third, Fourth6

12、. ;7. ui nfo-type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;8. uin fo-co unt = 1;9. uin fo-value.e nu merated.items= 4;10. if (uin fo-value.e nu merated.item 3)11. uin fo-value.e nu merated.item = 3;12. strcpy( uin fo-value.e nu merated .n ame,13. texts uin fo-value.e nu merated.item);14. return 0;15. alsa已經(jīng)

13、為我們實現(xiàn)了一些通用的info回調(diào)函數(shù),例如:snd_ctl_boolean_mono_info(),snd_ctl_boolean_stereo_info()等等。get回調(diào)函數(shù)該回調(diào)函數(shù)用于讀取control的當(dāng)前值,并返回給用戶空間的應(yīng)用程序c-sharp view pla in copy1. static int sn d_myctl_get(struct sn d_kc on trol *kc on trol,2. struct sn d_ctl_elem_value *uc on trol)3. 4. struct mychip *chip = sn d_kc on trol_ch

14、ip(kc on trol);5. ucon trol-value.i nteger.valueO = get_some_value(chip);6. return 0;7. value字段的賦值依賴于control的類型(如同info回調(diào))。很多聲卡的驅(qū)動 利用它存儲硬件寄存器的地址、 bit-shift 和bit-mask,這時,private_value 字段可以按以下例子進行設(shè)置:.private_value = reg | (shift 16) | (mask private_value & Oxff;int shift = (kco ntrol-private_value 16)

15、& Oxff;int mask = (kco ntrol-private_value 24) & Oxff;/根據(jù)以上的值讀取相應(yīng)寄存器的值并填入value中如果control 的count字段大于1,表示control 有多個元素單元,get回調(diào)函 數(shù)也應(yīng)該為value填充多個數(shù)值。put回調(diào)函數(shù)put回調(diào)函數(shù)用于把應(yīng)用程序的控制值設(shè)置到control中c-sharp view pla in copy1. static int sn d_myctl_put(struct sn d_kc on trol *kc on trol,2. struct sn d_ctl_elem_value *uc

16、 on trol)3. 4. struct mychip *chip = sn d_kc on trol_chip(kc on trol);5. int cha nged = 0;6. if (chip-curre nt_value !=7. ucon trol-value.i nteger.value0) cha nge_curre nt_value(chip.9.ucon trol-value.i nteger.valueO);10.changed =1;11.12.retur n cha nged;13. 如上述例子所示,當(dāng)control的值被改變時,put回調(diào)必須要返回1,如果值沒 有

17、被改變,則返回0。如果發(fā)生了錯誤,貝U返回一個負(fù)數(shù)的錯誤號。和get回調(diào)一樣,當(dāng)control的count大于1時,put回調(diào)也要處理多個 control中的元素值。創(chuàng)建 Controls當(dāng)把以上討論的內(nèi)容都準(zhǔn)備好了以后,我們就可以創(chuàng)建我們自己的con trol了。alsa-driver為我們提供了兩個用于創(chuàng)建control的API:* sn d_ctl_ new1()* sn d_ctl_add()我們可以用以下最簡單的方式創(chuàng)建control :c-sharp view pla in copy1. err = sn d_ctl_add(card, sn d_ctl_ new1(&my_con

18、 trol, chip);2. if (err private_data字段,該字段可以在回調(diào)函數(shù)中訪問。snd_ctl_new1()會分配一個新的snd_kcontrol實例,并把 my_control中相應(yīng) 的值復(fù)制到該實例中,所以,在定義my_control時,通常我們可以加上_devinitdata 前綴。snd_ctl_add則把該control綁定到聲卡對象card當(dāng) 中。元數(shù)據(jù)(Metadata )很多mixer control 需要提供以dB為單位的信息,我們可以使用 DECLARE_TLV_xX宏來定義一些包含這種信息的變量,然后把con trol的tlv.p字段指向這些變量

19、,最后,在 access字段中加上SNDRV_CTL_ELEM_ACCESS_TLV標(biāo)R志AD就像這樣: static DECLARE_TLV_DB_SCALE(db_scale_my_c on trol, -4050, 150, 0);static struct sn d_kc on trol_ new my_c on trol _devin itdata = .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |SNDRV_CTL_ELEM_ACCESS_TLV_READ,.tlv.p = db_scale_my_co ntrol,;DECLARE_TLV_

20、DB_SC宏定義的mixer control ,它所代表的值按一個固定的 dB值的步長變化。該宏的第一個參數(shù)是要定義變量的名字,第二個參數(shù)是最小 值,以0.01dB為單位。第三個參 數(shù)是變化的步長,也是以0.01dB為單位。如 果該control處于最小值時會做出mute時,需要把第四個參數(shù)設(shè)為1。DECLARE_TLV_DB_LINE宏定義的 mixer control ,它的輸出隨值的變化而線性變化。該宏的第一個參數(shù)是要定義變量的名字,第二個參數(shù)是最小值,以O(shè).OIdB為單位。第二個參數(shù)是最大 值,以O(shè).OIdB為單位。如果該control處于最小值時會做出mute時,需要把第二個參數(shù)設(shè)為

21、TLV_DB_GAIN_MUTE這兩個宏實際上就是定義一個整形數(shù)組,所謂 tlv,就是Type-Lenght-Value 的意思,數(shù)組的第0各元素代表數(shù)據(jù)的類型,第1個元素代表數(shù)據(jù)的長度,第 三個元素和之后的元素保存該變量的數(shù)據(jù)。Control設(shè)備的建立Control設(shè)備和PCM設(shè)備一樣,都屬于聲卡下的邏輯設(shè)備。用戶空間的應(yīng)用程 序通過alsa-lib 訪問該Control設(shè)備,讀取或控制control的控制狀態(tài),從而 達到控制音頻Codec進行各種Mixer等控制操作。Control設(shè)備的創(chuàng)建過程大體上和 PCMS備的創(chuàng)建過程相同。詳細的創(chuàng)建過程 可以參考本博的另一篇文章:Linux音頻驅(qū)動

22、之三:PCMS備的創(chuàng)建。下面我們 只討論有區(qū)別的地方。我們需要在我們的驅(qū)動程序初始化時主動調(diào)用snd_pcm_new()函數(shù)創(chuàng)建pcm設(shè)備,而 control 設(shè)備則在 snd_card_create() 內(nèi)被創(chuàng)建,snd_card_create() 通 過調(diào)用snd_ctl_create() 函數(shù)創(chuàng)建control設(shè)備節(jié)點。所以我們無需顯式地 創(chuàng)建control設(shè)備,只要建立聲卡,control設(shè)備被自動地創(chuàng)建。和pcm設(shè)備一樣,control設(shè)備的名字遵循一定的規(guī)則:controlCxx,這里的 xx代表聲卡的編號。我們也可以通過代碼正是這一點,下面的是sn d_ctl_dev_register()函數(shù)的代碼:c-sharp view pla in copy1. /*2. * registrati on of the con trol device3. */4. static int snd_ctl_dev_register(struct snd_device *device)5. 6. struct snd_card *card = device-de

溫馨提示

  • 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論