• ALSA声卡07_分析调用过程_学习笔记


    1、编译新的strace工具分析aplay和amixer应用程序对声卡的调用过程

    (1)因为旧的strace工具不能识别不能识别alsa声卡驱动程序里面的ioctrl.

    (2)编译过程参考http://blog.csdn.net/qingkongyeyue/article/details/52228729

    (3)出现错误


    需要建立相关的设备节点


    播放声音和调整音量


    (4)等待音频播放完,能得到一个完整的log,把log文件拷贝回windows下进行分析


    2、调用分析(aplay.log)(搜索设备节点“/dev/snd”)

    strace分析: aplay Windows.wav

    应用程序打开一个设备 节点的时候,肯定要找到他的file_operation结构体
    1. /dev/snd/controlC0(控制节点)对应的file_operations是snd_ctl_f_ops


    所以的ioctl都会进入到snd_ctl_ioctl,函数里面对控制链表snd_control_ioctls里面取出某个结构体p,调用它的ioctl函数


    open : snd_ctl_open
    SNDRV_CTL_IOCTL_PVERSION : snd_ctl_ioctl -> put_user(SNDRV_CTL_VERSION, ip) //把版本号返回给用户空间
    SNDRV_CTL_IOCTL_CARD_INFO : snd_ctl_ioctl -> snd_ctl_card_info(card, ctl, cmd, argp);//获取声卡信息返回给用户空间
                                                   copy_to_user
                                                   
    SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE : snd_ctl_ioctl -> snd_pcm_control_ioctl -> control->prefer_pcm_subdevice = val;//记录用户空间传进来的值(想使用的PCM的子设备),在嵌入式系统里面,子设备只有1个,值默认是0或1.
    close
    上述三个ioctl不涉及硬件操作(意味着以后写驱动程序的时候可能根本不需要管这个设备节点)


    2. /dev/snd/pcmC0D0p (播放节点)对应的file_operations是snd_pcm_f_ops[0]
    open :  snd_pcm_playback_open
               snd_pcm_open
                  snd_pcm_open_file
                  struct snd_pcm_substream *substream;//定义一个snd_pcm_substream 结构体
                  snd_pcm_open_substream//打开substream结构体
                  err = snd_pcm_hw_constraints_init(substream);//初始化substream结构体
                  snd_mask_any
                  snd_interval_any
                  ......
                  err = substream->ops->open(substream) // substream->ops : snd_pcm_ops结构体
                  soc_pcm_open
                  依次调用cpu_dai, dma, codec_dai, machine(三大模块)的open或startup函数
                  uda134x_startup 里:snd_pcm_hw_constraint_minmax(SNDRV_PCM_HW_PARAM_RATE),snd_pcm_hw_constraint_minmax(SNDRV_PCM_HW_PARAM_SAMPLE_BITS)
                  dma_open里: snd_pcm_hw_constraint_integer,snd_soc_set_runtime_hwparams
                             runtime->hw.info = hw->info; = SNDRV_PCM_INFO_INTERLEAVED |
       SNDRV_PCM_INFO_BLOCK_TRANSFER |
       SNDRV_PCM_INFO_MMAP |
       SNDRV_PCM_INFO_MMAP_VALID |
       SNDRV_PCM_INFO_PAUSE |   //得到PCM设备的一些信息
       SNDRV_PCM_INFO_RESUME,
                  snd_pcm_hw_constraints_complete
                  pcm_file->substream = substream;
                  file->private_data = pcm_file;


    注意:substream->ops =  soc_new_pcm函数里的soc_pcm_ops


    以下的ioctl入口都是:snd_pcm_playback_ioctl              
    SNDRV_PCM_IOCTL_INFO : snd_pcm_info_user(substream, arg);//得到ioctl的信息返回给用户空间
    substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_INFO, info);
     snd_pcm_lib_ioctl
     
    SNDRV_PCM_IOCTL_PVERSION : put_user(SNDRV_PCM_VERSION, (int __user *)arg)//lasa声卡驱动的版本号
    SNDRV_PCM_IOCTL_TTSTAMP  : snd_pcm_tstamp(substream, arg);
                                  
    SNDRV_PCM_IOCTL_SYNC_PTR : snd_pcm_sync_ptr(substream, arg); 先不管


    SNDRV_PCM_IOCTL_HW_REFINE .... : snd_pcm_hw_refine_user(substream, arg);//硬件参数重新规范
                                        memdup_user   //从用户空间传进来
                                        snd_pcm_hw_refine(substream, params); //修改
                                        copy_to_user //拷回给用户空间
    SNDRV_PCM_IOCTL_HW_PARAMS : snd_pcm_hw_params_user(substream, arg);//设置硬件参数
                                   snd_pcm_hw_params
                                      substream->ops->hw_params(substream, params);
                                         soc_pcm_hw_params
                                          依次调用machine,codec_dai,cpu_dai,platform(dma)的hw_params函数
    SNDRV_PCM_IOCTL_SYNC_PTR  //同步指针
    SNDRV_PCM_IOCTL_SW_PARAMS : snd_pcm_sw_params_user(substream, arg);//软件参数
                                   snd_pcm_sw_params 不涉及硬件操作
                                      
    SNDRV_PCM_IOCTL_SYNC_PTR//同步指针
    SNDRV_PCM_IOCTL_PREPARE  : snd_pcm_prepare(substream, file);//准备操作
                                   snd_power_wait // 电源管理相关,先不管
                                   .... 调用到platform里的prepare
                                      

    SNDRV_PCM_IOCTL_SYNC_PTR
    SNDRV_PCM_IOCTL_SW_PARAMS


    循环:
    SNDRV_PCM_IOCTL_WRITEI_FRAMES : copy_from_user  //从用户空间把音频数据拿过来,从wav文件中读出数据,写多帧数据
                                    snd_pcm_lib_write
                                    snd_pcm_lib_write1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_write_transfer)
                                    snd_pcm_lib_write_transfer
                                    copy_from_user
                                    snd_pcm_start(substream); // 启动传输
                                    
     
    SNDRV_PCM_IOCTL_SYNC_PTR//同步指针


    SNDRV_PCM_IOCTL_DRAIN
    SNDRV_PCM_IOCTL_DROP
    SNDRV_PCM_IOCTL_HW_FREE //硬件释放
    close



    3、file_operation结构体

    第0项对应的是播放,第1项对应的是录音,open对应的是and_pcm_playback_open




    4、调用分析

    strace分析: amixer cset numid=1 30 (设置音量)
    /dev/snd/controlC0
    open
    SNDRV_CTL_IOCTL_CARD_INFO
    SNDRV_CTL_IOCTL_PVERSION
    SNDRV_CTL_IOCTL_ELEM_INFO  //元素信息,这个元素可能指音量
    SNDRV_CTL_IOCTL_ELEM_READ  //读元素信息
    SNDRV_CTL_IOCTL_ELEM_WRITE : snd_ctl_elem_write_user  //写元素
    snd_ctl_elem_write
    // 找到一个snd_kcontrol
    kctl = snd_ctl_find_id(card, &control->id);
    // 调用它的put

  • 相关阅读:
    初步学习css 从css手册看起———text
    IE6双倍margin间距两大解决方案转载
    div+css的基本 常用到语法(一) 。
    初步学习css 从css手册看起———Font
    行内宽高设置无效的解决
    C++面对对象基础
    C++继承和派生
    基于MATLAB的FIR滤波器的设计
    C++多态
    C++中的静态成员和静态函数
  • 原文地址:https://www.cnblogs.com/alan666/p/8311869.html
Copyright © 2020-2023  润新知