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