在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > Linux ALSA聲卡驅(qū)動(dòng)之二:聲卡的創(chuàng)建

            Linux ALSA聲卡驅(qū)動(dòng)之二:聲卡的創(chuàng)建

            作者: 時(shí)間:2016-12-07 來(lái)源:網(wǎng)絡(luò) 收藏

              2.1.4. 第四步,創(chuàng)建聲卡的功能部件(邏輯設(shè)備),例如PCM,Mixer,MIDI等

            本文引用地址:http://www.biyoush.com/article/201612/341246.htm

              這時(shí)候可以創(chuàng)建聲卡的各種功能部件了,還記得開(kāi)頭的snd_card結(jié)構(gòu)體的devices字段嗎?每一種部件的創(chuàng)建最終會(huì)調(diào)用snd_device_new()來(lái)生成一個(gè)snd_device實(shí)例,并把該實(shí)例鏈接到snd_card的devices鏈表中。

              通常,alsa-driver的已經(jīng)提供了一些常用的部件的創(chuàng)建函數(shù),而不必直接調(diào)用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. 第五步,注冊(cè)聲卡

              err = snd_card_register(card);

              if (err < 0) {

              snd_card_free(card);

              return err;

              }

              2.2. 一個(gè)實(shí)際的例子

              我把/sound/arm/pxa2xx-ac97.c的部分代碼貼上來(lái):

              static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)

              {

              struct snd_card *card;

              struct snd_ac97_bus *ac97_bus;

              struct snd_ac97_template ac97_template;

              int ret;

              pxa2xx_audio_ops_t *pdata = dev->dev.platform_data;

              if (dev->id >= 0) {

              dev_err(&dev->dev, "PXA2xx has only one AC97 port./n");

              ret = -ENXIO;

              goto err_dev;

              }

              ////(1)////

              ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,

              THIS_MODULE, 0, &card);

              if (ret < 0)

              goto err;

              card->dev = &dev->dev;

              ////(3)////

              strncpy(card->driver, dev->dev.driver->name, sizeof(card->driver));

              ////(4)////

              ret = pxa2xx_pcm_new(card, &pxa2xx_ac97_pcm_client, &pxa2xx_ac97_pcm);

              if (ret)

              goto err;

              ////(2)////

              ret = pxa2xx_ac97_hw_probe(dev);

              if (ret)

              goto err;

              ////(4)////

              ret = snd_ac97_bus(card, 0, &pxa2xx_ac97_ops, NULL, &ac97_bus);

              if (ret)

              goto err_remove;

              memset(&ac97_template, 0, sizeof(ac97_template));

              ret = snd_ac97_mixer(ac97_bus, &ac97_template, &pxa2xx_ac97_ac97);

              if (ret)

              goto err_remove;

              ////(3)////

              snprintf(card->shortname, sizeof(card->shortname),

              "%s", snd_ac97_get_short_name(pxa2xx_ac97_ac97));

              snprintf(card->longname, sizeof(card->longname),

              "%s (%s)", dev->dev.driver->name, card->mixername);

              if (pdata && pdata->codec_pdata[0])

              snd_ac97_dev_add_pdata(ac97_bus->codec[0], pdata->codec_pdata[0]);

              snd_card_set_dev(card, &dev->dev);

              ////(5)////

              ret = snd_card_register(card);

              if (ret == 0) {

              platform_set_drvdata(dev, card);

              return 0;

              }

              err_remove:

              pxa2xx_ac97_hw_remove(dev);

              err:

              if (card)

              snd_card_free(card);

              err_dev:

              return ret;

              }

              static int __devexit pxa2xx_ac97_remove(struct platform_device *dev)

              {

              struct snd_card *card = platform_get_drvdata(dev);

              if (card) {

              snd_card_free(card);

              platform_set_drvdata(dev, NULL);

              pxa2xx_ac97_hw_remove(dev);

              }

              return 0;

              }

              static struct platform_driver pxa2xx_ac97_driver = {

              .probe = pxa2xx_ac97_probe,

              .remove = __devexit_p(pxa2xx_ac97_remove),

              .driver = {

              .name = "pxa2xx-ac97",

              .owner = THIS_MODULE,

              #ifdef CONFIG_PM

              .pm = &pxa2xx_ac97_pm_ops,

              #endif

              },

              };

              static int __init pxa2xx_ac97_init(void)

              {

              return platform_driver_register(&pxa2xx_ac97_driver);

              }

              static void __exit pxa2xx_ac97_exit(void)

              {

              platform_driver_unregister(&pxa2xx_ac97_driver);

              }

              module_init(pxa2xx_ac97_init);

              module_exit(pxa2xx_ac97_exit);

              MODULE_AUTHOR("Nicolas Pitre");

              MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");

              驅(qū)動(dòng)程序通常由probe回調(diào)函數(shù)開(kāi)始,對(duì)一下2.1中的步驟,是否有相似之處?

              經(jīng)過(guò)以上的創(chuàng)建步驟之后,聲卡的邏輯結(jié)構(gòu)如下圖所示:

                

             

              圖 2.2.1 聲卡的軟件邏輯結(jié)構(gòu)

              下面的章節(jié)里我們分別討論一下snd_card_create()和snd_card_register()這兩個(gè)函數(shù)。

              3. snd_card_create()

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

              /**

              * snd_card_create - create and initialize a soundcard structure

              * @idx: card index (address) [0 ... (SNDRV_CARDS-1)]

              * @xid: card identification (ASCII string)

              * @module: top level module for locking

              * @extra_size: allocate this extra size after the main soundcard structure

              * @card_ret: the pointer to store the created card instance

              *

              * Creates and initializes a soundcard structure.

              *

              * The function allocates snd_card instance via kzalloc with the given

              * space for the driver to use freely. The allocated struct is stored

              * in the given card_ret pointer.

              *

              * Returns zero if successful or a negative error code.

              */

              int snd_card_create(int idx, const char *xid,

              struct module *module, int extra_size,

              struct snd_card **card_ret)

              首先,根據(jù)extra_size參數(shù)的大小分配內(nèi)存,該內(nèi)存區(qū)可以作為芯片的專有數(shù)據(jù)使用(見(jiàn)前面的介紹):

              card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);

              if (!card)

              return -ENOMEM;

              拷貝聲卡的ID字符串:

              if (xid)

              strlcpy(card->id, xid, sizeof(card->id));

              如果傳入的聲卡編號(hào)為-1,自動(dòng)分配一個(gè)索引編號(hào):

              if (idx < 0) {

              for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)

              /* idx == -1 == 0xffff means: take any free slot */

              if (~snd_cards_lock & idx & 1<

              if (module_slot_match(module, idx2)) {

              idx = idx2;

              break;

              }

              }

              }

              if (idx < 0) {

              for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)

              /* idx == -1 == 0xffff means: take any free slot */

              if (~snd_cards_lock & idx & 1<

              if (!slots[idx2] || !*slots[idx2]) {

              idx = idx2;

              break;

              }

              }

              }

              初始化snd_card結(jié)構(gòu)中必要的字段:

              card->number = idx;

              card->module = module;

              INIT_LIST_HEAD(&card->devices);

              init_rwsem(&card->controls_rwsem);

              rwlock_init(&card->ctl_files_rwlock);

              INIT_LIST_HEAD(&card->controls);

              INIT_LIST_HEAD(&card->ctl_files);

              spin_lock_init(&card->files_lock);

              INIT_LIST_HEAD(&card->files_list);

              init_waitqueue_head(&card->shutdown_sleep);

              #ifdef CONFIG_PM

              mutex_init(&card->power_lock);

              init_waitqueue_head(&card->power_sleep);

              #endif

              建立邏輯設(shè)備:Control

              /* the control interface cannot be accessed from the user space until */

              /* snd_cards_bitmask and snd_cards are set with snd_card_register */

              err = snd_ctl_create(card);

              建立proc文件中的info節(jié)點(diǎn):通常就是/proc/asound/card0

              err = snd_info_card_create(card);

              把第一步分配的內(nèi)存指針?lè)湃雙rivate_data字段中:

              if (extra_size > 0)

              card->private_data = (char *)card + sizeof(struct snd_card);

              4. snd_card_register()

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

              /**

              * snd_card_register - register the soundcard

              * @card: soundcard structure

              *

              * This function registers all the devices assigned to the soundcard.

              * Until calling this, the  control interface is blocked from the

              * external accesses. Thus, you should call this function at the end

              * of the initialization of the card.

              *

              * Returns zero otherwise a negative error code if the registrain failed.

              */

              int snd_card_register(struct snd_card *card)

              首先,創(chuàng)建sysfs下的設(shè)備:

              if (!card->card_dev) {

              card->card_dev = device_create(sound_class, card->dev,

              MKDEV(0, 0), card,

              "card%i", card->number);

              if (IS_ERR(card->card_dev))

              card->card_dev = NULL;

              }

              其中,sound_class是在/sound/sound_core.c中創(chuàng)建的:

              static char *sound_devnode(struct device *dev, mode_t *mode)

              {

              if (MAJOR(dev->devt) == SOUND_MAJOR)

              return NULL;

              return kasprintf(GFP_KERNEL, "snd/%s", dev_name(dev));

              }

              static int __init init_soundcore(void)

              {

              int rc;

              rc = init_oss_soundcore();

              if (rc)

              return rc;

              sound_class = class_create(THIS_MODULE, "sound");

              if (IS_ERR(sound_class)) {

              cleanup_oss_soundcore();

              return PTR_ERR(sound_class);

              }

              sound_class->devnode = sound_devnode;

              return 0;

              }

              由此可見(jiàn),聲卡的class將會(huì)出現(xiàn)在文件系統(tǒng)的/sys/class/sound/下面,并且,sound_devnode()也決定了相應(yīng)的設(shè)備節(jié)點(diǎn)也將會(huì)出現(xiàn)在/dev/snd/下面。

              接下來(lái)的步驟,通過(guò)snd_device_register_all()注冊(cè)所有掛在該聲卡下的邏輯設(shè)備,snd_device_register_all()實(shí)際上是通過(guò)snd_card的devices鏈表,遍歷所有的snd_device,并且調(diào)用snd_device的ops->dev_register()來(lái)實(shí)現(xiàn)各自設(shè)備的注冊(cè)的。

              if ((err = snd_device_register_all(card)) < 0)

              return err;

              最后就是建立一些相應(yīng)的proc和sysfs下的文件或?qū)傩怨?jié)點(diǎn),代碼就不貼了。

              至此,整個(gè)聲卡完成了建立過(guò)程。


            上一頁(yè) 1 2 下一頁(yè)

            關(guān)鍵詞: Linux ALSA

            評(píng)論


            相關(guān)推薦

            技術(shù)專區(qū)

            關(guān)閉