您的位置:首页 > 编程语言

uvc摄像头代码解析之描述符

2014-11-11 17:30 555 查看


1.uvc驱动模块入口

module_init(uvc_init);	//1.模块入口


2.初始化函数
static int __init uvc_init(void)	// 2.初始化函数
{
int result;
result = usb_register(&uvc_driver.driver);	// 3.注册usb设备驱动(usb摄像头设备)
if (result == 0)	//注册失败
printk(KERN_INFO DRIVER_DESC " (" DRIVER_VERSION ")\n");
return result;
}


3.注册usb设备驱动(usb摄像头设备)

3.1 usb摄像头驱动
struct uvc_driver uvc_driver = {	// 3.1 usb摄像头设备
.driver = {
.name		= "uvcvideo",
.probe		= uvc_probe,	// 4. probe方法
.disconnect	= uvc_disconnect,
.suspend	= uvc_suspend,
.resume		= uvc_resume,
.reset_resume	= uvc_reset_resume,
.id_table	= uvc_ids,		//3.2 支持的设备id列表
.supports_autosuspend = 1,
},
};


3.2 支持的设备id列表uvc_ids
static struct usb_device_id uvc_ids[] = {
/* Genius eFace 2025 */
{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
.idVendor		= 0x0458,
.idProduct		= 0x706e,
.bInterfaceClass	= USB_CLASS_VIDEO,	//uvc接口类 0x0e
.bInterfaceSubClass	= 1,
.bInterfaceProtocol	= 0,
.driver_info		= UVC_QUIRK_PROBE_MINMAX },
...
...
...
/* SiGma Micro USB Web Camera */
{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
.idVendor		= 0x1c4f,
.idProduct		= 0x3000,
.bInterfaceClass	= USB_CLASS_VIDEO,
.bInterfaceSubClass	= 1,
.bInterfaceProtocol	= 0,
.driver_info		= UVC_QUIRK_PROBE_MINMAX | UVC_QUIRK_IGNORE_SELECTOR_UNIT },
/* Generic USB Video Class */	//通用usb视频类
{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },	//匹配方法:uvc类
{}
};


4.probe方法
static int uvc_probe(struct usb_interface *intf,const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);	//通过usb接口获取usb设备
struct uvc_device *dev;	//声明uvc设备
int ret;
if (id->idVendor && id->idProduct)	//有厂商id和商品id(知名设备)
uvc_trace(UVC_TRACE_PROBE, "Probing known UVC device %s (%04x:%04x)\n", udev->devpath, id->idVendor,id->idProduct);
else								//通用uvc设备
uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n",udev->devpath);
/* Allocate memory for the device and initialize it. */
if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL)	//分配uvc设备内存
return -ENOMEM;
INIT_LIST_HEAD(&dev->entities);	//初始化entities(实体)链表 Terminal或Unit
INIT_LIST_HEAD(&dev->chains);	//初始化chains(链)链表
INIT_LIST_HEAD(&dev->streams);	//初始化streams(视频流)链表
atomic_set(&dev->nstreams, 0);
atomic_set(&dev->users, 0);
atomic_set(&dev->nmappings, 0);
dev->udev = usb_get_dev(udev);	//捆绑usb设备,并增加其引用计数
dev->intf = usb_get_intf(intf);	//捆绑usb接口,并增加其引用计数
dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;	//获取usb接口描述符接口数
dev->quirks = (uvc_quirks_param == -1) ? id->driver_info : uvc_quirks_param;
if (udev->product != NULL)	//存在产品名
strlcpy(dev->name, udev->product, sizeof dev->name);	//设置uvc设备名字为其产品名
else						//通用的uvc设备名
snprintf(dev->name, sizeof dev->name,"UVC Camera (%04x:%04x)",le16_to_cpu(udev->descriptor.idVendor),le16_to_cpu(udev->descriptor.idProduct));
/* Parse the Video Class control descriptor. */
if (uvc_parse_control(dev) < 0) {	//-->5 uvc解析usb视频类控制描述符
uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC descriptors.\n");
goto error;
}
uvc_printk(KERN_INFO, "Found UVC %u.%02x device %s (%04x:%04x)\n",dev->uvc_version >> 8, dev->uvc_version & 0xff,
udev->product ? udev->product : "<unnamed>",le16_to_cpu(udev->descriptor.idVendor),le16_to_cpu(udev->descriptor.idProduct));
if (dev->quirks != id->driver_info) {
uvc_printk(KERN_INFO, "Forcing device quirks to 0x%x by module parameter for testing purpose.\n", dev->quirks);
uvc_printk(KERN_INFO, "Please report required quirks to the linux-uvc-devel mailing list.\n");
}
/* Initialize controls. */
if (uvc_ctrl_init_device(dev) < 0)	//8.uvc初始化控制
goto error;
/* Scan the device for video chains. */
if (uvc_scan_device(dev) < 0)	//10.uvc扫描视频链
goto error;
/* Register video devices. */
if (uvc_register_chains(dev) < 0)	//11.uvc注册视频设备
goto error;
/* Save our data pointer in the interface data. */
usb_set_intfdata(intf, dev);	//设置uvc设备为usb接口的数据
/* Initialize the interrupt URB. */
if ((ret = uvc_status_init(dev)) < 0) {	//12 uvc设备状态初始化
uvc_printk(KERN_INFO, "Unable to initialize the status endpoint (%d), status interrupt will not be supported.\n", ret);
}
uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n");
usb_enable_autosuspend(udev);	//使能自动挂起
return 0;
error:
uvc_unregister_video(dev);
return -ENODEV;
}


4.1 uvc设备结构体
struct uvc_device {
struct usb_device *udev;	//usb设备指针
struct usb_interface *intf;	//usb接口指针
unsigned long warnings;
__u32 quirks;
int intfnum;	//接口数
char name[32];	//设备名
enum uvc_device_state state;	//uvc设备状态
atomic_t users;
atomic_t nmappings;
/* Video control interface */
__u16 uvc_version;	//UVC协议版本
__u32 clock_frequency;	//时钟频率
struct list_head entities;	//uvc实体链表头(挂着uvc设备的Terminal和Unit)
struct list_head chains;	//uvc视频链链表头
/* Video Streaming interfaces */
struct list_head streams;	//uvc视频流链表头
atomic_t nstreams;//uvc视频流个数
/* Status Interrupt Endpoint */
struct usb_host_endpoint *int_ep;	//usb_host_endpoint对象
struct urb *int_urb;	//中断urb
__u8 *status;	//uvc设备状态标志
struct input_dev *input;	//输入设备
char input_phys[64];	//输入设备设备节点路径
};




4.2 uvc协议标准上的描述符布局



-->(Interface Association Descript)IDA接口描述符
-->标准VC接口描述符	--------------------------------VC(video control)
-->uvc类视频接口描述符(header)-->输入Terminal接口描述符-->处理Unit接口描述符-->编码Unit接口描述符-->输出Terminal接口描述符
-->标准中断端点描述符
-->uvc类中断端点描述符
-->标准VS接口描述符	--------------------------------VS(video streaming) Alt.Setting 0
-->uvc类视频接口描述符(header)-->format负荷格式描述符-->若干frame-->静态图像帧格式描述符
-->uvc类视频接口描述符(header)-->format负荷格式描述符-->若干frame-->静态图像帧格式描述符->颜色匹配描述符
...(1...n)
-->Bulk-in 静态图像数据端点描述符
-->标准VS接口描述符	--------------------------------VS(video streaming) Alt.Setting 1
-->标准同步输入视频端点描述符
-->Bulk-in 静态图像数据端点描述符
...(1...n)
-->标准VS接口描述符	--------------------------------VS(video streaming) Alt.Setting n
-->标准同步输入视频端点描述符
-->Bulk-in 静态图像数据端点描述符


这些布局是可变的 但大体布局是这样,下面两张图也是典型的布局





具体分析的时候可以利用lsubs工具打印所有描述符来分析

usb描述符的框架图



输入命令lsusb -d 0c45:62f1 -v

Bus 001 Device 002: ID 0c45:62f1 Microdia 	//总线 设备ID
Device Descriptor:							//设备描述符
bLength                18
bDescriptorType         1
bcdUSB               2.00
bDeviceClass          239 Miscellaneous Device
bDeviceSubClass         2 ?
bDeviceProtocol         1 Interface Association
bMaxPacketSize0        64
idVendor           0x0c45 Microdia
idProduct          0x62f1
bcdDevice            1.00
iManufacturer           2 Sonix Technology Co., Ltd.
iProduct                1 USB 2.0 Camera
iSerial                 0
bNumConfigurations      1
Configuration Descriptor:					//配置描述符
bLength                 9
bDescriptorType         2
wTotalLength          697
bNumInterfaces          4
bConfigurationValue     1
iConfiguration          0
bmAttributes         0x80
(Bus Powered)
MaxPower              500mA
Interface Association:					//3.6 Interface Association Descriptor
bLength                 8
bDescriptorType        11
bFirstInterface         0
bInterfaceCount         2
bFunctionClass         14 Video
bFunctionSubClass       3 Video Interface Collection
bFunctionProtocol       0
iFunction               5 USB Camera
Interface Descriptor:					//Table 3-2 Standard VC Interface Descriptor
bLength                 9
bDescriptorType         4
bInterfaceNumber        0
bAlternateSetting       0
bNumEndpoints           1
bInterfaceClass        14 Video
bInterfaceSubClass      1 Video Control
bInterfaceProtocol      0
iInterface              5 USB Camera
VideoControl Interface Descriptor:	//Table 3-3 Class-specific VC Interface Header Descriptor
bLength                13
bDescriptorType        36
bDescriptorSubtype      1 (HEADER)
bcdUVC               1.00
wTotalLength          103
dwClockFrequency       15.000000MHz
bInCollection           1
baInterfaceNr( 0)       1
VideoControl Interface Descriptor:	//Table 3-5 Output Terminal Descriptor
bLength                 9
bDescriptorType        36
bDescriptorSubtype      3 (OUTPUT_TERMINAL)
bTerminalID             2
wTerminalType      0x0101 USB Streaming
bAssocTerminal          0
bSourceID               5
iTerminal               0
VideoControl Interface Descriptor:	//Table 3-10 Extension Unit Descriptor
bLength                26
bDescriptorType        36
bDescriptorSubtype      6 (EXTENSION_UNIT)
bUnitID                 4
guidExtensionCode         {7033f028-1163-2e4a-ba2c-6890eb334016}
bNumControl             8
bNrPins                 1
baSourceID( 0)          3
bControlSize            1
bmControls( 0)       0x0f
iExtension              0
VideoControl Interface Descriptor:	//Table 3-10 Extension Unit Descriptor
bLength                26
bDescriptorType        36
bDescriptorSubtype      6 (EXTENSION_UNIT)
bUnitID                 5
guidExtensionCode         {3fae1228-d7bc-114e-a357-6f1edef7d61d}
bNumControl             8
bNrPins                 1
baSourceID( 0)          4
bControlSize            1
bmControls( 0)       0xff
iExtension              0
VideoControl Interface Descriptor:	//Table 3-6 Camera Terminal Descriptor
bLength                18
bDescriptorType        36
bDescriptorSubtype      2 (INPUT_TERMINAL)
bTerminalID             1
wTerminalType      0x0201 Camera Sensor
bAssocTerminal          0
iTerminal               0
wObjectiveFocalLengthMin      0
wObjectiveFocalLengthMax      0
wOcularFocalLength            0
bControlSize                  3
bmControls           0x00000000
VideoControl Interface Descriptor:	//Table 3-8 Processing Unit Descriptor
bLength                11
bDescriptorType        36
bDescriptorSubtype      5 (PROCESSING_UNIT)
Warning: Descriptor too short
bUnitID                 3
bSourceID               1
wMaxMultiplier          0
bControlSize            2
bmControls     0x0000053f
Brightness
Contrast
Hue
Saturation
Sharpness
Gamma
Backlight Compensation
Power Line Frequency
iProcessing             0
bmVideoStandards     0x 0
Endpoint Descriptor:					//Table 3-11 Standard VC Interrupt Endpoint Descriptor
bLength                 7
bDescriptorType         5
bEndpointAddress     0x83  EP 3 IN
bmAttributes            3
Transfer Type            Interrupt
Synch Type               None
Usage Type               Data
wMaxPacketSize     0x0010  1x 16 bytes
bInterval               6
Interface Descriptor:					//Table 3-13 Standard VS Interface Descriptor
bLength                 9
bDescriptorType         4
bInterfaceNumber        1
bAlternateSetting       0
bNumEndpoints           0
bInterfaceClass        14 Video
bInterfaceSubClass      2 Video Streaming
bInterfaceProtocol      0
iInterface              0
VideoStreaming Interface Descriptor:		//Table 3-14 Class-specific VS Interface Input Header Descriptor
bLength                            14
bDescriptorType                    36
bDescriptorSubtype                  1 (INPUT_HEADER)
bNumFormats                         1
wTotalLength                      323
bEndPointAddress                  129
bmInfo                              0
bTerminalLink                       2
bStillCaptureMethod                 2
bTriggerSupport                     1
bTriggerUsage                       1
bControlSize                        1
bmaControls( 0)                    27
VideoStreaming Interface Descriptor:		//Table 3-1 Uncompressed Video Format Descriptor
bLength                            27
bDescriptorType                    36
bDescriptorSubtype                  4 (FORMAT_UNCOMPRESSED)
bFormatIndex                        1
bNumFrameDescriptors                5
guidFormat                            {59555932-0000-1000-8000-00aa00389b71}
bBitsPerPixel                      16
bDefaultFrameIndex                  1
bAspectRatioX                       0
bAspectRatioY                       0
bmInterlaceFlags                 0x00
Interlaced stream or variable: No
Fields per frame: 1 fields
Field 1 first: No
Field pattern: Field 1 only
bCopyProtect                      0
VideoStreaming Interface Descriptor:		//Table 3-2 Uncompressed Video Frame Descriptors
bLength                            50
bDescriptorType                    36
bDescriptorSubtype                  5 (FRAME_UNCOMPRESSED)
bFrameIndex                         1
bmCapabilities                   0x00
Still image unsupported
wWidth                            640
wHeight                           480
dwMinBitRate                 24576000
dwMaxBitRate                147456000
dwMaxVideoFrameBufferSize      614400
dwDefaultFrameInterval         333333
bFrameIntervalType                  6
dwFrameInterval( 0)            333333
dwFrameInterval( 1)            400000
dwFrameInterval( 2)            500000
dwFrameInterval( 3)            666666
dwFrameInterval( 4)           1000000
dwFrameInterval( 5)           2000000
VideoStreaming Interface Descriptor:		//Table 3-2 Uncompressed Video Frame Descriptors
bLength                            50
bDescriptorType                    36
bDescriptorSubtype                  5 (FRAME_UNCOMPRESSED)
bFrameIndex                         2
bmCapabilities                   0x00
Still image unsupported
wWidth                            352
wHeight                           288
dwMinBitRate                  8110080
dwMaxBitRate                 48660480
dwMaxVideoFrameBufferSize      202752
dwDefaultFrameInterval         333333
bFrameIntervalType                  6
dwFrameInterval( 0)            333333
dwFrameInterval( 1)            400000
dwFrameInterval( 2)            500000
dwFrameInterval( 3)            666666
dwFrameInterval( 4)           1000000
dwFrameInterval( 5)           2000000
VideoStreaming Interface Descriptor:		//Table 3-2 Uncompressed Video Frame Descriptors
bLength                            50
bDescriptorType                    36
bDescriptorSubtype                  5 (FRAME_UNCOMPRESSED)
bFrameIndex                         3
bmCapabilities                   0x00
Still image unsupported
wWidth                            320
wHeight                           240
dwMinBitRate                  6144000
dwMaxBitRate                 36864000
dwMaxVideoFrameBufferSize      153600
dwDefaultFrameInterval         333333
bFrameIntervalType                  6
dwFrameInterval( 0)            333333
dwFrameInterval( 1)            400000
dwFrameInterval( 2)            500000
dwFrameInterval( 3)            666666
dwFrameInterval( 4)           1000000
dwFrameInterval( 5)           2000000
VideoStreaming Interface Descriptor:		//Table 3-2 Uncompressed Video Frame Descriptors
bLength                            50
bDescriptorType                    36
bDescriptorSubtype                  5 (FRAME_UNCOMPRESSED)
bFrameIndex                         4
bmCapabilities                   0x00
Still image unsupported
wWidth                            176
wHeight                           144
dwMinBitRate                  2027520
dwMaxBitRate                 12165120
dwMaxVideoFrameBufferSize       50688
dwDefaultFrameInterval         333333
bFrameIntervalType                  6
dwFrameInterval( 0)            333333
dwFrameInterval( 1)            400000
dwFrameInterval( 2)            500000
dwFrameInterval( 3)            666666
dwFrameInterval( 4)           1000000
dwFrameInterval( 5)           2000000
VideoStreaming Interface Descriptor:		//Table 3-2 Uncompressed Video Frame Descriptors
bLength                            50
bDescriptorType                    36
bDescriptorSubtype                  5 (FRAME_UNCOMPRESSED)
bFrameIndex                         5
bmCapabilities                   0x00
Still image unsupported
wWidth                            160
wHeight                           120
dwMinBitRate                  1536000
dwMaxBitRate                  9216000
dwMaxVideoFrameBufferSize       38400
dwDefaultFrameInterval         333333
bFrameIntervalType                  6
dwFrameInterval( 0)            333333
dwFrameInterval( 1)            400000
dwFrameInterval( 2)            500000
dwFrameInterval( 3)            666666
dwFrameInterval( 4)           1000000
dwFrameInterval( 5)           2000000
VideoStreaming Interface Descriptor:		//Table 3-18 Still Image Frame Descriptor
bLength                            26
bDescriptorType                    36
bDescriptorSubtype                  3 (STILL_IMAGE_FRAME)
bEndpointAddress                    0
bNumImageSizePatterns               5
wWidth( 0)                        640
wHeight( 0)                       480
wWidth( 1)                        352
wHeight( 1)                       288
wWidth( 2)                        320
wHeight( 2)                       240
wWidth( 3)                        176
wHeight( 3)                       144
wWidth( 4)                        160
wHeight( 4)                       120
bNumCompressionPatterns             5
VideoStreaming Interface Descriptor:		//Table 3-19 Color Matching Descriptor
bLength                             6
bDescriptorType                    36
bDescriptorSubtype                 13 (COLORFORMAT)
bColorPrimaries                     1 (BT.709,sRGB)
bTransferCharacteristics            1 (BT.709)
bMatrixCoefficients                 4 (SMPTE 170M (BT.601))
Interface Descriptor:						//Table 3-13 Standard VS Interface Descriptor
bLength                 9
bDescriptorType         4
bInterfaceNumber        1
bAlternateSetting       1
bNumEndpoints           1
bInterfaceClass        14 Video
bInterfaceSubClass      2 Video Streaming
bInterfaceProtocol      0
iInterface              0
Endpoint Descriptor:
bLength                 7
bDescriptorType         5
bEndpointAddress     0x81  EP 1 IN
bmAttributes            5
Transfer Type            Isochronous
Synch Type               Asynchronous
Usage Type               Data
wMaxPacketSize     0x0080  1x 128 bytes
bInterval               1
Interface Descriptor:						//Table 3-13 Standard VS Interface Descriptor
bLength                 9
bDescriptorType         4
bInterfaceNumber        1
bAlternateSetting       2
bNumEndpoints           1
bInterfaceClass        14 Video
bInterfaceSubClass      2 Video Streaming
bInterfaceProtocol      0
iInterface              0
Endpoint Descriptor:
bLength                 7
bDescriptorType         5
bEndpointAddress     0x81  EP 1 IN
bmAttributes            5
Transfer Type            Isochronous
Synch Type               Asynchronous
Usage Type               Data
wMaxPacketSize     0x0100  1x 256 bytes
bInterval               1
Interface Descriptor:						//Table 3-13 Standard VS Interface Descriptor
bLength                 9
bDescriptorType         4
bInterfaceNumber        1
bAlternateSetting       3
bNumEndpoints           1
bInterfaceClass        14 Video
bInterfaceSubClass      2 Video Streaming
bInterfaceProtocol      0
iInterface              0
Endpoint Descriptor:						//Table 3-20 Standard VS Isochronous Video Data Endpoint Descriptor
bLength                 7
bDescriptorType         5
bEndpointAddress     0x81  EP 1 IN
bmAttributes            5
Transfer Type            Isochronous
Synch Type               Asynchronous
Usage Type               Data
wMaxPacketSize     0x0320  1x 800 bytes
bInterval               1
Interface Descriptor:						//Table 3-13 Standard VS Interface Descriptor
bLength                 9
bDescriptorType         4
bInterfaceNumber        1
bAlternateSetting       4
bNumEndpoints           1
bInterfaceClass        14 Video
bInterfaceSubClass      2 Video Streaming
bInterfaceProtocol      0
iInterface              0
Endpoint Descriptor:						//Table 3-20 Standard VS Isochronous Video Data Endpoint Descriptor
bLength                 7
bDescriptorType         5
bEndpointAddress     0x81  EP 1 IN
bmAttributes            5
Transfer Type            Isochronous
Synch Type               Asynchronous
Usage Type               Data
wMaxPacketSize     0x0b20  2x 800 bytes
bInterval               1
Interface Descriptor:						//Table 3-13 Standard VS Interface Descriptor
bLength                 9
bDescriptorType         4
bInterfaceNumber        1
bAlternateSetting       5
bNumEndpoints           1
bInterfaceClass        14 Video
bInterfaceSubClass      2 Video Streaming
bInterfaceProtocol      0
iInterface              0
Endpoint Descriptor:						//Table 3-20 Standard VS Isochronous Video Data Endpoint Descriptor
bLength                 7
bDescriptorType         5
bEndpointAddress     0x81  EP 1 IN
bmAttributes            5
Transfer Type            Isochronous
Synch Type               Asynchronous
Usage Type               Data
wMaxPacketSize     0x1320  3x 800 bytes
bInterval               1
Interface Descriptor:						//Table 3-13 Standard VS Interface Descriptor
bLength                 9
bDescriptorType         4
bInterfaceNumber        1
bAlternateSetting       6
bNumEndpoints           1
bInterfaceClass        14 Video
bInterfaceSubClass      2 Video Streaming
bInterfaceProtocol      0
iInterface              0
Endpoint Descriptor:						//Table 3-20 Standard VS Isochronous Video Data Endpoint Descriptor
bLength                 7
bDescriptorType         5
bEndpointAddress     0x81  EP 1 IN
bmAttributes            5
Transfer Type            Isochronous
Synch Type               Asynchronous
Usage Type               Data
wMaxPacketSize     0x1400  3x 1024 bytes
bInterval               1
////////////////////////////////////////////////////////////////////////////音频部分
Interface Association:
bLength                 8
bDescriptorType        11
bFirstInterface         2
bInterfaceCount         2
bFunctionClass          1 Audio
bFunctionSubClass       0
bFunctionProtocol       0
iFunction               4 USB Microphone
Interface Descriptor:
bLength                 9
bDescriptorType         4
bInterfaceNumber        2
bAlternateSetting       0
bNumEndpoints           0
bInterfaceClass         1 Audio
bInterfaceSubClass      1 Control Device
bInterfaceProtocol      0
iInterface              4 USB Microphone
AudioControl Interface Descriptor:
bLength                 9
bDescriptorType        36
bDescriptorSubtype      1 (HEADER)
bcdADC               1.00
wTotalLength           41
bInCollection           1
baInterfaceNr( 0)       3
AudioControl Interface Descriptor:
bLength                12
bDescriptorType        36
bDescriptorSubtype      2 (INPUT_TERMINAL)
bTerminalID             1
wTerminalType      0x0201 Microphone
bAssocTerminal          0
bNrChannels             1
wChannelConfig     0x0000
iChannelNames           0
iTerminal               0
AudioControl Interface Descriptor:
bLength                11
bDescriptorType        36
bDescriptorSubtype      6 (FEATURE_UNIT)
bUnitID                 2
bSourceID               1
bControlSize            2
bmaControls( 0)      0x01
bmaControls( 0)      0x00
Mute
bmaControls( 1)      0x02
bmaControls( 1)      0x00
Volume
iFeature                0
AudioControl Interface Descriptor:
bLength                 9
bDescriptorType        36
bDescriptorSubtype      3 (OUTPUT_TERMINAL)
bTerminalID             3
wTerminalType      0x0101 USB Streaming
bAssocTerminal          0
bSourceID               2
iTerminal               0
Interface Descriptor:
bLength                 9
bDescriptorType         4
bInterfaceNumber        3
bAlternateSetting       0
bNumEndpoints           0
bInterfaceClass         1 Audio
bInterfaceSubClass      2 Streaming
bInterfaceProtocol      0
iInterface              0
Interface Descriptor:
bLength                 9
bDescriptorType         4
bInterfaceNumber        3
bAlternateSetting       1
bNumEndpoints           1
bInterfaceClass         1 Audio
bInterfaceSubClass      2 Streaming
bInterfaceProtocol      0
iInterface              0
AudioStreaming Interface Descriptor:
bLength                 7
bDescriptorType        36
bDescriptorSubtype      1 (AS_GENERAL)
bTerminalLink           3
bDelay                  1 frames
wFormatTag              1 PCM
AudioStreaming Interface Descriptor:
bLength                29
bDescriptorType        36
bDescriptorSubtype      2 (FORMAT_TYPE)
bFormatType             1 (FORMAT_TYPE_I)
bNrChannels             1
bSubframeSize           2
bBitResolution         16
bSamFreqType            7 Discrete
tSamFreq[ 0]         8000
tSamFreq[ 1]        11025
tSamFreq[ 2]        16000
tSamFreq[ 3]        22050
tSamFreq[ 4]        24000
tSamFreq[ 5]        44100
tSamFreq[ 6]        48000
Endpoint Descriptor:
bLength                 9
bDescriptorType         5
bEndpointAddress     0x84  EP 4 IN
bmAttributes            5
Transfer Type            Isochronous
Synch Type               Asynchronous
Usage Type               Data
wMaxPacketSize     0x0190  1x 400 bytes
bInterval               4
bRefresh                0
bSynchAddress           0
AudioControl Endpoint Descriptor:
bLength                 7
bDescriptorType        37
bDescriptorSubtype      1 (EP_GENERAL)
bmAttributes         0x01
Sampling Frequency
bLockDelayUnits         0 Undefined
wLockDelay              0 Undefined
/////////////////////////////////////////////////////////////////
Device Qualifier (for other device speed):	//设备限定符
bLength                10
bDescriptorType         6
bcdUSB               2.00
bDeviceClass          239 Miscellaneous Device
bDeviceSubClass         2 ?
bDeviceProtocol         1 Interface Association
bMaxPacketSize0        64
bNumConfigurations      1
Device Status:     0x0002
(Bus Powered)
Remote Wakeup Enabled


可以通过描述符布局,分析出摄像头框架

第一步找出Terminal和Unit的(bTerminalID/bUnitID)

IT(1)

OT(2)

XU(4)

XU(5)

PU(3)

第二步从OT输出Terminal开始分析

OT(2)的bSourceID=5

所以XU(5)->OT(2)

XU(5)的bNrPins=1所以只有一个输入baSourceID( 0)=4

所以XU(4)->XU(5)->OT(2)

XU(4)的bNrPins=1所以只有一个输入baSourceID( 0)=3

所以PU(3)->XU(4)->XU(5)->OT(2)

PU(3)的bSourceID=1

所以IT(1)->PU(3)->XU(4)->XU(5)->OT(2)



4.3 probe方法初始化uvc设备结构体对象



5 uvc解析usb视频类控制描述符
static int uvc_parse_control(struct uvc_device *dev)
{
struct usb_host_interface *alts = dev->intf->cur_altsetting;	//获取当前usb_host_interface
unsigned char *buffer = alts->extra;	//额外描述符
int buflen = alts->extralen;	//额外描述符长度
int ret;
/* 解析默认的交替设置,正如UVC标准协议定义的单个交替设置,默认是交替设置0(Alt.Setting 0)*/
while (buflen > 2) {
if (uvc_parse_vendor_control(dev, buffer, buflen) || buffer[1] != USB_DT_CS_INTERFACE)	//5.1解析厂商特殊控制
goto next_descriptor;	//特殊厂商处理则直接跳过标准处理


}


if ((ret = uvc_parse_standard_control(dev, buffer, buflen)) < 0)	//5.2.解析uvc标准控制
return ret;
next_descriptor:	//buffer[0]是bLength描述符长度
buflen -= buffer[0];	//调整buflen长度
buffer += buffer[0];	//调整buffer指针
}




