Вот мои вопросы:
Код: Выделить всё
1.What functions are responsible for transferring PCM data from the hardware to DMA in ALSA?
2.Where should I intercept or modify the data in the ALSA driver to achieve this?
3.Are there any recommended functions or hooks within ALSA for modifying PCM data at the DMA level?
Сначала я попытался изменить функцию __snd_pcm_lib_xfer, но это не дало никакого эффекта. Затем я использовал трассировку-cmd для отслеживания вызовов функций ядра Linux и обнаружил, что функция snd_pcm_update_hw_ptr0 вызывается часто. Я исследовал, как работают old_hw_ptr, new_hw_ptr и hw_base, и пытался их изменить, но это не дало желаемого результата.
Я пытаюсь понять, как пройти данные PCM внутри DMA. Позже я заметил, что функция snd_pcm_set_runtime_buffer вызывается в начале записи, поэтому я добавил журналы printk для проверки деталей буфера DMA.
Код: Выделить всё
static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substream,
struct snd_dma_buffer *bufp)
{
struct snd_pcm_runtime *runtime = substream->runtime;
if (bufp) {
printk(KERN_INFO "Setting DMA buffer for substream: %s\n", substream->name);
printk(KERN_INFO "Buffer area (virtual address): %p\n", bufp->area);
printk(KERN_INFO "Buffer address (physical address): %llx\n", (unsigned long long)bufp->addr);
printk(KERN_INFO "Buffer size: %zu bytes\n", bufp->bytes);
runtime->dma_buffer_p = bufp;
runtime->dma_area = bufp->area;
runtime->dma_addr = bufp->addr;
runtime->dma_bytes = bufp->bytes;
} else {
printk(KERN_INFO "Clearing DMA buffer for substream: %s\n", substream->name);
runtime->dma_buffer_p = NULL;
runtime->dma_area = NULL;
runtime->dma_addr = 0;
runtime->dma_bytes = 0;
}
// 打印运行时最终的 DMA 信息
printk(KERN_INFO "Runtime DMA area: %p\n", runtime->dma_area);
printk(KERN_INFO "Runtime DMA addr: %llx\n", (unsigned long long)runtime->dma_addr);
printk(KERN_INFO "Runtime DMA bytes: %zu\n", runtime->dma_bytes);
}
Код: Выделить всё
Setting DMA buffer for substream: subdevice #0
Buffer area (virtual address): 00000000b77507ac
Buffer address (physical address): 0
Buffer size: 356352 bytes
Runtime DMA area: 00000000b77507ac
Runtime DMA addr: 0
Runtime DMA bytes: 356352
Кроме того, я прочитал online, что мне, возможно, придется использовать dmaengine, но я обнаружил, что в моем случае он вообще не вызывался, из-за чего я не понимаю его роли в процессе передачи данных.
От чего Насколько я понимаю, данные PCM сначала сохраняются в буфере DMA, а затем сопоставляются с пользовательским пространством через mmap, а не копируются в пользовательское пространство с помощью copy_to_user (хотя я не совсем уверен). Это заставляет меня задуматься, есть ли способ перехватить данные перед операцией mmap.
Подробнее здесь: https://stackoverflow.com/questions/791 ... i-modify-i