ALSA架构简介(4)

2020-03-27 16:32

* 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)

首先,根据extra_size参数的大小分配内存,该内存区可以作为芯片的专有数据使用(见前面的介绍):

view plaincopy to clipboardprint?

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

return -ENOMEM; card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL); if (!card) return -ENOMEM;

拷贝声卡的ID字符串:

view plaincopy to clipboardprint? if (xid)

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

如果传入的声卡编号为-1,自动分配一个索引编号:

view plaincopy to clipboardprint? 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<

初始化snd_card结构中必要的字段:

view plaincopy to clipboardprint? 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 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

建立逻辑设备:Control

view plaincopy to clipboardprint?

/* 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); /* 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节点:通常就是/proc/asound/card0

view plaincopy to clipboardprint? err = snd_info_card_create(card); err = snd_info_card_create(card);

把第一步分配的内存指针放入private_data字段中:

view plaincopy to clipboardprint? if (extra_size > 0)

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

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

4. snd_card_register()

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

view plaincopy to clipboardprint? /**

* snd_card_register - register the soundcard * @card: soundcard structure *

* This function registers all the devices assigned to the soundcard. * Until calling this, the ALSA 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) /**

* snd_card_register - register the soundcard * @card: soundcard structure *

* This function registers all the devices assigned to the soundcard. * Until calling this, the ALSA 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)

首先,创建sysfs下的设备:

view plaincopy to clipboardprint? if (!card->card_dev) {

card->card_dev = device_create(sound_class, card->dev, MKDEV(0, 0), card,

\ if (IS_ERR(card->card_dev)) card->card_dev = NULL; } if (!card->card_dev) {

}

card->card_dev = device_create(sound_class, card->dev, MKDEV(0, 0), card, \if (IS_ERR(card->card_dev)) card->card_dev = NULL;

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

view plaincopy to clipboardprint?

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

if (MAJOR(dev->devt) == SOUND_MAJOR) return NULL;

return kasprintf(GFP_KERNEL, \ }

static int __init init_soundcore(void) {

int rc;

rc = init_oss_soundcore(); if (rc)

return rc;

sound_class = class_create(THIS_MODULE, \ if (IS_ERR(sound_class)) {

cleanup_oss_soundcore(); return PTR_ERR(sound_class); }

sound_class->devnode = sound_devnode;

return 0; }

static char *sound_devnode(struct device *dev, mode_t *mode) { if (MAJOR(dev->devt) == SOUND_MAJOR) return NULL; return kasprintf(GFP_KERNEL, \}

static int __init init_soundcore(void) { int rc;

}

rc = init_oss_soundcore(); if (rc) return rc;

sound_class = class_create(THIS_MODULE, \if (IS_ERR(sound_class)) { cleanup_oss_soundcore(); return PTR_ERR(sound_class); }

sound_class->devnode = sound_devnode; return 0;

由此可见,声卡的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()来实现各自设备的注册的。

view plaincopy to clipboardprint?

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

最后就是建立一些相应的proc和sysfs下的文件或属性节点,代码就不贴了。

至此,整个声卡完成了建立过程。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/DroidPhone/archive/2011/03/30/6289712.aspx


ALSA架构简介(4).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:县新型农村社会养老保险试点特见成效工作汇报[可编辑版]

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: