视频监控—从0写USB摄像头驱动(1)-描述符的分析与打印

  • 硬件平台:韦东山嵌入式Linxu开发板(S3C2440.v3)
  • 软件平台:运行于VMware Workstation 12 Player下UbuntuLTS16.04_x64 系统
  • 参考资料:USB_Video_Example 1.5、UVC 1.5 Class specification
  • 开发环境:Linux-4.13.0-41内核(虚拟机)、arm-linux-gcc-4.3.2工具链
  • 源码仓库:https://gitee.com/d_1254436976/Embedded-Linux-Phase-3

目录

  • 视频监控—从0写USB摄像头驱动(1)-描述符的分析与打印
    • 一、描述符
      • 1、什么是描述符
      • 2、USB设备的描述符
      • 3、UVC-Video类中的描述符
    • 二、打印USB摄像头的描述符
      • 1、代码的编写
      • 2、Makefile编写
      • 3、运行与分析
        • 3.1 运行
        • 3.2 分析

一、描述符


1、什么是描述符

关于这个概念也没有一个准确的定义,可以理解为与 “被描述物” 相关联一组数据或数据结构,用来记录被描述物的 “属性”。
具体体现如下(举例说明,并非所有)

  1. 数字,如Linux中的文件描述符,表示一个打开的文件
  2. 结构体,这个在C语言中比较常见,结构体中存储的成员变量的数据就是该设备的具体描述
  3. ,这个在C++与Java中比较常见,其成员变量的数据就是该设备的具体描述

2、USB设备的描述符

对于usb描述符,用来描述该usb设备的属性,如:设备类型、设备型号、配置、容量大小等等
对于一个usb设备,其必有如下固定描述符

  • USB设备描述符(usb_device_descriptor):描述该USB设备的一般信息,如厂家信息、协议信息、usb版本等,一个USB设备只有一个设备描述符
    访问方式USB设备结构体usb_device的descriptor成员变量中
