alsa架構分析

來源:互聯網
上載者:User

聲明:本博內容轉載自 http://blog.csdn.net/droidphone
一.  概述

    ALSA是Advanced Linux Sound Architecture 的縮寫,目前已經成為了linux的主流音頻體繫結構,想瞭解更多的關於ALSA的這一開源項目的資訊和知識,請查看以下網址:http://www.alsa-project.org/。

    在核心裝置驅動層,ALSA提供了alsa-driver,同時在應用程式層,ALSA為我們提供了alsa-lib,應用程式只要調用alsa-lib提供的API,即可以完成對底層音頻硬體的控制。

 

                                                           圖 1.1   alsa的軟體體繫結構

由圖1.1可以看出,使用者空間的alsa-lib對應用程式提供統一的API介面,這樣可以隱藏了驅動層的實現細節,簡化了應用程式的實現難度。核心空間中,alsa-soc其實是對alsa-driver的進一步封裝,他針對嵌入式裝置提供了一些列增強功能。本系列博文僅對嵌入式系統中的alsa-driver和alsa-soc進行討論。  二.  ALSA裝置檔案結構

    我們從alsa在linux中的裝置檔案結構開始我們的alsa之旅. 看看我的電腦中的alsa驅動的裝置檔案結構:

$ cd /dev/snd
$ ls -l

crw-rw----+ 1 root audio 116, 8 2011-02-23 21:38 controlC0
crw-rw----+ 1 root audio 116, 4 2011-02-23 21:38 midiC0D0
crw-rw----+ 1 root audio 116, 7 2011-02-23 21:39 pcmC0D0c
crw-rw----+ 1 root audio 116, 6 2011-02-23 21:56 pcmC0D0p
crw-rw----+ 1 root audio 116, 5 2011-02-23 21:38 pcmC0D1p
crw-rw----+ 1 root audio 116, 3 2011-02-23 21:38 seq
crw-rw----+ 1 root audio 116, 2 2011-02-23 21:38 timer
$


    我們可以看到以下裝置檔案: controlC0 -->                 用於音效卡的控制,例如通道選擇,混音,麥克風的控制等 midiC0D0  -->                用於播放midi音頻 pcmC0D0c --〉               用於錄音的pcm裝置 pcmC0D0p --〉               用於播放的pcm裝置 seq  --〉                        音序器 timer --〉                       定時器

其中,C0D0代表的是音效卡0中的裝置0,pcmC0D0c最後一個c代表capture,pcmC0D0p最後一個p代表playback,這些都是alsa-driver中的命名規則。從上面的列表可以看出,我的音效卡下掛了6個裝置,根據音效卡的實際能力,驅動實際上可以掛上更多種類的裝置,在include/sound/core.h中,定義了以下裝置類型:

[c-sharp] view plain copy print ? #define SNDRV_DEV_TOPLEVEL  ((__force snd_device_type_t) 0)   #define SNDRV_DEV_CONTROL   ((__force snd_device_type_t) 1)   #define SNDRV_DEV_LOWLEVEL_PRE  ((__force snd_device_type_t) 2)   #define SNDRV_DEV_LOWLEVEL_NORMAL ((__force snd_device_type_t) 0x1000)   #define SNDRV_DEV_PCM       ((__force snd_device_type_t) 0x1001)   #define SNDRV_DEV_RAWMIDI   ((__force snd_device_type_t) 0x1002)   #define SNDRV_DEV_TIMER     ((__force snd_device_type_t) 0x1003)   #define SNDRV_DEV_SEQUENCER ((__force snd_device_type_t) 0x1004)   #define SNDRV_DEV_HWDEP     ((__force snd_device_type_t) 0x1005)   #define SNDRV_DEV_INFO      ((__force snd_device_type_t) 0x1006)   #define SNDRV_DEV_BUS       ((__force snd_device_type_t) 0x1007)   #define SNDRV_DEV_CODEC     ((__force snd_device_type_t) 0x1008)   #define SNDRV_DEV_JACK          ((__force snd_device_type_t) 0x1009)   #define SNDRV_DEV_LOWLEVEL  ((__force snd_device_type_t) 0x2000)  

 通常,我們更關心的是pcm和control這兩種裝置。

  三.  驅動的代碼檔案結構

    在Linux2.6代碼樹中,Alsa的代碼檔案結構如下:

    sound
            /core
                     /oss
                    /seq
            /ioctl32
            /include
            /drivers
            /i2c
            /synth
                    /emux
            /pci
                    /(cards)
            /isa
                    /(cards)
            /arm
            /ppc
            /sparc
            /usb
            /pcmcia /(cards)
            /oss
            /soc
                    /codecs core               該目錄包含了ALSA驅動的中介層,它是整個ALSA驅動的核心部分 core/oss        包含類比舊的OSS架構的PCM和Mixer模組 core/seq        有關音序器相關的代碼 include          ALSA驅動的公用標頭檔目錄,該目錄的標頭檔需要匯出給使用者空間的應用程式使用,通常,驅動模組私人的標頭檔不應放置在這裡  drivers           放置一些與CPU、BUS架構無關的公用代碼 i2c                 ALSA自己的I2C控制碼 pci                 pci音效卡的頂層目錄,子目錄包含各種pci音效卡的代碼 isa                 isa音效卡的頂層目錄,子目錄包含各種isa音效卡的代碼 soc                針對system-on-chip體系的中介層代碼 soc/codecs    針對soc體系的各種codec的代碼,與平台無關 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

