亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 1609 | 回復(fù): 0
打印 上一主題 下一主題

writing-an-alsa-driver(編寫一個(gè)ALSA驅(qū)動(dòng))翻譯稿 第六章 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2008-06-27 17:21 |只看該作者 |倒序?yàn)g覽

       
       
第六章
控制接口
翻譯:creator

sz111@126.com

概要
   
控制接口非常廣泛的應(yīng)用在許多轉(zhuǎn)換,變調(diào)等場合,可以從用戶空間進(jìn)行控制;煲羝鹘涌谑且粋(gè)最重要的接口。換句話說,在ALSA0.9.x版本,所有的混音器的工作都是通過控制接口API實(shí)現(xiàn)的(在0.5.x版本混音器內(nèi)核API是獨(dú)立出來的)。
   
ALSA有一個(gè)定義很好的AC97的控制模塊。如果你的聲卡僅僅支持AC97,你可以忽略這章。
控制接口定義
   
為了創(chuàng)建一個(gè)新的控制接口,需要定義三個(gè)函數(shù):info,get和put。然后定義一個(gè)snd_kcontrol_new類型的記錄,例如:
   
Example6-1.定義一個(gè)控制接口
   
static struct
snd_kcontrol_new my_control __devinitdata = {
   
    .face =
SNDRV_CTL_ELEM_IFACE_MIXER,
   
    .name =
“PCM Playback Switch”,
   
    .index =
0,
   
    .access =
SNDRV_CTL_ELEM_ACCESS_READWRITE,
   
    .private_value
= 0xffff,
   
    .info =
my_control_info,
   
    .get =
my_control_get,
   
    .put =
my_control_put
   
};
   
大部分情況是通過snd_ctl_new1()來創(chuàng)建control,這種情況下,你可以像上面一樣,在定義的前面加上__devinitdata前綴.
   
iface字段表示control的類型,如:SNDRV_CTL_ELEM_IFACE_XXX,通常情況都是MIXER。CARD表示一個(gè)全局控制,而不是混音器的一部分。假如control和聲卡設(shè)備聯(lián)系的非常緊密,如HWDEP,RAMDIDI,TIMER或SEQUENCER,需要特別通過device和subdevice字段標(biāo)識出。
   
name字段是表示名稱的標(biāo)識符。在ALSA0.9.X,控制單元名字是非常重要的,因?yàn)榈慕巧褪峭ㄟ^它的名字進(jìn)行分類。有一些預(yù)定義的標(biāo)準(zhǔn)的control名字。詳細(xì)描述請參考下節(jié)的“控制單元名字”。
   
index字段存放這個(gè)control的索引號。假如一個(gè)名字下面有多個(gè)不同的control,就要通過index(索引)來區(qū)分了。這是當(dāng)一個(gè)聲卡擁有多個(gè)解碼的時(shí)候才會用到。加入索引設(shè)定為零,就可以忽略定義。
   
access字段包括了控制接口的存取控制。提供了一些位的組合,如:SNDRV_CTL_ELEM_XXX。詳細(xì)描述請參考“接口標(biāo)志位”一節(jié)。
   
private_value字段這個(gè)記錄的一個(gè)專有的的長整型變量。當(dāng)調(diào)用info,get和put函數(shù)的時(shí)候,可以通過這個(gè)字段傳遞一些參數(shù)值。如果參數(shù)都是些很小的數(shù),可以把它們通過移位來組合,也可以存放一個(gè)指向一個(gè)記錄的指針(因?yàn)樗情L整型的)。
   
另外三個(gè)在回調(diào)函數(shù)一節(jié)介紹。
  
控制接口名字
   
有一些control名字的標(biāo)準(zhǔn)。一個(gè)control通常根據(jù)“源,方向,功能”三部分來命名。
   
首先,SOURCE定義了control的源,是一個(gè)字符串,如:“Master”,“PCM”,“CD”,“Line”。已經(jīng)有很多預(yù)定義好的“源”了。
   
第二,“方向”則為“Playbck”,“Capture”,“Bypass
Playback”,“Bypass
Capture”;蛘,它如果省略,那就表示播放和錄音雙向。
   
第三個(gè),“功能”。根據(jù)控制接口的功能不同有下面三個(gè):“Switch”,“volume”,“route”。
   
