1.uvc驱动模块入口
- module_init(uvc_init); //1.模块入口
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;
- }
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,
- },
- };
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类
- {}
- };
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;
- }
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]; //输入设备设备节点路径
- };
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 静态图像数据端点描述符
-->(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
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; //特殊厂商处理则直接跳过标准处理
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指针
- }
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;
//判断描述符是否有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;
- }
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控制数组指针
- };
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
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_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)
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); //初始化控制位图
- }
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;
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_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_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_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;
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
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;
- }
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)分配内存空间
1.uvc驱动模块入口
- module_init(uvc_init); //1.模块入口
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;
- }
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,
- },
- };
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类
- {}
- };
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;
- }
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]; //输入设备设备节点路径
- };
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 静态图像数据端点描述符
-->(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
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; //特殊厂商处理则直接跳过标准处理
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指针
- }
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;
//判断描述符是否有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;
- }
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控制数组指针
- };
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
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_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)
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); //初始化控制位图
- }
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;
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_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_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_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;
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
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;
- }
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)分配内存空间
- module_init(uvc_init); //1.模块入口
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;
- }
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,
- },
- };
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类
- {}
- };
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;
- }
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]; //输入设备设备节点路径
- };
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 静态图像数据端点描述符
-->(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
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; //特殊厂商处理则直接跳过标准处理
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指针
- }
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;
//判断描述符是否有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;
- }
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控制数组指针
- };
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
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_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)
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); //初始化控制位图
- }
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;
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_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_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_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;
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
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;
- }
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)分配内存空间