//判断描述符是否有1个端点
if (alts->desc.bNumEndpoints == 1 && !(dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)) {
struct usb_host_endpoint *ep = &alts->endpoint[0];	//获取usb_host_endpoint
struct usb_endpoint_descriptor *desc = &ep->desc;	//获取端点描述符
//判断是否中断输入端点
if (usb_endpoint_is_int_in(desc) && le16_to_cpu(desc->wMaxPacketSize) >= 8 && desc->bInterval != 0) {
uvc_trace(UVC_TRACE_DESCR, "Found a Status endpoint (addr %02x).\n", desc->bEndpointAddress);
dev->int_ep = ep;
}
}
return 0;
}


5.1 解析厂商特殊控制 (特殊厂商处理返回1,不是返回0)
static int uvc_parse_vendor_control(struct uvc_device *dev,const unsigned char *buffer, int buflen)
{
struct usb_device *udev = dev->udev;
struct usb_host_interface *alts = dev->intf->cur_altsetting;	//获取usb_host_interface
struct uvc_entity *unit;
unsigned int n, p;
int handled = 0;	//返回值 默认为0
switch (le16_to_cpu(dev->udev->descriptor.idVendor)) {
case 0x046d:		/* Logitech 罗技*/
...
handled = 1;	//特殊厂商处理则返回1
break;
}
return handled;
}


