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 + -
显示快捷键?