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创建与注册和它们之间的关系可以见:
- 一些极度危险的linux命令(r2笔记49天)
- 挑战数据结构与算法面试题——80题全解析(一)
- 关于操作失误的数据修复(r2笔记48天)
- 挑战数据结构与算法面试题——80题全解析(三)
- 巧用rowid简化sql查询(r2笔记47天)
- 算法类面试题解析——美团2016校招:棋子翻转
- 算法类面试题解析——美团2016校招:最大差值
- 用Python进行机器学习小案例
- 启用ODM极速调优IO (r2笔记66天)
- 通过addm分析io问题(r2笔记64天)
- python爬虫+R数据可视化 实例
- 梯度下降优化算法综述
- 关于oracle后台启用的schedule job(r2笔记65天)
- 数据结构和算法——二叉树
- 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 数组属性和方法
- C#中Lambda表达式总结
- [打造自己的监控系统]使用Django批量监控Oracle长会话
- C# ref实例讲解
- [Oracle 故障处理]记一次undo表空间使用率99%的问题
- C# 队列(Queue)
- 记住没:永远不要在 MySQL 中使用 UTF-8!
- C#多线程委托ParameterizedThreadStart应用
- [Python爬虫]使用Selenium操作浏览器订购火车票
- IDEA多线程调试
- 为什么wait和notify方法要在同步块中调用?
- 一文说清楚Mysql Innodb的B+树索引原理及其推理过程
- [Oracle数据泵全解析]expdp交互式命令行模式命令
- SpringBoot Feign文件上传
- Docker_000
- 如何应对面试官的JVM调优问题