Android/Linux音频架构开发ALSA-篇6

上一张我们讲到pcm的创建,用户空间可以通过pcm设备节点进行放音和录音操作,但是这只能控制音频流的输入输出,如果我想要控制codec的增益(gain)或者说mixer方式怎么办?那我们就要用到另一个逻辑设备control。

还记的我们创建声卡的代码么,里面有这么一个函数,snd_ctl_create创建control设备节点

1、snd_ctl_create

与pcm设备一样,一开始先定义了一个ops,里面包含了三个函数指针。

static struct snd_device_ops ops = {
    .dev_free = snd_ctl_dev_free,
    .dev_register =  snd_ctl_dev_register,
    .dev_disconnect = snd_ctl_dev_disconnect,
};

初始化声卡的控制设备,然后给他命名controlC%d,再我们的/dev/snd目录下可以看到的controlC0就是这个节点,0就是声卡的number。


snd_device_initialize(&card->ctl_dev, card);
dev_set_name(&card->ctl_dev, "controlC%d", card->number);

最终也调用了snd_device_new将ops与声卡设备进行绑定,在创建声卡的时候回循环调用每个设备的dev_register。


err = snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops);
if (err < 0)
  put_device(&card->ctl_dev);

2、snd_ctl_dev_register

获取snd_card,然后调用snd_register_device。可以看到这里也传入了snd_ctl_f_ops。

struct snd_card *card = device->device_data;
return snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,
           &snd_ctl_f_ops, card, &card->ctl_dev);

snd_register_device我们上一篇介绍过了主要讲设备结构依据次设备号存入了snd_minors全局数组中。

3、snd_ctl_f_ops

依据我们上一篇的介绍来看,f_ops会被替换,用户层操作controlC0节点,最终就会调用到这些函数之中当中来。


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,
};

4、snd_ctl_open

我们先来看下snd_ctl_open这个函数,首先就是通过此设备号获取到了snd_card,snd_lookup_minor_data内部也就是通过次设备号从snd_minors全局数组中获取。


struct snd_card *card;
card = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_CONTROL);

将file添加到card->files_list链表中。

err = snd_card_file_add(card, file);

创建了snd_ctl_file并分配内存,然后将这个结构体内的card与card关联。最后将ctl保存为file的私有数据。


struct snd_ctl_f

你可能感兴趣的:(audio-alsa系列详解,音视频,android,linux)