一些控制接口名字的范例如下:“Master
Capture Switch”,“PCM
Playback Volume”.
   
也有一些不是采用“源,方向,功能”三部分來命名方式:
   
全局錄音和播放
   
“Capture
Source”,“Capture
Switch”和“Capture
Volume”用來做全局錄音(輸入)源,開關(guān),和音量的控制!癙layback
Switch”和“Playback
Volume”用來做全局的輸出開關(guān)和音量控制。
   
音調(diào)控制
   
音調(diào)開關(guān)和音量名稱形式為“Tone
Control-XXX”。如:“Tone
Control-Switch”,“Tone
Control – Bass”,“Tone
Control – Center”。
   
3D控制
   
3D控制開關(guān)和音量命名形式為“3D
Control – XXX”。如:“3D
Control – Switch”,“3D
Control – Switch”,“3D
Control – Center”,“3D Control – Space”。
   
麥克風(fēng)增益
   
麥克風(fēng)增益命名如“Mic
Boost”或“Mic
Boost(6dB)”。
   
更精確的信息請參考文檔(Documentation/sound/alsa/ControlNames.txt)
存取標(biāo)志
   
存取標(biāo)志是一個(gè)位標(biāo)志,主要是區(qū)分給定的control的存取類型。缺省的存取類型是SNDRV_CTL_ELEM_ACCESS_READWRITE,意思是允許對control進(jìn)行讀寫控制。當(dāng)這個(gè)標(biāo)志位被忽略的時(shí)候(為0),被認(rèn)為是缺省讀寫(READWRITE)。
   
當(dāng)這個(gè)control是只讀的時(shí)候,需要傳遞SNDRV_CTL_ELEM_ACCESS_READ。這時(shí)候,可以不定義put函數(shù)。類似的,如果control是只寫的話(雖然這種可能性很低),要設(shè)定為WRITE標(biāo)志,也可以不必定義get函數(shù)。
   
加入control的值是經(jīng)常改變的,應(yīng)該加上VOLATILE標(biāo)志,這意味著control可以不用顯式通知就可以改變。應(yīng)用程序應(yīng)經(jīng)常查詢control。
   
當(dāng)一個(gè)control是不活動(dòng)的話,設(shè)定INACTIVE標(biāo)志。還有LOCK和OWNER標(biāo)志用來改變寫權(quán)限。
   
回調(diào)函數(shù)
   
info函數(shù)
   
info函數(shù)可以得到對應(yīng)control的詳細(xì)信息。它必須存到一個(gè)給定的snd_ctl_elem_info對象中。例如,對于一個(gè)擁有一個(gè)元素的布爾型control的如下:
   
Example6-2.info函數(shù)示例
   
static int
snd_myctl_info(struct snd_kcontrol *kcontrol,
   
                          struct
snd_ctl_elem_info *uinfo)
   
{
   
     uinfo->type
= SNDRV_CTL_ELEM_TYPE_BOOLEAN;
   
     uinfo->count
= 1;
   
     uinfo->value.integer.min
= 0;
   
     uinfo->value.integer.max
= 1;
   
     return
0;
   
}
   
type字段表示control的類型。有如下幾種:布爾型,整形,枚舉型,BYTES型,IEC958,64位整形。count字段表示這個(gè)control里面的元素的數(shù)量。如:一個(gè)立體聲音量擁有的count為2。value字段是一個(gè)union(聯(lián)合)類型。value的存儲依賴于類型。布爾型和整形是一樣的。
   
枚舉型和其他類型有一點(diǎn)不同,需要為當(dāng)前給定的索引項(xiàng)設(shè)定字符串。
   
Static int
snd_myctl_info(struct snd_kcontrol *kcontrol,
   
                          struct
snd_ctl_elem_info *uinfo)
   
{
   
    static
char *texts[4] ={
   
        “First”,“Second”,“Third”,“Fourth”
   
    };
   
    uinfo->type
= SNDRV_CTL_ELEM_TYPE_ENUMRATED;
   
    uinfo->count
= 1;
   
    uinfo->value.enumerated.items
= 4;
   
    if
(uinfo->value.enumerated.item > 3)
   
      
uinfo->value.enumerated.item
= 3;
      
   
    strcpy(
uinfo->value.enumerated.name,texts[
uinfo->value.enumerated.item]);
   
    return
0;
   
}
   
get函數(shù)
   
