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

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

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

ds_limit;

if (register_chrdev(major, "alsa", &snd_fops)) {

snd_printk(KERN_ERR "unable to register native major device number %d/n", major);

return -EIO;

}

if (snd_info_init() < 0) {

unregister_chrdev(major, "alsa");

return -ENOMEM;

}

snd_info_minor_register();

return 0;

}

register_chrdev中的参数major与之前创建pcm设备是device_create时的major是同一个,这样的结果是,当应用程序open设备文件/dev/snd/pcmCxDxp时,会进入snd_fops的open回调函数,我们将在下一节中讲述open的过程。

4.3.2 打开pcm设备

从上一节中我们得知,open一个pcm设备时,将会调用snd_fops的open回调函数,我们先看看snd_fops的定义:

[c-sharp] view plain copystatic const struct file_operations snd_fops =

{

.owner = THIS_MODULE,

.open = snd_open

};

跟入snd_open函数,它首先从inode中取出此设备号,然后以次设备号为索引,从snd_minors全局数组中取出当初注册pcm设备时填充的snd_minor结构(参看4.1节的内容),然后从snd_minor结构中取出pcm设备的f_ops,并且把file->f_op替换为pcm设备的f_ops,紧接着直接调用pcm设备的f_ops->open(),然后返回。因为file->f_op已经被替换,以后,应用程序的所有read/write/ioctl调用都会进入pcm设备自己的回调函数中,也就是4.2节中提到的snd_pcm_f_ops结构中定义的回调。

[c-sharp] view plain copystatic int snd_open(struct inode *inode, struct file *file)

{

unsigned int minor = iminor(inode);

struct snd_minor *mptr = NULL;

const struct file_operations *old_fops;

int err = 0;

if (minor >= ARRAY_SIZE(snd_minors))

return -ENODEV;

mutex_lock(&sound_mutex);

mptr = snd_minors[minor];

if (mptr == NULL) {

mptr = autoload_device(minor);

if (!mptr) {

mutex_unlock(&sound_mutex);

return -ENODEV;

}

}

old_fops = file->f_op;

file->f_op = fops_get(mptr->f_ops);

if (file->f_op == NULL) {

file->f_op = old_fops;

err = -ENODEV;

}

mutex_unlock(&sound_mutex);

if (err < 0)

return err;

if (file->f_op->open) {

err = file->f_op->open(inode, file);

if (err) {

fops_put(file->f_op);

file->f_op = fops_get(old_fops);

}

}

fops_put(old_fops);

return err;

}

下面的序列图展示了应用程序如何最终调用到snd_pcm_f_ops结构中的回调函数:

  图4.3.2.1 应用程序操作pcm设备

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

网站地图

Top