再论声卡之control
来源:互联网 发布:常见的几个默认端口号 编辑:程序博客网 时间:2024/05/23 21:41
control是提供给用户使用。内核实现一个file_operations结构体,供给用户调用。
问题1、既然是file_operations,那么所有control
会当成字符设备注册,那么内核是如何做的?
答:首先是通过snd_soc_new_pcms函数里:
snd_soc_new_pcms
ret = snd_card_create(idx, xid, codec->owner, 0, &codec->card);
err = snd_ctl_create(card);
snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops); //ops就是
snd_ctl_create的ops
list_add(&dev->list, &card->devices);
这里是吧一个类型为SNDRV_DEV_CONTROL的设备放到card->devices连表里。
那么接下来就有个地方要做的事情就是从连表里取出来,然后注册(
并且我们就可以猜到会调用snd_ctl_create的ops的注册函数snd_ctl_dev_register)。
那个地方就在:
soc_probe(struct platform_device *pdev)
snd_soc_register_card(card);
snd_soc_instantiate_cards();
snd_soc_instantiate_card(struct snd_soc_card *card)
ret = snd_card_register(codec->card);
err = snd_device_register_all(card)
snd_device_register_all函数顾名思义就知道在这个函数里会注册card->
devicessnd_devices的所有设备,具体如下:
snd_device_register_all(struct snd_card *card)
list_for_each_entry(dev, &card->devices, list) {
if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) {
if ((err = dev->ops->dev_register(dev)) < 0)
...........
调用card->devices每一个dev->ops->dev_register(dev)来注册该设备。
所以对于上面的类型为SNDRV_DEV_CONTROL的设备就是调用注册函数
snd_ctl_dev_register来实现的。如下:
snd_ctl_dev_register(struct snd_device *device)
sprintf(name, "controlC%i", cardnum); //从这个名字就可以知道/dev下的
controlC0i设备节点就是对应这个设备了。
snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1, &snd_ctl_f_ops
, card, name); //controlC0i设备操作函数snd_ctl_f_ops。
好了到这里就把类型SNDRV_DEV_CONTROL的设备注册入内核了,并且提供了操作函数
snd_ctl_f_ops供用户系统调用。这个就是上片文件说道的“从用户空间调用角度谈
control”。
现在就看看如何通过操作函数来操作声卡的control了。
static const struct file_operations snd_ctl_f_ops =
{
.owner = THIS_MODULE,
.read = snd_ctl_read,
.open = snd_ctl_open,
.release = snd_ctl_release,
.llseek = no_llseek,
.poll = snd_ctl_poll,
.unlocked_ioctl = snd_ctl_ioctl,
.compat_ioctl = snd_ctl_ioctl_compat,
.fasync = snd_ctl_fasync,
};
在讲解用户操作control之前,得看看control的原型是怎么样的,以音量control为例子:
SOC_DOUBLE_TLV("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1,
out_tlv),
一看就是宏定义,我们展开得到如下东西:
{.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = (("Headphone Playback Volume"),
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |SNDRV_CTL_ELEM_ACCESS_READWRITE,
.tlv.p = (out_tlv),
.info = snd_soc_info_volsw,
.get = snd_soc_get_volsw,
.put = snd_soc_put_volsw,
.private_value = (unsigned long)&(struct soc_mixer_control){.reg =
AC97_HEADPHONE, .shift = 8, .rshift =0,\
.max = 31, .platform_max = 31, .invert = 1} }
现在先解释一下一些成员:
其中put设置该control;
get得到该control信息;
reg 是寄存器,该寄存器设置的对象包括左右设置(如音量有左右),shift
确定左设置在该寄存器的开始位数,rshift是右设置在该寄存器的开始位数。
max , invert是产生掩码位。
接下来就是用户如何使用control了。
- 再论声卡之control
- 再论声卡之control
- Linux ALSA声卡驱动之四:Control设备的创建
- Linux ALSA声卡驱动之四:Control设备的创建
- Linux ALSA声卡驱动之四:Control设备的创建
- Linux ALSA声卡驱动之四:Control设备的创建
- Linux ALSA声卡驱动之四:Control设备的创建
- Linux ALSA声卡驱动之四:Control设备的创建
- Linux ALSA声卡驱动之四:Control设备的创建
- Linux ALSA声卡驱动之四:Control设备的创建
- Linux ALSA声卡驱动之四:Control设备的创建
- Linux ALSA声卡驱动之四:Control设备的创建
- Linux ALSA声卡驱动之四:Control设备的创建
- Linux ALSA声卡驱动之四:Control设备的创建
- Linux ALSA声卡驱动之四:Control设备的创建
- Linux ALSA声卡驱动之四:Control设备的创建
- Linux ALSA声卡驱动之四:Control设备的创建
- Linux ALSA声卡驱动之四:Control设备的创建
- 黑马程序员_JQuery的ready函数与JS的onload的区别:
- 内存泄露检查
- vim 替换
- opatch apply 报错 OPatch failed with error code 73
- 树(一)二叉树
- 再论声卡之control
- 《深入解析Android:Telephony原理剖析及最佳实践》一书即将发行,欢迎各位Android开发、爱好者订阅
- Java之对象串行化
- 设计模式之工厂方法(factory method)
- linux内核编译过程的最终总结版
- ProGuard -- java代码进行混淆
- 移动互联网产业细分明显:儿童应用呈爆发趋势
- 程序员面试100题之34找出数组中两个只出现一次的数字
- 《Head First设计模式》读书笔记之装饰模式