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 了..
沒有留言:
張貼留言