UVC摄像头技术笔记
+ -

UVC输入头描述符在usbvideo.sys中的校验

2025-01-21 29 0

关于UVC输入头描述符的介绍可详见:https://www.usbzh.com/article/detail-98.html

在usbvideo.sys驱动中,调用IRP_MJ_PNP的回调函数USBVideoPnpStart调用StartUSBVideoDevice,该函数在获取的UVC相机的配配置描述符之后,调用DumpAndValidateAllDescriptors函数进行配置描述符校验,如果失败,则设备启动失败。

  • USBVideoPnpStart
    • StartUSBVideoDevice
      • DumpAndValidateAllDescriptors

DumpAndValidateAllDescriptors函数的反汇编如下:

_int64 __fastcall DumpAndValidateAllDescriptors(USB_CONFIGURATION_DESCRIPTOR *pDes)
{
  int iConfiguration; // esi
  unsigned int status; // ecx
  char *pEnd; // rdi
  char *v6; // rdx
  int ntStatus; // eax
  unsigned __int16 v8; // [rsp+30h] [rbp+8h] BYREF

  iConfiguration = 0;
  v8 = 0;
  status = 0;
  if ( pDes->bDescriptorType != 2 )             // USB_CONFIGURATION_DESCRIPTOR_TYPE
    return 0xC0000001i64;                       // STATUS_UNSUCCESSFUL
  pEnd = (char *)(&pDes->bLength + pDes->wTotalLength);
  while ( pDes < (USB_CONFIGURATION_DESCRIPTOR *)pEnd )
  {
    if ( &pDes->wTotalLength > (USHORT *)pEnd || (char *)pDes + pDes->bLength > pEnd )
      return 0xC0000001;
    switch ( pDes->bDescriptorType )
    {
      case 2u:                                  // USB_CONFIGURATION_DESCRIPTOR_TYPE
        ntStatus = DumpAndValidateConfigDescriptor(pDes, pEnd);
        break;
      case 4u:                                  // USB_INTERFACE_ASSOCIATION_DESCRIPTOR
        ntStatus = DumpAndValidateInterfaceDescriptor(pDes, pEnd);
        iConfiguration = pDes->iConfiguration;
        break;
      case 5u:                                  // USB_ENDPOINT_DESCRIPTOR
        ntStatus = DumpAndValidateEndpointDescriptor(pDes, pEnd);
        break;
      case 0x24u:                               // USB_VIDEO_DESCRIPTOR
        ntStatus = DumpAndValidateClassSpecInterfaceDescriptor(
                     (USB_INTERFACE_DESCRIPTOR *)pDes,
                     pEnd,
                     iConfiguration,
                     &v8);
        break;
      case 0x25u:                               // VC_INTERRUPT_ENDPOINT_DESCRIPTOR
        v6 = pEnd;
        if ( LOBYTE(pDes->wTotalLength) != 3 )
          goto LABEL_12;
        ntStatus = DumpAndValidateClassSpecificInterruptEndpointDescriptor(pDes, pEnd);
        break;
      default:
        v6 = pEnd;
LABEL_12:
        ntStatus = DumpAndValidateGenericDescriptor(pDes, v6);
        break;
    }
    status = ntStatus;
    if ( ntStatus < 0 )
      return status;
    pDes = (USB_CONFIGURATION_DESCRIPTOR *)((char *)pDes + pDes->bLength);
  }
  return status;
}

UVC中,重点关键描述符类型为0x24的.
在DumpAndValidateClassSpecInterfaceDescriptor函数中调用DumpAndValidateInputHeader来校验UVC输入头描述符
其关键代码如下:
163104700340

对于结构体定义:

typedef struct _USB_VS_INTERFACE_INPUT_HEADER_DESCRIPTOR
{
   UINT8  bLength;
   UINT8  bDescriptorType;
   UINT8  bDescriptorSubtype;
   UINT8  bNumFormats;
   UINT16 wTotalLength;
   UINT8  bEndpointAddress;
   UINT8  bmInfo;
   UINT8  bTerminalLink;
   UINT8  bStillCaptureMethod;
   UINT8  bTriggerSupport;
   UINT8  bTriggerUsage;
   UINT8  bControlSize;
   UINT8  bmaControls[bControlSize];
} USB_VS_INTERFACE_INPUT_HEADER_DESCRIPTOR;

bControlSize字段包括bControlSize本身总其13个字节,bmaControls的数量因bNumFormats变化而变化。
注意上面的是等号判断,而不是>=,必须bmaControls不像有的描述符后面中可以有空字节,其长度必须严格一致。

本人在HOOK配置描述符时,因定义了bmaControls数组为2,导致实际配置描述符长度和bNumFormats的不一致,会引起设备启动失改,返回的错误号也刚好是STATUS_UNSUCCESSFUL,故不会再有选择配置请求。

关于这个问题,本人昨天查了一天,今天通过反汇编才定位到此。
因为本人熟知获取配置描述符之后,会有选择配置请求,但是因上面的问题,导致没有选择配置请求。故问题一定是因配置描述符引起的,但配置描述符有400多个字节,又因为本人因以前的相关描述符定义不是很规范,但是Windows可以兼容,导致问题一直迟迟未定位。

题外话:
因windows未开源,在调试过程中可能会遇到奇奇怪怪的问题人,但是问题很难定位。但有强大的IDA,可以通过反汇编和通过Windbg栈回溯,可以定位到上层代码段中,这样就可以再静态分析。如这样:https://www.usbzh.com/article/detail-1405.html

HID人机交互QQ群:564808376    UAC音频QQ群:218581009    UVC相机QQ群:331552032    BOT&UASP大容量存储QQ群:258159197    STC-USB单片机QQ群:315457461    USB技术交流QQ群2:580684376    USB技术交流QQ群:952873936   

