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

📄 pwc-v4l.c

📁 webcam device driver
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Linux driver for Philips webcam   USB and Video4Linux interface part.   (C) 1999-2004 Nemosoft Unv.   (C) 2004-2006 Luc Saillard (luc@saillard.org)   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx   driver and thus may have bugs that are not present in the original version.   Please send bug reports and support requests to <luc@saillard.org>.   The decompression routines have been implemented by reverse-engineering the   Nemosoft binary pwcx module. Caveat emptor.   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*/#include <linux/errno.h>#include <linux/init.h>#include <linux/mm.h>#include <linux/module.h>#include <linux/poll.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <asm/io.h>#include "pwc.h"#include "pwc-ioctl.h"static struct v4l2_queryctrl pwc_controls[] = {        {	    .id      = V4L2_CID_BRIGHTNESS,	    .type    = V4L2_CTRL_TYPE_INTEGER,	    .name    = "Brightness",	    .minimum = 0,	    .maximum = 128,	    .step    = 1,	    .default_value = 64,	},        {	    .id      = V4L2_CID_CONTRAST,	    .type    = V4L2_CTRL_TYPE_INTEGER,	    .name    = "Contrast",	    .minimum = 0,	    .maximum = 64,	    .step    = 1,	    .default_value = 0,	},        {	    .id      = V4L2_CID_SATURATION,	    .type    = V4L2_CTRL_TYPE_INTEGER,	    .name    = "Saturation",	    .minimum = -100,	    .maximum = 100,	    .step    = 1,	    .default_value = 0,	},        {	    .id      = V4L2_CID_GAMMA,	    .type    = V4L2_CTRL_TYPE_INTEGER,	    .name    = "Gamma",	    .minimum = 0,	    .maximum = 32,	    .step    = 1,	    .default_value = 0,	},        {	    .id      = V4L2_CID_RED_BALANCE,	    .type    = V4L2_CTRL_TYPE_INTEGER,	    .name    = "Red Gain",	    .minimum = 0,	    .maximum = 256,	    .step    = 1,	    .default_value = 0,	},        {	    .id      = V4L2_CID_BLUE_BALANCE,	    .type    = V4L2_CTRL_TYPE_INTEGER,	    .name    = "Blue Gain",	    .minimum = 0,	    .maximum = 256,	    .step    = 1,	    .default_value = 0,	},        {	    .id      = V4L2_CID_AUTO_WHITE_BALANCE,	    .type    = V4L2_CTRL_TYPE_BOOLEAN,	    .name    = "Auto White Balance",	    .minimum = 0,	    .maximum = 1,	    .step    = 1,	    .default_value = 0,	},	{	    .id      = V4L2_CID_EXPOSURE,	    .type    = V4L2_CTRL_TYPE_INTEGER,	    .name    = "Shutter Speed (Exposure)",	    .minimum = 0,	    .maximum = 256,	    .step    = 1,	    .default_value = 200,	},	{	    .id      = V4L2_CID_AUTOGAIN,	    .type    = V4L2_CTRL_TYPE_BOOLEAN,	    .name    = "Auto Gain Enabled",	    .minimum = 0,	    .maximum = 1,	    .step    = 1,	    .default_value = 1,	},	{	    .id      = V4L2_CID_GAIN,	    .type    = V4L2_CTRL_TYPE_INTEGER,	    .name    = "Gain Level",	    .minimum = 0,	    .maximum = 256,	    .step    = 1,	    .default_value = 0,	},#if XAWTV_HAS_BEEN_FIXED        {	    .id      = V4L2_CID_PRIVATE_SAVE_USER,	    .type    = V4L2_CTRL_TYPE_BUTTON,	    .name    = "Save User Settings",	    .minimum = 0,	    .maximum = 0,	    .step    = 0,	    .default_value = 0,	},        {	    .id      = V4L2_CID_PRIVATE_RESTORE_USER,	    .type    = V4L2_CTRL_TYPE_BUTTON,	    .name    = "Restore User Settings",	    .minimum = 0,	    .maximum = 0,	    .step    = 0,	    .default_value = 0,	},        {	    .id      = V4L2_CID_PRIVATE_RESTORE_FACTORY,	    .type    = V4L2_CTRL_TYPE_BUTTON,	    .name    = "Restore Factory Settings",	    .minimum = 0,	    .maximum = 0,	    .step    = 0,	    .default_value = 0,	},	{	    .id      = V4L2_CID_PRIVATE_COLOUR_MODE,	    .type    = V4L2_CTRL_TYPE_BOOLEAN,	    .name    = "Colour mode",	    .minimum = 0,	    .maximum = 1,	    .step    = 1,	    .default_value = 0,	},	{	    .id      = V4L2_CID_PRIVATE_AUTOCONTOUR,	    .type    = V4L2_CTRL_TYPE_BOOLEAN,	    .name    = "Auto contour",	    .minimum = 0,	    .maximum = 1,	    .step    = 1,	    .default_value = 0,	},	{	    .id      = V4L2_CID_PRIVATE_CONTOUR,	    .type    = V4L2_CTRL_TYPE_INTEGER,	    .name    = "Contour",	    .minimum = 0,	    .maximum = 63,	    .step    = 1,	    .default_value = 0,	},	{	    .id      = V4L2_CID_PRIVATE_BACKLIGHT,	    .type    = V4L2_CTRL_TYPE_BOOLEAN,	    .name    = "Backlight compensation",	    .minimum = 0,	    .maximum = 1,	    .step    = 1,	    .default_value = 0,	},	{	  .id      = V4L2_CID_PRIVATE_FLICKERLESS,	    .type    = V4L2_CTRL_TYPE_BOOLEAN,	    .name    = "Flickerless",	    .minimum = 0,	    .maximum = 1,	    .step    = 1,	    .default_value = 0,	},	{	    .id      = V4L2_CID_PRIVATE_NOISE_REDUCTION,	    .type    = V4L2_CTRL_TYPE_INTEGER,	    .name    = "Noise reduction",	    .minimum = 0,	    .maximum = 3,	    .step    = 1,	    .default_value = 0,	},#endif};#if CONFIG_PWC_DEBUG #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)static const char *v4l1_ioctls[] = {        "?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",        "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",        "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",        "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",        "SMICROCODE", "GVBIFMT", "SVBIFMT" };#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)#else/* In 2.6.16-rc1 v4l_printk_ioctl is not defined but exported */extern void v4l_printk_ioctl(unsigned int cmd);#endif#endifstatic void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_format *f){	memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));	f->fmt.pix.width        = pdev->view.x;	f->fmt.pix.height       = pdev->view.y;	f->fmt.pix.field        = V4L2_FIELD_NONE;	if (pdev->vpalette == VIDEO_PALETTE_YUV420P) {		f->fmt.pix.pixelformat  = V4L2_PIX_FMT_YUV420;		f->fmt.pix.bytesperline = (f->fmt.pix.width * 3)/2;		f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;	} else {		/* vbandlength contains 4 lines ...  */		f->fmt.pix.bytesperline = pdev->vbandlength/4;		f->fmt.pix.sizeimage = pdev->frame_size + sizeof(struct pwc_raw_frame);		if (DEVICE_USE_CODEC1(pdev->type))			f->fmt.pix.pixelformat  = V4L2_PIX_FMT_PWC1;		else			f->fmt.pix.pixelformat  = V4L2_PIX_FMT_PWC2;	}	PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() "			"width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n", 			f->fmt.pix.width,			f->fmt.pix.height,			f->fmt.pix.bytesperline,			f->fmt.pix.sizeimage,			(f->fmt.pix.pixelformat)&255,			(f->fmt.pix.pixelformat>>8)&255,			(f->fmt.pix.pixelformat>>16)&255,			(f->fmt.pix.pixelformat>>24)&255);}/* ioctl(VIDIOC_TRY_FMT) */static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f){	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {		PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n");		return -EINVAL;	}	switch (f->fmt.pix.pixelformat) {		case V4L2_PIX_FMT_YUV420:			break;		case V4L2_PIX_FMT_PWC1:			if (DEVICE_USE_CODEC23(pdev->type)) {				PWC_DEBUG_IOCTL("codec1 is only supported for old pwc webcam\n");				return -EINVAL;			}			break;		case V4L2_PIX_FMT_PWC2:			if (DEVICE_USE_CODEC1(pdev->type)) {				PWC_DEBUG_IOCTL("codec23 is only supported for new pwc webcam\n");				return -EINVAL;			}			break;		default:			PWC_DEBUG_IOCTL("Unsupported pixel format\n");			return -EINVAL;	}	if (f->fmt.pix.width > pdev->view_max.x)		f->fmt.pix.width = pdev->view_max.x;	else if (f->fmt.pix.width < pdev->view_min.x)		f->fmt.pix.width = pdev->view_min.x;	if (f->fmt.pix.height > pdev->view_max.y)		f->fmt.pix.height = pdev->view_max.y;	else if (f->fmt.pix.height < pdev->view_min.y)		f->fmt.pix.height = pdev->view_min.y;	return 0;}/* ioctl(VIDIOC_SET_FMT) */static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f){	int ret, fps, snapshot, compression, pixelformat;	ret = pwc_vidioc_try_fmt(pdev, f);	if (ret<0)		return ret;	pixelformat = f->fmt.pix.pixelformat;	compression = pdev->vcompression;	snapshot = 0;	fps = pdev->vframes;	if (f->fmt.pix.priv) {		compression = (f->fmt.pix.priv & PWC_QLT_MASK) >> PWC_QLT_SHIFT;		snapshot = !!(f->fmt.pix.priv & PWC_FPS_SNAPSHOT);		fps = (f->fmt.pix.priv & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;		if (fps == 0)			fps = pdev->vframes;	}	if (pixelformat == V4L2_PIX_FMT_YUV420)		pdev->vpalette = VIDEO_PALETTE_YUV420P;	else		pdev->vpalette = VIDEO_PALETTE_RAW;	PWC_DEBUG_IOCTL("Try to change format to: width=%d height=%d fps=%d "			"compression=%d snapshot=%d format=%c%c%c%c\n",			f->fmt.pix.width, f->fmt.pix.height, fps,			compression, snapshot,			(pixelformat)&255,			(pixelformat>>8)&255,			(pixelformat>>16)&255,			(pixelformat>>24)&255);	ret = pwc_try_video_mode(pdev,				 f->fmt.pix.width,				 f->fmt.pix.height,				 fps,				 compression,				 snapshot);	PWC_DEBUG_IOCTL("pwc_try_video_mode(), return=%d\n", ret);	if (ret)		return ret;	pwc_vidioc_fill_fmt(pdev, f);	return 0;}int pwc_video_do_ioctl(struct inode *inode, struct file *file,	 	       unsigned int cmd, void *arg){	struct video_device *vdev = video_devdata(file);	struct pwc_device *pdev;	DECLARE_WAITQUEUE(wait, current);	if (vdev == NULL)		return -EFAULT;	pdev = vdev->priv;	if (pdev == NULL)		return -EFAULT;#if CONFIG_PWC_DEBUG#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)	switch (_IOC_TYPE(cmd)) {		case 'v':			PWC_DEBUG_IOCTL("ioctl 0x%x (v4l1, VIDIOC%s)\n", cmd,					(_IOC_NR(cmd) < V4L1_IOCTLS) ?  v4l1_ioctls[_IOC_NR(cmd)] : "???");			break;		case 'V':			PWC_DEBUG_IOCTL("ioctl 0x%x (v4l2, %s)\n", cmd,					v4l2_ioctl_names[_IOC_NR(cmd)]);			break;		default:			PWC_DEBUG_IOCTL("ioctl 0x%x (unknown)\n", cmd);	}#else	if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace)		v4l_printk_ioctl(cmd);#endif#endif	switch (cmd) {		/* Query cabapilities */		case VIDIOCGCAP:		{			struct video_capability *caps = arg;			strcpy(caps->name, vdev->name);			caps->type = VID_TYPE_CAPTURE;			caps->channels = 1;			caps->audios = 1;			caps->minwidth  = pdev->view_min.x;			caps->minheight = pdev->view_min.y;			caps->maxwidth  = pdev->view_max.x;			caps->maxheight = pdev->view_max.y;			break;		}		/* Channel functions (simulate 1 channel) */		case VIDIOCGCHAN:		{			struct video_channel *v = arg;

⌨️ 快捷键说明

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