📄 cpia.c
字号:
case VIDIOCSPICT: { struct video_picture p; if (copy_from_user(&p, arg, sizeof(p))) return -EFAULT; return 0; } case VIDIOCSWIN: { struct video_window vw; if (copy_from_user(&vw, arg, sizeof(vw))) return -EFAULT; if (vw.flags) return -EINVAL; if (vw.clipcount) return -EINVAL; if (vw.height != 288) return -EINVAL; if (vw.width != 352) return -EINVAL; cpia->compress = 0; return 0; } case VIDIOCGWIN: { struct video_window vw; vw.x = 0; vw.y = 0; vw.width = 352; vw.height = 288; vw.chromakey = 0; vw.flags = 30; /* 30 fps */ if (copy_to_user(arg, &vw, sizeof(vw))) return -EFAULT; return 0; } case VIDIOCGMBUF: { struct video_mbuf vm; memset(&vm, 0, sizeof(vm)); vm.size = MAX_FRAME_SIZE * 2; vm.frames = 2; vm.offsets[0] = 0; vm.offsets[1] = MAX_FRAME_SIZE; if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm))) return -EFAULT; return 0; } case VIDIOCMCAPTURE: { struct video_mmap vm; if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm))) return -EFAULT; if (debug >= 1) printk(KERN_DEBUG "frame: %d, size: %dx%d, format: %d\n", vm.frame, vm.width, vm.height, vm.format); if (vm.format != VIDEO_PALETTE_RGB24) return -EINVAL; if ((vm.frame != 0) && (vm.frame != 1)) return -EINVAL; if (cpia->frame[vm.frame].grabstate == FRAME_GRABBING) return -EBUSY; /* Don't compress if the size changed */ if ((cpia->frame[vm.frame].width != vm.width) || (cpia->frame[vm.frame].height != vm.height)) cpia->compress = 0; cpia->frame[vm.frame].width = vm.width; cpia->frame[vm.frame].height = vm.height; /* Mark it as ready */ cpia->frame[vm.frame].grabstate = FRAME_READY; return cpia_new_frame(cpia, vm.frame); } case VIDIOCSYNC: { int frame; if (copy_from_user((void *)&frame, arg, sizeof(int))) return -EFAULT; if (debug >= 1) printk(KERN_DEBUG "cpia: syncing to frame %d\n", frame); switch (cpia->frame[frame].grabstate) { case FRAME_UNUSED: return -EINVAL; case FRAME_READY: case FRAME_GRABBING: case FRAME_ERROR:redo: do {#if 0 init_waitqueue_head(&cpia->frame[frame].wq);#endif interruptible_sleep_on(&cpia->frame[frame].wq); if (signal_pending(current)) return -EINTR; } while (cpia->frame[frame].grabstate == FRAME_GRABBING); if (cpia->frame[frame].grabstate == FRAME_ERROR) { int ret; if ((ret = cpia_new_frame(cpia, frame)) < 0) return ret; goto redo; } case FRAME_DONE: cpia->frame[frame].grabstate = FRAME_UNUSED; break; } cpia->frame[frame].grabstate = FRAME_UNUSED; return 0; } case VIDIOCGFBUF: { struct video_buffer vb; memset(&vb, 0, sizeof(vb)); vb.base = NULL; /* frame buffer not supported, not used */ if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb))) return -EFAULT; return 0; } case VIDIOCKEY: return 0; case VIDIOCCAPTURE: return -EINVAL; case VIDIOCSFBUF: return -EINVAL; case VIDIOCGTUNER: case VIDIOCSTUNER: return -EINVAL; case VIDIOCGFREQ: case VIDIOCSFREQ: return -EINVAL; case VIDIOCGAUDIO: case VIDIOCSAUDIO: return -EINVAL; default: return -ENOIOCTLCMD; } return 0;}static long cpia_read(struct video_device *dev, char *buf, unsigned long count, int noblock){ struct usb_cpia *cpia = (struct usb_cpia *)dev; int frmx = -1; volatile struct cpia_frame *frame; if (debug >= 1) printk(KERN_DEBUG "cpia_read: %ld bytes, noblock=%d\n", count, noblock); if (!dev || !buf) return -EFAULT; /* See if a frame is completed, then use it. */ if (cpia->frame[0].grabstate >= FRAME_DONE) /* _DONE or _ERROR */ frmx = 0; else if (cpia->frame[1].grabstate >= FRAME_DONE)/* _DONE or _ERROR */ frmx = 1; if (noblock && (frmx == -1)) return -EAGAIN; /* If no FRAME_DONE, look for a FRAME_GRABBING state. */ /* See if a frame is in process (grabbing), then use it. */ if (frmx == -1) { if (cpia->frame[0].grabstate == FRAME_GRABBING) frmx = 0; else if (cpia->frame[1].grabstate == FRAME_GRABBING) frmx = 1; } /* If no frame is active, start one. */ if (frmx == -1) cpia_new_frame(cpia, frmx = 0); frame = &cpia->frame[frmx];restart: while (frame->grabstate == FRAME_GRABBING) { interruptible_sleep_on(&frame->wq); if (signal_pending(current)) return -EINTR; } if (frame->grabstate == FRAME_ERROR) { frame->bytes_read = 0;printk("cpia_read: errored frame %d\n", cpia->curframe); if (cpia_new_frame(cpia, frmx)) printk(KERN_ERR "cpia_read: cpia_new_frame error\n"); goto restart; } if (debug >= 1) printk(KERN_DEBUG "cpia_read: frmx=%d, bytes_read=%ld, scanlength=%ld\n", frmx, frame->bytes_read, frame->scanlength); /* copy bytes to user space; we allow for partials reads */ if ((count + frame->bytes_read) > frame->scanlength) count = frame->scanlength - frame->bytes_read; if (copy_to_user(buf, frame->data + frame->bytes_read, count)) return -EFAULT; frame->bytes_read += count; if (debug >= 1) printk(KERN_DEBUG "cpia_read: {copy} count used=%ld, new bytes_read=%ld\n", count, frame->bytes_read); if (frame->bytes_read >= frame->scanlength) { /* All data has been read */ frame->bytes_read = 0; /* Mark it as available to be used again. */ cpia->frame[frmx].grabstate = FRAME_UNUSED; if (cpia_new_frame(cpia, frmx ? 0 : 1)) printk(KERN_ERR "cpia_read: cpia_new_frame returned error\n"); } return count;}static int cpia_mmap(struct video_device *dev, const char *adr, unsigned long size){ struct usb_cpia *cpia = (struct usb_cpia *)dev; unsigned long start = (unsigned long)adr; unsigned long page, pos; if (size > (((2 * MAX_FRAME_SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) return -EINVAL; pos = (unsigned long)cpia->fbuf; while (size > 0) { page = kvirt_to_pa(pos); if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) return -EAGAIN; start += PAGE_SIZE; pos += PAGE_SIZE; if (size > PAGE_SIZE) size -= PAGE_SIZE; else size = 0; } return 0;}static struct video_device cpia_template = { "CPiA USB Camera", VID_TYPE_CAPTURE, VID_HARDWARE_CPIA, cpia_open, cpia_close, cpia_read, cpia_write, NULL, cpia_ioctl, cpia_mmap, cpia_init_done, NULL, 0, 0};static int usb_cpia_configure(struct usb_cpia *cpia){ struct usb_device *dev = cpia->dev; unsigned char version[4]; /* Set altsetting 0 */ if (usb_set_interface(dev, cpia->iface, 0) < 0) { printk(KERN_ERR "usb_set_interface error\n"); return -EBUSY; } if (usb_cpia_get_version(dev, version) < 0) { printk(KERN_ERR "cpia_get_version error\n"); return -EBUSY; } if (debug >= 1) printk(KERN_DEBUG "cpia: Firmware v%d.%d, VC Hardware v%d.%d\n", version[0], version[1], version[2], version[3]); memcpy(&cpia->vdev, &cpia_template, sizeof(cpia_template)); init_waitqueue_head(&cpia->frame[0].wq); init_waitqueue_head(&cpia->frame[1].wq); if (video_register_device(&cpia->vdev, VFL_TYPE_GRABBER) == -1) { printk(KERN_ERR "video_register_device failed\n"); return -EBUSY; } if (usb_cpia_goto_hi_power(dev) < 0) { printk(KERN_ERR "cpia_goto_hi_power error\n"); goto error; } if (usb_cpia_get_vp_version(dev, version) < 0) { printk(KERN_ERR "cpia_get_vp_version error\n"); goto error; } if (debug >= 1) { printk(KERN_DEBUG "cpia: VP v%d rev %d\n", version[0], version[1]); printk(KERN_DEBUG "cpia: Camera Head ID %04X\n", (version[3] << 8) + version[2]); } /* Turn on continuous grab */ if (usb_cpia_set_grab_mode(dev, 1) < 0) { printk(KERN_ERR "cpia_set_grab_mode error\n"); goto error; } /* Set up the sensor to be 30fps */ if (usb_cpia_set_sensor_fps(dev, 1, 0) < 0) { printk(KERN_ERR "cpia_set_sensor_fps error\n"); goto error; } /* Set video into CIF mode, and order into YUYV mode */ if (usb_cpia_set_format(dev, FORMAT_CIF, FORMAT_422, FORMAT_YUYV) < 0) { printk(KERN_ERR "cpia_set_format error\n"); goto error; } /* Turn off compression */ if (usb_cpia_set_compression(dev, COMP_DISABLED, DONT_DECIMATE) < 0) { printk(KERN_ERR "cpia_set_compression error\n"); goto error; } cpia->compress = 0; return 0;error: video_unregister_device(&cpia->vdev); usb_driver_release_interface(&cpia_driver, &dev->actconfig->interface[0]); kfree(cpia); return -EBUSY;}static void * cpia_probe(struct usb_device *dev, unsigned int ifnum){ struct usb_interface_descriptor *interface; struct usb_cpia *cpia; /* We don't handle multi-config cameras */ if (dev->descriptor.bNumConfigurations != 1) return NULL; interface = &dev->actconfig->interface[ifnum].altsetting[0]; /* Is it a CPiA? */ if (dev->descriptor.idVendor != 0x0553) return NULL; if (dev->descriptor.idProduct != 0x0002) return NULL; /* Checking vendor/product should be enough, but what the hell */ if (interface->bInterfaceClass != 0xFF) return NULL; if (interface->bInterfaceSubClass != 0x00) return NULL; /* We found a CPiA */ printk(KERN_INFO "USB CPiA camera found\n"); if ((cpia = kmalloc(sizeof(*cpia), GFP_KERNEL)) == NULL) { printk(KERN_ERR "couldn't kmalloc cpia struct\n"); return NULL; } memset(cpia, 0, sizeof(*cpia)); cpia->dev = dev; cpia->iface = interface->bInterfaceNumber; if (!usb_cpia_configure(cpia)) { cpia->user=0; init_MUTEX(&cpia->lock); /* to 1 == available */ return cpia; } else return NULL;}static void cpia_disconnect(struct usb_device *dev, void *ptr){ struct usb_cpia *cpia = (struct usb_cpia *) ptr; video_unregister_device(&cpia->vdev); usb_driver_release_interface(&cpia_driver, &cpia->dev->actconfig->interface[0]); /* Free the memory */ kfree(cpia);}static struct usb_driver cpia_driver = { "cpia", cpia_probe, cpia_disconnect, { NULL, NULL }};int usb_cpia_init(void){ return usb_register(&cpia_driver);}void usb_cpia_cleanup(void){ usb_deregister(&cpia_driver);}#ifdef MODULEint init_module(void){ return usb_cpia_init();}void cleanup_module(void){ usb_cpia_cleanup();}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -