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

📄 qcamvc.c

📁 VC编写的USB QuickCam驱动程序,实现四种视频格式在linux下的编码,信号来自摄像源
💻 C
📖 第 1 页 / 共 4 页
字号:
		qcamvc->hue = val;		err=0;	}	else if (MATCH("colour") && (val <= 255))	{		qcamvc->saturation = val;		err=0;	}	else if (MATCH("bpc"))	{		if ((val == 6) || (val == 8))		{			qcamvc->bpc = val;			qcamvc_camera_init(qcamvc);			err=0;		}		else		{			printk("Invalid Range: bpc can only be 6 or 8\n");		}	}	else if (MATCH("flipbgr"))	{		if (val == 0 || val == 1)		{			qcamvc->flip_bgr = val;			err = 0;		}		else		{			printk("Invalid setting: flipbgr can only be 0 or 1\n");		}	}	else if (MATCH("compression"))// && (val <= 255))	{		qcamvc->compression=val;		qcamvc_camera_init(qcamvc);		err=0;	}	else if (MATCH("sensitivity") && (val <= 255))	{		qcamvc->light_sens=val;		qcamvc_set_light_sensitivity(qcamvc,qcamvc->light_sens);		err=0;	}	if (!err)		printk("Set: %s=%i\n", name, val);	else		printk("Couldn't Set: %s=%i\n", name, val);#undef MATCH 	up(&qcamvc->busy_lock);}/* copied from zoran_procfs */static int qcamvc_write_proc(struct file *file, const char *buffer,                           unsigned long count, void *data){	char *string, *sp;	char *line, *ldelim, *varname, *svar, *tdelim;	struct qcamvc_data* qcamvc = (struct qcamvc_data*) data;	string = sp = vmalloc(count + 1);	if (!string) {		printk("write_proc: can not allocate memory\n");		return -ENOMEM;	}	if (copy_from_user(string, buffer, count)) {		vfree (string);		return -EFAULT;	}	string[count] = 0;	ldelim = " \t\n";	tdelim = "=";	line = strpbrk(sp, ldelim);	while (line) {		*line = 0;		svar = strpbrk(sp, tdelim);		if (svar) {			*svar = 0;			varname = sp;			svar++;			setparam(qcamvc, varname, svar);		}		sp = line + 1;		line = strpbrk(sp, ldelim);	}	vfree(string);	return count;}static void create_proc_qcamvc_cam(struct qcamvc_data *qcamvc){	char name[8];	struct proc_dir_entry *ent;		if (!qcamvc_proc_root || !qcamvc)		return;	printk(KERN_INFO "QuickCam VC: Creating a camera entry in /proc/qcamvc\n");	//printk("QuickCam VC: QuickCam dev struct in create_proc_qcamvc %p\n",qcamvc);	sprintf(name, "video%d", qcamvc->vdev->minor);		ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, qcamvc_proc_root);	if (!ent)	{		printk(KERN_ERR "QuickCam VC: couldn't create /proc/qcamvc/%s\n", name);		return;	}	ent->data = qcamvc;	ent->read_proc = qcamvc_read_proc;	ent->write_proc = qcamvc_write_proc;	ent->size = 0;	qcamvc->proc_entry = ent;}static void destroy_proc_qcamvc_cam(struct qcamvc_data *qcamvc){	char name[8];		if (!qcamvc || !qcamvc->proc_entry)		return;		sprintf(name, "video%d", qcamvc->vdev->minor);	remove_proc_entry(name, qcamvc_proc_root);	qcamvc->proc_entry = NULL;}static void proc_qcamvc_create(void){	qcamvc_proc_root = create_proc_entry("qcamvc", S_IFDIR, 0);	if (qcamvc_proc_root)		qcamvc_proc_root->owner = THIS_MODULE;	else		LOG("Unable to initialise /proc/qcamvc\n");}static void __exit proc_qcamvc_destroy(void){	remove_proc_entry("qcamvc", 0);}#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS *//*****************************************************************************//*                                                                           *//* Video 4 Linux                                                             *//*                                                                           *//*****************************************************************************/static int qcamvc_vopen(struct inode *inode, struct file *file){	struct video_device *dev = video_devdata(file);	struct qcamvc_data *qcamvc = (struct qcamvc_data *)dev->priv;#ifdef DBG_CAM	printk("QuickCam qcamvc_vopen:\n");#endif	if (!qcamvc) {		printk("Internal error, qcamvc_data not found!\n");		return -ENODEV;	}	if (qcamvc->open_count > 0) {		printk("Camera already open\n");		return -EBUSY;	}	if (!try_module_get(qcamvc->ops->owner))	{		printk("qcamvc_vopen: try_module_get() FAILED\n");		return -ENODEV;	}	/* Init the frame buffers to nothing */	qcamvc->curframe = 0;	qcamvc->frame_count = 0;	qcamvc->frame_waiting = 0;	free_frame_buf(qcamvc);	if (qcamvc->ops->qcamvc_open(qcamvc->lowlevel_data))		return -ENODEV;	/* if the camera hasn't already been initialised, do it now */	if (!qcamvc->camera_init)	{		if (qcamvc_camera_init(qcamvc) == -1)			return -ENODEV;	}	/* Set ownership of /proc/qcamvc/videoX to current user */	if(qcamvc->proc_entry)		qcamvc->proc_entry->uid = current->uid;	file->private_data = dev;	qcamvc->open_count++;	return 0;}static int qcamvc_vrelease(struct inode *inode, struct file *file){	struct video_device *dev = video_devdata(file);	struct qcamvc_data *qcamvc = (struct qcamvc_data *)dev->priv;	if (qcamvc->ops)	{		/* Return ownership of /proc/qcamvc/videoX to root */		if(qcamvc->proc_entry)			qcamvc->proc_entry->uid = 0;			qcamvc->ops->qcamvc_close(qcamvc->lowlevel_data);		put_cam(qcamvc->ops);	}	if (--qcamvc->open_count == 0)	{		free_frame_buf(qcamvc);		free_raw_frame(qcamvc);		if (!qcamvc->ops)			kfree(qcamvc);	}		file->private_data = NULL;	return 0;}static ssize_t qcamvc_vread(struct file *file, char *data, size_t count, loff_t *ppos){ 	if (!file)		return -EINVAL;	struct video_device *dev = file->private_data;	struct qcamvc_data *qcamvc = dev->priv;	char *tmpbuf;	if (!qcamvc || !data || !count)		return -EINVAL;			if ( ((qcamvc->colordepth / 8) * qcamvc->width * qcamvc->height) > count )	{		printk("QuickCam VC: Image buffer (%ld) too small for bit count (%d bites, %d bytes required). Forcing to 24bit.\n",				count, qcamvc->colordepth, (qcamvc->colordepth / 8) * qcamvc->width * qcamvc->height);		/* force it to 24. If it still fails next time, there's not much we can do about it. */		qcamvc->colordepth = 24;		qcamvc->pixelformat = V4L2_PIX_FMT_RGB24;		return -EFAULT;	}	if (down_interruptible(&qcamvc->busy_lock))		return -EINTR;	/* grab a raw frame from the camera */	if (send_grab_image(qcamvc, 1))	{		up(&qcamvc->busy_lock);		return 0;	}		count = get_raw_frame(qcamvc);		if (count < 0)	{ /* error or no data from camera? */		up(&qcamvc->busy_lock);		return 0;	}	/* convert the raw CMYG image to something usable */	count = qcamvc->colordepth / 8 * qcamvc->width * qcamvc->height;	tmpbuf = vmalloc(count);	if (!tmpbuf)	{		printk("QCamVC: Could not allocate %ld bytes\n", count);		count = -ENOMEM;	}	else	{		qcamvc_parse(qcamvc, tmpbuf);		if (copy_to_user(data, tmpbuf, count))			count = -EFAULT;		vfree(tmpbuf);	}	up(&qcamvc->busy_lock);	return count;}static int qcamvc_vmmap(struct file *file, struct vm_area_struct *vma){	struct video_device *dev = file->private_data;	unsigned long start = vma->vm_start;	unsigned long size  = vma->vm_end - vma->vm_start;	unsigned long page, pos;	struct qcamvc_data *cam = dev->priv;	int retval;	if (!cam || !cam->ops)		return -ENODEV;		if (size > QCAMVC_NUMFRAMES*MAX_FRAME_SIZE)		return -EINVAL;	if (!cam || !cam->ops)		return -ENODEV;		if (down_interruptible(&cam->busy_lock))		return -EINTR;	if ( (retval = allocate_frame_buf(cam)) )	{		up(&cam->busy_lock);		return retval;	}	pos = (unsigned long)(cam->frame_buf);	while (size > 0) {		page = kvirt_to_pa(pos);		if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {			up(&cam->busy_lock);			return -EAGAIN;		}		start += PAGE_SIZE;		pos += PAGE_SIZE;		if (size > PAGE_SIZE)			size -= PAGE_SIZE;		else			size = 0;	}	DBG("qcamvc_mmap: %ld\n", size);	up(&cam->busy_lock);	return 0;}static int qcamvc_vioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	return video_usercopy(inode, file, cmd, arg, qcamvc_do_ioctl);}static int qcamvc_querycap(struct qcamvc_data *qcamvc, struct v4l2_capability *cap){	memset(cap, 0, sizeof(*cap));	strcpy(cap->driver,"qcamvc");	strlcpy(cap->card,qcamvc->camtypedesc,sizeof(cap->card));	cap->version = QCAMVC_VERSION_CODE;	cap->capabilities = 		V4L2_CAP_VIDEO_CAPTURE |		V4L2_CAP_READWRITE;	return 0;}static int qcamvc_enum_fmt(struct v4l2_fmtdesc *f){	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)		return -EINVAL;	switch(f->index)	{	case 0:		f->pixelformat = V4L2_PIX_FMT_RGB24;		strcpy(f->description, "RGB 8-8-8");		break;	case 1:		f->pixelformat = V4L2_PIX_FMT_BGR24;		strcpy(f->description, "BGRA 8-8-8");		break;	case 2:		f->pixelformat = V4L2_PIX_FMT_RGB32;		strcpy(f->description, "RGBA 8-8-8-8");		break;	case 3:		f->pixelformat = V4L2_PIX_FMT_BGR32;		strcpy(f->description, "BGR 8-8-8-8");		break;	case 4:		f->pixelformat = V4L2_PIX_FMT_RGB555;		strcpy(f->description, "RGB 5-5-5");		break;	case 5:		f->pixelformat = V4L2_PIX_FMT_RGB565;		strcpy(f->description, "RGB 5-6-5");		break;	case 6:		f->pixelformat = V4L2_PIX_FMT_GREY;		strcpy(f->description, "Greyscale");		break;	case 7:		f->pixelformat = V4L2_PIX_FMT_YUYV;		strcpy(f->description, "YUV 4:2:2 (YUYV)");		break;	case 8:		f->pixelformat = V4L2_PIX_FMT_UYVY;		strcpy(f->description, "YUV 4:2:2 (UYVY)");		break;	default:		return -EINVAL;	}	f->flags = 0;	return 0;}static int qcamvc_try_fmt(struct v4l2_format *f){	int depth;	int width;	int height;	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||	    (f->fmt.pix.field != V4L2_FIELD_INTERLACED &&	     f->fmt.pix.field != V4L2_FIELD_ANY))		return -EINVAL;	depth = mode_depth(f->fmt.pix.pixelformat);	if (!depth)		return -EINVAL;	width = f->fmt.pix.width;	height = f->fmt.pix.height;	make_valid_res(&width, &height);	f->fmt.pix.width = width;	f->fmt.pix.height = height;	f->fmt.pix.field = V4L2_FIELD_INTERLACED;	f->fmt.pix.bytesperline = f->fmt.pix.width * depth / 8;	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;	f->fmt.pix.colorspace = mode_colorspace(f->fmt.pix.pixelformat);	return 0;}static int qcamvc_s_fmt(struct qcamvc_data *qcamvc, struct v4l2_format *f){	int depth;	int newbpc;	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||	    (f->fmt.pix.field != V4L2_FIELD_INTERLACED &&	     f->fmt.pix.field != V4L2_FIELD_ANY))		return -EINVAL;	printk("Setting format to %dx%d %c%c%c%c\n",			f->fmt.pix.width, f->fmt.pix.height,			f->fmt.pix.pixelformat,			f->fmt.pix.pixelformat >> 8,			f->fmt.pix.pixelformat >> 16,			f->fmt.pix.pixelformat >> 24);	depth = mode_depth(f->fmt.pix.pixelformat);	if (!depth)		return -EINVAL;	newbpc = mode_bpc(f->fmt.pix.pixelformat);	if (newbpc != qcamvc->bpc)	{		if (down_interruptible(&qcamvc->busy_lock))			return -EBUSY;	}	qcamvc_set_res(qcamvc, f->fmt.pix.width, f->fmt.pix.height);	qcamvc->colordepth = depth;	qcamvc->pixelformat = f->fmt.pix.pixelformat;	f->fmt.pix.width = qcamvc->width;	f->fmt.pix.height = qcamvc->height;	f->fmt.pix.field = V4L2_FIELD_INTERLACED;	f->fmt.pix.bytesperline = f->fmt.pix.width * depth / 8;	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;	f->fmt.pix.colorspace = mode_colorspace(f->fmt.pix.pixelformat);	if (newbpc != qcamvc->bpc)	{		qcamvc->bpc = newbpc;		qcamvc_camera_init(qcamvc);		up(&qcamvc->busy_lock);	}	return 0;}static int qcamvc_g_fmt(struct qcamvc_data *qcamvc, struct v4l2_format *f){	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)		return -EINVAL;	f->fmt.pix.width = qcamvc->width;	f->fmt.pix.height = qcamvc->height;	f->fmt.pix.pixelformat = qcamvc->pixelformat;	f->fmt.pix.field = V4L2_FIELD_INTERLACED;	f->fmt.pix.bytesperline = f->fmt.pix.width * qcamvc->colordepth / 8;	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;	f->fmt.pix.colorspace = mode_colorspace(f->fmt.pix.pixelformat);	f->fmt.pix.priv = 0;	return 0;}static int qcamvc_cropcap(struct qcamvc_data *qcamvc, struct v4l2_cropcap *cap){	if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)		return -EINVAL;	memset(cap, 0, sizeof(*cap));	cap->bounds.left = 0;	cap->bounds.top = 0;	cap->bounds.width = qcamvc->width;	cap->bounds.height = qcamvc->height;	cap->defrect.left = 0;	cap->defrect.top = 0;	cap->defrect.width = qcamvc->width;	cap->defrect.height = qcamvc->height;	cap->pixelaspect.numerator = 1;	cap->pixelaspect.denominator = 1;	return 0;}#define IGNORE_IOCTL(x) case x: printk("QCamVC: Ignoring " #x "\n"); return -EINVAL;#define NOACTION_IOCTL(x) case x: printk("QCamVC: No action taken for " #x "\n"); return 0;static int qcamvc_enuminput(struct v4l2_input *pin){	if (pin->index != 0)		return -EINVAL;	strcpy(pin->name, "Camera");	pin->type = V4L2_INPUT_TYPE_CAMERA;	pin->audioset = 0;	pin->tuner = 0;	pin->std = 0;	pin->status = 0;	memset(pin->reserved, 0, sizeof(pin->reserved));	return 0;}static int qcamvc_queryctrl(struct v4l2_queryctrl *qc){	switch (qc->id)	{	case V4L2_CID_BRIGHTNESS:		strcpy(qc->name, "Brightness");		qc->type = V4L2_CTRL_TYPE_INTEGER;		qc->maximum = 256 << 8;		qc->default_value = 175 << 8;		qc->step = 256;		break;	case V4L2_CID_WHITENESS:		strcpy(qc->name, "Exposure");		qc->type = V4L2_CTRL_TYPE_INTEGER;		qc->maximum = 255 << 8;		qc->default_value = 57 << 8;		qc->step = 256;		break;	case V4L2_CID_CONTRAST:		strcpy(qc->name, "Contrast");		qc->type = V4L2_CTRL_TYPE_INTEGER;		qc->maximum = 255 << 8;		qc->default_value = 128 << 8;		qc->step = 256;		break;	case V4L2_CID_SATURATION:		strcpy(qc->name, "Saturation");		qc->type = V4L2_CTRL_TYPE_INTEGER;		qc->maximum = 255 << 8;		qc->default_value = 128 << 8;		qc->step = 256;		break;	case V4L2_CID_HUE:		strcpy(qc->name, "Hue");		qc->type = V4L2_CTRL_TYPE_INTEGER;		qc->maximum = 255 << 8;		qc->default_value = 128 << 8;		qc->step = 256;		break;	case V4L2_CID_DO_WHITE_BALANCE:		strcpy(qc->name, "Auto Brightness");		qc->type = V4L2_CTRL_TYPE_BOOLEAN;		qc->maximum = 1;		qc->default_value = 0;		qc->step = 1;		break;	default:		return -EINVAL;	}	qc->minimum = 0;	qc->flags = 0;	memset(qc->reserved, 0, sizeof(qc->reserved));	return 0;}static int qcamvc_s_ctrl(struct qcamvc_data *qcamvc, struct v4l2_control *c){	__u16 value = c->value; /* Works around a bug in V4L1-V4L2 conversion */	switch (c->id)

⌨️ 快捷键说明

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