1. 程式人生 > >Linux ALSA音效卡驅動之二:音效卡的建立

Linux ALSA音效卡驅動之二:音效卡的建立

1. struct snd_card

1.1. snd_card是什麼

snd_card可以說是整個ALSA音訊驅動最頂層的一個結構,整個音效卡的軟體邏輯結構開始於該結構,幾乎所有與聲音相關的邏輯裝置都是在snd_card的管理之下,音效卡驅動的第一個動作通常就是建立一個snd_card結構體。正因為如此,本節中,我們也從 struct cnd_card開始吧。

1.2. snd_card的定義

snd_card的定義位於改標頭檔案中:include/sound/core.h

  • struct list_head devices     記錄該音效卡下所有邏輯裝置的連結串列
  • struct list_head controls    記錄該音效卡下所有的控制單元的連結串列
  • void *private_data            音效卡的私有資料,可以在建立音效卡時通過引數指定資料的大小

2. 音效卡的建立流程

2.1.1. 第一步,建立snd_card的一個例項

 

  • index           一個整數值,該音效卡的編號
  • id                字串,音效卡的識別符號
  • 第四個引數    該引數決定在建立snd_card例項時,需要同時額外分配的私有資料的大小,該資料的指標最終會賦值給snd_card的private_data資料成員
  • card             返回所建立的snd_card例項的指標

2.1.2. 第二步,建立音效卡的晶片專用資料

音效卡的專用資料主要用於存放該音效卡的一些資源資訊,例如中斷資源、io資源、dma資源等。可以有兩種建立方法:

  • 通過上一步中snd_card_create()中的第四個引數,讓snd_card_create自己建立

  • 自己建立:

然後,把晶片的專有資料註冊為音效卡的一個低階裝置:

 註冊為低階裝置主要是為了當音效卡被登出時,晶片專用資料所佔用的記憶體可以被自動地釋放。

2.1.3. 第三步,設定Driver的ID和名字

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連結串列中。

通常,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. 第五步,註冊音效卡

 

2.2. 一個實際的例子

我把/sound/arm/pxa2xx-ac97.c的部分程式碼貼上來:

驅動程式通常由probe回撥函式開始,對一下2.1中的步驟,是否有相似之處?

經過以上的建立步驟之後,音效卡的邏輯結構如下圖所示:

                                             圖 2.2.1  音效卡的軟體邏輯結構

下面的章節裡我們分別討論一下snd_card_create()和snd_card_register()這兩個函式。

3. snd_card_create()

 snd_card_create()在/sound/core/init.c中定義。

首先,根據extra_size引數的大小分配記憶體,該記憶體區可以作為晶片的專有資料使用(見前面的介紹):

拷貝音效卡的ID字串:

如果傳入的音效卡編號為-1,自動分配一個索引編號:

初始化snd_card結構中必要的欄位:

建立邏輯裝置:Control

建立proc檔案中的info節點:通常就是/proc/asound/card0

把第一步分配的記憶體指標放入private_data欄位中:

4. snd_card_register()

  snd_card_create()在/sound/core/init.c中定義。

首先,建立sysfs下的裝置:

其中,sound_class是在/sound/sound_core.c中建立的:

由此可見,音效卡的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()來實現各自裝置的註冊的。

最後就是建立一些相應的proc和sysfs下的檔案或屬性節點,程式碼就不貼了。

至此,整個音效卡完成了建立過程。