date
Mar 23, 2022
slug
2022-03-23-linux-uac-gadget-audio-control-application
status
Published
tags
USB
UAC
summary
本文总结了SigmaStar提供的在基于Linux kernel的UAC gadget设备中增加audio control控制功能的完整工作流程,应用层部分。
type
Post
category
Linux
AI summary
基于对SigmaStar Webcam方案源代码的学习,通过三篇文章的篇幅,整体总结了SigmaStar提供的在基于Linux kernel的UAC gadget设备中增加audio control控制功能的完整工作流程:
以下为应用层部分的完整总结。详细解析了SigmaStar SDK中提供的在应用层通过ALSA KControl机制实现audio control命令的通知和功能实现。
Linux USB Gadget中的UAC部分与kernel部分的交互,实际上使用了Linux的ALSA音频驱动框架。这一点有点类似于在UVC Gadget中使用了v4l2摄像头驱动框架一样:
- v4l2摄像头框架原本的设计是要实现一个内核中的摄像头驱动,以方便应用层以统一的流程和接口从kenel中读取摄像头的数据;而在UVC中使用v4l2的图像流的走向刚好与原本的v4l2框架相反,是把应用层的图像流通过v4l2机制发到内核,然后由内核调用USB底层驱动发给Host;
- 在UAC上使用ALSA音频驱动框架的逻辑也是类似。ALSA原本的设计,是通过ALSA框架定义的标准,从kernel中读取麦克风的数据到应用层,向kernel中写入需要通过喇叭来播放的音频数据,以及通过kcontrol机制实现对音频硬件的控制;UAC中对于ALSA的使用刚好相反,是把应用层整理好的音频数据使用SNDRV_PCM_IOCTL_WRITEI_FRAMES ioctl code写入kernel,然后由kernel调用USB硬件发给Host,以及把USB Host发过来的音频数据通过使用SNDRV_PCM_IOCTL_READI_FRAMES ioctl code读取到应用层,再调用SDK应用层的API把这个声音从喇叭中播放出来,而USB Host所发过来的audio control类的命令则是通过kcontrol机制返回给应用层,由应用层做针对的处理。
应用层部分的实现逻辑
应用层实现audio control的大致流程,与ALSA声卡驱动框架的kcontrol一致:
- 调用mixer_open函数打开audio control设备文件,以及通过这个设备文件读取kernel中支持kcontrol列表;
- 调用mixer_subscribe_events函数开启内核audio control事件的订阅;
- 循环执行:
- 调用mixer_wait_event函数等待audio control设备文件是否有新的command通知上来;
- 调用mixer_ctl_get_event和mixer_ctl_get_value获取事件详细信息及其参数;
- 利用从内核设备文件中读取到的事件和参数,通过SigmaStar SDK应用层的MI_AI_SetVqeVolume接口设置新的音量参数。
mixer_open函数的解析:
mixer_subscribe_events
mixer_subscribe_events的实现比较简单,实际上就是通过ioctl code SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS开启或者关闭对内核ALSA control事件的订阅;
Audio Control消息处理循环结构
- 通过在事件监听和处理循环中,通过mixer_ctl_get_event可以知道哪个audio control的参数发生了变化,然后通过mixer_ctl_get_value函数读取这个audio control在kernel中的当前设置值,然后就可以在应用层调用对应的audio control的功能函数,把Host发过来的audio control功能实现出来。
- 以上例子代码只是实现了一个volume control的例子。如果要增加其他的audio control功能,可以在mixer_ctl_get_value函数中进行判断和识别,究竟是哪个audio control的参数发生了变化,然后对应的在mixer_ctl_get_value函数中读取其内核中的设置值,并在应用层设置功能。