terface *alts; ?
? ? ? ? ? ? unsigned int psize; ?
? ? ? ? ? ? alts = &intf->altsetting[i]; ?
? ? ? ? ? ? ep = uvc_find_endpoint(alts,stream->header.bEndpointAddress); ?
? ? ? ? ? ? if (ep == NULL) ?
? ? ? ? ? ? ? ? continue; ?
? ? ? ? ? ? /* Check if the bandwidth is high enough. */ ?
? ? ? ? ? ? psize = le16_to_cpu(ep->desc.wMaxPacketSize); ?
? ? ? ? ? ? psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); ?
? ? ? ? ? ? if (psize >= bandwidth && psize <= best_psize) { ?
? ? ? ? ? ? ? ? altsetting = i; ?
? ? ? ? ? ? ? ? best_psize = psize; ?
? ? ? ? ? ? ? ? best_ep = ep; ?
? ? ? ? ? ? } ?
? ? ? ? } ?
? ? ? ? if (best_ep == NULL) { ?
? ? ? ? ? ? uvc_trace(UVC_TRACE_VIDEO, "No fast enough alt setting for requested bandwidth.\n"); ?
? ? ? ? ? ? return -EIO; ?
? ? ? ? } ?
? ? ? ? uvc_trace(UVC_TRACE_VIDEO, "Selecting alternate setting %u (%u B/frame bandwidth).\n", altsetting, best_psize); ?
? ? ? ? ret = usb_set_interface(stream->dev->udev, intfnum, altsetting); ?
? ? ? ? if (ret < 0) ?
? ? ? ? ? ? return ret; ?
? ? ? ? ret = uvc_init_video_isoc(stream, best_ep, gfp_flags); ?//uvc初始化视频(同步方法) ?
? ? } ??
? ? else { ?//Bulk方式 ?
? ? ? ? /* Bulk endpoint, proceed to URB initialization. */ ?
? ? ? ? ep = uvc_find_endpoint(&intf->altsetting[0],stream->header.bEndpointAddress); ?
? ? ? ? if (ep == NULL) ?
? ? ? ? ? ? return -EIO; ?
? ? ? ? ret = uvc_init_video_bulk(stream, ep, gfp_flags); ? //uvc初始化视频(bulk方法) ?
? ? } ?
? ? if (ret < 0) ?
? ? ? ? return ret; ?
? ? /* Submit the URBs. */ ?
? ? for (i = 0; i < UVC_URBS; ++i) { ?
? ? ? ? ret = usb_submit_urb(stream->urb[i], gfp_flags); //提交urb ?
? ? ? ? if (ret < 0) { ?
? ? ? ? ? ? uvc_printk(KERN_ERR, "Failed to submit URB %u (%d).\n", i, ret); ?
? ? ? ? ? ? uvc_uninit_video(stream, 1); ?
? ? ? ? ? ? return ret; ?
? ? ? ? } ?
? ? } ?
??
? ? return 0; ?
}a.1.3.1 同步方式 ?
static int uvc_init_video_isoc(struct uvc_streaming *stream,struct usb_host_endpoint *ep, gfp_t gfp_flags) ?
{ ?
? ? struct urb *urb; ?
? ? unsigned int npackets, i, j; ?
? ? u16 psize; ?
? ? u32 size; ?
? ? psize = le16_to_cpu(ep->desc.wMaxPacketSize); ?
? ? psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); ?
? ? size = stream->ctrl.dwMaxVideoFrameSize; ?
? ? npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags); ? //分配urb缓冲区 ?
? ? if (npackets == 0) ?
? ? ? ? return -ENOMEM; ?
? ? size = npackets * psize; ?
? ? for (i = 0; i < UVC_URBS; ++i) { ?
? ? ? ? urb = usb_alloc_urb(npackets, gfp_flags); ? //分配urb ?
? ? ? ? if (urb == NULL) { ?
? ? ? ? ? ? uvc_uninit_video(stream, 1); ?
? ? ? ? ? ? return -ENOMEM; ?
? ? ? ? } ?
? ? ? ? urb->dev = stream->dev->udev; ?//设置urb ?
? ? ? ? urb->context = stream; ?
? ? ? ? urb->pipe = usb_rcvisocpipe(stream->dev->udev,ep->desc.bEndpointAddress); ?
? ? ? ? urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; ?
? ? ? ? urb->interval = ep->desc.bInterval; ?
? ? ? ? urb->transfer_buffer = stream->urb_buffer[i]; ?
? ? ? ? urb->transfer_dma = stream->urb_dma[i]; ?
? ? ? ? urb->complete = uvc_video_complete; ?
? ? ? ? urb->number_of_packets = npackets; ?
? ? ? ? urb->transfer_buffer_length = size; ?
? ? ? ? for (j = 0; j < npackets; ++j) { ?
? ? ? ? ? ? urb->iso_frame_desc[j].offset = j * psize; ?
? ? ? ? ? ? urb->iso_frame_desc[j].length = psize; ?
? ? ? ? } ?
? ? ? ? stream->urb[i] = urb; ?
? ? } ?
? ? return 0; ?
}a.1.3.2 Bluk方式 ?
static int uvc_init_video_bulk(struct uvc_streaming *stream,struct usb_host_endpoint *ep, gfp_t gfp_flags) ?
{ ?
? ? struct urb *urb; ?
? ? unsigned int npackets, pipe, i; ?
? ? u16 psize; ?
? ? u32 size; ?
? ? psize = le16_to_cpu(