Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15489949
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: LINUX

2009-11-17 12:05:49

static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm,
                 struct snd_pcm_hw_params *params,
                 snd_pcm_hw_param_t var, unsigned int best,
                 int *dir)
{
    struct snd_pcm_hw_params *save = NULL;
    int v;
    unsigned int saved_min;
    int last = 0;
    int min, max;
    int mindir, maxdir;
    int valdir = dir ? *dir : 0;
    // 调用函数为:choose_rate,所以dir=NULL,所以valdir将等于0
    // 下面以var等于SNDRV_PCM_HW_PARAM_RATE
    // best等于8000为例
    /* FIXME */
    if (best > INT_MAX)
        best = INT_MAX;
    min = max = best;
    mindir = maxdir = valdir; // 将等于0,所以查找的是值为best的integer整型值[luther.gliethttp]
    if (maxdir > 0)
        maxdir = 0;
    else if (maxdir == 0)
        maxdir = -1;
    else {
        maxdir = 1;
        max--;
    }
    save = kmalloc(sizeof(*save), GFP_KERNEL);
    if (save == NULL)
        return -ENOMEM;
    *save = *params;        // 和choose_rate中一样,预存*params到save,如果下面对params设置失败,那么
    saved_min = min;        // 将save中的数据回滚到params,以恢复params[luther.gliethttp].
    // 尝试将params中var量的最小值i->min设置为min, 如果想设置成功,就必须保证i->min小于min,
    // 这样才能有进一步缩小i->min数值的硬性条件,该操作没有与i->max进行任何关联,所以
    // min大于i->min的情况下,甚至可以大于i->max[luther.gliethttp]
    min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir);
    if (min >= 0) {
        struct snd_pcm_hw_params *params1;
        if (max < 0)
            goto _end;
        if ((unsigned int)min == saved_min && mindir == valdir)
            goto _end;  // 如果成功设置了i->min为saved_min,那么太好了[luther.gliethttp]
        params1 = kmalloc(sizeof(*params1), GFP_KERNEL);
        if (params1 == NULL) {
            kfree(save);
            return -ENOMEM;
        }
        *params1 = *save; // 这里将save内存拷贝一份到params1,对params1进行参数修改,如果成功,那么
        // *params = *params1;对params彻底赋值,一切顺利[luther.gliethttp]
        // 和上面的i->min进一步缩小一样,
        // i->max必须max才能设置成功,这样才能进一步缩小i->max的数值到max[luther.gliethttp]
        max = snd_pcm_hw_param_max(pcm, params1, var, max, &maxdir);
        if (max < 0) {
            kfree(params1);
            goto _end;
        }
        // 好,执行到这里说明i->max也进一步缩小成功
        // boundary_nearer Return 1 if min is nearer to best than max
        // 函数用来计算究竟best - min小还是max - best小,
        // 即:best这个数值更靠近min端还是max端
        // 返回1表示best更靠近min端[luther.gliethttp]
        if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) {
            *params = *params1;
            last = 1;
        }
        kfree(params1);
    } else {
        // 执行到这里说明i->min大于min
        // 和上面的i->min进一步缩小一样,
        // i->max必须max才能设置成功,这样才能进一步缩小i->max的数值到max[luther.gliethttp]
        *params = *save;
        max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir);
        if (max < 0)
            return max;
        // 好了最能匹配上的数值位于i->max那端[luther.gliethttp]
        last = 1;
    }
 _end:
     kfree(save);
    // 调用snd_pcm_hw_refine执行一次配置更新 《浅析alsa声卡驱动snd_pcm_hw_refine函数》
    if (last) // snd_pcm_hw_param_last - refine config space and return maximum value
        v = snd_pcm_hw_param_last(pcm, params, var, dir); // last等于1表示更靠近max,所以返回max
    else      // snd_pcm_hw_param_first - refine config space and return minimum value
        v = snd_pcm_hw_param_first(pcm, params, var, dir);
    snd_BUG_ON(v < 0);
    return v;
}
阅读(3387) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~