[c-sharp] view plain copy print ? /* main structure for soundcard */      struct snd_card {       int number;         /* number of soundcard (index to                                  snd_cards) */          char id[16];            /* id string of this card */       char driver[16];        /* driver name */       char shortname[32];     /* short name of this soundcard */       char longname[80];      /* name of this soundcard */       char mixername[80];     /* mixer name */       char components[128];       /* card components delimited with                                  space */       struct module *module;      /* top-level module */          void *private_data;     /* private data for soundcard */       void (*private_free) (struct snd_card *card); /* callback for freeing of                                  private data */       struct list_head devices;   /* devices */          unsigned int last_numid;    /* last used numeric ID */       struct rw_semaphore controls_rwsem; /* controls list lock */       rwlock_t ctl_files_rwlock;  /* ctl_files list lock */       int controls_count;     /* count of all controls */       int user_ctl_count;     /* count of all user controls */       struct list_head controls;  /* all controls for this card */       struct list_head ctl_files; /* active control files */          struct snd_info_entry *proc_root;   /* root for soundcard specific files */       struct snd_info_entry *proc_id; /* the card id */       struct proc_dir_entry *proc_root_link;  /* number link to real id */          struct list_head files_list;    /* all files associated to this card */       struct snd_shutdown_f_ops *s_f_ops; /* file operations in the shutdown                                  state */       spinlock_t files_lock;      /* lock the files for this card */       int shutdown;           /* this card is going down */       int free_on_last_close;     /* free in context of file_release */       wait_queue_head_t shutdown_sleep;       struct device *dev;     /* device assigned to this card */  #ifndef CONFIG_SYSFS_DEPRECATED        struct device *card_dev;    /* cardX object for sysfs */  #endif   #ifdef CONFIG_PM        unsigned int power_state;   /* power state */       struct mutex power_lock;    /* power lock */       wait_queue_head_t power_sleep;   #endif   #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)        struct snd_mixer_oss *mixer_oss;       int mixer_oss_change_count;   #endif    };  

struct list_head devices     記錄該音效卡下所有邏輯裝置的鏈表 struct list_head controls    記錄該音效卡下所有的控制單元的鏈表 void *private_data            音效卡的私人資料,可以在建立音效卡時通過參數指定資料的大小 2. 音效卡的建立流程

  2.1.1. 第一步,建立snd_card的一個執行個體

[c-sharp] struct snd_card *card;   int err;   ....   err = snd_card_create(index, id, THIS_MODULE, 0, &card);  

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

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

音效卡的專用資料主要用於存放該音效卡的一些資源資訊,例如中斷資源、io資源、dma資源等。可以有兩種建立方法: 通過上一步中snd_card_create()中的第四個參數,讓snd_card_create自己建立

[c-sharp] view plain copy print ? // struct mychip 用於儲存專用資料    err = snd_card_create(index, id, THIS_MODULE,                   sizeof(struct mychip), &card);   // 從private_data中取出    struct mychip *chip = card->private_data;  

自己建立:

[c-sharp] view plain copy print ? struct mychip {       struct snd_card *card;       ....   };   struct snd_card *card;   struct mychip *chip;   err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);   // 專用資料記錄snd_card執行個體    chip->card = card;   .....   chip = kzalloc(sizeof(*chip), GFP_KERNEL);  

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

[c-sharp] view plain copy print ? static int snd_mychip_dev_free(struct snd_device *device)   {       return snd_mychip_free(device->device_data);   }      static struct snd_device_ops ops = {       .dev_free = snd_mychip_dev_free,   };   ....   snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);  

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.