继上一篇文章: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中:
代码语言:javascript复制 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函数中来:
代码语言:javascript复制 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可以看到,进入:
代码语言:javascript复制1 case SNDRV_CTL_IOCTL_ELEM_WRITE:
2 return snd_ctl_elem_write_user(ctl, argp);
相应流程如下:
代码语言:javascript复制|->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创建与注册和它们之间的关系可以见: