Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15358619
  • 博文数量: 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-19 14:12:40

static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const char __user *buf, size_t bytes)
{
    size_t xfer = 0;
    ssize_t tmp;
    struct snd_pcm_runtime *runtime = substream->runtime;

    if (atomic_read(&substream->mmap_count))
        return -ENXIO;

    if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
        return tmp;
    mutex_lock(&runtime->oss.params_lock);
    while (bytes > 0) {
/*
函数snd_pcm_oss_period_size最终将建立如下一个视图:[luther.gliethttp]
struct a { char one_period[runtime->oss.period_bytes] };
struct a periods_array[runtime->oss.periods] 《浅析alsa声卡驱动snd_pcm_oss_period_size函数》
runtime->oss.period_frames为当前可用a[]数组索引号+1,
语言描述的话,一共有periods个重复物理地址上连续的存储空间,每个存储空间的大小为period_bytes
*/
        if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
            tmp = bytes;
        // 如果该period_bytes存储空间不能容纳下tmp个字节数据了,那么
        // tmp等于period_bytes存储空间还能够容纳的字节数, 否则tmp等于bytes,能够全部容纳
            if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes)
                tmp = runtime->oss.period_bytes - runtime->oss.buffer_used;
            if (tmp > 0) {
        // 将用户空间的数据buf,拷贝到runtime->oss.buffer + runtime->oss.buffer_used开始处
                if (copy_from_user(runtime->oss.buffer + runtime->oss.buffer_used, buf, tmp)) {
                    tmp = -EFAULT;
                    goto err;
                }
            }
            runtime->oss.buffer_used += tmp; // 移动可用空间起始指针
            buf += tmp;
            bytes -= tmp;
            xfer += tmp;
            if (substream->oss.setup.partialfrag ||
                runtime->oss.buffer_used == runtime->oss.period_bytes) {
            // 如果runtime->oss.buffer_used == runtime->oss.period_bytes成立,表示
            // 本period缓冲区已经全部装满,那么下发该缓冲区中period_bytes字节音频数据
                tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr,
                             runtime->oss.buffer_used - runtime->oss.period_ptr, 1); // 1表示buf来自内核空间 《浅析alsa声卡驱动snd_pcm_oss_write2函数》
                if (tmp <= 0)
                    goto err;
            // 调整指针和数据大小
                runtime->oss.bytes += tmp;
                runtime->oss.period_ptr += tmp;
                runtime->oss.period_ptr %= runtime->oss.period_bytes;
                if (runtime->oss.period_ptr == 0 ||
                    runtime->oss.period_ptr == runtime->oss.buffer_used)
                    runtime->oss.buffer_used = 0;
                else if ((substream->f_flags & O_NONBLOCK) != 0) {
                    tmp = -EAGAIN;
                    goto err;
                }
            }
        } else {
            // 因为runtime->oss.buffer_used等于0,所以表示runtime->oss.buffer缓冲区中现在一个音频
            // 数据都没有,同样bytes一定大于runtime->oss.period_bytes
            // 所以不需要做上面的拼接操作,直接调用snd_pcm_oss_write2下发一整个period满数据大小的音频数据[luther.gliethttp]
            tmp = snd_pcm_oss_write2(substream, 《浅析alsa声卡驱动snd_pcm_oss_write2函数》
                         (const char __force *)buf,
                         runtime->oss.period_bytes, 0); // 0表示buf来自用户空间
            if (tmp <= 0)
                goto err;
            runtime->oss.bytes += tmp;
            buf += tmp;
            bytes -= tmp;
            xfer += tmp;
            if ((substream->f_flags & O_NONBLOCK) != 0 &&
                tmp != runtime->oss.period_bytes)
                break;
        }
    }
    mutex_unlock(&runtime->oss.params_lock);
    return xfer;

 err:
    mutex_unlock(&runtime->oss.params_lock);
    return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
}
阅读(1635) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~