struct usb_device_descriptor {__u8  bLength;               //本描述符的size__u8  bDescriptorType;       //描述符的类型,这里是设备描述符DEVICE__u16 bcdUSB;                //指明usb的版本,比如usb2.0__u8  bDeviceClass;          //类__u8  bDeviceSubClass;       //子类__u8  bDeviceProtocol;       //指定协议__u8  bMaxPacketSize0;       //端点0对应的最大包大小__u16 idVendor;              //厂家ID__u16 idProduct;             //产品ID__u16 bcdDevice;             //设备的发布号__u8  iManufacturer;         //字符串描述符中厂家ID的索引__u8  iProduct;              //字符串描述符中产品ID的索引__u8  iSerialNumber;         //字符串描述符中设备序列号的索引__u8  bNumConfigurations;    //配置描述符的个数,表示有多少个配置描述符
} __attribute__ ((packed));
  • USB配置描述符(usb_config_descriptor):描述有关特定设备配置的信息主机获取到设备描述符之后,就会获取配置描述符一个设置描述符可以有一个或多个配置描述符
    访问方式USB设备结构体usb_device->config[ ](所有配置).desc
    usb_device->actconfig(当前激活的配置)->desc
 struct usb_config_descriptor {   __u8  bLength;                 //描述符的长度__u8  bDescriptorType;         //描述符类型的编号__le16 wTotalLength;           //配置 所返回的所有数据的大小__u8  bNumInterfaces;          //配置 所支持的接口个数, 表示有多少个接口描述符__u8  bConfigurationValue;     //Set_Configuration命令需要的参数值__u8  iConfiguration;          //描述该配置的字符串的索引值__u8  bmAttributes;            //供电模式的选择__u8  bMaxPower;               //设备从总线提取的最大电流} __attribute__ ((packed));
  • USB接口描述符(usb_interface_descriptor):描述配置中的特定接口一个配置提供一个或多个接口(对于一个声卡设备,拥有音频输入接口与输出接口)
    访问方式usb_interface->cur_altsetting(当前激活的接口)->desc
    usb_interface->altsetting[ ](所有的接口).desc
struct usb_interface_descriptor {  __u8  bLength;                 //描述符的长度__u8  bDescriptorType;         //描述符类型的编号__u8  bInterfaceNumber;        //接口的编号__u8  bAlternateSetting;       //备用的接口描述符编号,提供不同质量的服务参数.__u8  bNumEndpoints;           //要使用的端点个数(不包括端点0), 表示有多少个端点描述符,比如鼠标就只有一个端点__u8  bInterfaceClass;         //接口类型,与驱动的id_table__u8  bInterfaceSubClass;      //接口子类型__u8  bInterfaceProtocol;      //接口所遵循的协议__u8  iInterface;              //描述该接口的字符串索引值
} __attribute__ ((packed)
  • USB端点描述符(usb_endpoint_descriptor):描述该接口中每个端点的带宽要求所需的信息
    访问方式usb_interface->cur_altsetting(当前激活的接口)->endpoint[] (所有端点).desc
struct usb_endpoint_descriptor {__u8  bLength;                 //描述符的长度__u8  bDescriptorType;         //描述符类型的编号__u8  bEndpointAddress;        //端点编号,比如端点1,就是1__u8  bmAttributes;            //端点的属性, 比如中断传输类型,输入类型__le16 wMaxPacketSize;         //一个端点的最大包大小,__u8  bInterval;               //间隔时间,用在中断传输上,比如间隔时间查询鼠标的数据/* NOTE:  these two are _only_ in audio endpoints. *//* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */__u8  bRefresh;__u8  bSynchAddress;
} __attribute__ ((packed));

四者的关系如下:

  • 一个USB设备只有一个USB设备描述符

  • 一个设置描述符可以有一个或多个配置描述符

  • 一个配置描述符可以有一个或多个接口描述符

  • 一个接口描述符可以有一个或多个端点描述符


3、UVC-Video类中的描述符

参考手册,得到如下图:其中白色底为固定的描述符灰色底为此设备拓展的描述符


二、打印USB摄像头的描述符

使用到的USB摄像头为百问网的usb-cmos二合一摄像头,参考libusb-1.0.16-rc10源码


1、代码的编写

/******************************************************************************** Copyleft (c) 2021 Kcode** @file    myuvc.c* @brief   打印usb的设备、配置、IAD、接口、自定义、端点描述符并解析自定义描述符* @author  K* @version 0.0.1* @date    2021-07-21* @license MulanPSL-1.0** 文件修改历史:* <时间>         | <版本>      | <作者>    | <描述>* 2021-07-21   | v0.0.1    | Kcode   | 打印并解析描述符* -----------------------------------------------------------------------------******************************************************************************/#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/videodev2.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <asm/atomic.h>
#include <asm/unaligned.h>#include <media/v4l2-common.h>/*!* 所支持的usb设备类*/
static struct usb_device_id myuvc_ids[] = {/* Generic USB Video Class */{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },    /**< VideoControl interface */{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 2, 0) }, /**< VideoStreaming interface */{}
};static const char *get_guid(const unsigned char *buf)
{static char guid[39];/* NOTE:  see RFC 4122 for more information about GUID/UUID* structure.  The first fields fields are historically big* endian numbers, dating from Apollo mc68000 workstations.*/sprintf(guid, "{%02x%02x%02x%02x""-%02x%02x""-%02x%02x""-%02x%02x""-%02x%02x%02x%02x%02x%02x}",buf[0], buf[1], buf[2], buf[3],buf[4], buf[5],buf[6], buf[7],buf[8], buf[9],buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);return guid;
}/*!* 解析VideoControl Interface接口的自定义描述符*/
static void parse_videocontrol_interface(struct usb_interface *intf,unsigned char *buf, int buflen)
{static const char * const ctrlnames[] = {"Brightness", "Contrast", "Hue", "Saturation", "Sharpness", "Gamma","White Balance Temperature", "White Balance Component", "Backlight Compensation","Gain", "Power Line Frequency", "Hue, Auto", "White Balance Temperature, Auto","White Balance Component, Auto", "Digital Multiplier", "Digital Multiplier Limit","Analog Video Standard", "Analog Video Lock Status"};static const char * const camctrlnames[] = {"Scanning Mode", "Auto-Exposure Mode", "Auto-Exposure Priority","Exposure Time (Absolute)", "Exposure Time (Relative)", "Focus (Absolute)","Focus (Relative)", "Iris (Absolute)", "Iris (Relative)", "Zoom (Absolute)","Zoom (Relative)", "PanTilt (Absolute)", "PanTilt (Relative)","Roll (Absolute)", "Roll (Relative)", "Reserved", "Reserved", "Focus, Auto","Privacy"};static const char * const stdnames[] = {"None", "NTSC - 525/60", "PAL - 625/50", "SECAM - 625/50","NTSC - 625/50", "PAL - 525/60" };unsigned int i, ctrls, stds, n, p, termt, freq;/*!* 打印所有的在VideoControl Interface接口下的自定义描述符*/while (buflen > 0) {if (buf[1] != USB_DT_CS_INTERFACE)printk("      Warning: Invalid descriptor\n");else if (buf[0] < 3)printk("      Warning: Descriptor too short\n");printk("      VideoControl Interface Descriptor:\n""        bLength             %5u\n""        bDescriptorType     %5u\n""        bDescriptorSubtype  %5u ",buf[0], buf[1], buf[2]);switch (buf[2]) {case 0x01:  /* HEADER */printk("(HEADER)\n");n = buf[11];if (buf[0] < 12+n)printk("      Warning: Descriptor too short\n");freq = buf[7] | (buf[8] << 8) | (buf[9] << 16) | (buf[10] << 24);printk("        bcdUVC              %2x.%02x\n""        wTotalLength        %5u\n""        dwClockFrequency    %5u.%06uMHz\n""        bInCollection       %5u\n",buf[4], buf[3], buf[5] | (buf[6] << 8), freq / 1000000,freq % 1000000, n);for (i = 0; i < n; i++)printk("        baInterfaceNr(%2u)   %5u\n", i, buf[12+i]);break;case 0x02:  /* INPUT_TERMINAL */printk("(INPUT_TERMINAL)\n");termt = buf[4] | (buf[5] << 8);n = termt == 0x0201 ? 7 : 0;if (buf[0] < 8 + n)printk("      Warning: Descriptor too short\n");printk("        bTerminalID         %5u\n""        wTerminalType      0x%04x\n""        bAssocTerminal      %5u\n",buf[3], termt, buf[6]);printk("        iTerminal           %5u\n",buf[7]);if (termt == 0x0201) {n += buf[14];printk("        wObjectiveFocalLengthMin  %5u\n""        wObjectiveFocalLengthMax  %5u\n""        wOcularFocalLength        %5u\n""        bControlSize              %5u\n",buf[8] | (buf[9] << 8), buf[10] | (buf[11] << 8),buf[12] | (buf[13] << 8), buf[14]);ctrls = 0;for (i = 0; i < 3 && i < buf[14]; i++)ctrls = (ctrls << 8) | buf[8+n-i-1];printk("        bmControls           0x%08x\n", ctrls);for (i = 0; i < 19; i++)if ((ctrls >> i) & 1)printk("          %s\n", camctrlnames[i]);}break;case 0x03:  /* OUTPUT_TERMINAL */printk("(OUTPUT_TERMINAL)\n");termt = buf[4] | (buf[5] << 8);if (buf[0] < 9)printk("      Warning: Descriptor too short\n");printk("        bTerminalID         %5u\n""        wTerminalType      0x%04x\n""        bAssocTerminal      %5u\n""        bSourceID           %5u\n""        iTerminal           %5u\n",buf[3], termt, buf[6], buf[7], buf[8]);break;case 0x04:  /* SELECTOR_UNIT */printk("(SELECTOR_UNIT)\n");p = buf[4];if (buf[0] < 6+p)printk("      Warning: Descriptor too short\n");printk("        bUnitID             %5u\n""        bNrInPins           %5u\n",buf[3], p);for (i = 0; i < p; i++)printk("        baSource(%2u)        %5u\n", i, buf[5+i]);printk("        iSelector           %5u\n",buf[5+p]);break;case 0x05:  /* PROCESSING_UNIT */printk("(PROCESSING_UNIT)\n");n = buf[7];if (buf[0] < 10+n)printk("      Warning: Descriptor too short\n");printk("        bUnitID             %5u\n""        bSourceID           %5u\n""        wMaxMultiplier      %5u\n""        bControlSize        %5u\n",buf[3], buf[4], buf[5] | (buf[6] << 8), n);ctrls = 0;for (i = 0; i < 3 && i < n; i++)ctrls = (ctrls << 8) | buf[8+n-i-1];printk("        bmControls     0x%08x\n", ctrls);for (i = 0; i < 18; i++)if ((ctrls >> i) & 1)printk("          %s\n", ctrlnames[i]);stds = buf[9+n];printk("        iProcessing         %5u\n""        bmVideoStandards     0x%2x\n", buf[8+n], stds);for (i = 0; i < 6; i++)if ((stds >> i) & 1)printk("          %s\n", stdnames[i]);break;case 0x06:  /* EXTENSION_UNIT */printk("(EXTENSION_UNIT)\n");p = buf[21];n = buf[22+p];if (buf[0] < 24+p+n)printk("      Warning: Descriptor too short\n");printk("        bUnitID             %5u\n""        guidExtensionCode         %s\n""        bNumControl         %5u\n""        bNrPins             %5u\n",buf[3], get_guid(&buf[4]), buf[20], buf[21]);for (i = 0; i < p; i++)printk("        baSourceID(%2u)      %5u\n", i, buf[22+i]);printk("        bControlSize        %5u\n", buf[22+p]);for (i = 0; i < n; i++)printk("        bmControls(%2u)       0x%02x\n", i, buf[23+p+i]);printk("        iExtension          %5u\n",buf[23+p+n]);break;default:printk("(unknown)\n""        Invalid desc subtype:");break;}buflen -= buf[0];buf    += buf[0];}
}/*!* 打印端点描述符*/
static void dump_endpoint(const struct usb_endpoint_descriptor *endpoint)
{static const char * const typeattr[] = {"Control","Isochronous","Bulk","Interrupt"};static const char * const syncattr[] = {"None","Asynchronous","Adaptive","Synchronous"};static const char * const usage[] = {"Data","Feedback","Implicit feedback Data","(reserved)"};static const char * const hb[] = { "1x", "2x", "3x", "(?\?)" };unsigned wmax = le16_to_cpu(endpoint->wMaxPacketSize);printk("      Endpoint Descriptor:\n""        bLength             %5u\n""       bDescriptorType     %5u\n""       bEndpointAddress     0x%02x  EP %u %s\n""     bmAttributes        %5u\n""         Transfer Type            %s\n""       Synch Type               %s\n""       Usage Type               %s\n""     wMaxPacketSize     0x%04x  %s %d bytes\n""        bInterval           %5u\n",endpoint->bLength,endpoint->bDescriptorType,endpoint->bEndpointAddress,endpoint->bEndpointAddress & 0x0f,(endpoint->bEndpointAddress & 0x80) ? "IN" : "OUT",endpoint->bmAttributes,typeattr[endpoint->bmAttributes & 3],syncattr[(endpoint->bmAttributes >> 2) & 3],usage[(endpoint->bmAttributes >> 4) & 3],wmax, hb[(wmax >> 11) & 3], wmax & 0x7ff,endpoint->bInterval);/* only for audio endpoints */if (endpoint->bLength == 9)printk("       bRefresh            %5u\n""       bSynchAddress       %5u\n",endpoint->bRefresh, endpoint->bSynchAddress);}/*!* 解析VideoStreaming Interface接口的自定义描述符*/
static void parse_videostreaming_interface(struct usb_interface *intf, unsigned char *buf, int buflen)
{static const char * const colorPrims[] = { "Unspecified", "BT.709,sRGB","BT.470-2 (M)", "BT.470-2 (B,G)", "SMPTE 170M", "SMPTE 240M" };static const char * const transferChars[] = { "Unspecified", "BT.709","BT.470-2 (M)", "BT.470-2 (B,G)", "SMPTE 170M", "SMPTE 240M","Linear", "sRGB"};static const char * const matrixCoeffs[] = { "Unspecified", "BT.709","FCC", "BT.470-2 (B,G)", "SMPTE 170M (BT.601)", "SMPTE 240M" };unsigned int i, m, n, p, flags, len;/*!* 打印所有的在VideoSteaming Interface接口下的自定义描述符*/while (buflen > 0) {if (buf[1] != USB_DT_CS_INTERFACE)printk("   Warning: Invalid descriptor\n");else if (buf[0] < 3)printk("    Warning: Descriptor too short\n");printk("   VideoStreaming Interface Descriptor:\n""        bLength                         %5u\n""       bDescriptorType                 %5u\n""       bDescriptorSubtype              %5u ",buf[0], buf[1], buf[2]);switch (buf[2]) {case 0x01: /* INPUT_HEADER */printk("(INPUT_HEADER)\n");p = buf[3];n = buf[12];if (buf[0] < 13+p*n)printk("      Warning: Descriptor too short\n");printk("     bNumFormats                     %5u\n""       wTotalLength                    %5u\n""       bEndPointAddress                %5u\n""       bmInfo                          %5u\n""       bTerminalLink                   %5u\n""       bStillCaptureMethod             %5u\n""       bTriggerSupport                 %5u\n""       bTriggerUsage                   %5u\n""       bControlSize                    %5u\n",p, buf[4] | (buf[5] << 8), buf[6], buf[7], buf[8],buf[9], buf[10], buf[11], n);for (i = 0; i < p; i++)printk("        bmaControls(%2u)                 %5u\n",i, buf[13+p*n]);break;case 0x02: /* OUTPUT_HEADER */printk("(OUTPUT_HEADER)\n");p = buf[3];n = buf[8];if (buf[0] < 9+p*n)printk("   Warning: Descriptor too short\n");printk("     bNumFormats                 %5u\n""       wTotalLength                %5u\n""       bEndpointAddress            %5u\n""       bTerminalLink               %5u\n""       bControlSize                %5u\n",p, buf[4] | (buf[5] << 8), buf[6], buf[7], n);for (i = 0; i < p; i++)printk("         bmaControls(%2u)             %5u\n",i, buf[9+p*n]);break;case 0x03: /* STILL_IMAGE_FRAME */printk("(STILL_IMAGE_FRAME)\n");n = buf[4];m = buf[5+4*n];if (buf[0] < 6+4*n+m)printk("      Warning: Descriptor too short\n");printk("     bEndpointAddress                %5u\n""       bNumImageSizePatterns             %3u\n",buf[3], n);for (i = 0; i < n; i++)printk("        wWidth(%2u)                      %5u\n""      wHeight(%2u)                     %5u\n",i, buf[5+4*i] | (buf[6+4*i] << 8),i, buf[7+4*i] | (buf[8+4*i] << 8));printk("        bNumCompressionPatterns           %3u\n", n);for (i = 0; i < m; i++)printk("      bCompression(%2u)                %5u\n",i, buf[6+4*n+i]);break;case 0x04: /* FORMAT_UNCOMPRESSED */case 0x10: /* FORMAT_FRAME_BASED */if (buf[2] == 0x04) {printk("(FORMAT_UNCOMPRESSED)\n");len = 27;} else {printk("(FORMAT_FRAME_BASED)\n");len = 28;}if (buf[0] < len)printk("   Warning: Descriptor too short\n");flags = buf[25];printk("      bFormatIndex                    %5u\n""       bNumFrameDescriptors            %5u\n""       guidFormat                            %s\n""      bBitsPerPixel                   %5u\n""       bDefaultFrameIndex              %5u\n""       bAspectRatioX                   %5u\n""       bAspectRatioY                   %5u\n""       bmInterlaceFlags                 0x%02x\n",buf[3], buf[4], get_guid(&buf[5]), buf[21], buf[22],buf[23], buf[24], flags);printk("         Interlaced stream or variable: %s\n",(flags & (1 << 0)) ? "Yes" : "No");printk("         Fields per frame: %u fields\n",(flags & (1 << 1)) ? 1 : 2);printk("          Field 1 first: %s\n",(flags & (1 << 2)) ? "Yes" : "No");printk("         Field pattern: ");switch ((flags >> 4) & 0x03) {case 0:printk("Field 1 only\n");break;case 1:printk("Field 2 only\n");break;case 2:printk("Regular pattern of fields 1 and 2\n");break;case 3:printk("Random pattern of fields 1 and 2\n");break;}printk("        bCopyProtect                  %5u\n", buf[26]);if (buf[2] == 0x10)printk("         bVariableSize                 %5u\n", buf[27]);break;case 0x05: /* FRAME UNCOMPRESSED */case 0x07: /* FRAME_MJPEG */case 0x11: /* FRAME_FRAME_BASED */if (buf[2] == 0x05) {printk("(FRAME_UNCOMPRESSED)\n");n = 25;} else if (buf[2] == 0x07) {printk("(FRAME_MJPEG)\n");n = 25;} else {printk("(FRAME_FRAME_BASED)\n");n = 21;}len = (buf[n] != 0) ? (26+buf[n]*4) : 38;if (buf[0] < len)printk("     Warning: Descriptor too short\n");flags = buf[4];printk("       bFrameIndex                     %5u\n""       bmCapabilities                   0x%02x\n",buf[3], flags);printk("       Still image %ssupported\n",(flags & (1 << 0)) ? "" : "un");if (flags & (1 << 1))printk("        Fixed frame-rate\n");printk("      wWidth                          %5u\n""       wHeight                         %5u\n""       dwMinBitRate                %9u\n""       dwMaxBitRate                %9u\n",buf[5] | (buf[6] <<   8), buf[7] | (buf[8] << 8),buf[9] | (buf[10] << 8) | (buf[11] << 16) | (buf[12] << 24),buf[13] | (buf[14] << 8) | (buf[15] << 16) | (buf[16] << 24));if (buf[2] == 0x11)printk("     dwDefaultFrameInterval      %9u\n""       bFrameIntervalType              %5u\n""       dwBytesPerLine              %9u\n",buf[17] | (buf[18] << 8) | (buf[19] << 16) | (buf[20] << 24),buf[21],buf[22] | (buf[23] << 8) | (buf[24] << 16) | (buf[25] << 24));elseprintk("       dwMaxVideoFrameBufferSize   %9u\n""       dwDefaultFrameInterval      %9u\n""       bFrameIntervalType              %5u\n",buf[17] | (buf[18] << 8) | (buf[19] << 16) | (buf[20] << 24),buf[21] | (buf[22] << 8) | (buf[23] << 16) | (buf[24] << 24),buf[25]);if (buf[n] == 0)printk("     dwMinFrameInterval          %9u\n""       dwMaxFrameInterval          %9u\n""       dwFrameIntervalStep         %9u\n",buf[26] | (buf[27] << 8) | (buf[28] << 16) | (buf[29] << 24),buf[30] | (buf[31] << 8) | (buf[32] << 16) | (buf[33] << 24),buf[34] | (buf[35] << 8) | (buf[36] << 16) | (buf[37] << 24));elsefor (i = 0; i < buf[n]; i++)printk("      dwFrameInterval(%2u)         %9u\n",i, buf[26+4*i] | (buf[27+4*i] << 8) |(buf[28+4*i] << 16) | (buf[29+4*i] << 24));break;case 0x06: /* FORMAT_MJPEG */printk("(FORMAT_MJPEG)\n");if (buf[0] < 11)printk("   Warning: Descriptor too short\n");flags = buf[5];printk("       bFormatIndex                    %5u\n""       bNumFrameDescriptors            %5u\n""       bFlags                          %5u\n",buf[3], buf[4], flags);printk("        Fixed-size samples: %s\n",(flags & (1 << 0)) ? "Yes" : "No");flags = buf[9];printk("        bDefaultFrameIndex              %5u\n""       bAspectRatioX                   %5u\n""       bAspectRatioY                   %5u\n""       bmInterlaceFlags                 0x%02x\n",buf[6], buf[7], buf[8], flags);printk("         Interlaced stream or variable: %s\n",(flags & (1 << 0)) ? "Yes" : "No");printk("         Fields per frame: %u fields\n",(flags & (1 << 1)) ? 2 : 1);printk("          Field 1 first: %s\n",(flags & (1 << 2)) ? "Yes" : "No");printk("         Field pattern: ");switch ((flags >> 4) & 0x03) {case 0:printk("Field 1 only\n");break;case 1:printk("Field 2 only\n");break;case 2:printk("Regular pattern of fields 1 and 2\n");break;case 3:printk("Random pattern of fields 1 and 2\n");break;}printk("        bCopyProtect                  %5u\n", buf[10]);break;case 0x0a: /* FORMAT_MPEG2TS */printk("(FORMAT_MPEG2TS)\n");len = buf[0] < 23 ? 7 : 23;if (buf[0] < len)printk("      Warning: Descriptor too short\n");printk("     bFormatIndex                    %5u\n""       bDataOffset                     %5u\n""       bPacketLength                   %5u\n""       bStrideLength                   %5u\n",buf[3], buf[4], buf[5], buf[6]);if (len > 7)printk("        guidStrideFormat                      %s\n",get_guid(&buf[7]));break;case 0x0d: /* COLORFORMAT */printk("(COLORFORMAT)\n");if (buf[0] < 6)printk("      Warning: Descriptor too short\n");printk("     bColorPrimaries                 %5u (%s)\n",buf[3], (buf[3] <= 5) ? colorPrims[buf[3]] : "Unknown");printk("     bTransferCharacteristics        %5u (%s)\n",buf[4], (buf[4] <= 7) ? transferChars[buf[4]] : "Unknown");printk("      bMatrixCoefficients             %5u (%s)\n",buf[5], (buf[5] <= 5) ? matrixCoeffs[buf[5]] : "Unknown");break;default:printk("     Invalid desc subtype:");break;}buflen -= buf[0];buf    += buf[0];}}static int myuvc_probe(struct usb_interface *intf,const struct usb_device_id *id)
{    unsigned char *buffer;int i, j, k, l, m;int buflen;int desc_len;int desc_cnt;static int cnt = 0;struct usb_device *dev = interface_to_usbdev(intf);struct usb_device_descriptor *descriptor = &dev->descriptor;struct usb_host_config *hostconfig;struct usb_config_descriptor *config;struct usb_interface_assoc_descriptor *assoc_desc;struct usb_interface_descriptor *interface;struct usb_endpoint_descriptor  *endpoint;printk("myuvc_probe : cnt = %d\n", cnt++);/*!* 打印设备描述符*/printk("Device Descriptor:\n""  bLength             %5u\n""  bDescriptorType     %5u\n""  bcdUSB              %2x.%02x\n""  bDeviceClass        %5u \n""  bDeviceSubClass     %5u \n""  bDeviceProtocol     %5u \n""  bMaxPacketSize0     %5u\n""  idVendor           0x%04x \n""  idProduct          0x%04x \n""  bcdDevice           %2x.%02x\n""  iManufacturer       %5u\n""  iProduct            %5u\n""  iSerial             %5u\n""  bNumConfigurations  %5u\n",descriptor->bLength, descriptor->bDescriptorType,descriptor->bcdUSB >> 8, descriptor->bcdUSB & 0xff,descriptor->bDeviceClass, descriptor->bDeviceSubClass,descriptor->bDeviceProtocol, descriptor->bMaxPacketSize0,descriptor->idVendor,  descriptor->idProduct,descriptor->bcdDevice >> 8, descriptor->bcdDevice & 0xff,descriptor->iManufacturer, descriptor->iProduct, descriptor->iSerialNumber, descriptor->bNumConfigurations);/*!* 打印配置描述符*/for (i = 0; i < descriptor->bNumConfigurations; i++) {hostconfig = &dev->config[i];config     = &hostconfig->desc;printk("  Configuration Descriptor %d:\n""    bLength             %5u\n""    bDescriptorType     %5u\n""    wTotalLength        %5u\n""    bNumInterfaces      %5u\n""    bConfigurationValue %5u\n""    iConfiguration      %5u\n""    bmAttributes         0x%02x\n",i, config->bLength, config->bDescriptorType,le16_to_cpu(config->wTotalLength),config->bNumInterfaces, config->bConfigurationValue,config->iConfiguration,config->bmAttributes);/*!* 打印IAD描述符*/assoc_desc = hostconfig->intf_assoc[0];printk("    Interface Association:\n""      bLength             %5u\n""      bDescriptorType     %5u\n""      bFirstInterface     %5u\n""      bInterfaceCount     %5u\n""      bFunctionClass      %5u\n""      bFunctionSubClass   %5u\n""      bFunctionProtocol   %5u\n""      iFunction           %5u\n",assoc_desc->bLength,assoc_desc->bDescriptorType,assoc_desc->bFirstInterface,assoc_desc->bInterfaceCount,assoc_desc->bFunctionClass,assoc_desc->bFunctionSubClass,assoc_desc->bFunctionProtocol,assoc_desc->iFunction);/*!* 可能有多个接口,根据intf->num_altsetting数* 打印每一个接口的描述符*/for (j = 0; j < intf->num_altsetting; j++) {interface = &intf->altsetting[j].desc;printk("    Interface Descriptor altsetting %d:\n""      bLength             %5u\n""      bDescriptorType     %5u\n""      bInterfaceNumber    %5u\n""      bAlternateSetting   %5u\n""      bNumEndpoints       %5u\n""      bInterfaceClass     %5u\n""      bInterfaceSubClass  %5u\n""      bInterfaceProtocol  %5u\n""      iInterface          %5u\n",j, interface->bLength, interface->bDescriptorType, interface->bInterfaceNumber, interface->bAlternateSetting, interface->bNumEndpoints, interface->bInterfaceClass,interface->bInterfaceSubClass, interface->bInterfaceProtocol,interface->iInterface);/*!* 打印端点描述符*/for (m = 0; m < interface->bNumEndpoints; m++) {endpoint = &intf->altsetting[j].endpoint[m].desc;dump_endpoint(endpoint);}}/*!* 打印设备本身自定义的描述符,二进制形式*/buffer = intf->cur_altsetting->extra;buflen = intf->cur_altsetting->extralen;printk("extra buffer of interface %d:\n", cnt-1);k = 0;desc_cnt = 0;while (k < buflen){desc_len = buffer[k];printk("extra desc %d: ", desc_cnt);for (l = 0; l < desc_len; l++, k++) {printk("%02x ", buffer[k]);}desc_cnt++;printk("\n");}interface = &intf->cur_altsetting->desc;    /**< 获取接口描述符 *//*!*  解析VideoControl Interface接口下的自定义描述符*/if ((buffer[1] == USB_DT_CS_INTERFACE) && (interface->bInterfaceSubClass == 1))parse_videocontrol_interface(intf, buffer, buflen);/*!*  解析VideoStreaming Interface接口下的自定义描述符*/if ((buffer[1] == USB_DT_CS_INTERFACE) && (interface->bInterfaceSubClass == 2))parse_videostreaming_interface(intf, buffer, buflen);              }return 0;
}static void myuvc_disconnect(struct usb_interface *intf)
{static int cnt = 0;printk("myuvc_disconnect : cnt = %d\n", cnt++);
}struct usb_driver myuvc_driver = {.name        = "myuvcvideo",.probe       = myuvc_probe,.disconnect = myuvc_disconnect,.id_table  = myuvc_ids,
};static int myuvc_init(void)
{int result;result = usb_register(&myuvc_driver);if (result == 0)printk("USB register error!\n");return result;
}static void myuvc_cleanup(void)
{usb_deregister(&myuvc_driver);
}module_init(myuvc_init);
module_exit(myuvc_cleanup);
MODULE_LICENSE("GPL")

2、Makefile编写

KERN_DIR = /usr/src/linux-headers-4.13.0-41-genericall:make -C $(KERN_DIR) M=`pwd` modules clean:make -C $(KERN_DIR) M=`pwd` modules cleanrm -rf modules.orderobj-m  += myuvc.o

3、运行与分析

3.1 运行

执行make生成驱动文件并插入USB摄像头之后,卸载原先虚拟机的摄像头驱动sudo rmmod uvcvideo装载新驱动sudo insmod myuvc.ko,后执行dmesg > dmesg.txt把信息输出到txt中

3.2 分析

整理后的dmesg.txt信息如下:
由于代码中支持列表填写了VideoControl InterfaceVideoStreaming Interface,且摄像头都支持,所以会打印两次设备描述符(两次打印的是同一个设备描述符),实际使用只需要保留第一个

对于使用的摄像头

  • 有一个配置: bDeviceProtocol 1
  • 该配置下有4个接口:bNumInterfaces 4
  • 打印所有接口下的端点信息
  • 打印并解析了VideoControl InterfaceVideoStreaming Interface接口下的自定义配置
 myuvc_disconnect : cnt = 0myuvc_disconnect : cnt = 1myuvc_probe : cnt = 0Device Descriptor:bLength                18bDescriptorType         1bcdUSB               2.00bDeviceClass          239 bDeviceSubClass         2 bDeviceProtocol         1 bMaxPacketSize0        64idVendor           0x1b3b idProduct          0x2977 bcdDevice            1.0aiManufacturer           0iProduct                0iSerial                 0bNumConfigurations      1Configuration Descriptor 0:bLength                 9bDescriptorType         2wTotalLength          492bNumInterfaces          4bConfigurationValue     1iConfiguration          0bmAttributes         0x80Interface Association:bLength                 8bDescriptorType        11bFirstInterface         0bInterfaceCount         2bFunctionClass         14bFunctionSubClass       3bFunctionProtocol       0iFunction               0Interface Descriptor altsetting 0:bLength                 9bDescriptorType         4bInterfaceNumber        0bAlternateSetting       0bNumEndpoints           1bInterfaceClass        14bInterfaceSubClass      1bInterfaceProtocol      0iInterface              0Endpoint Descriptor:bLength                 7bDescriptorType      5bEndpointAddress  0x81  EP 1 INbmAttributes          3Transfer Type           InterruptSynch Type             NoneUsage Type              DatawMaxPacketSize      0x0040  1x 64 bytesbInterval               6extra buffer of interface 0:extra desc 0: 0d 24 01 00 01 4d 00 80 8d 5b 00 01 01 extra desc 1: 12 24 02 01 01 02 00 00 01 00 03 00 01 00 03 80 2a 00 extra desc 2: 0b 24 05 03 01 00 00 02 3f 05 00 extra desc 3: 1a 24 06 04 3a ab 91 99 ef b2 c9 48 8f e9 8f e3 63 47 71 d0 08 01 03 01 0f 00 extra desc 4: 09 24 03 02 01 01 00 04 00 VideoControl Interface Descriptor:bLength                13bDescriptorType        36bDescriptorSubtype      1 (HEADER)bcdUVC               1.00wTotalLength           77dwClockFrequency        6.000000MHzbInCollection           1baInterfaceNr( 0)       1VideoControl Interface Descriptor:bLength                18bDescriptorType        36bDescriptorSubtype      2 (INPUT_TERMINAL)bTerminalID             1wTerminalType      0x0201bAssocTerminal          0iTerminal               0wObjectiveFocalLengthMin      1wObjectiveFocalLengthMax      3wOcularFocalLength            1bControlSize                  3bmControls           0x00002a80Iris (Absolute)Zoom (Absolute)PanTilt (Absolute)Roll (Absolute)VideoControl Interface Descriptor:bLength                11bDescriptorType        36bDescriptorSubtype      5 (PROCESSING_UNIT)Warning: Descriptor too shortbUnitID                 3bSourceID               1wMaxMultiplier          0bControlSize            2bmControls     0x0000053fBrightnessContrastHueSaturationSharpnessGammaBacklight CompensationPower Line FrequencyiProcessing             0bmVideoStandards     0x1aNTSC - 525/60SECAM - 625/50NTSC - 625/50VideoControl Interface Descriptor:bLength                26bDescriptorType        36bDescriptorSubtype      6 (EXTENSION_UNIT)bUnitID                 4guidExtensionCode         {3aab9199-efb2-c948-8fe9-8fe3634771d0}bNumControl             8bNrPins                 1baSourceID( 0)          3bControlSize            1bmControls( 0)       0x0fiExtension              0VideoControl Interface Descriptor:bLength                 9bDescriptorType        36bDescriptorSubtype      3 (OUTPUT_TERMINAL)bTerminalID             2wTerminalType      0x0101bAssocTerminal          0bSourceID               4iTerminal               0myuvc_probe : cnt = 1Device Descriptor:bLength                18bDescriptorType         1bcdUSB               2.00bDeviceClass          239 bDeviceSubClass         2 bDeviceProtocol         1 bMaxPacketSize0        64idVendor           0x1b3b idProduct          0x2977 bcdDevice            1.0aiManufacturer           0iProduct                0iSerial                 0bNumConfigurations      1Configuration Descriptor 0:bLength                 9bDescriptorType         2wTotalLength          492bNumInterfaces          4bConfigurationValue     1iConfiguration          0bmAttributes         0x80Interface Association:bLength                 8bDescriptorType        11bFirstInterface         0bInterfaceCount         2bFunctionClass         14bFunctionSubClass       3bFunctionProtocol       0iFunction               0Interface Descriptor altsetting 0:bLength                 9bDescriptorType         4bInterfaceNumber        1bAlternateSetting       0bNumEndpoints           0bInterfaceClass        14bInterfaceSubClass      2bInterfaceProtocol      0iInterface              0Interface Descriptor altsetting 1:bLength                 9bDescriptorType         4bInterfaceNumber        1bAlternateSetting       1bNumEndpoints           1bInterfaceClass        14bInterfaceSubClass      2bInterfaceProtocol      0iInterface              0Endpoint Descriptor:bLength                 7bDescriptorType      5bEndpointAddress  0x82  EP 2 INbmAttributes          5Transfer Type           IsochronousSynch Type               AsynchronousUsage Type              DatawMaxPacketSize      0x0080  1x 128 bytesbInterval              1Interface Descriptor altsetting 2:bLength                 9bDescriptorType         4bInterfaceNumber        1bAlternateSetting       2bNumEndpoints           1bInterfaceClass        14bInterfaceSubClass      2bInterfaceProtocol      0iInterface              0Endpoint Descriptor:bLength                 7bDescriptorType      5bEndpointAddress  0x82  EP 2 INbmAttributes          5Transfer Type           IsochronousSynch Type               AsynchronousUsage Type              DatawMaxPacketSize      0x0100  1x 256 bytesbInterval              1Interface Descriptor altsetting 3:bLength                 9bDescriptorType         4bInterfaceNumber        1bAlternateSetting       3bNumEndpoints           1bInterfaceClass        14bInterfaceSubClass      2bInterfaceProtocol      0iInterface              0Endpoint Descriptor:bLength                 7bDescriptorType      5bEndpointAddress  0x82  EP 2 INbmAttributes          5Transfer Type           IsochronousSynch Type               AsynchronousUsage Type              DatawMaxPacketSize      0x0200  1x 512 bytesbInterval              1Interface Descriptor altsetting 4:bLength                 9bDescriptorType         4bInterfaceNumber        1bAlternateSetting       4bNumEndpoints           1bInterfaceClass        14bInterfaceSubClass      2bInterfaceProtocol      0iInterface              0Endpoint Descriptor:bLength                 7bDescriptorType      5bEndpointAddress  0x82  EP 2 INbmAttributes          5Transfer Type           IsochronousSynch Type               AsynchronousUsage Type              DatawMaxPacketSize      0x0258  1x 600 bytesbInterval              1Interface Descriptor altsetting 5:bLength                 9bDescriptorType         4bInterfaceNumber        1bAlternateSetting       5bNumEndpoints           1bInterfaceClass        14bInterfaceSubClass      2bInterfaceProtocol      0iInterface              0Endpoint Descriptor:bLength                 7bDescriptorType      5bEndpointAddress  0x82  EP 2 INbmAttributes          5Transfer Type           IsochronousSynch Type               AsynchronousUsage Type              DatawMaxPacketSize      0x0320  1x 800 bytesbInterval              1Interface Descriptor altsetting 6:bLength                 9bDescriptorType         4bInterfaceNumber        1bAlternateSetting       6bNumEndpoints           1bInterfaceClass        14bInterfaceSubClass      2bInterfaceProtocol      0iInterface              0Endpoint Descriptor:bLength                 7bDescriptorType      5bEndpointAddress  0x82  EP 2 INbmAttributes          5Transfer Type           IsochronousSynch Type               AsynchronousUsage Type              DatawMaxPacketSize      0x03bc  1x 956 bytesbInterval              1extra buffer of interface 1:extra desc 0: 0e 24 01 01 79 00 82 00 02 00 00 01 01 00 extra desc 1: 0b 24 06 01 03 00 01 00 00 00 00 extra desc 2: 1e 24 07 01 01 80 02 e0 01 00 28 23 00 00 28 23 00 00 2c 01 00 15 16 05 00 01 15 16 05 00 extra desc 3: 1e 24 07 02 01 40 01 f0 00 00 ca 08 00 00 ca 08 00 00 4b 00 00 15 16 05 00 01 15 16 05 00 extra desc 4: 1e 24 07 03 01 a0 00 78 00 80 32 02 00 80 32 02 00 c0 12 00 00 15 16 05 00 01 15 16 05 00 extra desc 5: 06 24 0d 01 01 04 VideoStreaming Interface Descriptor:bLength                          14bDescriptorType                 36bDescriptorSubtype                   1 (INPUT_HEADER)bNumFormats                         1wTotalLength                   121bEndPointAddress               130bmInfo                               0bTerminalLink                        2bStillCaptureMethod              0bTriggerSupport                  0bTriggerUsage                        1bControlSize                     1bmaControls( 0)                   11VideoStreaming Interface Descriptor:bLength                            11bDescriptorType                 36bDescriptorSubtype                   6 (FORMAT_MJPEG)bFormatIndex                        1bNumFrameDescriptors             3bFlags                               0Fixed-size samples: NobDefaultFrameIndex                  1bAspectRatioX                        0bAspectRatioY                        0bmInterlaceFlags              0x00Interlaced stream or variable: NoFields per frame: 1 fieldsField 1 first: NoField pattern: Field 1 onlybCopyProtect                        0VideoStreaming Interface Descriptor:bLength                          30bDescriptorType                 36bDescriptorSubtype                   7 (FRAME_MJPEG)bFrameIndex                      1bmCapabilities                    0x01Still image supportedwWidth                            640wHeight                        480dwMinBitRate               2304000dwMaxBitRate               2304000dwMaxVideoFrameBufferSize        76800dwDefaultFrameInterval          333333bFrameIntervalType                   1dwFrameInterval( 0)          333333VideoStreaming Interface Descriptor:bLength                         30bDescriptorType                 36bDescriptorSubtype                   7 (FRAME_MJPEG)bFrameIndex                      2bmCapabilities                    0x01Still image supportedwWidth                            320wHeight                        240dwMinBitRate                576000dwMaxBitRate                576000dwMaxVideoFrameBufferSize        19200dwDefaultFrameInterval          333333bFrameIntervalType                   1dwFrameInterval( 0)          333333VideoStreaming Interface Descriptor:bLength                         30bDescriptorType                 36bDescriptorSubtype                   7 (FRAME_MJPEG)bFrameIndex                      3bmCapabilities                    0x01Still image supportedwWidth                            160wHeight                        120dwMinBitRate                144000dwMaxBitRate                144000dwMaxVideoFrameBufferSize         4800dwDefaultFrameInterval          333333bFrameIntervalType                   1dwFrameInterval( 0)          333333VideoStreaming Interface Descriptor:bLength                          6bDescriptorType                 36bDescriptorSubtype                  13 (COLORFORMAT)bColorPrimaries                  1 (BT.709,sRGB)bTransferCharacteristics         1 (BT.709)bMatrixCoefficients              4 (SMPTE 170M (BT.601))

第三阶段应用层——2.4 视频监控—从0写USB摄像头驱动(1)-描述符的分析与打印相关推荐

  1. 第三阶段应用层——2.7 视频监控—从零写CMOS摄像头驱动

    视频监控-从零写CMOS摄像头驱动 硬件平台:韦东山嵌入式Linxu开发板(S3C2440.v3),OV7740摄像头 软件平台:运行于VMware Workstation 12 Player下Ubu ...

  2. 第三阶段应用层——2.6 视频监控—CMOS摄像头的硬件原理

    视频监控-CMOS摄像头的硬件原理 硬件平台:韦东山嵌入式Linxu开发板(S3C2440.v3) 软件平台:运行于VMware Workstation 12 Player下UbuntuLTS16.0 ...

  3. Video4Linux下USB摄像头驱动和视频采集的实现

    1 引言 多媒体通信技术的发展为信息的获取和传输提供了丰富的手段,视频采集是其中不可缺少的重要组成部分.视频采集的手段多种多样,随着人们对降低系统成本和提高可靠性的迫切需求,基于嵌入式的视频采集系统成 ...

  4. 正点原子imx6ull开发板视频监控项目实战系列5: 摄像头(V4L2)和声卡(ALSA)接口简介

    1.摄像头: 1).对于不同的摄像头,有不同的接口方式,eg:USB,CMOS等,但是他们都遵循同样的标准-V4L2. 所以,不同的APP可以使用同样的API访问不同硬件接口的摄像头. 2).摄像头参 ...

  5. 基于3G网络的汽车防盗报警系统视频监控设计

    引言随着第三代移动通信网络的成熟发展,基于移动通信网络的视频监控技术的应用越来越广泛.本文基于3G网络覆盖率高.可靠性强.传输速率快的优势,设计实现汽车防盗报警系统的可视监控.本设计在现有的电子式汽车 ...

  6. 网络视频监控P2P解决方案

    一.摘要 本文分析了日益增长的民用级别家庭和个人网络视频监控市场的需求特点,并给出了一种经济可行易于大规模部署的P2P解决方案.由于篇幅有限,本文只给出了方案的思路,未对更深入的技术细节做详细的论述, ...

  7. 视频监控P2P解决方案

    一.摘要 本文分析了日益增长的民用级别家庭和个人网络视频监控市场的需求特点,并给出了一种经济可行易于大规模部署的P2P解决方案. 由于篇幅有限,本文只给出了方案的思路,未对更深入的技术细节做详细的论述 ...

  8. 一、视频监控技术概述

    前言 校招结束后,实验室要求一直在搞论文,11月底提交完成.开始按照沈工列的读书清单看看书.海康威视从安防起家,虽然自己搞的是计算机视觉算法,出于对领域业务的熟悉,也需要读读相关的书. 说来也很有意思 ...

  9. 《森林防火视频监控系统技术规范》解读

    <森林防火视频监控系统技术规范>(以下简称"标准")经过全国森林消防标准化技术委员会和编制组及相关单位两年的不懈努力,于2016年1月18日由国家林业局发布,于2016 ...

