alsa音频架构1 (四)

2014-11-24 02:34:44 · 作者: · 浏览: 19
snd_printk(KERN_ERR "unable to create card info\n");
goto __error_ctl;
}
if (extra_size > 0) //有额外数据
card->private_data = (char *)card + sizeof(struct snd_card);
*card_ret = card;
return 0;

__error_ctl:
snd_device_free_all(card, SNDRV_DEV_CMD_PRE);
__error:
kfree(card);
return err;
}
EXPORT_SYMBOL(snd_card_create);

int snd_card_create(int idx, const char *xid,struct module *module, int extra_size,struct snd_card **card_ret)
{
struct snd_card *card;
int err, idx2;
if (snd_BUG_ON(!card_ret))
return -EINVAL;
*card_ret = NULL;
if (extra_size < 0)
extra_size = 0;
card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL); //分配声卡对象和额外空间的内存
if (!card)
return -ENOMEM;
if (xid) //若需要填充声卡id识别字串
strlcpy(card->id, xid, sizeof(card->id)); //card->id=xid 声卡id识别字串
err = 0;

mutex_lock(&snd_card_mutex); //idx为负值则交由系统选择一个值______________________<
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;
}
}
}
if (idx < 0)
err = -ENODEV;
else if (idx < snd_ecards_limit) {
if (snd_cards_lock & (1 << idx))
err = -EBUSY; /* invalid */
} else if (idx >= SNDRV_CARDS)
err = -ENODEV;
if (err < 0) {
mutex_unlock(&snd_card_mutex);
snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i), error: %d\n",idx, snd_ecards_limit - 1, err);
goto __error;
}
snd_cards_lock |= 1 << idx; /* lock it */
if (idx >= snd_ecards_limit)
snd_ecards_limit = idx + 1; /* increase the limit */
mutex_unlock(&snd_card_mutex); //______________________>

card->number = idx; //声卡对象索引号 全局数组snd_cards的数组下标
card->module = module; //声卡对象模块所有者THIS_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
err = snd_ctl_create(card); //创建用于控制的声卡设备对象
if (err < 0) {
snd_printk(KERN_ERR "unable to register control minors\n");
goto __error;
}
err = snd_info_card_create(card); //proc下面的接口
if (err < 0) {
snd_printk(KERN_ERR "unable to create card info\n");
goto __error_ctl;
}
if (extra_size > 0) //有额外数据
card->private_data = (char *)card + sizeof(struct snd_card);
*card_ret = card;
return 0;

__error_ctl:
snd_device_free_all(card, SNDRV_DEV_CMD_PRE);
__error:
kfree(card);
return err;
}
EXPORT_SYMBOL(snd_card_create);这里主要是初始化了声卡的devices声卡设备链表,以后创建的声卡设备将挂在该链表上

并调用了snd_ctl_create创建了用于控制的声卡设备对象,这我们可以得出一个结论每个声卡都有一个声卡控制设备对象

\


第三部分 声卡设备

1.创建声卡设备

在这里 声卡设备与声卡捆绑,指定声卡设备类型,设置声卡设备状态,捆绑对应的snd_device_ops方法,添加声卡设备到声卡的devices链表

[cpp]
int snd_device_new(struct snd_card *card, snd_device_type_t type,void *device_data, struct snd_device_ops *ops)
{
struct snd_device *dev;

if (snd_BUG_ON(!c