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

📄 uvcvideo.c.svn-base

📁 linux video4Linux 驱动
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
		.v4l2		= V4L2_CID_PANTILT_RELATIVE,		.name		= "Pan/Tilt (relative)",		.id		= LXU_MOTOR_PANTILT_RELATIVE_CONTROL,		.bit		= 0,		.size		= 4,		.type		= V4L2_CTRL_TYPE_INTEGER,		.unit		= UVC_GUID_LOGITECH_MOTOR,		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN				| UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_DEF,	},	{		.v4l2		= V4L2_CID_PANTILT_RESET,		.name		= "Pan/Tilt (reset)",		.id		= LXU_MOTOR_PANTILT_RESET_CONTROL,		.bit		= 0,		.size		= 1,		.type		= V4L2_CTRL_TYPE_INTEGER,		.unit		= UVC_GUID_LOGITECH_MOTOR,		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN				| UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES				| UVC_CONTROL_GET_DEF,	},	{		.v4l2		= V4L2_CID_EXPOSURE_AUTO,		.name		= "Exposure, Auto",		.id		= CT_AE_MODE_CONTROL,		.bit		= 1,		.size		= 1,		.type		= V4L2_CTRL_TYPE_INTEGER,		.unit		= UVC_GUID_UVC_CAMERA,		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR				| UVC_CONTROL_GET_DEF | UVC_CONTROL_GET_RES,	},	{		.v4l2		= V4L2_CID_EXPOSURE_ABSOLUTE,		.name		= "Exposure (Absolute)",		.id		= CT_EXPOSURE_TIME_ABSOLUTE_CONTROL,		.bit		= 3,		.size		= 4,		.type		= V4L2_CTRL_TYPE_INTEGER,		.unit		= UVC_GUID_UVC_CAMERA,		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN				| UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES				| UVC_CONTROL_GET_DEF,	},	{		.v4l2		= V4L2_CID_WHITE_BALANCE_TEMPERATURE_AUTO,		.name		= "White Balance Temperature, Auto",		.id		= PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,		.bit		= 12,		.size		= 1,		.type		= V4L2_CTRL_TYPE_BOOLEAN,		.unit		= UVC_GUID_UVC_PROCESSING,		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR				| UVC_CONTROL_GET_DEF,	},	{		.v4l2		= V4L2_CID_WHITE_BALANCE_TEMPERATURE,		.name		= "White Balance Temperature",		.id		= PU_WHITE_BALANCE_TEMPERATURE_CONTROL,		.bit		= 6,		.size		= 2,		.type		= V4L2_CTRL_TYPE_INTEGER,		.unit		= UVC_GUID_UVC_PROCESSING,		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN				| UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES				| UVC_CONTROL_GET_DEF,	}};static struct uvc_format_desc uvc_fmts[] = {	{		.guid		= UVC_GUID_FORMAT_YUY2,		.fcc		= V4L2_PIX_FMT_YUYV,	},	{		.guid		= UVC_GUID_FORMAT_YUY2,		.fcc		= V4L2_PIX_FMT_YUYV,	},	{		.guid		= UVC_GUID_FORMAT_NV12,		.fcc		= V4L2_PIX_FMT_NV12,	},};static const __u8 uvc_processing_guid[16] = UVC_GUID_UVC_PROCESSING;static const __u8 uvc_camera_guid[16] = UVC_GUID_UVC_CAMERA;/*#define PU_WHITE_BALANCE_COMPONENT_CONTROL              0x0c#define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL         0x0d#define PU_DIGITAL_MULTIPLIER_CONTROL                   0x0e#define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL             0x0f*//* ------------------------------------------------------------------------ * Debugging, printing and logging */#define UVC_TRACE_PROBE		(1 << 0)#define UVC_TRACE_DESCR		(1 << 1)#define UVC_TRACE_CONTROL	(1 << 2)#define UVC_TRACE_FORMAT	(1 << 3)#define UVC_TRACE_CAPTURE	(1 << 4)#define UVC_TRACE_CALLS		(1 << 5)#define UVC_TRACE_IOCTL		(1 << 6)#define UVC_TRACE_FRAME		(1 << 7)static unsigned int trace = 0;#define uvc_trace(flag, msg...) \	do { \		if (trace & flag) \			printk(KERN_DEBUG "uvcvideo: " msg); \	} while(0)#define uvc_printk(level, msg...) \	printk(level "uvcvideo: " msg)#if 0static void uvc_print_streaming_control(struct uvc_streaming_control *ctrl){	printk(KERN_DEBUG "bmHint:                      0x%04x\n", ctrl->bmHint);	printk(KERN_DEBUG "bFormatIndex:                   %3u\n", ctrl->bFormatIndex);	printk(KERN_DEBUG "bFrameIndex:                    %3u\n", ctrl->bFrameIndex);	printk(KERN_DEBUG "dwFrameInterval:          %9u\n", ctrl->dwFrameInterval);	printk(KERN_DEBUG "wKeyFrameRate:                %5u\n", ctrl->wKeyFrameRate);	printk(KERN_DEBUG "wPFrameRate:                  %5u\n", ctrl->wPFrameRate);	printk(KERN_DEBUG "wCompQuality:                 %5u\n", ctrl->wCompQuality);	printk(KERN_DEBUG "wCompWindowSize:              %5u\n", ctrl->wCompWindowSize);	printk(KERN_DEBUG "wDelay:                       %5u\n", ctrl->wDelay);	printk(KERN_DEBUG "dwMaxVideoFrameSize:      %9u\n", ctrl->dwMaxVideoFrameSize);	printk(KERN_DEBUG "dwMaxPayloadTransferSize: %9u\n", ctrl->dwMaxPayloadTransferSize);	printk(KERN_DEBUG "dwClockFrequency:         %9u\n", ctrl->dwClockFrequency);	printk(KERN_DEBUG "bmFramingInfo:                 0x%02x\n", ctrl->bmFramingInfo);	printk(KERN_DEBUG "bPreferedVersion:               %3u\n", ctrl->bPreferedVersion);	printk(KERN_DEBUG "bMinVersion:                    %3u\n", ctrl->bMinVersion);	printk(KERN_DEBUG "bMaxVersion:                    %3u\n", ctrl->bMaxVersion);}#endif/* ------------------------------------------------------------------------ * Utility functions */static inline int uvc_get_bit(const __u8 *data, int bit){	return (data[bit >> 3] >> (bit & 7)) & 1;}static __s32 uvc_get_le_value(const __u8 *data, int size){	switch (size) {	case 1:		return data[0];	case 2:		return le16_to_cpup((__le16*)data);	case 4:		return le32_to_cpup((__le32*)data);	}	return 0;}static void uvc_set_le_value(__s32 value, __u8 *data, int size){	switch (size) {	case 1:		data[0] = value;		break;	case 2:		*(__le16*)&data[0] = cpu_to_le16(value);		break;	case 4:		*(__le32*)&data[0] = cpu_to_le32(value);		break;	}}static struct usb_host_endpoint *uvc_find_endpoint(struct usb_host_interface *alts,		__u8 epaddr){	struct usb_host_endpoint *ep;	unsigned int i;	for (i = 0; i < alts->desc.bNumEndpoints; ++i) {		ep = &alts->endpoint[i];		if (ep->desc.bEndpointAddress == epaddr)			return ep;	}	return NULL;}static __u32 uvc_guid_to_fcc(const __u8 guid[16]){	unsigned int len = ARRAY_SIZE(uvc_fmts);	unsigned int i;	for (i = 0; i < len; ++i) {		if (memcmp(guid, uvc_fmts[i].guid, 16) == 0)			return uvc_fmts[i].fcc;	}	return -1;}static __u32 uvc_colorspace(const __u8 primaries){	static const __u8 colorprimaries[] = {		0,		V4L2_COLORSPACE_SRGB,		V4L2_COLORSPACE_470_SYSTEM_M,		V4L2_COLORSPACE_470_SYSTEM_BG,		V4L2_COLORSPACE_SMPTE170M,		V4L2_COLORSPACE_SMPTE240M,	};	if (primaries < ARRAY_SIZE(colorprimaries))		return colorprimaries[primaries];	return 0;}/* Simplify a fraction using a simple continued fraction decomposition. The * idea here is to convert fractions such as 333333/10000000 to 1/30 using * 32 bit arithmetic only. The algorithm is not perfect and relies upon two * arbitrary parameters to remove non-significative terms from the simple * continued fraction decomposition. Using 8 and 333 for n_terms and threshold * respectively seems to give nice results. */static void uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator,		unsigned int n_terms, unsigned int threshold){	uint32_t *an;	uint32_t x, y, r;	unsigned int i, n;	an = kmalloc(n_terms * sizeof *an, GFP_KERNEL);	if (an == NULL)		return;	/* Convert the fraction to a simple continued fraction. See	 * http://mathforum.org/dr.math/faq/faq.fractions.html	 * Stop if the current term is bigger than or equal to the given	 * threshold.	 */	memset(an, 0, sizeof an);	x = *numerator;	y = *denominator;	for (n = 0; n < n_terms && y != 0; ++n) {		an[n] = x / y;		if (an[n] >= threshold) {			if (n < 2)				n++;			break;		}		r = x - an[n] * y;		x = y;		y = r;	}	/* Expand the simple continued fraction back to an integer fraction. */	x = 0;	y = 1;	for (i = n; i > 0; --i) {		r = y;		y = an[i-1] * y + x;		x = r;	}	*numerator = y;	*denominator = x;	kfree(an);}/* Convert a fraction to a frame interval in 100ns multiples. The idea here is * to compute numerator / denominator * 10000000 using 32 bit fixed point * arithmetic only. */static uint32_t uvc_fraction_to_interval(uint32_t numerator, uint32_t denominator){	uint32_t multiplier;	/* Saturate the result if the operation would overflow. */	if (numerator/denominator >= ((uint32_t)-1)/10000000)		return (uint32_t)-1;	/* Divide both the denominator and the multiplier by two until	 * numerator * multiplier doesn't overflow. If anyone knows a better	 * algorithm please let me know.	 */	multiplier = 10000000;	while (numerator > ((uint32_t)-1)/multiplier) {		multiplier /= 2;		denominator /= 2;	}	return denominator ? numerator * multiplier / denominator : 0;}/* ------------------------------------------------------------------------ * Terminal and unit management */static struct uvc_terminal *uvc_terminal(struct uvc_device *dev, int id){	struct list_head *p;	list_for_each(p, &dev->terminals) {		struct uvc_terminal *terminal;		terminal = list_entry(p, struct uvc_terminal, list);		if (terminal->id == id)			return terminal;	}	return NULL;}static struct uvc_unit *uvc_unit_by_id(struct uvc_device *dev, int id){	struct list_head *p;	list_for_each(p, &dev->units) {		struct uvc_unit *unit;		unit = list_entry(p, struct uvc_unit, list);		if (unit->id == id)			return unit;	}	return NULL;}static struct uvc_unit *uvc_unit_by_guid(struct uvc_device *dev, __u8 guid[16]){	struct list_head *p;	list_for_each(p, &dev->units) {		struct uvc_unit *unit;		unit = list_entry(p, struct uvc_unit, list);		if (unit->type == VC_EXTENSION_UNIT &&		    memcmp(unit->extension.guidExtensionCode, guid, 16) == 0)			return unit;	}	return NULL;}/* ------------------------------------------------------------------------ * Video buffers queue management. * * Video queues is initialized by uvc_queue_init(). The function performs * basic initialization of the uvc_video_queue struct and never fails. * * Video buffer allocation and freeing are performed by uvc_alloc_buffers and * uvc_free_buffers respectively. The former acquires the video queue lock, * while the later must be called with the lock held (so that allocation can * free previously allocated buffers). Trying to free buffers that are mapped * to user space will return -EBUSY. * * Video buffers are managed using two queues. However, unlike most USB video * drivers which use an in queue and an out queue, we use a main queue which * holds all queued buffers (both 'empty' and 'done' buffers), and an irq * queue which holds empty buffers. This design (copied from video-buf) * minimizes locking in interrupt, as only one queue is shared between * interrupt and user contexts. * * Use cases * --------- * * Unless stated otherwise, all operations which modify the irq buffers queue * are protected by the irq spinlock. * * 1. The user queues the buffers, starts streaming and dequeues a buffer. * *    The buffers are added to the main and irq queues. Both operations are *    protected by the queue lock, and the latert is protected by the irq *    spinlock as well. * *    The completion handler fetches a buffer from the irq queue and fills it *    with video data. If no buffer is available (irq queue empty), the handler *    returns immediately. * *    When the buffer is full, the completion handler removes it from the irq *    queue, marks it as ready (UVC_BUF_STATE_DONE) and wake its wait queue. *    At that point, any process waiting on the buffer will be woken up. If a *    process tries to dequeue a buffer after it has been marked ready, the *    dequeing will succeed immediately. * * 2. Buffers are queued, user is waiting on a buffer and the device gets *    disconnected. * *    When the device is disconnected, the kernel calls the completion handler *    with an appropriate status code. The handler marks all buffers in the *    irq queue as being erroneous (UVC_BUF_STATE_ERROR) and wakes them up so *    that any process waiting on a buffer gets woken up. * *    Waking up up the first buffer on the irq list is not enough, as the *    process waiting on the buffer might restart the dequeue operation *    immediately. * *//* * Free the video buffers. * * This function must be called with the queue lock held. */static int uvc_free_buffers(struct uvc_video_queue *queue){	unsigned int i;	for (i = 0; i < queue->count; ++i) {		if (queue->buffer[i].vma_use_count != 0)			return -EBUSY;	}	if (queue->count) {#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)		unsigned long addr = (unsigned long)queue->mem;		size_t size = queue->count * queue->buffer[0].size;		while (size > 0) {			ClearPageReserved(vmalloc_to_page((void*)addr));			addr += PAGE_SIZE;			size -= PAGE_SIZE;		}#endif		vfree(queue->mem);		queue->count = 0;	}	return 0;}/* * Allocate the video buffers. * * Pages are reserved to make sure they will not be swaped, as they will be * filled in URB completion handler. *  * Buffers will be individually mapped, so they must all be page aligned. */static int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,		unsigned int buflength){	unsigned int bufsize = PAGE_ALIGN(buflength);	unsigned int i;	void *mem = NULL;	int ret;	if (nbuffers > UVC_MAX_VIDEO_BUFFERS)		nbuffers = UVC_MAX_VIDEO_BUFFERS;	down(&queue->lock);	if ((ret = uvc_free_buffers(queue)) < 0)		goto done;	/* Decrement the number of buffers until allocation succeeds. */	for (; nbuffers > 0; --nbuffers) {		mem = vmalloc_32(nbuffers * bufsize);		if (mem != NULL)			break;	}	if (mem == NULL) {		ret = -ENOMEM;		goto done;	}	for (i = 0; i < nbuffers; ++i) {		memset(&queue->buffer[i], 0, sizeof queue->buffer[i]);		queue->buffer[i].size = bufsize;		queue->buffer[i].buf.index = i;		queue->buffer[i].buf.m.offset = i * bufsize;		queue->buffer[i].buf.length = buflength;		queue->buffer[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;		queue->buffer[i].buf.sequence = 0;		queue->buffer[i].buf.field = V4L2_FIELD_NONE;		queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP;		queue->buffer[i].buf.flags = 0;		init_waitqueue_head(&queue->buffer[i].wait);	}	queue->mem = mem;	queue->count = nbuffers;

⌨️ 快捷键说明

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