5.1.1 uvc实体结构体
struct uvc_entity {	//uvc实体
struct list_head list;	//实体链表头
struct list_head chain;	//视频链链表头
__u8 id;	//实体id
__u16 type;	//实体类型
char name[64];	//实体名
union {
struct {
__u16 wObjectiveFocalLengthMin;
__u16 wObjectiveFocalLengthMax;
__u16 wOcularFocalLength;
__u8  bControlSize;	//控制位域大小
__u8  *bmControls;	//控制位图指针
} camera;		//输入Terminal UVC_ITT_CAMERA
struct {
__u8  bControlSize;	//控制位域大小
__u8  *bmControls;	//控制位图指针
__u8  bTransportModeSize;
__u8  *bmTransportModes;
} media;		//输入Terminal UVC_ITT_MEDIA_TRANSPORT_INPUT
struct {
} output;		//输出Terminal
//处理Unit
struct {
__u16 wMaxMultiplier;
__u8  bControlSize;	//控制位域大小
__u8  *bmControls;	//控制位图指针
__u8  bmVideoStandards;
} processing;	//处理Unit
//选择器Unit
struct {
} selector;		//选择器Unit
//扩展Unit
struct {
__u8  guidExtensionCode[16];
__u8  bNumControls;
__u8  bControlSize;	//控制位域大小
__u8  *bmControls;	//控制位图指针
__u8  *bmControlsType;
} extension;	//扩展Unit
};
__u8 bNrInPins;	//输入引脚数
__u8 *baSourceID;	//第一个输入引脚ID(Terminal/Unit ID)
unsigned int ncontrols;	//uvc控制个数
struct uvc_control *controls;	//ucv控制数组指针
};