0 篇笔记 写笔记

USB音箱 UAC配置描述符分析
该USB音箱的配置描述符和普通USB设备描述符结构体一致,并无特别区别。该配置描述符的总长度(包括后续的所有其它描述符)为110字节,这里相对华为耳机的要少了很多,这是因为少了像麦克风和HID。从配置描述符的字段bmAttributes来看,并不支持远程唤醒功能。 ------------......
华为UAC耳机 配置描述符
配置描述符的大小其实不光包括配置描述符自身,也包括后续的所有描述符。这里我们只先介绍一下配置描述符,后续的接口描述符和其它UAC相关描述符在后续一节介绍。配置描述符的内容如下: ------------------ Configuration Descriptor --------------......
UAC 其它速率配置描述符
在UAC规范中,并没有定义特别的其它速率配置描述符,故UAC音频设备的其它速率描述符应符合USB规范中的其它速率配置描述符。......
USB-UAC麦克风 配置描述符
UAC麦克风采用的配置描述符结构和USB配置描述符的结构一致.偏移地址字段长度值描述0bLength10x09配置描述符的长度1bDescriptorType10x02描述符类型,配置描述符类型2wTotalLength20x0064配置描述符的总长度(包括后续的UAC音频控制和UAC音频流接口描述......
USB设备描述符、配置描述符、接口描述符和端点描述符的拓扑关系
在USB设备的逻辑组织中,包含设备、配置、接口和端点4个层次。每个USB设备都提供了不同级别的配置信息,可以包含一个或多个配置,不同的配置使设备表现出不同的功能组合(在探测/连接期间需从其中选定一个),配置由多个接口组成。一次只能有一个配置是活动的。大多数的设备只有一个配置和一个接口,当一个设备......
USB 其它速率配置描述符
其它速率配置描述符(OTHER_SPEED_CONFIGURATION)。其它速率配置描述符与设备限定描述符(Device Qualifier Descriptor)配合使用, 当工作在其他速度下时使用, 除了描述符类型, 其他字段含义格式与配置描述符完全一致。 位移字段名称长度(字节......
UAC 配置描述符
UAC配置描述符仅用于单一功能的USB设备,没有专门的UAC特定的配置描述符,所以UAC音频设备的配置描述符应满足通用USB设备的配置描述符规范。......
UVC 输入头描述符
输入头描述符用于包含视频流输入端点的接口集。它提供了后续不同格式描述符数量的信息以及所有类特定描述符的总大小在转换设置为0的情况下的接口。// Class-specific VS Interface Input Header Descriptortypedef struct _USB_VS_IN......
USB 配置描述符
配置描述符定义了设备的配置信息,一个设备可以有多个配置描述符。大部分的USB设备只有一个配置描这符,设备存在多个配置描述符时.配置描述符指定设备的供电方式、最大功耗是多少、它拥有的接口数量。因此,可以有两种配置,一种用于设备由总线供电时,另一种用于设备供电时。由于这是接口描述符的“头”,因此使一种配......
HID报表描述符与设备描述符、配置描述符、字符串描述符的通讯格式对比
报表描述符是USB HID规范中一个很重要的概念。USB HID设备报表描述符内容表述了该HID设备的功能及数据传输的格式。USB HID报表描述符在概念上和设备描述符,配置描述符,接口描述符,端点描述符和其它USB设备描述符类似,但是还是有一些细微的区别。我里我们做一个简要的区别:设备描述符、......
UAC麦克风配置描述符
配置描述符包含了设备的配置信息,随配置描述符一起返回给主机的其它描述符代表了该设备的特性。UAC麦克风配置描述符的数据配置如下:数据结构定义如下:struct usb_config_descriptor { __u8 bLength; __u8 bDescriptorType; ......
仿照USBCCGP.SYS对USB配置描述符按功能拆分
USB大的规范中两个最麻烦的描述符一个是配置描述符,另一个是HID的报告描述符。一个因与其它描述符相互组合而复杂,一个因其自身的多样性而复杂。但你要问要问USB设备中那个描述符最烦人,答案肯定是配置描述符了。这是因为USB配置描述符不仅包含自己本身,也包含了其它描述符,如常用的接口描述符、端点描述符......
USB 设备同时支持全速模式与高速模式
当一个USB高速设备接入全速的HUB时,这时会出现高速模式协商失败,这时为了设备能正常使用,会自动使用全速模式来运行。所以为了同时支持全速与高速的设备,必须有Device Qualifier Descriptor和其它速率配置描述符(OTHER_SPEED_CONFIGURATION),用于描述全速......
Windows和Linux不同主机下USB设备枚举过程中的差别
第一次获取设备描述符的不同USB设备刚上电时,是通过端点0使用控制方式来获取设备描述符。不同的设备模式获取端点0的大小不同的:高速模式的端点0最大包长固定为64个字节;全速模式可端点0在8、16、32、64字节中选择;低速模式的端点0最大包长固定为8个字节由于USB主机和USB设备第一次通讯时......
Windows内核USB配置描述符解析函数
从USB配置描述符中解析相关的描述符,大量利用系统提供的函数。可以大量节省时间。#include PUSB_INTERFACE_DESCRIPTORdsc_find_first_intf(PUSB_CONFIGURATION_DESCRIPTOR dsc_......
关注公众号
  • HID人机交互
  • Linux&USB
  • UAC音频
  • TYPE-C
  • USB规范
  • USB大容量存储
  • USB百科
  • USB周边
  • UVC摄像头
  • Windows系统USB
  • 音视频博客
  • 取消
    感谢您的支持,我会继续努力的!
    扫码支持
    扫码打赏,你说多少就多少

    打开支付宝扫一扫,即可进行扫码打赏哦

    您的支持,是我们前进的动力!