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

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

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

nor结构的地址放入全局数组snd_minors[minor]中

最后,调用device_create创建设备节点

4.2 设备文件的建立

在4.1节的最后,设备文件已经建立,不过4.1节的重点在于snd_minors数组的赋值过程,在本节中,我们把重点放在设备文件中。

回到pcm的回调函数snd_pcm_dev_register()中:

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

{

int cidx, err;

char str[16];

struct snd_pcm *pcm;

struct device *dev;

pcm = device->device_data;

......

for (cidx = 0; cidx < 2; cidx++) {

......

switch (cidx) {

case SNDRV_PCM_STREAM_PLAYBACK:

sprintf(str, "pcmC%iD%ip", pcm->card->number, pcm->device);

devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK;

break;

case SNDRV_PCM_STREAM_CAPTURE:

sprintf(str, "pcmC%iD%ic", pcm->card->number, pcm->device);

devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE;

break;

}

/* device pointer to use, pcm->dev takes precedence if

* it is assigned, otherwise fall back to card's device

* if possible */

dev = pcm->dev;

if (!dev)

dev = snd_card_get_device_link(pcm->card);

/* register pcm */

err = snd_register_device_for_dev(devtype, pcm->card,

pcm->device,

&snd_pcm_f_ops[cidx],

pcm, str, dev);

......

}

......

}

以上代码我们可以看出,对于一个pcm设备,可以生成两个设备文件,一个用于playback,一个用于capture,代码中也确定了他们的命名规则:

playback -- pcmCxDxp,通常系统中只有一各声卡和一个pcm,它就是pcmC0D0p

capture -- pcmCxDxc,通常系统中只有一各声卡和一个pcm,它就是pcmC0D0c

snd_pcm_f_ops

snd_pcm_f_ops是一个标准的文件系统file_operations结构数组,它的定义在sound/core/pcm_native.c中:

[c-sharp] view plain copyconst struct file_operations snd_pcm_f_ops[2] = {

{

.owner = THIS_MODULE,

.write = snd_pcm_write,

.aio_write = snd_pcm_aio_write,

.open = snd_pcm_playback_open,

.release = snd_pcm_release,

.llseek = no_llseek,

.poll = snd_pcm_playback_poll,

.unlocked_ioctl = snd_pcm_playback_ioctl,

.compat_ioctl = snd_pcm_ioctl_compat,

.mmap = snd_pcm_mmap,

.fasync = snd_pcm_fasync,

.get_unmapped_area = snd_pcm_get_unmapped_area,

},

{

.owner = THIS_MODULE,

.read = snd_pcm_read,

.aio_read = snd_pcm_aio_read,

.open = snd_pcm_capture_open,

.release = snd_pcm_release,

.llseek = no_llseek,

.poll = snd_pcm_capture_poll,

.unlocked_ioctl = snd_pcm_capture_ioctl,

.compat_ioctl = snd_pcm_ioctl_compat,

.mmap = snd_pcm_mmap,

.fasync = snd_pcm_fasync,

.get_unmapped_area = snd_pcm_get_unmapped_area,

}

};

snd_pcm_f_ops作为snd_register_device_for_dev的参数被传入,并被记录在snd_minors[minor]中的字段f_ops中。最后,在snd_register_device_for_dev中创建设备节点:

[c-sharp] view plain copysnd_minors[minor] = preg;

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

private_data, "%s", name);

4.3 层层深入,从应用程序到驱动层pcm

4.3.1 字符设备注册

在sound/core/sound.c中有alsa_sound_init()函数,定义如下:

[c-sharp] view plain copystatic int __init alsa_sound_init(void)

{

snd_major = major;

snd_ecards_limit = car

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

网站地图

Top