5.2 解析uvc标准控制
static int uvc_parse_standard_control(struct uvc_device *dev,const unsigned char *buffer, int buflen)
{
struct usb_device *udev = dev->udev;	//获取usb设备
struct uvc_entity *unit, *term;	//uvc实体Unit或Terminal
struct usb_interface *intf;	//usb接口
struct usb_host_interface *alts = dev->intf->cur_altsetting;	//获取当前usb接口配置描述符
unsigned int i, n, p, len;
__u16 type;

switch (buffer[2]) {	//buffer[2]存放bDescriptorSubType




case UVC_VC_HEADER:	//vc 接口头部描述符
n = buflen >= 12 ? buffer[11] : 0;	//bInCollection 视频流接口数
if (buflen < 12 || buflen < 12 + n) {
uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol interface %d HEADER error\n", udev->devnum,alts->desc.bInterfaceNumber);
return -EINVAL;
}
dev->uvc_version = get_unaligned_le16(&buffer[3]);	//bcdUVC
dev->clock_frequency = get_unaligned_le32(&buffer[7]);	//获取时钟频率
/* Parse all USB Video Streaming interfaces. 解析所有USB视频接口*/
for (i = 0; i < n; ++i) {	//遍历视频流接口
intf = usb_ifnum_to_if(udev, buffer[12+i]);	//baInterfaceNr(n) 获取视频流对应的usb接口
if (intf == NULL) {
uvc_trace(UVC_TRACE_DESCR, "device %d interface %d doesn't exists\n",udev->devnum, i);
continue;
}
uvc_parse_streaming(dev, intf);	//6.uvc解析uvc视频流
}
break;




case UVC_VC_INPUT_TERMINAL:	//UVC输入Terminal
if (buflen < 8) {	//检验buflen长度
uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol interface %d INPUT_TERMINAL error\n",udev->devnum, alts->desc.bInterfaceNumber);
return -EINVAL;
}
/* Make sure the terminal type MSB is not null, otherwise it could be confused with a unit.*/
type = get_unaligned_le16(&buffer[4]);	//获取Terminal类型(ITT_ VENDOR_SPECIFIC/ITT_CAMERA/ITT_MEDIA_TRANSPORT_INPUT)
if ((type & 0xff00) == 0) {	//错误类型
uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol interface %d INPUT_TERMINAL %d has invalid type 0x%04x, skipping\n", udev->devnum,alts->desc.bInterfaceNumber,buffer[3], type);
return 0;
}
n = 0;
p = 0;
len = 8;	//标准长度(0~7)




if (type == UVC_ITT_CAMERA) {	//摄像头传感器	(speciafication.pdf P67)
n = buflen >= 15 ? buffer[14] : 0;	//bControlSize 控制位域大小
len = 15;
}
else if (type == UVC_ITT_MEDIA_TRANSPORT_INPUT) {	//连续的媒体 (USB_Video_Transport_1.5.pdf P11)
n = buflen >= 9 ? buffer[8] : 0;	//bControlSize 控制位域大小
p = buflen >= 10 + n ? buffer[9+n] : 0;	//bmTransportModesSize 传输模式位域大小
len = 10;
}
if (buflen < len + n + p) {	//检验buflen长度是否合适
uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol interface %d INPUT_TERMINAL error\n",udev->devnum, alts->desc.bInterfaceNumber);
return -EINVAL;
}
term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3],1, n + p);	//分配uvc实体 buffer[3]是实体ID
if (term == NULL)
return -ENOMEM;
if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) {	//摄像头传感器
term->camera.bControlSize = n;	//bControlSize 控制位域大小
term->camera.bmControls = (__u8 *)term + sizeof *term;	//bmControls 控制位图指针
term->camera.wObjectiveFocalLengthMin = get_unaligned_le16(&buffer[8]);	// wObjectiveFocalLengthMin 焦点长度最小值
term->camera.wObjectiveFocalLengthMax = get_unaligned_le16(&buffer[10]);	//wObjectiveFocalLengthMax 焦点长度最大值
term->camera.wOcularFocalLength = get_unaligned_le16(&buffer[12]);	//wOcularFocalLength  Ocular焦距
memcpy(term->camera.bmControls, &buffer[15], n);	//初始化控制位图
}




else if (UVC_ENTITY_TYPE(term) == UVC_ITT_MEDIA_TRANSPORT_INPUT) {	//连续的媒体
term->media.bControlSize = n;	//bControlSize 控制位域大小
term->media.bmControls = (__u8 *)term + sizeof *term;	//bmControls控制位图指针
term->media.bTransportModeSize = p;	//bTransportModeSize 传输模式位域大小
term->media.bmTransportModes = (__u8 *)term + sizeof *term + n;	//bmTransportModes传输模式位图指针
memcpy(term->media.bmControls, &buffer[9], n);	//初始化控制位图
memcpy(term->media.bmTransportModes, &buffer[10+n], p);	//初始化传输模式位图
}
if (buffer[7] != 0)	//设置实体名
usb_string(udev, buffer[7], term->name,sizeof term->name);
else if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA)	//设置Camera Terminal实体名
sprintf(term->name, "Camera %u", buffer[3]);
else if (UVC_ENTITY_TYPE(term) == UVC_ITT_MEDIA_TRANSPORT_INPUT)	//设置Media Terminal实体名
sprintf(term->name, "Media %u", buffer[3]);
else
sprintf(term->name, "Input %u", buffer[3]);
list_add_tail(&term->list, &dev->entities);	//添加uvc实体到uvc实体链表中
break;




case UVC_VC_OUTPUT_TERMINAL:	//UVC输出Terminal
if (buflen < 9) {	//检验buflen长度
uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol interface %d OUTPUT_TERMINAL error\n",udev->devnum, alts->desc.bInterfaceNumber);
return -EINVAL;
}
/* Make sure the terminal type MSB is not null, otherwise it could be confused with a unit.*/
type = get_unaligned_le16(&buffer[4]);	//wTerminalType 输出Terminal类型
if ((type & 0xff00) == 0) {
uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol interface %d OUTPUT_TERMINAL %d has invalid type 0x%04x, skipping\n", udev->devnum,
alts->desc.bInterfaceNumber, buffer[3], type);
return 0;
}
term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3],1, 0);	//分配uvc实体 buffer[3]是实体ID
if (term == NULL)
return -ENOMEM;
memcpy(term->baSourceID, &buffer[7], 1);	//复制Terminal ID到baSourceID
if (buffer[8] != 0)	//设置Terminal实体名
usb_string(udev, buffer[8], term->name,sizeof term->name);
else	//设置output Terminal实体名
sprintf(term->name, "Output %u", buffer[3]);
list_add_tail(&term->list, &dev->entities);	//添加uvc实体到uvc实体链表中
break;




case UVC_VC_SELECTOR_UNIT:	//UVC选择器Unit
p = buflen >= 5 ? buffer[4] : 0;	//Unit输入引脚数
if (buflen < 5 || buflen < 6 + p) {	//检验buflen是否符合
uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol interface %d SELECTOR_UNIT error\n",udev->devnum, alts->desc.bInterfaceNumber);
return -EINVAL;
}
unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0);	//分配uvc实体 buffer[3]是实体ID
if (unit == NULL)
return -ENOMEM;
memcpy(unit->baSourceID, &buffer[5], p);	//复制Unit ID到bSourceID
if (buffer[5+p] != 0)	//设置selector Unit名
usb_string(udev, buffer[5+p], unit->name,sizeof unit->name);
else
sprintf(unit->name, "Selector %u", buffer[3]);
list_add_tail(&unit->list, &dev->entities);	//添加uvc实体到uvc实体链表中
break;