這個(gè)函數(shù)用來讀取當(dāng)前control的值并返回到用戶空間。
   
例如:
   
Example6-3.get函數(shù)示例
   
static int
snd_myctl_get(struct snd_kcontrol *kcontrol,
   
                         struct
snd_ctl_ctl_elem_value *ucontrol)
   
{
   
    struct
mychip *chip = snd_kcontrol_chip(kcontrol);
   
    ucontrol->value.integer.value[0]
= get_some_value(chip);
   
    return 0;
   
}
   
value字段和control類型有關(guān),這點(diǎn)和info類似。例如,子驅(qū)動(dòng)和用這個(gè)字段來存儲一些寄存器的偏移,位的屏蔽。private_value設(shè)定如下:
   
.private_value
= reg | (shift
   
可以通過以下函數(shù)重新得到:
   
static int
snd_sbmixer_get_single(struct snd_kcontrol *kcontrol,
   
                                   struct
snd_ctl_elem_value *ucontrol)
   
{
   
     int reg
= kcontrol->private_value & 0xff;
   
     int
shift = (kcontrol->private_value >> 16) & 0xff;
   
     int mask
= (kcontrol->private_value >> 24) & 0xff;
   
     ....
   
}
   
在get函數(shù)中,加入control擁有超過一個(gè)的元素。如count大于1,就必須填充所有的元素。上面的例子中,因?yàn)槲覀兗俣╟ount為1,所以我們僅僅填充了一個(gè)元素(value.integer.value[0])。
   
   
put函數(shù)
   
這個(gè)函數(shù)主要是從用戶空間寫一個(gè)值
   
例如:
   
Example6-4.put函數(shù)示例
   
static int
snd_myctrl_put(struct snd_kcontrol *kcontrol,
   
                          struct
snd_ctl_elem_value *ucontrol)
   
{
   
    struct
mychip *chip = snd_kcontrol_chip(kcontrol);
   
    int
changed = 0;
   
    if
(chip->current_value != ucontrol->value.integer.value[0]){
   
        change_current_value(chip,ucontrol->value.integer.value[0]);
   
        changed
= 1;
   
    }
   
    return
changed;
   
}
   
如上,假如value被改變要返回1,沒有改變返回0。假如有錯(cuò)誤發(fā)生,通常返回一個(gè)帶錯(cuò)誤碼的負(fù)數(shù)。
   
像get函數(shù)一樣,如果control擁有超過一個(gè)的元素,在put函數(shù)中所有的元素都要比較一下。
   
回調(diào)函數(shù)不是原子的。
   
所有上面的3個(gè)回調(diào)函數(shù)都是非原子的。
構(gòu)造器
   
當(dāng)所有事情都準(zhǔn)備好的時(shí)候,我們就可以創(chuàng)建一個(gè)新的control了。為了創(chuàng)建它,首先要調(diào)用兩個(gè)函數(shù),snd_ctl_new1()和snd_ctl_add()。
   
一個(gè)簡單的方式如下:
   
if ((err =
snd_ctl_add(card, snd_ctl_new1(&my_control, chip)))
   
    return
err;
   
my_control是前面定義好的snd_kcontrol_new類型的對象,chip是一個(gè)指向kcontrol->private_data的指針,可以被回調(diào)函數(shù)調(diào)用。
   
snd_ctl_new1()分配了一個(gè)新的snd_kcontrol實(shí)例(這也是為何my_control可以帶有__devinitdata前綴的原因了),snd_ctl_add會把給定的control組件添加到card里面。
   
更改通知
   
假如你需要在中斷程序中改變或更新一個(gè)control,你需要調(diào)用snd_ctl_notify()。
    例如:
   
snd_ctl_notify(card,
SNDRV_CTL_EVENT_MASK_VALUE,id_pointer);
   
這個(gè)函數(shù)需要card指針,event_mask,和control
id指針作為參數(shù)。event-mask表示notification的類型,如上述示例,是通知改變control的值。id指針是指向一個(gè)snd_ctl_elem_id的結(jié)構(gòu)體。在es1938.c或es1968.c中關(guān)于硬件的卷的中斷部分有相關(guān)示例。
  
   
               
               
               

本文來自ChinaUnix博客,如果查看原文請點(diǎn):http://blog.chinaunix.net/u1/49088/showart_1018357.html
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP