Android音频驱动-ASOC之Control Open

本文探讨了Android音频驱动中的ASOC Control Open过程,涉及获取kcontrol列表、控制信息、打开通路及回调函数。讲解了nd_ctl_elem_info结构体,控件类型与元素数量,以及tinyalsa接口的使用。着重解释了kcontrol如何表示多个物理控件,以及snd_ctl_ioctl在kernel中的作用。此外,提到了中断服务程序中更新control值的方法和snd_kcontrol的注册过程。
摘要由CSDN通过智能技术生成
struct mixer *mixer_open(unsigned int card)
{
    struct snd_ctl_elem_list elist;
    struct snd_ctl_elem_info tmp;
    struct snd_ctl_elem_id *eid = NULL;
    struct mixer *mixer = NULL;
    unsigned int n, m;
    int fd;
    char fn[256];
    /* 获取对应操作的文件句柄名称 */  
    snprintf(fn, sizeof(fn), "/dev/snd/controlC%u", card);
    fd = open(fn, O_RDWR);//打开control设备
    memset(&elist, 0, sizeof(elist));
    /* 第一遍调用SNDRV_CTL_IOCTL_ELEM_LIST,获取snd_kcontrol的个数 */  
    if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0)
        goto fail;

    mixer = calloc(1, sizeof(*mixer));/* 获取个数后,对应分配空间 */ 
    mixer->ctl = calloc(elist.count, sizeof(struct mixer_ctl));
    mixer->elem_info = calloc(elist.count, sizeof(struct snd_ctl_elem_info));

    if (ioctl(fd, SNDRV_CTL_IOCTL_CARD_INFO, &mixer->card_info) < 0)//获取card信息
        goto fail;

    eid = calloc(elist.count, sizeof(struct snd_ctl_elem_id));
    mixer->count = elist.count;
    mixer->fd = fd;
    elist.space = mixer->count;//space大于0,第二次调用SNDRV_CTL_IOCTL_ELEM_LIST获取更多信息
    elist.pids = eid;//传入kernel获得实际值,包含了所有kctl的id对象
    /* 第二遍调用,获取对应的snd_ctl_elem_id数组,且numid从1开始,0表示无效 */  
    if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0)
        goto fail;

    for (n = 0; n < mixer->count; n++) {
        struct snd_ctl_elem_info *ei = mixer->elem_info + n;
        ei->id.numid = eid[n].numid;//从kernel获得了实际的numid值
        /*根据获取的snd_kcontrol对应的numid,调用获取对应的snd_ctl_elem_info, 
        内核的具体步骤是,根据numid,获取对应的snd_kcontrol,之后调用其info操
        作接口,填充用户传入snd_ctl_elem_info缓冲。*/
        if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, ei) < 0)//第一次获取指定控件信息,例如enumerated.items
            goto fail;
        mixer->ctl[n].info = ei;
        mixer->ctl[n].mixer = mixer;
        /* 如果为枚举量,还需要进一步获取每个枚举量对应的字符串描述 */
        if (ei->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
            char **enames = calloc(ei->value.enumerated.items, sizeof(char*));//根据字符串的个数来申请,如on、off
            mixer->ctl[n].ename = enames;
            for (m = 0; m < ei->value.enumerated.items; m++) {
                memset(&tmp, 0, sizeof(tmp));
                tmp.id.numid = ei->id.numid;
                tmp.value.enumerated.item = m;//字符串下标
                if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, &tmp) < 0)//第二次
                    goto fail;
                enames[m] = strdup(tmp.value.enumerated.name);//将字符串On、Off保存在mixer->ctl[n].ename中
            }
        }
    }
    return mixer;
}
static int snd_open(struct inode *inode, struct file *file)
{
    unsigned int minor = iminor(inode);
    struct snd_minor *mptr = NULL;
    const struct file_operations *new_fops;

    int err = 0;
    if (minor >= ARRAY_SIZE(snd_minors))
        return -ENODEV;
    mptr = snd_minors[minor];
    new_fops = fops_get(mptr->f_ops);
    replace_fops(file, new_fops);
    if (file->f_op->open)
        err = file->f_op->open(inode, file);
    return err;
}
/*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,
};*/
static int snd_ctl_open(struct inode *inode, struct file *file)
{
    unsigned long flags;
    struct snd_card *card;
    struct snd_ctl_file *ctl;
    int err;

    err = nonseekable_open(inode, file);
    card = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_CONTROL);
    err = snd_card_file_add(card, file);

    ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
    ctl->card = card;
    ctl->prefer_pcm_subdevice = -1;
    ctl->prefer_rawmidi_subdevice = -1;
    ctl->pid = get_pid(task_pid(current));
    file->private_data = ctl;//保存snd_ctl_file对象
    list_add_tail(&ctl->list, &card->ctl_files);
    return 0;
}

获取所有kcontrol的列表,包含了所有kcontrol对应的物理控件

static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    case SNDRV_CTL_IOCTL_ELEM_LIST:
        return snd_ctl_elem_list(card, argp);
}
static int snd_ctl_elem_list(struct snd_card *card,
                 struct snd_ctl_elem_list __user *_list)
{
    struct list_head *plist;
    struct snd_ctl_elem_list list;
    struct snd_kcontrol *kctl;
    struct snd_ctl_elem_id *dst, *id;
    unsigned int offset, space, jidx;

    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值