case UVC_VC_PROCESSING_UNIT:	//UVC处理Unit
n = buflen >= 8 ? buffer[7] : 0;	//bControlSize控制位域大小
p = dev->uvc_version >= 0x0110 ? 10 : 9;	//uvc类协议版本
if (buflen < p + n) {		//检验buflen长度是否符合
uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol interface %d PROCESSING_UNIT error\n",udev->devnum, alts->desc.bInterfaceNumber);
return -EINVAL;
}
unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n);	//分配uvc实体 buffer[3]是实体ID
if (unit == NULL)
return -ENOMEM;
memcpy(unit->baSourceID, &buffer[4], 1);	//复制Unit ID到bSourceID
unit->processing.wMaxMultiplier = get_unaligned_le16(&buffer[5]);	//最大数字放大率
unit->processing.bControlSize = buffer[7];	//bControlSize 控制位域大小
unit->processing.bmControls = (__u8 *)unit + sizeof *unit;	//bmControls控制位图指针
memcpy(unit->processing.bmControls, &buffer[8], n);	//初始化控制位图
if (dev->uvc_version >= 0x0110)	//版本大于1.1
unit->processing.bmVideoStandards = buffer[9+n];	//设置视频标准支持位图
if (buffer[8+n] != 0)	//设置处理Unit名
usb_string(udev, buffer[8+n], unit->name,sizeof unit->name);
else
sprintf(unit->name, "Processing %u", buffer[3]);
list_add_tail(&unit->list, &dev->entities);	//添加uvc实体到uvc实体链表中
break;




case UVC_VC_EXTENSION_UNIT:	//UVC扩展Unit
p = buflen >= 22 ? buffer[21] : 0;	//Unit输入引脚数
n = buflen >= 24 + p ? buffer[22+p] : 0;	//bControlSize控制位域长度
if (buflen < 24 + p + n) {	//判断buflen长度是否符合
uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol interface %d EXTENSION_UNIT error\n",udev->devnum, alts->desc.bInterfaceNumber);
return -EINVAL;
}
unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n);	//分配uvc实体 buffer[3]是实体ID
if (unit == NULL)
return -ENOMEM;
memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);	//guidExtensionCode 厂商特殊<span class="wp_keywordlink" style="margin: 0px; padding: 0px; border: 0px; background: transparent;"><a target=_blank href="http://www.xuebuyuan.com/" title="代码" target="_blank" style="text-decoration: none; color: rgb(1, 150, 227);">代码</a></span>id
unit->extension.bNumControls = buffer[20];	//Unit的控件数
memcpy(unit->baSourceID, &buffer[22], p);	//复制Unit ID到baSourceID
unit->extension.bControlSize = buffer[22+p];	//bControlSize 控制位域大小
unit->extension.bmControls = (__u8 *)unit + sizeof *unit;	//bmControls控制位图指针
memcpy(unit->extension.bmControls, &buffer[23+p], n);	//初始化控制位图
if (buffer[23+p+n] != 0)	//设置扩展Unit实体名
usb_string(udev, buffer[23+p+n], unit->name,sizeof unit->name);
else
sprintf(unit->name, "Extension %u", buffer[3]);
list_add_tail(&unit->list, &dev->entities);	//添加uvc实体到uvc实体链表中
break;
default:
uvc_trace(UVC_TRACE_DESCR, "Found an unknown CS_INTERFACE descriptor (%u)\n", buffer[2]);
break;
}
return 0;
}


5.2.1 添加uvc实体到uvc设备的实体链表下

list_add_tail(&term->list, &dev->entities);



5.2.2 分配uvc实体

static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id,unsigned int num_pads, unsigned int extra_size)
case VC_INPUT_TERMINAL(n=bControlSize控制位域长度,p=bmTransportModesSize 传输模式位域大小)
term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3],1, n + p);	//输入Terminal只有一个pad
case VC_OUTPUT_TERMINAL
term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3],1, 0);	//输出Terminal只有一个pad
case VC_SELECTOR_UNIT:(p=Unit输入引脚数)
unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0);			//选择Unit有p个输入pad,1个输出pad
case VC_PROCESSING_UNIT(n=bControlSize控制位域长度)
unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n);				//处理Unit只有1个输入pad,1个输出pad
case VC_EXTENSION_UNIT(n=bControlSize控制位域长度,p=Unit输入引脚数)
unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n);			//扩展Unit有p个输入pad,1个输出pad


这里的pad可以理解为规范书上说的pin,画了个圈圈那个叫做"pad"
static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id,unsigned int num_pads, unsigned int extra_size)
{
struct uvc_entity *entity;
unsigned int num_inputs;
unsigned int size;
num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1;	//输入Terminal个数=pad个数-1个输出Terminal
size = sizeof(*entity) + extra_size + num_inputs;	//uvc实体大小+额外尺寸+输入Ternimal个数
entity = kzalloc(size, GFP_KERNEL);	//分配uvc实体内存
if (entity == NULL)
return NULL;
entity->id = id;	//设置uvc实体id
entity->type = type;	//设置uvc实体类型
entity->bNrInPins = num_inputs;	//设置uvc实体输入Terminal个数
entity->baSourceID = ((__u8 *)entity) + sizeof(*entity) + extra_size;	//Ternimal ID指针
return entity;
}


这里extra_size是给uvc实体的联合体中的*指针变量(*bmControls、*bmTransportModes;)分配内存空间,而num_inputs是给*baSourceID(指向输入Terminal ID)分配内存空间
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: