zr364xx.c

来自「linux 内核源代码」· C语言 代码 · 共 932 行 · 第 1/2 页

C
932
字号
	case V4L2_CID_BRIGHTNESS:		c->type = V4L2_CTRL_TYPE_INTEGER;		strcpy(c->name, "Brightness");		c->minimum = 0;		c->maximum = 127;		c->step = 1;		c->default_value = cam->brightness;		c->flags = 0;		break;	default:		return -EINVAL;	}	return 0;}static int zr364xx_vidioc_s_ctrl(struct file *file, void *priv,				 struct v4l2_control *c){	struct video_device *vdev = video_devdata(file);	struct zr364xx_camera *cam;	if (vdev == NULL)		return -ENODEV;	cam = video_get_drvdata(vdev);	switch (c->id) {	case V4L2_CID_BRIGHTNESS:		cam->brightness = c->value;		break;	default:		return -EINVAL;	}	return 0;}static int zr364xx_vidioc_g_ctrl(struct file *file, void *priv,				 struct v4l2_control *c){	struct video_device *vdev = video_devdata(file);	struct zr364xx_camera *cam;	if (vdev == NULL)		return -ENODEV;	cam = video_get_drvdata(vdev);	switch (c->id) {	case V4L2_CID_BRIGHTNESS:		c->value = cam->brightness;		break;	default:		return -EINVAL;	}	return 0;}static int zr364xx_vidioc_enum_fmt_cap(struct file *file,				       void *priv, struct v4l2_fmtdesc *f){	if (f->index > 0)		return -EINVAL;	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)		return -EINVAL;	memset(f, 0, sizeof(*f));	f->index = 0;	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;	f->flags = V4L2_FMT_FLAG_COMPRESSED;	strcpy(f->description, "JPEG");	f->pixelformat = V4L2_PIX_FMT_JPEG;	return 0;}static int zr364xx_vidioc_try_fmt_cap(struct file *file, void *priv,				      struct v4l2_format *f){	struct video_device *vdev = video_devdata(file);	struct zr364xx_camera *cam;	if (vdev == NULL)		return -ENODEV;	cam = video_get_drvdata(vdev);	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)		return -EINVAL;	if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG)		return -EINVAL;	if (f->fmt.pix.field != V4L2_FIELD_ANY &&	    f->fmt.pix.field != V4L2_FIELD_NONE)		return -EINVAL;	f->fmt.pix.field = V4L2_FIELD_NONE;	f->fmt.pix.width = cam->width;	f->fmt.pix.height = cam->height;	f->fmt.pix.bytesperline = f->fmt.pix.width * 2;	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;	f->fmt.pix.colorspace = 0;	f->fmt.pix.priv = 0;	return 0;}static int zr364xx_vidioc_g_fmt_cap(struct file *file, void *priv,				    struct v4l2_format *f){	struct video_device *vdev = video_devdata(file);	struct zr364xx_camera *cam;	if (vdev == NULL)		return -ENODEV;	cam = video_get_drvdata(vdev);	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)		return -EINVAL;	memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;	f->fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;	f->fmt.pix.field = V4L2_FIELD_NONE;	f->fmt.pix.width = cam->width;	f->fmt.pix.height = cam->height;	f->fmt.pix.bytesperline = f->fmt.pix.width * 2;	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;	f->fmt.pix.colorspace = 0;	f->fmt.pix.priv = 0;	return 0;}static int zr364xx_vidioc_s_fmt_cap(struct file *file, void *priv,				    struct v4l2_format *f){	struct video_device *vdev = video_devdata(file);	struct zr364xx_camera *cam;	if (vdev == NULL)		return -ENODEV;	cam = video_get_drvdata(vdev);	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)		return -EINVAL;	if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG)		return -EINVAL;	if (f->fmt.pix.field != V4L2_FIELD_ANY &&	    f->fmt.pix.field != V4L2_FIELD_NONE)		return -EINVAL;	f->fmt.pix.field = V4L2_FIELD_NONE;	f->fmt.pix.width = cam->width;	f->fmt.pix.height = cam->height;	f->fmt.pix.bytesperline = f->fmt.pix.width * 2;	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;	f->fmt.pix.colorspace = 0;	f->fmt.pix.priv = 0;	DBG("ok!");	return 0;}static int zr364xx_vidioc_streamon(struct file *file, void *priv,				   enum v4l2_buf_type type){	return 0;}static int zr364xx_vidioc_streamoff(struct file *file, void *priv,				    enum v4l2_buf_type type){	return 0;}/* open the camera */static int zr364xx_open(struct inode *inode, struct file *file){	struct video_device *vdev = video_devdata(file);	struct zr364xx_camera *cam = video_get_drvdata(vdev);	struct usb_device *udev = cam->udev;	int i, err;	DBG("zr364xx_open");	cam->skip = 2;	err = video_exclusive_open(inode, file);	if (err < 0)		return err;	if (!cam->framebuf) {		cam->framebuf = vmalloc_32(MAX_FRAME_SIZE * FRAMES);		if (!cam->framebuf) {			info("vmalloc_32 failed!");			return -ENOMEM;		}	}	mutex_lock(&cam->lock);	for (i = 0; init[cam->method][i].size != -1; i++) {		err =		    send_control_msg(udev, 1, init[cam->method][i].value,				     0, init[cam->method][i].bytes,				     init[cam->method][i].size);		if (err < 0) {			info("error during open sequence: %d", i);			mutex_unlock(&cam->lock);			return err;		}	}	file->private_data = vdev;	/* Added some delay here, since opening/closing the camera quickly,	 * like Ekiga does during its startup, can crash the webcam	 */	mdelay(100);	mutex_unlock(&cam->lock);	return 0;}/* release the camera */static int zr364xx_release(struct inode *inode, struct file *file){	struct video_device *vdev = video_devdata(file);	struct zr364xx_camera *cam;	struct usb_device *udev;	int i, err;	DBG("zr364xx_release");	if (vdev == NULL)		return -ENODEV;	cam = video_get_drvdata(vdev);	udev = cam->udev;	mutex_lock(&cam->lock);	for (i = 0; i < 2; i++) {		err =		    send_control_msg(udev, 1, init[cam->method][i].value,				     0, init[i][cam->method].bytes,				     init[cam->method][i].size);		if (err < 0) {			info("error during release sequence");			mutex_unlock(&cam->lock);			return err;		}	}	file->private_data = NULL;	video_exclusive_release(inode, file);	/* Added some delay here, since opening/closing the camera quickly,	 * like Ekiga does during its startup, can crash the webcam	 */	mdelay(100);	mutex_unlock(&cam->lock);	return 0;}static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma){	void *pos;	unsigned long start = vma->vm_start;	unsigned long size = vma->vm_end - vma->vm_start;	struct video_device *vdev = video_devdata(file);	struct zr364xx_camera *cam;	DBG("zr364xx_mmap: %ld\n", size);	if (vdev == NULL)		return -ENODEV;	cam = video_get_drvdata(vdev);	pos = cam->framebuf;	while (size > 0) {		if (vm_insert_page(vma, start, vmalloc_to_page(pos)))			return -EAGAIN;		start += PAGE_SIZE;		pos += PAGE_SIZE;		if (size > PAGE_SIZE)			size -= PAGE_SIZE;		else			size = 0;	}	return 0;}static struct file_operations zr364xx_fops = {	.owner = THIS_MODULE,	.open = zr364xx_open,	.release = zr364xx_release,	.read = zr364xx_read,	.mmap = zr364xx_mmap,	.ioctl = video_ioctl2,	.llseek = no_llseek,};static struct video_device zr364xx_template = {	.owner = THIS_MODULE,	.name = DRIVER_DESC,	.type = VID_TYPE_CAPTURE,	.fops = &zr364xx_fops,	.release = video_device_release,	.minor = -1,	.vidioc_querycap	= zr364xx_vidioc_querycap,	.vidioc_enum_fmt_cap	= zr364xx_vidioc_enum_fmt_cap,	.vidioc_try_fmt_cap	= zr364xx_vidioc_try_fmt_cap,	.vidioc_s_fmt_cap	= zr364xx_vidioc_s_fmt_cap,	.vidioc_g_fmt_cap	= zr364xx_vidioc_g_fmt_cap,	.vidioc_enum_input	= zr364xx_vidioc_enum_input,	.vidioc_g_input		= zr364xx_vidioc_g_input,	.vidioc_s_input		= zr364xx_vidioc_s_input,	.vidioc_streamon	= zr364xx_vidioc_streamon,	.vidioc_streamoff	= zr364xx_vidioc_streamoff,	.vidioc_queryctrl	= zr364xx_vidioc_queryctrl,	.vidioc_g_ctrl		= zr364xx_vidioc_g_ctrl,	.vidioc_s_ctrl		= zr364xx_vidioc_s_ctrl,};/*******************//* USB integration *//*******************/static int zr364xx_probe(struct usb_interface *intf,			 const struct usb_device_id *id){	struct usb_device *udev = interface_to_usbdev(intf);	struct zr364xx_camera *cam = NULL;	int err;	DBG("probing...");	info(DRIVER_DESC " compatible webcam plugged");	info("model %04x:%04x detected", udev->descriptor.idVendor,	     udev->descriptor.idProduct);	cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL);	if (cam == NULL) {		info("cam: out of memory !");		return -ENOMEM;	}	/* save the init method used by this camera */	cam->method = id->driver_info;	cam->vdev = video_device_alloc();	if (cam->vdev == NULL) {		info("cam->vdev: out of memory !");		kfree(cam);		return -ENOMEM;	}	memcpy(cam->vdev, &zr364xx_template, sizeof(zr364xx_template));	video_set_drvdata(cam->vdev, cam);	if (debug)		cam->vdev->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;	cam->udev = udev;	if ((cam->buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL)) == NULL) {		info("cam->buffer: out of memory !");		video_device_release(cam->vdev);		kfree(cam);		return -ENODEV;	}	switch (mode) {	case 1:		info("160x120 mode selected");		cam->width = 160;		cam->height = 120;		break;	case 2:		info("640x480 mode selected");		cam->width = 640;		cam->height = 480;		break;	default:		info("320x240 mode selected");		cam->width = 320;		cam->height = 240;		break;	}	m0d1[0] = mode;	m1[2].value = 0xf000 + mode;	m2[1].value = 0xf000 + mode;	header2[437] = cam->height / 256;	header2[438] = cam->height % 256;	header2[439] = cam->width / 256;	header2[440] = cam->width % 256;	cam->nb = 0;	cam->brightness = 64;	mutex_init(&cam->lock);	err = video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1);	if (err) {		info("video_register_device failed");		video_device_release(cam->vdev);		kfree(cam->buffer);		kfree(cam);		return err;	}	usb_set_intfdata(intf, cam);	info(DRIVER_DESC " controlling video device %d", cam->vdev->minor);	return 0;}static void zr364xx_disconnect(struct usb_interface *intf){	struct zr364xx_camera *cam = usb_get_intfdata(intf);	usb_set_intfdata(intf, NULL);	dev_set_drvdata(&intf->dev, NULL);	info(DRIVER_DESC " webcam unplugged");	if (cam->vdev)		video_unregister_device(cam->vdev);	cam->vdev = NULL;	kfree(cam->buffer);	if (cam->framebuf)		vfree(cam->framebuf);	kfree(cam);}/**********************//* Module integration *//**********************/static struct usb_driver zr364xx_driver = {	.name = "zr364xx",	.probe = zr364xx_probe,	.disconnect = zr364xx_disconnect,	.id_table = device_table};static int __init zr364xx_init(void){	int retval;	retval = usb_register(&zr364xx_driver);	if (retval)		info("usb_register failed!");	else		info(DRIVER_DESC " module loaded");	return retval;}static void __exit zr364xx_exit(void){	info(DRIVER_DESC " module unloaded");	usb_deregister(&zr364xx_driver);}module_init(zr364xx_init);module_exit(zr364xx_exit);MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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