2015/11/13

pcm_write

tinyalsa 的 pcm_write:
static int pcm_write_wrapper(struct pcm *pcm, const void * buffer, size_t bytes, int flags)
{
    int ret = 0;
    if(flags & PCM_MMAP)
         ret = pcm_mmap_write(pcm, (void *)buffer, bytes);
    else
         ret = pcm_write(pcm, (void *)buffer, bytes);
一般都沒有用 MMAP.
所以都是直接 call pcm_write( )

tinyalsa 實做的 pcm_write( ) 就是用for loop 把 buffer 一一寫入 ioctl:
    struct snd_xferi x;

    x.buf = (void*)data;
    x.frames = count / (pcm->config.channels *
                        pcm_format_to_bits(pcm->config.format) / 8);

    ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x))

這樣就進入 kernel 了..

kernel 的 snd_pcm_playback_ioctl1 呼叫 snd_pcm_lib_write 來做:
static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
                                      unsigned int hwoff,
                                      unsigned long data, unsigned int off,
                                      snd_pcm_uframes_t frames)
{
        struct snd_pcm_runtime *runtime = substream->runtime;
        int err;
        char __user *buf = (char __user *) data + frames_to_bytes(runtime, off);

        if (substream->ops->copy) {
                if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0)
                        return err;
        } else {
                char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff);
                if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, frames)))
                        return -EFAULT;
        }
        return 0;
}



錯了。結果是用 MMAP...
所以,trace 到最後,是 call kernel 的 snd_pcm_sync_ptr..

修改一下 hardware/imx/alsa/tinyalsa_hal.c, 拿掉 MMAP, 就會 call pcm_write(), 就可以換掉 pcm_write 了..

沒有留言:

張貼留言