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

📄 uvc_video.c

📁 linux camera下的uvc driver驱动源码
💻 C
📖 第 1 页 / 共 2 页
字号:
			return;		}		video->bulk.header_size = ret;		memcpy(video->bulk.header, mem, video->bulk.header_size);		mem += ret;		len -= ret;	}	/* The buffer queue might have been cancelled while a bulk transfer	 * was in progress, so we can reach here with buf equal to NULL. Make	 * sure buf is never dereferenced if NULL.	 */	/* Process video data. */	if (!video->bulk.skip_payload && buf != NULL)		uvc_video_decode_data(video, buf, mem, len);	/* Detect the payload end by a URB smaller than the maximum size (or	 * a payload size equal to the maximum) and process the header again.	 */	if (urb->actual_length < urb->transfer_buffer_length ||	    video->bulk.payload_size >= video->bulk.max_payload_size) {		if (!video->bulk.skip_payload && buf != NULL) {			uvc_video_decode_end(video, buf, video->bulk.header,				video->bulk.header_size);			if (buf->state == UVC_BUF_STATE_DONE ||			    buf->state == UVC_BUF_STATE_ERROR)				buf = uvc_queue_next_buffer(&video->queue, buf);		}		video->bulk.header_size = 0;		video->bulk.skip_payload = 0;		video->bulk.payload_size = 0;	}}#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. */		if (queue->frozen)			return;	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_first_entry(&queue->irqqueue, struct uvc_buffer, queue);	spin_unlock_irqrestore(&queue->irqlock, flags);	video->decode(urb, video, 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;	/* Compute the number of isochronous packets to allocate by dividing	 * the maximum video frame size by the packet size. Limit the result	 * to UVC_MAX_ISO_PACKETS.	 */	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;	}	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;	__u16 psize;	__u32 size;	/* Compute the bulk URB size. Some devices set the maximum payload	 * size to a value too high for memory-constrained devices. We must	 * then transfer the payload accross multiple URBs. To be consistant	 * with isochronous mode, allocate maximum UVC_MAX_ISO_PACKETS per bulk	 * URB.	 */	psize = le16_to_cpu(ep->desc.wMaxPacketSize) & 0x07ff;	size = video->streaming->ctrl.dwMaxPayloadTransferSize;	video->bulk.max_payload_size = size;	if (size > psize * UVC_MAX_ISO_PACKETS)		size = psize * UVC_MAX_ISO_PACKETS;	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;	}	return 0;}/* * Initialize isochronous/bulk URBs and allocate transfer buffers. */static int uvc_init_video(struct uvc_video_device *video){	struct usb_interface *intf = video->streaming->intf;	struct usb_host_interface *alts;	struct usb_host_endpoint *ep = NULL;	int intfnum = video->streaming->intfnum;	unsigned int bandwidth, psize, i;	int ret;	video->last_fid = -1;	video->bulk.header_size = 0;	video->bulk.skip_payload = 0;	video->bulk.payload_size = 0;	if (intf->num_altsetting > 1) {		/* Isochronous endpoint, select the alternate setting. */		bandwidth = video->streaming->ctrl.dwMaxPayloadTransferSize;		if (bandwidth == 0) {			uvc_printk(KERN_WARNING, "device %s requested null "				"bandwidth, defaulting to lowest.\n",				video->vdev->name);			bandwidth = 1;		}		for (i = 0; i < intf->num_altsetting; ++i) {			alts = &intf->altsetting[i];			ep = uvc_find_endpoint(alts,				video->streaming->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)				break;		}		if (i >= intf->num_altsetting)			return -EIO;		if ((ret = usb_set_interface(video->dev->udev, intfnum, i)) < 0)			return ret;		ret = uvc_init_video_isoc(video, ep);	} else {		/* Bulk endpoint, proceed to URB initialization. */		ep = uvc_find_endpoint(&intf->altsetting[0],				video->streaming->header.bEndpointAddress);		if (ep == NULL)			return -EIO;		ret = uvc_init_video_bulk(video, ep);	}	if (ret < 0)		return ret;	/* 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 URB %u "					"(%d).\n", i, ret);			uvc_uninit_video(video);			return ret;		}	}	return 0;}/* -------------------------------------------------------------------------- * Suspend/resume *//* * Stop streaming without disabling the video queue. * * To let userspace applications resume without trouble, we must not touch the * video buffers in any way. We mark the queue as frozen to make sure the URB * completion handler won't try to cancel the queue when we kill the URBs. */int uvc_video_suspend(struct uvc_video_device *video){	if (!video->queue.streaming)		return 0;	video->queue.frozen = 1;	uvc_uninit_video(video);	usb_set_interface(video->dev->udev, video->streaming->intfnum, 0);	return 0;}/* * Reconfigure the video interface and restart streaming if it was enable * before suspend. * * If an error occurs, disable the video queue. This will wake all pending * buffers, making sure userspace applications are notified of the problem * instead of waiting forever. */int uvc_video_resume(struct uvc_video_device *video){	int ret;	video->queue.frozen = 0;	if ((ret = uvc_set_video_ctrl(video, &video->streaming->ctrl, 0)) < 0) {		uvc_queue_enable(&video->queue, 0);		return ret;	}	if (!video->queue.streaming)		return 0;	if ((ret = uvc_init_video(video)) < 0)		uvc_queue_enable(&video->queue, 0);	return ret;}/* ------------------------------------------------------------------------ * Video device *//* * Initialize the UVC video device by retrieving the default format and * committing it. * * Some cameras (namely the Fuji Finepix) set the format and frame * indexes to zero. The UVC standard doesn't clearly make this a spec * violation, so try to silently fix the values if possible. * * 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;	unsigned int i;	int ret;	if (video->streaming->nformats == 0) {		uvc_printk(KERN_INFO, "No supported video formats found.\n");		return -EINVAL;	}	/* Alternate setting 0 should be the default, yet the XBox Live Vision	 * Cam (and possibly other devices) crash or otherwise misbehave if	 * they don't receive a SET_INTERFACE request before any other video	 * control request.	 */	usb_set_interface(video->dev->udev, video->streaming->intfnum, 0);	/* Some webcams don't suport GET_DEF request on the probe control. We	 * fall back to GET_CUR if GET_DEF fails.	 */	if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_DEF)) < 0 &&	    (ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0)		return ret;	/* Check if the default format descriptor exists. Use the first	 * available format otherwise.	 */	for (i = video->streaming->nformats; i > 0; --i) {		format = &video->streaming->format[i-1];		if (format->index == probe->bFormatIndex)			break;	}	if (format->nframes == 0) {		uvc_printk(KERN_INFO, "No frame descriptor found for the "			"default format.\n");		return -EINVAL;	}	/* Zero bFrameIndex might be correct. Stream-based formats (including	 * MPEG-2 TS and DV) do not support frames but have a dummy frame	 * descriptor with bFrameIndex set to zero. If the default frame	 * descriptor is not found, use the first avalable frame.	 */	for (i = format->nframes; i > 0; --i) {		frame = &format->frame[i-1];		if (frame->bFrameIndex == probe->bFrameIndex)			break;	}	/* Commit the default settings. */	probe->bFormatIndex = format->index;	probe->bFrameIndex = frame->bFrameIndex;	if ((ret = uvc_set_video_ctrl(video, probe, 0)) < 0)		return ret;	video->streaming->cur_format = format;	video->streaming->cur_frame = frame;	atomic_set(&video->active, 0);	/* Select the video decoding function */	if (video->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)		video->decode = uvc_video_decode_isight;	else if (video->streaming->intf->num_altsetting > 1)		video->decode = uvc_video_decode_isoc;	else 		video->decode = uvc_video_decode_bulk;	return 0;}/* * Enable or disable the video stream. */int uvc_video_enable(struct uvc_video_device *video, int enable){	int ret;	if (!enable) {		uvc_uninit_video(video);		usb_set_interface(video->dev->udev,			video->streaming->intfnum, 0);		uvc_queue_enable(&video->queue, 0);		return 0;	}	if ((ret = uvc_queue_enable(&video->queue, 1)) < 0)		return ret;	return uvc_init_video(video);}

⌨️ 快捷键说明

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