alsa声卡分析alsa-utils调用过程(二)-tinymixer
时间:2022-05-06
本文章向大家介绍alsa声卡分析alsa-utils调用过程(二)-tinymixer,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
继上一篇文章:http://www.cnblogs.com/linhaostudy/p/8515277.html
三、tinymixer调用分析:(tinymixer.log搜索节点:/dev/snd/controlCx)
还是一样,系统调用从应用层到kernel层,都要通过VFS来到file_operations;
我们使用tinymixer "SEC_MI2S_RX Audio Mixer MultiMedia1" 1打开通道看一下相应的流程;
log中的open("/dev/snd_controlCx")中对应的file_operations中:
1 /*
2 * INIT PART
3 */
4
5 static const struct file_operations snd_ctl_f_ops =
6 {
7 .owner = THIS_MODULE,
8 .read = snd_ctl_read,
9 .open = snd_ctl_open,
10 .release = snd_ctl_release,
11 .llseek = no_llseek,
12 .poll = snd_ctl_poll,
13 .unlocked_ioctl = snd_ctl_ioctl,
14 .compat_ioctl = snd_ctl_ioctl_compat,
15 .fasync = snd_ctl_fasync,
16 };
tinymixer首先先调用open操作函数集;也就是snd_ctl_open打开control逻辑设备;
我们主要分析ioctl函数,由file_operations来到snd_ctl_ioctl函数中来:
1 static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2 {
3 struct snd_ctl_file *ctl;
4 struct snd_card *card;
5 struct snd_kctl_ioctl *p;
6 void __user *argp = (void __user *)arg;
7 int __user *ip = argp;
8 int err;
9
10 ctl = file->private_data;
11 card = ctl->card;
12 if (snd_BUG_ON(!card))
13 return -ENXIO;
14 switch (cmd) {
15 case SNDRV_CTL_IOCTL_PVERSION:
16 return put_user(SNDRV_CTL_VERSION, ip) ? -EFAULT : 0;
17 case SNDRV_CTL_IOCTL_CARD_INFO:
18 return snd_ctl_card_info(card, ctl, cmd, argp);
19 case SNDRV_CTL_IOCTL_ELEM_LIST:
20 return snd_ctl_elem_list(card, argp);
21 case SNDRV_CTL_IOCTL_ELEM_INFO:
22 return snd_ctl_elem_info_user(ctl, argp);
23 case SNDRV_CTL_IOCTL_ELEM_READ:
24 return snd_ctl_elem_read_user(card, argp);
25 case SNDRV_CTL_IOCTL_ELEM_WRITE:
26 return snd_ctl_elem_write_user(ctl, argp);
27 case SNDRV_CTL_IOCTL_ELEM_LOCK:
28 return snd_ctl_elem_lock(ctl, argp);
29 case SNDRV_CTL_IOCTL_ELEM_UNLOCK:
30 return snd_ctl_elem_unlock(ctl, argp);
31 case SNDRV_CTL_IOCTL_ELEM_ADD:
32 return snd_ctl_elem_add_user(ctl, argp, 0);
33 case SNDRV_CTL_IOCTL_ELEM_REPLACE:
34 return snd_ctl_elem_add_user(ctl, argp, 1);
35 case SNDRV_CTL_IOCTL_ELEM_REMOVE:
36 return snd_ctl_elem_remove(ctl, argp);
37 case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
38 return snd_ctl_subscribe_events(ctl, ip);
39 case SNDRV_CTL_IOCTL_TLV_READ:
40 return snd_ctl_tlv_ioctl(ctl, argp, 0);
41 case SNDRV_CTL_IOCTL_TLV_WRITE:
42 return snd_ctl_tlv_ioctl(ctl, argp, 1);
43 case SNDRV_CTL_IOCTL_TLV_COMMAND:
44 return snd_ctl_tlv_ioctl(ctl, argp, -1);
45 case SNDRV_CTL_IOCTL_POWER:
46 return -ENOPROTOOPT;
47 case SNDRV_CTL_IOCTL_POWER_STATE:
48 #ifdef CONFIG_PM
49 return put_user(card->power_state, ip) ? -EFAULT : 0;
50 #else
51 return put_user(SNDRV_CTL_POWER_D0, ip) ? -EFAULT : 0;
52 #endif
53 }
54 down_read(&snd_ioctl_rwsem);
55 list_for_each_entry(p, &snd_control_ioctls, list) {
56 err = p->fioctl(card, ctl, cmd, arg);
57 if (err != -ENOIOCTLCMD) {
58 up_read(&snd_ioctl_rwsem);
59 return err;
60 }
61 }
62 up_read(&snd_ioctl_rwsem);
63 snd_printdd("unknown ioctl = 0x%xn", cmd);
64 return -ENOTTY;
65 }
通过tinymixer.log搜索ioctl可以看到,进入:
1 case SNDRV_CTL_IOCTL_ELEM_WRITE:
2 return snd_ctl_elem_write_user(ctl, argp);
相应流程如下:
|->snd_ctl_ioctl
|->snd_ctl_elem_write_user
|->snd_ctl_elem_wirte
|->kctl->put
|=snd_soc_dapm_put_volsw
|->snd_soc_dapm_mixer_update_power//找到使用这个kcontrol的path,根据该kcontrol的值来更新path的connect状态
//更新path->connect状态
kcontrol、dapm widget、route/path创建与注册和它们之间的关系可以见:
- 【Spark研究】用Apache Spark进行大数据处理第一部分:入门介绍
- “一切都是消息”--MSF(消息服务框架)入门简介
- 【Spark研究】用Apache Spark进行大数据处理第二部分:Spark SQL
- Android基础总结(2)——活动Activity
- Java实现的IP处理工具类——可用于项目
- 使用SQLServer同义词和SQL邮件,解决发布订阅中订阅库丢失数据的问题
- 一次误报引发的DNS检测方案的思考:DNS隧道检测平民解决方案
- Andriod基础——Adapter类
- ORM查询语言(OQL)简介--高级篇:脱胎换骨
- 用Java实现处理日期的工具类——常用日期处理方法
- ORM查询语言(OQL)简介--实例篇
- 漏洞预警 | 海洋CMS(SEACMS)0day漏洞预警
- 【机器学习】分类算法评价
- Java中图片处理工具类——能满足各种需求
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- MySQL8.0.18 试用Hash Join
- InnoDB:表空间管理
- MyBatis 增删改查
- python分析wav文件
- CICD实战——服务自动构建与部署
- python+opencv实时视频目标检测
- python数据化运营分析实例---销售预测
- Leetcode 1444. 切披萨的方案数(DP,类似石材切割,二维前缀和)
- Python生成内涵图片
- Linux 下makefile实战 ——编写真实的C项目
- MySQL8功能详解——Common table expression (CTE)
- 游戏数据分析
- MySQL8功能详解——隐藏索引
- python 操作excel(附案例)
- 如何在 Spring Boot 中 读写数据