Поддерживает ли аппаратура hwbuf в userspace можно узнать с помощью ioctl SNDRV_PCM_INFO_MMAP. Если поддерживает, то мы можем положить hwbuf в userspace с помощью mmap (пример можно посмотреть в функции pcm_open() из все той же tinyalsa)
Но тут важная оговорка!
При работе с hwbuf нам нужны два указателя:
1) hw_ptr — это указатель на самые последние данные которые обработала аппаратура. Этот hw_ptr обычно можно узнать, прочитав какой-нибудь регистр SoC
2) appl_ptr — это указатель на последние обработанные _пользователем_ данные.
При нахождении hwbuf в kernelspace, ядро само аккуратно с ними работает — синхронизирует и смотрит, чтобы один указатель не обогнал второй. Такое бывает, например, когда система перегружена и пользовательский процесс работы со звуком просто не успевает выгребать данные. В таком случае надо либо дропать фреймы, либо аварийно завершаться.
В случае mmap вся эта работа ложится на пользовательский код. Он должен сам обновлять указатели с помощью ioctl SNDRV_PCM_SYNC_PTR_HWSYNC и подобных.
Итог. При mmap мы не избавляемся от ioctl, из-за работы с указателями и добавляем проблем в пользовательский код. Зато экономим copy_from/to_user().
Но тут важная оговорка!
При работе с hwbuf нам нужны два указателя:
1) hw_ptr — это указатель на самые последние данные которые обработала аппаратура. Этот hw_ptr обычно можно узнать, прочитав какой-нибудь регистр SoC
2) appl_ptr — это указатель на последние обработанные _пользователем_ данные.
При нахождении hwbuf в kernelspace, ядро само аккуратно с ними работает — синхронизирует и смотрит, чтобы один указатель не обогнал второй. Такое бывает, например, когда система перегружена и пользовательский процесс работы со звуком просто не успевает выгребать данные. В таком случае надо либо дропать фреймы, либо аварийно завершаться.
В случае mmap вся эта работа ложится на пользовательский код. Он должен сам обновлять указатели с помощью ioctl SNDRV_PCM_SYNC_PTR_HWSYNC и подобных.
Итог. При mmap мы не избавляемся от ioctl, из-за работы с указателями и добавляем проблем в пользовательский код. Зато экономим copy_from/to_user().