📄 ovfx2.c
字号:
/* This code breaks a few apps (Gnomemeeting, possibly others). Disable it until a solution can be found */#if 0 if (vw->flags || vw->clipcount) return -EINVAL;#endif rc = ov51x_wait_frames_inactive(ov); if (rc) return rc; rc = mode_init_regs(ov, vw->width, vw->height, ov->frame[0].format, ov->sub_flag); if (rc < 0) return rc; for (i = 0; i < OVFX2_NUMFRAMES; i++) { ov->frame[i].width = vw->width; ov->frame[i].height = vw->height; } return 0; } case VIDIOCGWIN: { struct video_window *vw = arg; memset(vw, 0, sizeof(struct video_window)); vw->x = 0; /* FIXME */ vw->y = 0; vw->width = ov->frame[0].width; vw->height = ov->frame[0].height; PDEBUG(4, "Get window: %dx%d", vw->width, vw->height); return 0; } case VIDIOCGMBUF: { struct video_mbuf *vm = arg; int i; memset(vm, 0, sizeof(struct video_mbuf)); vm->size = OVFX2_NUMFRAMES * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight); vm->frames = OVFX2_NUMFRAMES; vm->offsets[0] = 0; for (i = 1; i < OVFX2_NUMFRAMES; i++) { vm->offsets[i] = vm->offsets[i-1] + MAX_DATA_SIZE(ov->maxwidth, ov->maxheight); } return 0; } case VIDIOCMCAPTURE: { struct video_mmap *vm = arg; int rc, depth; unsigned int f = vm->frame; PDEBUG(4, "MCAPTURE: frame: %d, %dx%d, %s", f, vm->width, vm->height, symbolic(v4l1_plist, vm->format)); depth = get_depth(vm->format); if (!depth) { PDEBUG(2, "MCAPTURE: invalid format (%s)", symbolic(v4l1_plist, vm->format)); return -EINVAL; } if (f >= OVFX2_NUMFRAMES) { err("MCAPTURE: invalid frame (%d)", f); return -EINVAL; } if (vm->width > ov->maxwidth || vm->height > ov->maxheight) { err("MCAPTURE: requested dimensions too big"); return -EINVAL; } if (ov->frame[f].grabstate == FRAME_GRABBING) { PDEBUG(4, "MCAPTURE: already grabbing"); return -EBUSY; } if (force_palette && (vm->format != force_palette)) { PDEBUG(2, "MCAPTURE: palette rejected (%s)", symbolic(v4l1_plist, vm->format)); return -EINVAL; } if ((ov->frame[f].width != vm->width) || (ov->frame[f].height != vm->height) || (ov->frame[f].format != vm->format) || (ov->frame[f].sub_flag != ov->sub_flag) || (ov->frame[f].depth != depth)) { PDEBUG(4, "MCAPTURE: change in image parameters"); rc = ov51x_wait_frames_inactive(ov); if (rc) return rc; rc = mode_init_regs(ov, vm->width, vm->height, vm->format, ov->sub_flag);#if 0 if (rc < 0) { PDEBUG(1, "Got error while initializing regs "); return rc; }#endif ov->frame[f].width = vm->width; ov->frame[f].height = vm->height; ov->frame[f].format = vm->format; ov->frame[f].sub_flag = ov->sub_flag; ov->frame[f].depth = depth; } /* Mark it as ready */ ov->frame[f].grabstate = FRAME_READY; return ovfx2_new_frame(ov, f); } case VIDIOCSYNC: { unsigned int fnum = *((unsigned int *) arg); struct ovfx2_frame *frame; int rc; if (fnum >= OVFX2_NUMFRAMES) { err("SYNC: invalid frame (%d)", fnum); return -EINVAL; } frame = &ov->frame[fnum]; PDEBUG(4, "syncing to frame %d, grabstate = %d", fnum, frame->grabstate); switch (frame->grabstate) { case FRAME_UNUSED: return -EINVAL; case FRAME_READY: case FRAME_GRABBING: case FRAME_ERROR:redo: rc = wait_event_interruptible(frame->wq, (frame->grabstate == FRAME_DONE) || (frame->grabstate == FRAME_ERROR) || !ov->present); if (rc) return rc; if (!ov->present) return -ENODEV; if (frame->grabstate == FRAME_ERROR) { if ((rc = ovfx2_new_frame(ov, fnum)) < 0) return rc; goto redo; } /* Fall through */ case FRAME_DONE: PDEBUG(4, "SYNC: frame %d is DONE", fnum); frame->grabstate = FRAME_UNUSED; /* Decompression, format conversion, etc... */ ovfx2_postprocess(ov, frame); break; } /* end switch */ return 0; } case VIDIOCGFBUF: { struct video_buffer *vb = arg; memset(vb, 0, sizeof(struct video_buffer)); return 0; } case VIDIOCGUNIT: { struct video_unit *vu = arg; memset(vu, 0, sizeof(struct video_unit)); vu->video = ov->vdev->minor; vu->vbi = VIDEO_NO_UNIT; vu->radio = VIDEO_NO_UNIT; vu->audio = VIDEO_NO_UNIT; vu->teletext = VIDEO_NO_UNIT; return 0; }#if defined(HAVE_V4L2) case VIDIOC_QUERYCAP: { struct v4l2_capability *c = arg; if (!v4l2) return -EINVAL; memset(c, 0, sizeof(*c)); strcpy(c->driver, "ovfx2"); // FIXME: Use a better description (e.g. from device table) snprintf(c->card, sizeof(c->card), "FX2/%s", symbolic(senlist, ov->sensor)); strncpy(c->bus_info, ov->usb_path, sizeof(c->bus_info)); c->version = DRIVER_VERSION_CODE; c->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;// FIXME: Implement this later// c->capabilities |= V4L2_CAP_STREAMING; return 0; } case VIDIOC_CROPCAP: { struct v4l2_cropcap *c = arg; if (c->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; c->bounds.left = 0; c->bounds.top = 0; c->bounds.width = ov->maxwidth; c->bounds.height = ov->maxheight; c->defrect.left = 0; c->defrect.top = 0; c->defrect.width = ov->maxwidth; c->defrect.height = ov->maxheight; return 0; } case VIDIOC_ENUM_FMT: { struct v4l2_fmtdesc *f = arg; const struct v4l2_fmtdesc *ptr = NULL; int index = f->index; if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; if (force_palette) { if (index) return -EINVAL; switch (force_palette) {// case VIDEO_PALETTE_GREY:// ptr = &ovfx2_fmt_grey;// break; case VIDEO_PALETTE_RGB24: ptr = &ovfx2_fmt_bgr24; break; } } else { switch (index) {// case 0:// ptr = &ovfx2_fmt_grey;// break; case 1: ptr = &ovfx2_fmt_bgr24; break; } } if (ptr) memcpy(f, ptr, sizeof(*f)); else return -EINVAL; f->index = index; f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; return 0; } case VIDIOC_G_FMT: { struct v4l2_format *f = arg; if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); f->fmt.pix.width = ov->frame[0].width; f->fmt.pix.height = ov->frame[0].height; switch (ov->frame[0].format) {// case VIDEO_PALETTE_GREY:// f->fmt.pix.pixelformat = V4L2_PIX_FMT_GREY;// f->fmt.pix.bytesperline = f->fmt.pix.width;// f->fmt.pix.sizeimage =// f->fmt.pix.bytesperline * f->fmt.pix.height;// break; case VIDEO_PALETTE_RGB24: f->fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24; f->fmt.pix.bytesperline = f->fmt.pix.width * 3; f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height; break; default: err("Bad pixel format"); return -ENODATA; } f->fmt.pix.field = V4L2_FIELD_NONE; // FIXME: This might not be right f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; return 0; } case VIDIOC_S_FMT: { struct v4l2_format *f = arg; int format, i; if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; switch (f->fmt.pix.pixelformat) {// case V4L2_PIX_FMT_GREY:// format = VIDEO_PALETTE_GREY;// f->fmt.pix.bytesperline = f->fmt.pix.width;// f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *// f->fmt.pix.height;// break; case V4L2_PIX_FMT_BGR24: format = VIDEO_PALETTE_RGB24; f->fmt.pix.bytesperline = f->fmt.pix.width * 3; f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height; break; default: PDEBUG(2, "App requested unsupported pix format: 0x%x", f->fmt.pix.pixelformat); /* According to V4L2 spec, we're allowed to return * -EINVAL iff v4l2_format is ambiguous */ return -EINVAL; } if (force_palette && (format != force_palette)) { PDEBUG(2, "palette rejected (%s)", symbolic(v4l1_plist, format)); return -EINVAL; } f->fmt.pix.field = V4L2_FIELD_NONE; // FIXME: This might not be right f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; // FIXME: This sucks. mode_init_regs() should handle this for (i = 0; i < OVFX2_NUMFRAMES; i++) { ov->frame[i].width = f->fmt.pix.width; ov->frame[i].height = f->fmt.pix.height; ov->frame[i].sub_flag = 0; ov->frame[i].depth = get_depth(format); ov->frame[i].format = format; } // FIXME: This function gives up rather than forcing the // closest supported size. return mode_init_regs(ov, f->fmt.pix.width, f->fmt.pix.height, format, 0); } case VIDIOC_ENUMINPUT: { struct v4l2_input *i = arg; __u32 n; n = i->index; if (n) return -EINVAL; memset(i, 0, sizeof(*i)); i->index = n; sprintf(i->name, "%s", "Camera"); i->type = V4L2_INPUT_TYPE_CAMERA; i->std = V4L2_STD_UNKNOWN; return 0; } case VIDIOC_G_INPUT: { *((int *)arg) = 0; return 0; } case VIDIOC_S_INPUT: { if (*((int *)arg)) return -EINVAL; else return 0; } case VIDIOC_QUERYCTRL: case VIDIOC_S_CTRL: case VIDIOC_G_CTRL: { struct v4l2_queryctrl *c = arg; int rc; /* Since controls are implemented at multiple driver layers, * we need translate the IDs in some cases and route them * accordingly. Apps should find private controls by name * rather than by ID */ if (c->id >= V4L2_CID_BASE || c->id < V4L2_CID_LASTP1) { rc = ovfx2_control_op(ov, cmd, c); // FIXME: -EINVAL could mean multiple things here if (rc == -EINVAL) rc = sensor_cmd(ov, cmd, c); } else if ((c->id >= V4L2_CID_PRIVATE_BASE) && (c->id < OVFX2_CID_LASTP1)) { rc = ovfx2_control_op(ov, cmd, c); } else if (c->id < (SENSOR_CID_OFFSET + OVCAMCHIP_V4L2_CID_LASTP1)) { c->id += SENSOR_CID_OFFSET; rc = sensor_cmd(ov, cmd, c); c->id -= SENSOR_CID_OFFSET; } else { rc = -EINVAL; } return rc; }// mmap() capture disabled until select() and rest of ioctls are implemented#if 0 case VIDIOC_REQBUFS: { struct v4l2_requestbuffers *rb = arg; if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || rb->memory != V4L2_MEMORY_MMAP) return -EINVAL; // FIXME: This shouldn't be hardcoded rb->count = OV511_NUMFRAMES;// memset(rb->reserved, 0, sizeof(*(rb->reserved))); // FIXME: Driver should check that this ioctl was called // before allowing buffers to be queued or queried return 0; } case VIDIOC_STREAMON: { int type = *((int *)arg); int i; if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; // FIXME: ISO streaming shouldn't be started until this ioctl for (i = 1; i < OV511_NUMFRAMES; i++) if (ov->frame[i].grabstate == FRAME_UNUSED) ov->frame[i].grabstate = FRAME_READY; // Racy!! return 0; } case VIDIOC_STREAMOFF: { int type = *((int *)arg); int i; if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; // FIXME: ISO streaming should be stopped by this ioctl for (i = 1; i < OV511_NUMFRAMES; i++) ov->frame[i].grabstate = FRAME_UNUSED; return 0; }#endif// Incomplete code#if 0 case: VIDIOC_QBUF: { struct v4l2_buffer *buf = arg; struct ov511_frame *frame; int rc; if (buf->index >= OV511_NUMFRAMES) { PDEBUG(2, "VIDIOC_QBUF: invalid index: %d", buf->index); return -EINVAL; } frame = &ov->frame[buf->index]; if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; switch (frame->grabstate) { case FRAME_READY: case FRAME_GRABBING: buf->flags |= V4L2_BUF_FLAG_MAPPED; buf->flags |= V4L2_BUF_FLAG_QUEUED; buf->flags = buf->flags &~ V4L2_BUF_FLAG_DONE; } return 0; } case: VIDIOC_DQBUF: { struct v4l2_buffer *buf = arg; if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; return 0; }#endif#endif /* HAVE_V4L2 */ default: PDEBUG(3, "Unsupported IOCtl: 0x%X", cmd); return -ENOIOCTLCMD; /* V4L layer handles this */ } /* end switch */ return 0;}static intovfx2_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ struct video_device *vdev = file->private_data; struct usb_ovfx2 *ov = video_get_drvdata(vdev); int rc; if (down_interruptible(&ov->lock)) return -EINTR; rc = video_usercopy(inode, file, cmd, arg, ovfx2_do_ioctl); up(&ov->lock); return rc;}static ssize_t#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)ovfx2_read(struct file *file, char __user *buf, size_t cnt, loff_t *p
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -