最近在RK3308平台研究UAC功能,网上资料少的可怜,稍微有点用的资料还是专栏,还得开会员或者付费查看,真的是坑死了。
看了下相关资料,基本原理就是通过usb gadget虚拟成一个usb音频设备,然后在linux层虚拟出一个声卡。
1.如何开启UAC功能
检查kernel 编译宏配置 buildroot/configs/rockchip_rk3308_release_defconfig
检查是否开启如下宏配置:
CONFIG_USB_DWC2=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DEBUG_FILES=y
CONFIG_USB_GADGET_VBUS_DRAW=500
CONFIG_USB_CONFIGFS=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_UEVENT=y
CONFIG_USB_CONFIGFS_F_UAC1=y
CONFIG_USB_CONFIGFS_F_HID=y #打开HID,是考虑后期需要配置软件调节音量等功能。
由于是通过configfs来配置的,RK3308使用/etc/init.d/S50usbdevice脚本对我们需要的功能进行配置,包括UAC、ADB、UVC等USB相关功能,而这些功能又由/etc/init.d/.usb_config和/tmp/.usb_config文件内容决定是否开启。刚开始摸的时候,打开kernel配置的uac宏后,将板子的usb连接到电脑上后,死活检测不到usb音频设备,纠结了好一阵,最后发现就是个.usb_config文件配置导致的。
查看/etc/init.d/S50usbdevice启动脚本可以看到,就是通过这个文件内容来判断要初始化哪种usb设备:
而.usb_config文件中内容可以配置为什么呢?可以根据parameter_init()函数的case值可以看出支持哪些usb设备:
而RK的配置默认不支持adb和uac同时开启,我在此做了一些修改,可以同时开启adb和uac功能,方便调试,供大家参考。
diff --git a/S50usbdevice b/S50usbdevice
index 878ca3b..d1d2228 100755
--- a/S50usbdevice
+++ b/S50usbdevice
@@ -12,6 +12,7 @@ MTP_EN=off
NTB_EN=off
ACM_EN=off
UAC1_EN=off
+UAC1_ADB_EN=off
UAC2_EN=off
UVC_EN=off
RNDIS_EN=off
@@ -52,9 +53,11 @@ function_init()
mkdir ${USB_FUNCTIONS_DIR}/uac1.gs0
test_write 1 ${USB_FUNCTIONS_DIR}/uac1.gs0/c_feature_unit
test_write 1 ${USB_FUNCTIONS_DIR}/uac1.gs0/p_feature_unit
echo -e "8000,16000,32000,48000" > ${USB_FUNCTIONS_DIR}/uac1.gs0/c_srate
echo -e "8000,16000,32000,48000" > ${USB_FUNCTIONS_DIR}/uac1.gs0/p_srate
#echo -e "16000" > ${USB_FUNCTIONS_DIR}/uac1.gs0/c_srate
#echo -e "16000" > ${USB_FUNCTIONS_DIR}/uac1.gs0/c_srate
mkdir ${USB_FUNCTIONS_DIR}/uac2.gs0
@@ -174,6 +177,10 @@ parameter_init()
UAC1_EN=on
make_config_string uac1
;;
+ usb_uac1_adb_en)
+ UAC1_ADB_EN=on
+ make_config_string uac1_adb
+ ;;
usb_uac2_en)
UAC2_EN=on
make_config_string uac2
@@ -215,6 +222,9 @@ parameter_init()
acm)
PID=0x1005
;;
+ uac1_adb)
+ PID=0x0029
+ ;;
*)
PID=0x3301
esac
@@ -230,7 +240,7 @@ use_os_desc()
pre_run_binary()
{
- if [ $ADB_EN = on ];then
+ if [ $ADB_EN = on ] || [ $UAC1_ADB_EN = on ];then
mkdir /dev/usb-ffs/adb -m 0770
mount -o uid=2000,gid=2000 -t functionfs adb /dev/usb-ffs/adb
start-stop-daemon --start --quiet --background --exec /usr/bin/adbd
@@ -302,6 +312,7 @@ bind_functions()
test $RNDIS_EN = on && syslink_function rndis.gs0
test $UAC1_EN = on && syslink_function uac1.gs0
+ test $UAC1_ADB_EN = on && syslink_function uac1.gs0 && syslink_function ffs.adb
test $UAC2_EN = on && syslink_function uac2.gs0
echo 0x1 > ${USB_FUNCTIONS_DIR}/uac2.gs0/p_chmask
# test $UAC1_EN = on && syslink_function uac1.gs0
在如下目录即可查看kernel当前对哪些类型的usb设备进行了配置:
ls /sys/kernel/config/usb_gadget/rockchip/functions/
如下图表示,kernel已经生成了uac1.gs0配置,此时我们只需要修改.usb_config文件内容为usb_uac1_en或者usb_uac1_adb_en,即可开启UAC功能。
cat /etc/init.d/.usb_config #查看当前配置
只有其值为usb_uac1_en 或者 usb_uac1_adb_en时,才会生效
echo usb_uac1_en > /etc/init.d/.usb_config #启用 UAC
echo usb_adb_en > /etc/init.d/.usb_config #启用 ADB
echo usb_uac1_adb_en > /etc/init.d/.usb_config #同时启用 UAC和ADB
修改完后重启系统即可生效。若想让配置固件烧录后即可生效,需要手动修改buildroot/output/rockchip_rk3308_release/target/etc/init.d/.usb_config的文件内容,然后重新编译即可。
UAC功能正常开启后,即可在设备管理器中看到一个麦克风设备和扬声器设备。
2.修改UAC通道数、采样率、数据类型等参数
x_chmask:表示录/放音通道数(p相当于PC的录音通道个数, c相当于PC的播放通道个数):
bit为1的个数表示通道数,二进制11111111 等于 十进制 255
echo 255 > ${USB_FUNCTIONS_DIR}/uac1.gs0/p_chmask
表示配置为八声道,配置为双声道设置为3,配置为10声道则应该设置为1023。
x_srate: 录/放音的采样率,Rockchip UAC支持多采样率。
x_ssize: 录/放音数据的类型,单位bytes,对应PCM_16的数据,其值为2.
由于windows对驱动有记忆功能,修改UAC的参数后,我们需要卸载windows的驱动,才能使修改的参数生效。注意:必须要卸载声音、视频和游戏控制器中的 Source/Sink 设备,而不是音频输入和输出中的设备。
3. 修改UAC配置period_size大小
这个period_size会受驱动设置的buff大小和UAC通道数影响,如果开的通道比较多,需要相应增大buff的大小。
修改后如下图所示: