记一次UAC无法使用的bug
记一次UAC无法使用的bug
现象
最近遇到一个BUG,一个USB摄像头自带的MIC没法在Linux下使用。
记录下UAC相关排查过程
分析
查看驱动加载及节点
使用lsusb
可以看到,该UAC的设备已经加载对应通用驱动snd-usb-audio
:
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 480M
|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
|__ Port 4: Dev 4, If 0, Class=Hub, Driver=hub/4p, 480M
|__ Port 1: Dev 6, If 0, Class=Mass Storage, Driver=usb-storage, 480M
|__ Port 2: Dev 8, If 0, Class=Wireless, Driver=btusb, 12M
|__ Port 2: Dev 8, If 1, Class=Wireless, Driver=btusb, 12M
|__ Port 4: Dev 10, If 0, Class=Vendor Specific Class, Driver=, 12M
|__ Port 2: Dev 22, If 0, Class=Hub, Driver=hub/7p, 480M
|__ Port 4: Dev 25, If 0, Class=Human Interface Device, Driver=, 12M
|__ Port 2: Dev 23, If 3, Class=Audio, Driver=snd-usb-audio, 480M
|__ Port 2: Dev 23, If 1, Class=Video, Driver=uvcvideo, 480M
|__ Port 2: Dev 23, If 2, Class=Audio, Driver=snd-usb-audio, 480M
|__ Port 2: Dev 23, If 0, Class=Video, Driver=uvcvideo, 480M
但是在/dev/snd/
下未生成对应的采集节点,只有控制器节点
查看相关日志
从dmesg
日志中可以看到有关UAC报错:
... ...
[ 591.789645] usb 1-2.2: 3:1 : invalid UAC_FORMAT_TYPE desc
查看相关内核代码
查看相关内核代码,在sound/usb/format.c
, parse_audio_format_rates_v1()
函数:
static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audioformat *fp,
unsigned char *fmt, int offset)
{
int nr_rates = fmt[offset];
if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) {
usb_audio_err(chip,
"%u:%d : invalid UAC_FORMAT_TYPE desc\n",
fp->iface, fp->altsetting);
return -EINVAL;
}
... ...
}
可以看出是在解析UAC相关配置的时候出错了,进一步分析,是在判断其正常的字段长度时出错;
查看USB报告描述符
查看该摄像头的USB报告描述符,音频格式配置出错的相关部分:
AudioStreaming Interface Descriptor:
bLength 8
bDescriptorType 36
bDescriptorSubtype 2 (FORMAT_TYPE)
bFormatType 1 (FORMAT_TYPE_I)
Warning: Descriptor too short
bNrChannels 2
bSubframeSize 2
bBitResolution 16
bSamFreqType 0 Continuous
tLowerSamFreq 20480
tUpperSamFreq 0
结合UAC的官方文档,可以看到该USB摄像头的音频UAC采用的是连续采样率(bSamFreqType=0 Continuous),即代码中的nr_rates=0;
采样率范围为:最低采样率tLowerSamFreq=20480,最高采样率tUpperSamFreq=0,其值明显有问题;
每个采样率的长度为3字节,所以字段的总长度(代码中的fmt[0])应该为8+2*3=14,而描述符中的长度却为bLength=8,所以其长度也有问题,从而导致代码中的判断为真,并报错;
结论
该设备音频相关的USB描述符有问题,反馈给相应的厂家进行修改
或者通过判断UID和PID进行规避,将就修改代码。。。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 DD'Notes!
评论