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

📄 qcamvc.c

📁 VC编写的USB QuickCam驱动程序,实现四种视频格式在linux下的编码,信号来自摄像源
💻 C
📖 第 1 页 / 共 4 页
字号:
	{	case V4L2_CID_BRIGHTNESS:		if (value > 255 << 8)			return -ERANGE;		if (down_interruptible(&qcamvc->busy_lock))			return -EBUSY;		qcamvc->brightness = value >> 8;		qcamvc_set_brightness(qcamvc, qcamvc->brightness);		up(&qcamvc->busy_lock);		return 0;	case V4L2_CID_WHITENESS:		if (value > 255 << 8)			return -ERANGE;		if (down_interruptible(&qcamvc->busy_lock))			return -EBUSY;		qcamvc->exposure = value >> 8;		qcamvc_set_exposure(qcamvc, qcamvc->exposure);		up(&qcamvc->busy_lock);		return 0;	case V4L2_CID_CONTRAST:		if (value > 255 << 8)			return -ERANGE;		qcamvc->contrast = value >> 8;		qcamvc->gamma_done = 0;		return 0;	case V4L2_CID_SATURATION:		if (value > 255 << 8)			return -ERANGE;		qcamvc->saturation = value >> 8;		return 0;	case V4L2_CID_HUE:		if (value > 255 << 8)			return -ERANGE;		qcamvc->hue = value >> 8;		return 0;	case V4L2_CID_DO_WHITE_BALANCE:		return 0;	}	return -EINVAL;}static int qcamvc_g_ctrl(struct qcamvc_data *qcamvc, struct v4l2_control *c){	switch (c->id)	{	case V4L2_CID_BRIGHTNESS:		c->value = qcamvc->brightness << 8;		break;	case V4L2_CID_WHITENESS:		c->value = qcamvc->exposure << 8;		break;	case V4L2_CID_CONTRAST:		c->value = qcamvc->contrast << 8;		break;	case V4L2_CID_SATURATION:		c->value = qcamvc->saturation << 8;		break;	case V4L2_CID_HUE:		c->value = qcamvc->hue << 8;		break;	case V4L2_CID_DO_WHITE_BALANCE:		c->value = 0;		break;	default:		return -EINVAL;	}	return 0;}static int qcamvc_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg){	struct video_device *dev = file->private_data;	struct qcamvc_data *qcamvc = dev->priv;	int retval = 0;	if (!qcamvc || !qcamvc->ops)		return -ENODEV;	if ((cmd & 0xff00) == 0x7600)	{		/* V4L version 1 - call the compatibility routine */		retval = v4l_compat_translate_ioctl(inode, file, cmd, arg, qcamvc_do_ioctl);		if (retval >= 0)		{			// Fix things that v4l_compat can't handle						switch (cmd)			{			case VIDIOCGPICT:				((struct video_picture *)arg)->depth = mode_depth(qcamvc->pixelformat);				break;			case VIDIOCGCAP:				{					struct video_capability *cap = (struct video_capability *) arg;					cap->minwidth = MIN_WIDTH;					cap->minheight = MIN_HEIGHT;				}				break;			}		}		return retval;	}	switch(cmd)	{#if 0	/* mmap interface for V4L1 - kept here in case we need to implement it	 * for V4L2, although we shouldn't do so unless an app requires it.	 * This implementation seems somewhat hackish since it still causes the	 * caller to sleep, which the mmap interface should not do.	 */	case VIDIOCGMBUF:	{		struct video_mbuf *vm = arg;		int i;		DBG("VIDIOCGMBUF\n");		memset(vm, 0, sizeof(*vm));		vm->size = QCAMVC_NUMFRAMES*MAX_FRAME_SIZE;		vm->frames = QCAMVC_NUMFRAMES;		for (i = 0; i < QCAMVC_NUMFRAMES; i++)			vm->offsets[i] = MAX_FRAME_SIZE * i;		break;	}      	case VIDIOCMCAPTURE:	{		struct video_mmap *vm = arg;//printk("VIDIOCMCAPTURE: %d / %d / %dx%d\n", vm->format, vm->frame, vm->width, vm->height);		if (vm->frame<0||vm->frame>=QCAMVC_NUMFRAMES)		{			retval = -EINVAL;			break;		}		switch(vm->format)		{		case V4L2_PIX_FMT_GREY:			qcamvc->vpic.depth=8;			break;		/*		case V4L2_PIX_FMT_RGB555:		case V4L2_PIX_FMT_RGB565:		case V4L2_PIX_FMT_YUYV:		case V4L2_PIX_FMT_UYVY:			qcamvc->vpic.depth = 16;			break;*/		case V4L2_PIX_FMT_RGB24:			qcamvc->vpic.depth = 24;			break;		case V4L2_PIX_FMT_RGB32:			qcamvc->vpic.depth = 32;			break;		default:			retval = -EINVAL;			break;		}		if (retval)			break;					qcamvc->vpic.palette = vm->format;		if (res_changed(qcamvc, vm->width, vm->height))		{printk("size changing\n");			//memset(&qcamvc->vc, 0, sizeof(qcamvc->vc));						qcamvc_set_res(qcamvc, vm->width, vm->height);		}				retval = capture_frame(qcamvc, vm->frame);		break;	}	case VIDIOCSYNC:	{		int *frame = arg;		if (*frame<0 || *frame >= QCAMVC_NUMFRAMES )		{			retval = -EINVAL;			break;		}			switch (qcamvc->frame[*frame].state) 		{			case FRAME_GRABBING:			{				/* parse the frame now */				if (capture_frame(qcamvc, *frame))					retval = -EINVAL;								qcamvc->frame[*frame].state = FRAME_READY;				break;			}						case FRAME_READY:			case FRAME_UNUSED:			{				printk("QuickCam VC: Sync to unused frame\n");				retval = -EINVAL;				break;			}						case FRAME_DONE:			/* if the frame has already been captured & parsed, just mark it as ready */	    	qcamvc->frame[*frame].state = FRAME_READY;			break;						default:			retval = -EINVAL;			break;		}		break;	}#endif		/* ***  v4l2  *** ************************************************ */	case VIDIOC_QUERYCAP:		return qcamvc_querycap(qcamvc, (struct v4l2_capability *) arg);	case VIDIOC_S_FMT:		return qcamvc_s_fmt(qcamvc, (struct v4l2_format *) arg);		case VIDIOC_G_FMT:		return qcamvc_g_fmt(qcamvc, (struct v4l2_format *) arg);	case VIDIOC_ENUM_FMT:		return qcamvc_enum_fmt((struct v4l2_fmtdesc *) arg);		case VIDIOC_TRY_FMT:		return qcamvc_try_fmt((struct v4l2_format *) arg);	case VIDIOC_CROPCAP:		return qcamvc_cropcap(qcamvc, (struct v4l2_cropcap *) arg);	case VIDIOC_ENUMINPUT:		return qcamvc_enuminput((struct v4l2_input *) arg);		case VIDIOC_G_INPUT:		*(int *) arg = 0;		return 0;		case VIDIOC_S_INPUT:		if (*(int *) arg != 0)			return -EINVAL;		return 0;	case VIDIOC_QUERYCTRL:		return qcamvc_queryctrl((struct v4l2_queryctrl *) arg);		case VIDIOC_S_CTRL:		return qcamvc_s_ctrl(qcamvc, (struct v4l2_control *) arg);		case VIDIOC_G_CTRL:		return qcamvc_g_ctrl(qcamvc, (struct v4l2_control *) arg);	case VIDIOC_G_STD: /* Should return -EINVAL but SANE fails if we do */	case VIDIOC_QUERYSTD: /* for broken apps - ideally we should return -EINVAL */		*(v4l2_std_id *) arg = 0;		return 0;	/* This relates to both memory mapping and user pointers. Implementing user	 * pointers may be a reasonable thing to do if an application needs it	 */	IGNORE_IOCTL(VIDIOC_REQBUFS)	NOACTION_IOCTL(VIDIOC_STREAMOFF)	NOACTION_IOCTL(VIDIOC_STREAMON)	IGNORE_IOCTL(VIDIOC_QBUF)	IGNORE_IOCTL(VIDIOC_DQBUF)	/* This relates to memory mapping. It is probably not a good idea to implement	 * the mmap interface unless an application is found that requires them - memory	 * mapping is * required to allocate DMA-able memory for the buffers (that is,	 * kalloc memory * rather than vmalloc memory), which is a scarce resource and	 * highly prone to * failure with blocks the size of the ones we would be	 * allocating. All this for little to no performance improvement in our case	 * since we need to translate the pixels to something the app will understand	 * anyway.	 */	IGNORE_IOCTL(VIDIOC_QUERYBUF)	/* These are miscellaneous features we shouldn't need to implement */	IGNORE_IOCTL(VIDIOC_QUERYMENU)	IGNORE_IOCTL(VIDIOC_G_CROP)	IGNORE_IOCTL(VIDIOC_S_CROP)	IGNORE_IOCTL(VIDIOC_G_JPEGCOMP)	/*These should never apply to this device */	IGNORE_IOCTL(VIDIOC_OVERLAY)	IGNORE_IOCTL(VIDIOC_G_FBUF)	IGNORE_IOCTL(VIDIOC_S_FBUF)	IGNORE_IOCTL(VIDIOC_ENUMSTD)	IGNORE_IOCTL(VIDIOC_S_STD)	IGNORE_IOCTL(VIDIOC_G_PARM)	IGNORE_IOCTL(VIDIOC_S_PARM)	case VIDIOC_G_TUNER:	case VIDIOC_S_TUNER:	case VIDIOC_G_AUDIO:	case VIDIOC_S_AUDIO:	case VIDIOC_G_OUTPUT:	case VIDIOC_S_OUTPUT:	case VIDIOC_ENUMOUTPUT:	case VIDIOC_G_AUDOUT:	case VIDIOC_S_AUDOUT:	case VIDIOC_G_MODULATOR:	case VIDIOC_S_MODULATOR:	case VIDIOC_G_FREQUENCY:	case VIDIOC_S_FREQUENCY:		/* These can never apply and so are ignored without		 * any notification.		 */		return -EINVAL;	default:		printk("QuickCam VC: Unknown IOCTL cmd: %X\n", cmd);		retval = -ENOIOCTLCMD;		break;    }		return retval;}/***************************************************************************** QuickCam Init*****************************************************************************/static int qcamvc_camera_init(struct qcamvc_data *qcamvc){	if (!qcamvc) return -1;	long i;	unsigned char *bigbuffer;	unsigned char bitmask;	memset(&qcamvc->misc_reg, 0, sizeof(qcamvc->misc_reg));		bigbuffer=kmalloc(BIGBUFFER_SIZE, GFP_KERNEL);	if (bigbuffer==NULL) 	{		printk("QuickCam VC: Init bigbuffer kmalloc error.\n");		return -1;	}		qcamvc->camera_init = 1;		/* setup a 128KB bit mask for 6bit/8bit per component */	bitmask = 0xFF << qcamvc->bpc;	for(i=0; i<BIGBUFFER_SIZE ; i+=2)	{		*(bigbuffer + i) = (unsigned char )(i >> 11);		*(bigbuffer + i + 1) = bitmask;	}		get_camera_model(qcamvc);		set_register(qcamvc, QCAM_VC_SET_BRIGHTNESS, 0x38);	set_register(qcamvc, QCAM_VC_SET_BRIGHTNESS, 0x78);		/* clear config bit & disable video streaming */	set_register(qcamvc, QCAM_VC_SET_MISC, 0x00);		/* clear 0x0e address (whatever this address actually does?) */	set_register(qcamvc, 0x0E, 0x00);		/* write 128KB of 6bit/8bit mask */	set_registers(qcamvc, QCAM_VC_GET_FRAME, bigbuffer, BIGBUFFER_SIZE);		/* set address 0x0e to 0x01 */	set_register(qcamvc, 0x0E, 0x01);		/* this might have somthing to do with setting the amount of compression - don't know how though. */	set_register(qcamvc, QCAM_VC_SET_BRIGHTNESS, 0x78);	set_register(qcamvc, QCAM_VC_SET_BRIGHTNESS, 0x78);	set_register(qcamvc, QCAM_VC_SET_BRIGHTNESS, 0x58);	/* set brightness & exposure - probably not needed here */	qcamvc_set_brightness(qcamvc, qcamvc->brightness);	qcamvc_set_exposure(qcamvc, qcamvc->exposure);	/* set config bit. (whatever this bit actually does?) */	set_register(qcamvc, QCAM_VC_SET_MISC, 0x01);		/* set CCD columns & rows */	qcamvc_set_ccd_area(qcamvc);	/* set brightness & exposure */	qcamvc_set_brightness(qcamvc, qcamvc->brightness);	qcamvc_set_exposure(qcamvc, qcamvc->exposure);		/* set the Light Sensitivity (no gain/no attenuation = 128 ) */	qcamvc_set_light_sensitivity(qcamvc, qcamvc->light_sens);	/* set Misc options & re-enable video streaming now */	qcamvc->misc_reg.config = 1;	qcamvc->misc_reg.multiplier = (qcamvc->ccd_area.multiplier ? 0 : 1);	qcamvc->misc_reg.compression = (qcamvc->compression ? 1 : 0);	qcamvc->misc_reg.video_enable = 1;	set_registers(qcamvc, QCAM_VC_SET_MISC, (unsigned char*)&qcamvc->misc_reg, 1);		/* send a get frame to clear the previous resolution */	set_register(qcamvc, QCAM_VC_GET_FRAME, 0xFF);	/* done with init */	kfree(bigbuffer);		return 0;}/*****************************************************************************//*                                                                           *//* QuickCam Video Camera layer                                               *//*                                                                           *//*****************************************************************************/static int qcamvc_initialise(struct qcamvc_data *qcamvc, char *camtype){	strcpy(qcamvc->camtypedesc, camtype);		/* defaults */	qcamvc->camera_model	= 0;	qcamvc->camera_type		= 0;	qcamvc->width			= 352;	qcamvc->height			= 288;	qcamvc->bpc				= 8;			qcamvc->compression		= 0;	//FIXME: on/off - don't know how to set amount of compression.	qcamvc->light_sens		= 128;	qcamvc->brightness		= 175;	qcamvc->exposure		= 57;	qcamvc->gamma_done		= 0;	qcamvc->hue				= 128;	qcamvc->saturation		= 128;	qcamvc->contrast		= 128;	qcamvc->pixelformat		= V4L2_PIX_FMT_RGB24;	qcamvc->colordepth		= 24;	qcamvc->flip_bgr		= 0;		qcamvc->transfer_rate	= 0;	qcamvc->curframe		= 0;	qcamvc->frame_count		= 0;	qcamvc->frame_waiting	= 0;		qcamvc->raw_frame		= NULL;	qcamvc->frame_buf		= NULL;	free_frame_buf(qcamvc);		qcamvc->proc_entry		= NULL;	qcamvc->open_count		= 0;	qcamvc->camera_init		= 0;		qcamvc->vdev = video_device_alloc();	if (qcamvc->vdev == NULL)	{		printk(KERN_ERR "QuickCam VC: video_device_alloc() returned NULL!");		return -1;	}	*qcamvc->vdev = qcamvc_template;	strcpy(qcamvc->vdev->name, qcamvc->camtypedesc);	qcamvc->vdev->minor = -1;	qcamvc->vdev->dev = NULL;	qcamvc->vdev->release = video_device_release;	qcamvc->vdev->priv = qcamvc;		return 0;}struct qcamvc_data *qcamvc_register_camera(struct qcamvc_camera_ops *ops, void *lowlevel, char *camtype){	struct qcamvc_data *qcamvc;	if ((qcamvc = kmalloc(sizeof(struct qcamvc_data), GFP_KERNEL)) == NULL)	{		printk(KERN_ERR "QuickCam VC: Error allocating memory in qcamvc_register_camera\n");		return NULL;	}	memset(qcamvc, 0, sizeof(struct qcamvc_data));	qcamvc->ops = ops;	qcamvc->lowlevel_data = lowlevel;		init_MUTEX(&qcamvc->busy_lock);		if (qcamvc_initialise(qcamvc, camtype) < 0)	{		kfree(qcamvc);		return NULL;	}	if (video_register_device(qcamvc->vdev, VFL_TYPE_GRABBER, video_nr) == -1)	{		kfree(qcamvc);		printk(KERN_ERR "QuickCam VC: video_register_device failed.\n"); 		return NULL;	}#ifdef CONFIG_PROC_FS	create_proc_qcamvc_cam(qcamvc);#endif	if (!qcamvc->ops->qcamvc_open(qcamvc->lowlevel_data))	{		qcamvc_camera_init(qcamvc);		qcamvc->ops->qcamvc_close(qcamvc->lowlevel_data);	}	return qcamvc;}void qcamvc_unregister_camera(struct qcamvc_data *qcamvc){#ifdef CONFIG_PROC_FS	printk(KERN_INFO "QuickCam VC: destroying /proc/qcamvc/video%d\n", qcamvc->vdev->minor);	destroy_proc_qcamvc_cam(qcamvc);#endif		printk(KERN_INFO "QuickCam VC: unregistering video...\n");		if (qcamvc->vdev)	{		if (-1 != qcamvc->vdev->minor)			video_unregister_device(qcamvc->vdev);		else			video_device_release(qcamvc->vdev);		qcamvc->vdev = NULL;	}	if (qcamvc->open_count)	{		put_cam(qcamvc->ops);		printk(KERN_INFO "QuickCam VC: camera open -- setting ops to NULL\n");		qcamvc->ops = NULL;	}	free_raw_frame(qcamvc);	if (!qcamvc->open_count)	{		printk(KERN_INFO "QuickCam VC: freeing camera\n");		kfree(qcamvc);	}}/*****************************************************************************//*                                                                           *//* QuickCam Video Camera layer                                               *//* Module subs                                                               *//*                                                                           *//*****************************************************************************/static int __init qcamvc_driver_init(void){	printk("QuickCam VC: (C) 2001 by De Marchi Daniele, <demarchidaniele@libero.it>\n");	printk("QuickCam VC: v4l level driver version %s registered.\n",QCAMVCVERSION);#ifdef CONFIG_PROC_FS	proc_qcamvc_create();#endif	#ifdef CONFIG_KMOD#ifdef CONFIG_VIDEO_QCAMVC_PP_MODULE	request_module("qcamvc_pp");#endif#ifdef CONFIG_VIDEO_QCAMVC_USB_MODULE	request_module("qcamvc_usb");#endif#endif	/* CONFIG_KMOD */	#ifdef CONFIG_VIDEO_QCAMVC_PP	qcamvc_pp_init();#endif#ifdef CONFIG_VIDEO_QCAMVC_USB	qcamvc_usb_init();#endif	return 0;}static void __exit qcamvc_driver_exit(void){#ifdef CONFIG_PROC_FS	proc_qcamvc_destroy();#endif	printk(KERN_INFO "QuickCam VC: v4l driver unregistered\n");}module_init(qcamvc_driver_init);module_exit(qcamvc_driver_exit);/* Exported symbols for modules. */EXPORT_SYMBOL(qcamvc_register_camera);EXPORT_SYMBOL(qcamvc_unregister_camera);

⌨️ 快捷键说明

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