uvc摄像头代码解析2

来源:互联网 发布:申通快递单打印软件 编辑:程序博客网 时间:2024/03/29 16:44
1.uvc驱动模块入口
module_init(uvc_init);  //1.模块入口
2.初始化函数
    static int __init uvc_init(void)    // 2.初始化函数      {          int result;          result = usb_register(&uvc_driver.driver);  // 3.注册usb设备驱动(usb摄像头设备)          if (result == 0)    //注册失败              printk(KERN_INFO DRIVER_DESC " (" DRIVER_VERSION ")\n");          return result;      }  
3.注册usb设备驱动(usb摄像头设备)

3.1 usb摄像头驱动

    struct uvc_driver uvc_driver = {    // 3.1 usb摄像头设备          .driver = {              .name       = "uvcvideo",              .probe      = uvc_probe,    // 4. probe方法              .disconnect = uvc_disconnect,              .suspend    = uvc_suspend,              .resume     = uvc_resume,              .reset_resume   = uvc_reset_resume,              .id_table   = uvc_ids,      //3.2 支持的设备id列表              .supports_autosuspend = 1,          },      };  
3.2 支持的设备id列表uvc_ids
    static struct usb_device_id uvc_ids[] = {          /* Genius eFace 2025 */          { .match_flags      = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,            .idVendor     = 0x0458,            .idProduct        = 0x706e,            .bInterfaceClass  = USB_CLASS_VIDEO,  //uvc接口类 0x0e            .bInterfaceSubClass   = 1,            .bInterfaceProtocol   = 0,            .driver_info      = UVC_QUIRK_PROBE_MINMAX },          ...          ...          ...          /* SiGma Micro USB Web Camera */          { .match_flags      = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,            .idVendor     = 0x1c4f,            .idProduct        = 0x3000,            .bInterfaceClass  = USB_CLASS_VIDEO,            .bInterfaceSubClass   = 1,            .bInterfaceProtocol   = 0,            .driver_info      = UVC_QUIRK_PROBE_MINMAX | UVC_QUIRK_IGNORE_SELECTOR_UNIT },          /* Generic USB Video Class */   //通用usb视频类          { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },  //匹配方法:uvc类          {}      };  
4.probe方法
    static int uvc_probe(struct usb_interface *intf,const struct usb_device_id *id)      {          struct usb_device *udev = interface_to_usbdev(intf);    //通过usb接口获取usb设备          struct uvc_device *dev; //声明uvc设备          int ret;          if (id->idVendor && id->idProduct)    //有厂商id和商品id(知名设备)              uvc_trace(UVC_TRACE_PROBE, "Probing known UVC device %s (%04x:%04x)\n", udev->devpath, id->idVendor,id->idProduct);          else                                //通用uvc设备              uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n",udev->devpath);          /* Allocate memory for the device and initialize it. */          if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL)   //分配uvc设备内存              return -ENOMEM;          INIT_LIST_HEAD(&dev->entities);  //初始化entities(实体)链表 Terminal或Unit          INIT_LIST_HEAD(&dev->chains);    //初始化chains(链)链表          INIT_LIST_HEAD(&dev->streams);   //初始化streams(视频流)链表          atomic_set(&dev->nstreams, 0);          atomic_set(&dev->users, 0);          atomic_set(&dev->nmappings, 0);          dev->udev = usb_get_dev(udev);   //捆绑usb设备,并增加其引用计数          dev->intf = usb_get_intf(intf);  //捆绑usb接口,并增加其引用计数          dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;    //获取usb接口描述符接口数          dev->quirks = (uvc_quirks_param == -1) ? id->driver_info : uvc_quirks_param;          if (udev->product != NULL)   //存在产品名              strlcpy(dev->name, udev->product, sizeof dev->name);   //设置uvc设备名字为其产品名          else                        //通用的uvc设备名              snprintf(dev->name, sizeof dev->name,"UVC Camera (%04x:%04x)",le16_to_cpu(udev->descriptor.idVendor),le16_to_cpu(udev->descriptor.idProduct));          /* Parse the Video Class control descriptor. */          if (uvc_parse_control(dev) < 0) {    //-->5 uvc解析usb视频类控制描述符              uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC descriptors.\n");              goto error;          }          uvc_printk(KERN_INFO, "Found UVC %u.%02x device %s (%04x:%04x)\n",dev->uvc_version >> 8, dev->uvc_version & 0xff,              udev->product ? udev->product : "<unnamed>",le16_to_cpu(udev->descriptor.idVendor),le16_to_cpu(udev->descriptor.idProduct));          if (dev->quirks != id->driver_info) {              uvc_printk(KERN_INFO, "Forcing device quirks to 0x%x by module parameter for testing purpose.\n", dev->quirks);              uvc_printk(KERN_INFO, "Please report required quirks to the linux-uvc-devel mailing list.\n");          }          /* Initialize controls. */          if (uvc_ctrl_init_device(dev) < 0)   //8.uvc初始化控制              goto error;          /* Scan the device for video chains. */          if (uvc_scan_device(dev) < 0)    //10.uvc扫描视频链              goto error;          /* Register video devices. */          if (uvc_register_chains(dev) < 0)    //11.uvc注册视频设备              goto error;          /* Save our data pointer in the interface data. */          usb_set_intfdata(intf, dev);    //设置uvc设备为usb接口的数据          /* Initialize the interrupt URB. */          if ((ret = uvc_status_init(dev)) < 0) {  //12 uvc设备状态初始化              uvc_printk(KERN_INFO, "Unable to initialize the status endpoint (%d), status interrupt will not be supported.\n", ret);          }          uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n");          usb_enable_autosuspend(udev);   //使能自动挂起          return 0;      error:          uvc_unregister_video(dev);          return -ENODEV;      }  
4.1 uvc设备结构体
    struct uvc_device {          struct usb_device *udev;    //usb设备指针          struct usb_interface *intf; //usb接口指针          unsigned long warnings;          __u32 quirks;          int intfnum;    //接口数          char name[32];  //设备名          enum uvc_device_state state;    //uvc设备状态          atomic_t users;          atomic_t nmappings;          /* Video control interface */          __u16 uvc_version;  //UVC协议版本          __u32 clock_frequency;  //时钟频率          struct list_head entities;  //uvc实体链表头(挂着uvc设备的Terminal和Unit)          struct list_head chains;    //uvc视频链链表头          /* Video Streaming interfaces */          struct list_head streams;   //uvc视频流链表头          atomic_t nstreams;//uvc视频流个数          /* Status Interrupt Endpoint */          struct usb_host_endpoint *int_ep;   //usb_host_endpoint对象          struct urb *int_urb;    //中断urb          __u8 *status;   //uvc设备状态标志          struct input_dev *input;    //输入设备          char input_phys[64];    //输入设备设备节点路径      };  

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

     参考USB_Video_Class_1.1.pdf中 Figure 3-1 Video Camera Descriptor Layout Example

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

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


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

usb描述符的框架图

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

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

第一步找出Terminal和Unit的(bTerminalID/bUnitID)
IT(1)
OT(2)
XU(4)
XU(5)
PU(3)
第二步从OT输出Terminal开始分析
OT(2)的bSourceID=5
所以XU(5)->OT(2)
XU(5)的bNrPins=1所以只有一个输入baSourceID( 0)=4
所以XU(4)->XU(5)->OT(2)
XU(4)的bNrPins=1所以只有一个输入baSourceID( 0)=3
所以PU(3)->XU(4)->XU(5)->OT(2)
PU(3)的bSourceID=1
所以IT(1)->PU(3)->XU(4)->XU(5)->OT(2)

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

 

 5 uvc解析usb视频类控制描述符

    static int uvc_parse_control(struct uvc_device *dev)      {          struct usb_host_interface *alts = dev->intf->cur_altsetting;  //获取当前usb_host_interface          unsigned char *buffer = alts->extra; //额外描述符          int buflen = alts->extralen; //额外描述符长度          int ret;          /* 解析默认的交替设置,正如UVC标准协议定义的单个交替设置,默认是交替设置0(Alt.Setting 0)*/          while (buflen > 2) {              if (uvc_parse_vendor_control(dev, buffer, buflen) || buffer[1] != USB_DT_CS_INTERFACE)  //5.1解析厂商特殊控制                  goto next_descriptor;   //特殊厂商处理则直接跳过标准处理              if ((ret = uvc_parse_standard_control(dev, buffer, buflen)) < 0) //5.2.解析uvc标准控制                  return ret;      next_descriptor:    //buffer[0]是bLength描述符长度              buflen -= buffer[0];    //调整buflen长度              buffer += buffer[0];    //调整buffer指针          }  
//判断描述符是否有1个端点  if (alts->desc.bNumEndpoints == 1 && !(dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)) {      struct usb_host_endpoint *ep = &alts->endpoint[0];   //获取usb_host_endpoint      struct usb_endpoint_descriptor *desc = &ep->desc;    //获取端点描述符      //判断是否中断输入端点      if (usb_endpoint_is_int_in(desc) && le16_to_cpu(desc->wMaxPacketSize) >= 8 && desc->bInterval != 0) {          uvc_trace(UVC_TRACE_DESCR, "Found a Status endpoint (addr %02x).\n", desc->bEndpointAddress);          dev->int_ep = ep;      }  }  return 0; 
5.1 解析厂商特殊控制 (特殊厂商处理返回1,不是返回0)
    static int uvc_parse_vendor_control(struct uvc_device *dev,const unsigned char *buffer, int buflen)      {          struct usb_device *udev = dev->udev;          struct usb_host_interface *alts = dev->intf->cur_altsetting;  //获取usb_host_interface          struct uvc_entity *unit;          unsigned int n, p;          int handled = 0;    //返回值 默认为0          switch (le16_to_cpu(dev->udev->descriptor.idVendor)) {          case 0x046d:        /* Logitech 罗技*/              ...              handled = 1;    //特殊厂商处理则返回1              break;          }          return handled;      }  
5.1.1 uvc实体结构体
    struct uvc_entity { //uvc实体          struct list_head list;  //实体链表头          struct list_head chain; //视频链链表头          __u8 id;    //实体id          __u16 type; //实体类型          char name[64];  //实体名          union {              struct {                  __u16 wObjectiveFocalLengthMin;                  __u16 wObjectiveFocalLengthMax;                  __u16 wOcularFocalLength;                  __u8  bControlSize; //控制位域大小                  __u8  *bmControls;  //控制位图指针              } camera;       //输入Terminal UVC_ITT_CAMERA              struct {                  __u8  bControlSize; //控制位域大小                  __u8  *bmControls;  //控制位图指针                  __u8  bTransportModeSize;                  __u8  *bmTransportModes;              } media;        //输入Terminal UVC_ITT_MEDIA_TRANSPORT_INPUT              struct {              } output;       //输出Terminal              //处理Unit              struct {                  __u16 wMaxMultiplier;                  __u8  bControlSize; //控制位域大小                  __u8  *bmControls;  //控制位图指针                  __u8  bmVideoStandards;              } processing;   //处理Unit              //选择器Unit              struct {              } selector;     //选择器Unit              //扩展Unit              struct {                  __u8  guidExtensionCode[16];                  __u8  bNumControls;                  __u8  bControlSize; //控制位域大小                  __u8  *bmControls;  //控制位图指针                  __u8  *bmControlsType;              } extension;    //扩展Unit          };          __u8 bNrInPins; //输入引脚数          __u8 *baSourceID;   //第一个输入引脚ID(Terminal/Unit ID)          unsigned int ncontrols; //uvc控制个数          struct uvc_control *controls;   //ucv控制数组指针      };  

5.2 解析uvc标准控制
    static int uvc_parse_standard_control(struct uvc_device *dev,const unsigned char *buffer, int buflen)      {          struct usb_device *udev = dev->udev; //获取usb设备          struct uvc_entity *unit, *term; //uvc实体Unit或Terminal          struct usb_interface *intf; //usb接口          struct usb_host_interface *alts = dev->intf->cur_altsetting;  //获取当前usb接口配置描述符          unsigned int i, n, p, len;          __u16 type;                    switch (buffer[2]) {    //buffer[2]存放bDescriptorSubType  
Table 3-3 Class-specific VC Interface Header Descriptor
    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;  
Table 3-4 Input Terminal Descriptor
    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)  
Table 3-6 Camera Terminal Descriptor
    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;  
Table 3-5 Output Terminal Descriptor
    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;  
Table 3-7 Selector Unit Descriptor
    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;  
Table 3-8 Processing Unit Descriptor
    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;  
Table 3-9 Extension Unit Descriptor
    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 厂商特殊代码id          unit->extension.bNumControls = buffer[20];   //Unit的控件数          memcpy(unit->baSourceID, &buffer[22], p);    //复制Unit ID到baSourceID          unit->extension.bControlSize = buffer[22+p]; //bControlSize 控制位域大小          unit->extension.bmControls = (__u8 *)unit + sizeof *unit;    //bmControls控制位图指针          memcpy(unit->extension.bmControls, &buffer[23+p], n);    //初始化控制位图          if (buffer[23+p+n] != 0)    //设置扩展Unit实体名              usb_string(udev, buffer[23+p+n], unit->name,sizeof unit->name);          else              sprintf(unit->name, "Extension %u", buffer[3]);          list_add_tail(&unit->list, &dev->entities);   //添加uvc实体到uvc实体链表中          break;      default:          uvc_trace(UVC_TRACE_DESCR, "Found an unknown CS_INTERFACE descriptor (%u)\n", buffer[2]);          break;      }      return 0;  

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

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


5.2.2 分配uvc实体

static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id,unsigned int num_pads, unsigned int extra_size)

    case VC_INPUT_TERMINAL(n=bControlSize控制位域长度,p=bmTransportModesSize 传输模式位域大小)      term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3],1, n + p); //输入Terminal只有一个pad      case VC_OUTPUT_TERMINAL      term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3],1, 0);    //输出Terminal只有一个pad      case VC_SELECTOR_UNIT:(p=Unit输入引脚数)      unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0);            //选择Unit有p个输入pad,1个输出pad      case VC_PROCESSING_UNIT(n=bControlSize控制位域长度)      unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n);                //处理Unit只有1个输入pad,1个输出pad      case VC_EXTENSION_UNIT(n=bControlSize控制位域长度,p=Unit输入引脚数)      unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n);            //扩展Unit有p个输入pad,1个输出pad  
这里的pad可以理解为规范书上说的pin,画了个圈圈那个叫做"pad"
    static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id,unsigned int num_pads, unsigned int extra_size)      {          struct uvc_entity *entity;          unsigned int num_inputs;          unsigned int size;          num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1;    //输入Terminal个数=pad个数-1个输出Terminal          size = sizeof(*entity) + extra_size + num_inputs;   //uvc实体大小+额外尺寸+输入Ternimal个数          entity = kzalloc(size, GFP_KERNEL); //分配uvc实体内存          if (entity == NULL)              return NULL;          entity->id = id; //设置uvc实体id          entity->type = type; //设置uvc实体类型          entity->bNrInPins = num_inputs;  //设置uvc实体输入Terminal个数          entity->baSourceID = ((__u8 *)entity) + sizeof(*entity) + extra_size;    //Ternimal ID指针          return entity;      }  
这里extra_size是给uvc实体的联合体中的*指针变量(*bmControls、*bmTransportModes;)分配内存空间,而num_inputs是给*baSourceID(指向输入Terminal ID)分配内存空间
0 0
原创粉丝点击