6. uvc parses the important structure of uvc video stream 6.1 6.1.1 uvc data stream [cpp] struct uvc_streaming {struct list_head list; // struct uvc_device * dev; // uvc device struct video_device * vdev; // V4L2 video device struct uvc_video_chain * chain; // uvc video chain atomic_t active; struct usb_interface * intf; // usb interface device int intfnum; // usb interface No. _ maxpsize; // maximum package size struct uvc_streaming_header; // uvc video stream header enum v4l2_buf_type; // V4L2 buffer type input/output un Signed int nformats; // Number of uvc formats struct uvc_format * format; // uvc format pointer struct uvc_streaming_control ctrl; // uvc Data Stream Control struct uvc_format * cur_format; // The current uvc format pointer struct uvc_frame * cur_frame; // The current uvc frame pointer struct mutex; unsigned int frozen: 1; struct uvc_video_queue; // uvc video queue void (* decode) (struct urb * urb, struct uvc_streaming * video, struct uvc_buffer * buf ); // decoding function struct {_ u8 header [256]; Unsigned int header_size; int skip_payload; _ u32 payload_size; _ u32 hour;} bulk; struct urb * urb [UVC_URBS]; // urb array char * urb_buffer [UVC_URBS]; // urb buffer dma_addr_t urb_dma [UVC_URBS]; // urb DMA buffer unsigned int urb_size; _ u32 sequence; _ u8 last_fid ;}; 6.1.2 uvc format [cpp] struct uvc_format {// uvc format _ u8 type; // type _ u8 index; // index _ u8 bpp; // bits per pixel _ u8 colorspace per pixel; // The color is empty _ U32 fcc; // compression format _ u32 flags; // mark char name [32]; // name unsigned int nframes; // The number of uvc frames included: struct uvc_frame * frame; // uvc frame pointer}; 6.1.3 uvc frame [cpp] struct uvc_frame {// uvc frame _ u8 bFrameIndex; // frame index No. _ u8 bmCapabilities; // uvc frame compatibility _ wWidth; // width _ wHeight; // height _ u32 dwMinBitRate; // latest bit stream _ u32 dwMaxBitRate; // maximum bit stream _ u32 dwMaxVideoFrameBufferSize; // maximum video frame buffer _ u8 bFrameIntervalType; // gap type _ u32 Dwdefaframeframeinterval; // default frame gap _ u32 * dwFrameInterval; // frame gap pointer}; 6.2 uvc_parse_streaming function [cpp] static int uvc_parse_streaming (struct uvc_device * dev, struct usb_interface * intf) {struct uvc_streaming * streaming = NULL; // uvc data stream struct uvc_format * format; // uvc format struct uvc_frame * frame; // uvc frame struct usb_host_interface * alts = & intf-> altsetting [0]; // obtain the first usb _ host_interface (Alt. setting 0) Unsigned char * _ buffer, * buffer = alts-> extra; // get the extra descriptor int _ buflen, buflen = alts-> extralen; // obtain the length of the extra descriptor unsigned int nformats = 0, nframes = 0, nintervals = 0; unsigned int size, I, n, p; _ u32 * interval; _ 2010psize; int ret =-EINVAL; if (intf-> cur_altsetting-> desc. bInterfaceSubClass! = UVC_ SC _VIDEOSTREAMING) {// determines whether the usb interface descriptor subclass is a video data stream interface subclass uvc_trace (UVC_TRACE_DESCR, "device % d interface % d isn't a video streaming interface \ n ", dev-> udev-> devnum, intf-> altsetting [0]. desc. bInterfaceNumber); return-EINVAL;} if (usb_driver_claim_interface (& uvc_driver.driver, intf, dev) {// bind the usb driver and usb interface uvc_trace (UVC_TRACE_DESCR, "device % d interface % d is already claimed \ n", dev-> udev-> devnum, Intf-> altsetting [0]. desc. bInterfaceNumber); return-EINVAL;} streaming = kzarloc (sizeof * streaming, GFP_KERNEL); // allocate uvc data stream memory if (streaming = NULL) {usb_driver_release_interface (& uvc_driver.driver, intf); return-EINVAL;} mutex_init (& streaming-> mutex); streaming-> dev = dev; // bind the uvc data stream to the uvc device streaming-> intf = usb_get_intf (intf); // bind the uvc data stream to the usb interface and add reference count streaming-> intfnum = intf-> cur_altsettin G-> desc. bInterfaceNumber; // set The interface number/* the Pico iMage webcam has its class-specific interface descriptors after The endpoint descriptors. */if (buflen = 0) {// Pico iMage webcam special processing for (I = 0; I <alts-> desc. bNumEndpoints; ++ I) {struct usb_host_endpoint * ep = & alts-> endpoint [I]; if (ep-> extralen = 0) continue; if (ep-> extralen> 2 & ep-> extra [1] = USB_DT_CS_INTERFACE) {uvc_trace (UVC_TRACE_D ESCR, "trying extra data from endpoint % u. \ n ", I); buffer = alts-> endpoint [I]. extra; buflen = alts-> endpoint [I]. extralen; break ;}}/ * Skip the standard interface descriptors. skip the standard interface descriptor */while (buflen> 2 & buffer [1]! = USB_DT_CS_INTERFACE) {buflen-= buffer [0]; buffer + = buffer [0];} if (buflen <= 2) {uvc_trace (UVC_TRACE_DESCR, "no class-specific streaming interface descriptors found. \ n "); goto error;}/* Parse the header descriptor. parse the header Descriptor * // Class-specific VS Interface Input Header Descriptor switch (buffer [2]) {// bDescriptorSubtype case UVC_VS_OUTPUT_HEADER: // output video stream streaming-> type = V4L2_BUF_TY PE_VIDEO_OUTPUT; // set to V4L2 video buf output size = 9; break; case UVC_VS_INPUT_HEADER: // input-type Video Stream streaming-> type = V4L2_BUF_TYPE_VIDEO_CAPTURE; // set to V4L2 video buf input size = 13; break; default: uvc_trace (UVC_TRACE_DESCR, "device % d videostreaming interface % d HEADER descriptor not found. \ n ", dev-> udev-> devnum, alts-> desc. bInterfaceNumber); goto error;} p = buflen> = 4? Buffer [3]: 0; // number of formats in bNumFormats uvc format n = buflen> = size? Buffer [size-1]: 0; // bControlSize controls the bit domain size if (buflen <size + p * n) {// checks whether the buflen length is uvc_trace (UVC_TRACE_DESCR, "device % d videostreaming interface % d HEADER descriptor is invalid. \ n ", dev-> udev-> devnum, alts-> desc. bInterfaceNumber); goto error;} // initialize the uvc video stream header streaming-> header. bNumFormats = p; // number of formats in uvc format streaming-> header. bEndpointAddress = buffer [6]; // endpoint address if (buffer [2] = UVC_VS_INPUT _ HEADER) {// input video stream streaming-> header. bmInfo = buffer [7]; // information Bitmap (compatibility) streaming-> header. bTerminalLink = buffer [8]; // the output of the connection Terminal ID streaming-> header. bStillCaptureMethod = buffer [9]; // Static Image Capturing Method (Method 1, Method 2, Method 3) streaming-> header. bTriggerSupport = buffer [10]; // supports streaming-> header for hardware triggering. bTriggerUsage = buffer [11]; // trigger case} else {streaming-> header. bTerminalLink = buffer [7]; // connected input Ter Minal ID} streaming-> header. bControlSize = n; // control bit domain size streaming-> header. bmaControls = kmemdup (& buffer [size], p * n, GFP_KERNEL); // initialize bmaControls (x) Bitmap (size = number of frames * bit domain size) if (streaming-> header. bmaControls = NULL) {ret =-ENOMEM; goto error;} buflen-= buffer [0]; buffer ++ = buffer [0]; // point to the next descriptor _ buffer = buffer; _ buflen = buflen; // point to the same descriptor. After parsing the vs header, parse the remaining vs descriptor. The first time the descriptor is parsed, calculate the uvc frame, uvc format, and interval, and allocate the memory [cpp]/* Count the format and frame descriptors. calculate the number of format descriptors and frame descriptors */while (_ buflen> 2 & _ buffer [1] = USB_DT_CS_INTERFACE) {switch (_ buffer [2]) {case UVC_VS_FORMAT_UNCOMPRESSED: case UVC_VS_FORMAT_MJPEG: case UVC_VS_FORMAT_FRAME_BASED: nformats ++; break; case UVC_VS_FORMAT_DV:/* DV format has no frame descriptor. we will create a dummy frame descriptor with a dummy frame interval. */nformats ++; nframe S ++; nintervals ++; break; case UVC_VS_FORMAT_MPEG2TS: case UVC_VS_FORMAT_STREAM_BASED: uvc_trace (UVC_TRACE_DESCR, "device % d videostreaming interface % d FORMAT % u is not supported. \ n ", dev-> udev-> devnum, alts-> desc. bInterfaceNumber, _ buffer [2]); break; case UVC_VS_FRAME_UNCOMPRESSED: case UVC_VS_FRAME_MJPEG: nframes ++; if (_ buflen> 25) nintervals + = _ buffer [25]? _ Buffer [25]: 3; break; case UVC_VS_FRAME_FRAME_BASED: nframes ++; if (_ buflen> 21) nintervals + = _ buffer [21]? _ Buffer [21]: 3; break;} // calculates the number and interval of uvc frames and uvc formats _ buflen-= _ buffer [0]; _ buffer + = _ buffer [0]; // jump to the next descriptor} if (nformats = 0) {uvc_trace (UVC_TRACE_DESCR, "device % d videostreaming interface % d has no supported formats defined. \ n ", dev-> udev-> devnum, alts-> desc. bInterfaceNumber); goto error ;} // Number of uvc formats * uvc format size + uvc frame * uvc frame size + interval * interval size = nformats * sizeof * format + nframes * sizeof * frame + nintervals * sizeof * interval; format = kzarloc (size, GFP_KERNEL); // allocate the uvc format and uvc frame memory if (format = NULL) {ret =-ENOMEM; goto error ;} frame = (struct uvc_frame *) & format [nformats]; // The uvc frame is stored behind the uvc format array interval = (_ u32 *) & frame [nframes]; // streaming-> format = format after the frame; // The uvc video stream bundle the uvc format Structure streaming-> nformats = nformats; // uvc format number second resolution descriptor [cpp]/* Parse the format descriptors. parse format descriptor */while (buflen> 2 & buffer [1] = USB_DT_CS_INTERFACE) {switch (buffer [2]) {// bDescriptorSubtype descriptor type case UVC_VS_FORMAT_UNCOMPRESSED: case UVC_VS_FORMAT_MJPEG: case UVC_VS_FORMAT_DV: case UVC_VS_FORMAT_FRAME_BASED: format-> frame = frame; // frame pointer in uvc format points to uvc frame address ret = uvc_parse_format (dev, streaming, format, & interval, buffer, buflen); // 7. parse the uvc format descriptor if (ret <0) goto error; frame + = format-> nframes; // The uvc frame address points to the uvc frame address format ++ of the next uvc format; // point to the next uvc format buflen-= ret; buffer + = ret; // point to the next uvc format descriptor continue;