最新文章

  1. 2019-7-29 考试总结
  2. iOS:app直播---采集篇
  3. MySQL 视图的基础操作
  4. 【LeetCode笔记】剑指Offer 41. 数据流中的中位数(Java、堆、优先队列、知识点)
  5. 四大组件---Activity
  6. Dropout也能自动化了,谷歌Quoc Le等人利用强化学习自动找寻模型专用Dropout
  7. 如何为团队选择有用的增量进度衡量标准
  8. 活与死、回调以及面向对象设计
  9. 开源文本编辑器Vim的作者Bram Moolenaar推出了新的编程语言Zimbu.doc
  10. 手把手教你写电商爬虫-第四课 淘宝网商品爬虫自动JS渲染
  11. 啊D注入工具是一种主要用于SQL的注入工具
  12. EPIVAN | 基于预训练和注意力机制的启动子增强子相互作用预测
  13. 凌晨 3 点不回家:成年人的世界不是他们说的那样子
  14. 小程序 滚动加载分页处理【亲测有效】
  15. PS制作五彩抽象人像
  16. python比c语言好学吗-总算找到c语言和python哪个好学
  17. Sourcetree 使用详解
  18. 《革命之路-目击众神死亡的草原上野花一片》
  19. 预测|2019软件测试职业发展趋势,附BAT、TMD入职指南!
  20. int 等数据类型的含义

热门文章

  1. 基线_基线性能模型-Persistence Model for Forest
  2. 二叉排序树binary_sort_tree
  3. SpringBoot使用junit测试
  4. 如何增强英语听力能力?
  5. C++ 类的成员变量
  6. 【黑金动力社区】发布MS531第二版 MS531-II
  7. iOS开发面试的43道最新面试题,让你稳拿大厂offer
  8. 第一季:12Linux常用服务类相关命令【Java面试题】
  9. 看看你是如何被QQ监视的!
  10. 昨天被一个老乞丐给教训了一番