⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uvc_video.c

📁 LINUXvideopPREVIEW, LINUX下面打开图像的工具源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	 * an exponent of two. Some developers forgot about it.	 */	if (interval > 16 && dev->udev->speed == USB_SPEED_HIGH &&	    (dev->quirks & UVC_QUIRK_STATUS_INTERVAL))		interval = fls(interval) - 1;	usb_fill_int_urb(dev->int_urb, dev->udev, pipe,		dev->status, sizeof dev->status, uvc_status_complete,		dev, interval);	return usb_submit_urb(dev->int_urb, GFP_KERNEL);}/* * Completion handler for video URBs. */static void uvc_video_complete_isoc(struct urb *urb,	struct uvc_video_queue *queue, struct uvc_buffer *buf){	int ret, i;	for (i = 0; i < urb->number_of_packets; ++i) {		if (urb->iso_frame_desc[i].status < 0) {			uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame "				"lost (%d).\n", urb->iso_frame_desc[i].status);			continue;		}		/* Decode the payload packet.		 * uvc_video_decode is entered twice when a frame transition		 * has been detected because the end of frame can only be		 * reliably detected when the first packet of the new frame		 * is processed. The first pass detects the transition and		 * closes the previous frame's buffer, the second pass		 * processes the data of the first payload of the new frame.		 */		do {			ret = uvc_video_decode(queue, buf,				urb->transfer_buffer + urb->iso_frame_desc[i].offset,				urb->iso_frame_desc[i].actual_length);			if (buf == NULL)				break;			if (buf->state == UVC_BUF_STATE_DONE ||			    buf->state == UVC_BUF_STATE_ERROR)				buf = uvc_queue_next_buffer(queue, buf);		} while (ret == -EAGAIN);	}}static void uvc_video_complete_bulk(struct urb *urb,	struct uvc_video_queue *queue, struct uvc_buffer *buf){	int ret;	/* Decode the payload packet.	 * uvc_video_decode is entered twice when a frame transition	 * has been detected because the end of frame can only be	 * reliably detected when the first packet of the new frame	 * is processed. The first pass detects the transition and	 * closes the previous frame's buffer, the second pass	 * processes the data of the first payload of the new frame.	 */	do {		ret = uvc_video_decode(queue, buf,			urb->transfer_buffer, urb->actual_length);		if (buf == NULL)			break;		if (buf->state == UVC_BUF_STATE_DONE ||		    buf->state == UVC_BUF_STATE_ERROR)			buf = uvc_queue_next_buffer(queue, buf);	} while (ret == -EAGAIN);}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)static void uvc_video_complete(struct urb *urb, struct pt_regs *regs)#elsestatic void uvc_video_complete(struct urb *urb)#endif{	struct uvc_video_device *video = urb->context;	struct uvc_video_queue *queue = &video->queue;	struct uvc_buffer *buf = NULL;	unsigned long flags;	int ret;	switch (urb->status) {	case 0:		break;	default:		uvc_printk(KERN_WARNING, "Non-zero status (%d) in video "			"completion handler.\n", urb->status);	case -ENOENT:		/* usb_kill_urb() called. */	case -ECONNRESET:	/* usb_unlink_urb() called. */	case -ESHUTDOWN:	/* The endpoint is being disabled. */		uvc_queue_cancel(queue);		return;	}	spin_lock_irqsave(&queue->irqlock, flags);	if (!list_empty(&queue->irqqueue))		buf = list_entry(queue->irqqueue.next, struct uvc_buffer, queue);	spin_unlock_irqrestore(&queue->irqlock, flags);	if (urb->number_of_packets)		uvc_video_complete_isoc(urb, queue, buf);	else		uvc_video_complete_bulk(urb, queue, buf);	if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {		uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n",			ret);        }}/* * Uninitialize isochronous/bulk URBs and free transfer buffers. */static void uvc_uninit_video(struct uvc_video_device *video){	struct urb *urb;	unsigned int i;	for (i = 0; i < UVC_URBS; ++i) {		if ((urb = video->urb[i]) == NULL)			continue;		usb_kill_urb(urb);		/* urb->transfer_buffer_length is not touched by USB core, so		 * we can use it here as the buffer length.		 */		if (video->urb_buffer[i]) {			usb_buffer_free(video->dev->udev,				urb->transfer_buffer_length,				video->urb_buffer[i], urb->transfer_dma);			video->urb_buffer[i] = NULL;		}		usb_free_urb(urb);		video->urb[i] = NULL;	}}/* * Initialize isochronous URBs and allocate transfer buffers. The packet size * is given by the endpoint. */static int uvc_init_video_isoc(struct uvc_video_device *video, struct usb_host_endpoint *ep){	struct urb *urb;	unsigned int npackets, i, j;	__u16 psize;	__u32 size;	int ret;	psize = le16_to_cpu(ep->desc.wMaxPacketSize);	psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));	size = video->streaming->ctrl.dwMaxVideoFrameSize;	if (size > UVC_MAX_FRAME_SIZE)		return -EINVAL;	npackets = (size + psize - 1) / psize;	if (npackets > UVC_MAX_ISO_PACKETS)		npackets = UVC_MAX_ISO_PACKETS;	size = npackets * psize;	for (i = 0; i < UVC_URBS; ++i) {		urb = usb_alloc_urb(npackets, GFP_KERNEL);		if (urb == NULL) {			uvc_uninit_video(video);			return -ENOMEM;		}		video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev,			size, GFP_KERNEL, &urb->transfer_dma);		if (video->urb_buffer[i] == NULL) {			usb_free_urb(urb);			uvc_uninit_video(video);			return -ENOMEM;		}		urb->dev = video->dev->udev;		urb->context = video;		urb->pipe = usb_rcvisocpipe(video->dev->udev,				ep->desc.bEndpointAddress);		urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;		urb->interval = ep->desc.bInterval;		urb->transfer_buffer = video->urb_buffer[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;		}		video->urb[i] = urb;	}	/* Submit the URBs. */	for (i = 0; i < UVC_URBS; ++i) {		if ((ret = usb_submit_urb(video->urb[i], GFP_KERNEL)) < 0) {			uvc_printk(KERN_ERR, "Failed to submit isoc URB %u "					"(%d).\n", i, ret);			uvc_uninit_video(video);			return ret;		}	}	return 0;}/* * Initialize bulk URBs and allocate transfer buffers. The packet size is * given by the endpoint. */static int uvc_init_video_bulk(struct uvc_video_device *video, struct usb_host_endpoint *ep){	struct urb *urb;	unsigned int pipe, i;	__u32 size;	int ret;	size = video->streaming->ctrl.dwMaxPayloadTransferSize;	if (size > UVC_MAX_FRAME_SIZE)		return -EINVAL;	pipe = usb_rcvbulkpipe(video->dev->udev, ep->desc.bEndpointAddress);	for (i = 0; i < UVC_URBS; ++i) {		urb = usb_alloc_urb(0, GFP_KERNEL);		if (urb == NULL) {			uvc_uninit_video(video);			return -ENOMEM;		}		video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev,			size, GFP_KERNEL, &urb->transfer_dma);		if (video->urb_buffer[i] == NULL) {			usb_free_urb(urb);			uvc_uninit_video(video);			return -ENOMEM;		}		usb_fill_bulk_urb(urb, video->dev->udev, pipe,			video->urb_buffer[i], size, uvc_video_complete,			video);		urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;		video->urb[i] = urb;	}	/* Submit the URBs. */	for (i = 0; i < UVC_URBS; ++i) {		if ((ret = usb_submit_urb(video->urb[i], GFP_KERNEL)) < 0) {			uvc_printk(KERN_ERR, "Failed to submit bulk URB %u "					"(%d).\n", i, ret);			uvc_uninit_video(video);			return ret;		}	}	return 0;}/* ------------------------------------------------------------------------ * Video device *//* * Initialize the UVC video device. * * This function is called before registering the device with V4L. */int uvc_video_init(struct uvc_video_device *video){	struct uvc_streaming_control *probe = &video->streaming->ctrl;	struct uvc_format *format = NULL;	struct uvc_frame *frame = NULL;	int ret;	/* Retrieve the default format and commit it. */	if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_DEF)) < 0)		return ret;	if ((ret = uvc_set_video_ctrl(video, probe, 0)) < 0)		return ret;	/* Validate the default format and frame. */	if (probe->bFormatIndex <= video->streaming->nformats)		format = &video->streaming->format[probe->bFormatIndex - 1];	if (format && probe->bFrameIndex <= format->nframes)		frame = &format->frame[probe->bFrameIndex - 1];	if (format == NULL || frame == NULL) {		uvc_printk(KERN_WARNING "Device initialization failed: the "			"default format and/or frame are not valid.\n");		return -EINVAL;	}	video->streaming->cur_format = format;	video->streaming->cur_frame = frame;	atomic_set(&video->active, 1);	return 0;}/* * Enable or disable the video stream. */int uvc_video_enable(struct uvc_video_device *video, int enable){	struct usb_interface *intf = video->streaming->intf;	struct usb_host_interface *alts;	struct usb_host_endpoint *ep;	int intfnum = video->streaming->intfnum;	unsigned int bandwidth, psize, i;	int ret;	if (!enable) {		uvc_uninit_video(video);		usb_set_interface(video->dev->udev, intfnum, 0);		uvc_queue_enable(&video->queue, 0);		return 0;	}	if ((ret = uvc_queue_enable(&video->queue, 1)) < 0) 		return ret;	if (intf->num_altsetting > 1) {		/* Isochronous endpoint, select the alternate setting. */		bandwidth = video->streaming->ctrl.dwMaxPayloadTransferSize;		for (i = 0; i < intf->num_altsetting; ++i) {			alts = &intf->altsetting[i];			ep = uvc_find_endpoint(alts,					video->streaming->input.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 || i == intf->num_altsetting - 1)			//if (psize >= bandwidth)        [wlq]				break;		}		if (i >= intf->num_altsetting)			return -EIO;		if ((ret = usb_set_interface(video->dev->udev, intfnum, i)) < 0)			return ret;		return uvc_init_video_isoc(video, ep);	} else {		/* Bulk endpoint, proceed to URB initialization. */		ep = uvc_find_endpoint(&intf->altsetting[0],				video->streaming->input.bEndpointAddress);		if (ep == NULL)			return -EIO;		return uvc_init_video_bulk(video, ep);	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -