微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Linux ALSA声卡驱动之三:PCM设备的创建

Linux ALSA声卡驱动之三:PCM设备的创建

时间:12-14 来源:互联网 点击:

调用。

snd_pcm_set_ops 设置操作该pcm的控制/操作接口函数,参数中的snd_pcm_ops结构中的函数通常就是我们驱动要实现的函数

snd_card_register 注册声卡,在这个阶段会遍历声卡下的所有逻辑设备,并且调用各设备的注册回调函数,对于pcm,就是第二步提到的snd_pcm_dev_register函数,该回调函数建立了和用户空间应用程序(alsa-lib)通信所用的设备文件节点:/dev/snd/pcmCxxDxxp和/dev/snd/pcmCxxDxxc

4. 设备文件节点的建立(dev/snd/pcmCxxDxxp、pcmCxxDxxc)

4.1 struct snd_minor

每个snd_minor结构体保存了声卡下某个逻辑设备的上下文信息,他在逻辑设备建立阶段被填充,在逻辑设备被使用时就可以从该结构体中得到相应的信息。pcm设备也不例外,也需要使用该结构体。该结构体在include/sound/core.h中定义。

[c-sharp] view plain copystruct snd_minor {

int type; /* SNDRV_DEVICE_TYPE_XXX */

int card; /* card number */

int device; /* device number */

const struct file_operations *f_ops; /* file operations */

void *private_data; /* private data for f_ops->open */

struct device *dev; /* device for sysfs */

};

在sound/sound.c中定义了一个snd_minor指针的全局数组:

[c-sharp] view plain copystatic struct snd_minor *snd_minors[256];

前面说过,在声卡的注册阶段(snd_card_register),会调用pcm的回调函数snd_pcm_dev_register(),这个函数里会调用函数snd_register_device_for_dev():

[c-sharp] view plain copystatic int snd_pcm_dev_register(struct snd_device *device)

{

......

/* register pcm */

err = snd_register_device_for_dev(devtype, pcm->card,

pcm->device,

&snd_pcm_f_ops[cidx],

pcm, str, dev);

......

}

我们再进入snd_register_device_for_dev():

[c-sharp] view plain copyint snd_register_device_for_dev(int type, struct snd_card *card, int dev,

const struct file_operations *f_ops,

void *private_data,

const char *name, struct device *device)

{

int minor;

struct snd_minor *preg;

if (snd_BUG_ON(!name))

return -EINVAL;

preg = kmalloc(sizeof *preg, GFP_KERNEL);

if (preg == NULL)

return -ENOMEM;

preg->type = type;

preg->card = card ? card->number : -1;

preg->device = dev;

preg->f_ops = f_ops;

preg->private_data = private_data;

mutex_lock(&sound_mutex);

#ifdef CONFIG_SND_DYNAMIC_MINORS

minor = snd_find_free_minor();

#else

minor = snd_kernel_minor(type, card, dev);

if (minor >= 0 && snd_minors[minor])

minor = -EBUSY;

#endif

if (minor < 0) {

mutex_unlock(&sound_mutex);

kfree(preg);

return minor;

}

snd_minors[minor] = preg;

preg->dev = device_create(sound_class, device, MKDEV(major, minor),

private_data, "%s", name);

if (IS_ERR(preg->dev)) {

snd_minors[minor] = NULL;

mutex_unlock(&sound_mutex);

minor = PTR_ERR(preg->dev);

kfree(preg);

return minor;

}

mutex_unlock(&sound_mutex);

return 0;

}

首先,分配并初始化一个snd_minor结构中的各字段

type:SNDRV_DEVICE_TYPE_PCM_PLAYBACK/SNDRV_DEVICE_TYPE_PCM_CAPTURE

card: card的编号

device:pcm实例的编号,大多数情况为0

f_ops:snd_pcm_f_ops

private_data:指向该pcm的实例

根据type,card和pcm的编号,确定数组的索引值minor,minor也作为pcm设备的此设备号

把该snd_mi

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top