📄 cpia2_v4l.c
字号:
frame->length = 0; return 0; } mutex_unlock(&cam->busy_lock); wait_event_interruptible(cam->wq_stream, !cam->streaming || frame->status == FRAME_READY); mutex_lock(&cam->busy_lock); if (signal_pending(current)) return -ERESTARTSYS; if(!cam->present) return -ENOTTY; }}/****************************************************************************** * * ioctl_set_window_size * *****************************************************************************/static int ioctl_set_window_size(void *arg, struct camera_data *cam, struct cpia2_fh *fh){ /* copy_from_user, check validity, copy to internal structure */ struct video_window *vw; int frame, err; vw = arg; if (vw->clipcount != 0) /* clipping not supported */ return -EINVAL; if (vw->clips != NULL) /* clipping not supported */ return -EINVAL; /* Ensure that only this process can change the format. */ err = v4l2_prio_change(&cam->prio, &fh->prio, V4L2_PRIORITY_RECORD); if(err != 0) return err; cam->pixelformat = V4L2_PIX_FMT_JPEG; /* Be sure to supply the Huffman tables, this isn't MJPEG */ cam->params.compression.inhibit_htables = 0; /* we set the video window to something smaller or equal to what * is requested by the user??? */ DBG("Requested width = %d, height = %d\n", vw->width, vw->height); if (vw->width != cam->vw.width || vw->height != cam->vw.height) { cam->vw.width = vw->width; cam->vw.height = vw->height; cam->params.roi.width = vw->width; cam->params.roi.height = vw->height; cpia2_set_format(cam); } for (frame = 0; frame < cam->num_frames; ++frame) { if (cam->buffers[frame].status == FRAME_READING) if ((err = sync(cam, frame)) < 0) return err; cam->buffers[frame].status = FRAME_EMPTY; } return 0;}/****************************************************************************** * * ioctl_get_mbuf * *****************************************************************************/static int ioctl_get_mbuf(void *arg, struct camera_data *cam){ struct video_mbuf *vm; int i; vm = arg; memset(vm, 0, sizeof(*vm)); vm->size = cam->frame_size*cam->num_frames; vm->frames = cam->num_frames; for (i = 0; i < cam->num_frames; i++) vm->offsets[i] = cam->frame_size * i; return 0;}/****************************************************************************** * * ioctl_mcapture * *****************************************************************************/static int ioctl_mcapture(void *arg, struct camera_data *cam, struct cpia2_fh *fh){ struct video_mmap *vm; int video_size, err; vm = arg; if (vm->frame < 0 || vm->frame >= cam->num_frames) return -EINVAL; /* set video size */ video_size = cpia2_match_video_size(vm->width, vm->height); if (cam->video_size < 0) { return -EINVAL; } /* Ensure that only this process can change the format. */ err = v4l2_prio_change(&cam->prio, &fh->prio, V4L2_PRIORITY_RECORD); if(err != 0) return err; if (video_size != cam->video_size) { cam->video_size = video_size; cam->params.roi.width = vm->width; cam->params.roi.height = vm->height; cpia2_set_format(cam); } if (cam->buffers[vm->frame].status == FRAME_READING) if ((err=sync(cam, vm->frame)) < 0) return err; cam->buffers[vm->frame].status = FRAME_EMPTY; return cpia2_usb_stream_start(cam,cam->params.camera_state.stream_mode);}/****************************************************************************** * * ioctl_sync * *****************************************************************************/static int ioctl_sync(void *arg, struct camera_data *cam){ int frame; frame = *(int*)arg; if (frame < 0 || frame >= cam->num_frames) return -EINVAL; return sync(cam, frame);}/****************************************************************************** * * ioctl_set_gpio * *****************************************************************************/static int ioctl_set_gpio(void *arg, struct camera_data *cam){ __u32 gpio_val; gpio_val = *(__u32*) arg; if (gpio_val &~ 0xFFU) return -EINVAL; return cpia2_set_gpio(cam, (unsigned char)gpio_val);}/****************************************************************************** * * ioctl_querycap * * V4L2 device capabilities * *****************************************************************************/static int ioctl_querycap(void *arg, struct camera_data *cam){ struct v4l2_capability *vc = arg; memset(vc, 0, sizeof(*vc)); strcpy(vc->driver, "cpia2"); if (cam->params.pnp_id.product == 0x151) strcpy(vc->card, "QX5 Microscope"); else strcpy(vc->card, "CPiA2 Camera"); switch (cam->params.pnp_id.device_type) { case DEVICE_STV_672: strcat(vc->card, " (672/"); break; case DEVICE_STV_676: strcat(vc->card, " (676/"); break; default: strcat(vc->card, " (???/"); break; } switch (cam->params.version.sensor_flags) { case CPIA2_VP_SENSOR_FLAGS_404: strcat(vc->card, "404)"); break; case CPIA2_VP_SENSOR_FLAGS_407: strcat(vc->card, "407)"); break; case CPIA2_VP_SENSOR_FLAGS_409: strcat(vc->card, "409)"); break; case CPIA2_VP_SENSOR_FLAGS_410: strcat(vc->card, "410)"); break; case CPIA2_VP_SENSOR_FLAGS_500: strcat(vc->card, "500)"); break; default: strcat(vc->card, "???)"); break; } if (usb_make_path(cam->dev, vc->bus_info, sizeof(vc->bus_info)) <0) memset(vc->bus_info,0, sizeof(vc->bus_info)); vc->version = KERNEL_VERSION(CPIA2_MAJ_VER, CPIA2_MIN_VER, CPIA2_PATCH_VER); vc->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; return 0;}/****************************************************************************** * * ioctl_input * * V4L2 input get/set/enumerate * *****************************************************************************/static int ioctl_input(unsigned int ioclt_nr,void *arg,struct camera_data *cam){ struct v4l2_input *i = arg; if(ioclt_nr != VIDIOC_G_INPUT) { if (i->index != 0) return -EINVAL; } memset(i, 0, sizeof(*i)); strcpy(i->name, "Camera"); i->type = V4L2_INPUT_TYPE_CAMERA; return 0;}/****************************************************************************** * * ioctl_enum_fmt * * V4L2 format enumerate * *****************************************************************************/static int ioctl_enum_fmt(void *arg,struct camera_data *cam){ struct v4l2_fmtdesc *f = arg; int index = f->index; if (index < 0 || index > 1) return -EINVAL; memset(f, 0, sizeof(*f)); f->index = index; f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->flags = V4L2_FMT_FLAG_COMPRESSED; switch(index) { case 0: strcpy(f->description, "MJPEG"); f->pixelformat = V4L2_PIX_FMT_MJPEG; break; case 1: strcpy(f->description, "JPEG"); f->pixelformat = V4L2_PIX_FMT_JPEG; break; default: return -EINVAL; } return 0;}/****************************************************************************** * * ioctl_try_fmt * * V4L2 format try * *****************************************************************************/static int ioctl_try_fmt(void *arg,struct camera_data *cam){ struct v4l2_format *f = arg; if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG && f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) return -EINVAL; f->fmt.pix.field = V4L2_FIELD_NONE; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = cam->frame_size; f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; f->fmt.pix.priv = 0; switch (cpia2_match_video_size(f->fmt.pix.width, f->fmt.pix.height)) { case VIDEOSIZE_VGA: f->fmt.pix.width = 640; f->fmt.pix.height = 480; break; case VIDEOSIZE_CIF: f->fmt.pix.width = 352; f->fmt.pix.height = 288; break; case VIDEOSIZE_QVGA: f->fmt.pix.width = 320; f->fmt.pix.height = 240; break; case VIDEOSIZE_288_216: f->fmt.pix.width = 288; f->fmt.pix.height = 216; break; case VIDEOSIZE_256_192: f->fmt.pix.width = 256; f->fmt.pix.height = 192; break; case VIDEOSIZE_224_168: f->fmt.pix.width = 224; f->fmt.pix.height = 168; break; case VIDEOSIZE_192_144: f->fmt.pix.width = 192; f->fmt.pix.height = 144; break; case VIDEOSIZE_QCIF: default: f->fmt.pix.width = 176; f->fmt.pix.height = 144; break; } return 0;}/****************************************************************************** * * ioctl_set_fmt * * V4L2 format set * *****************************************************************************/static int ioctl_set_fmt(void *arg,struct camera_data *cam, struct cpia2_fh *fh){ struct v4l2_format *f = arg; int err, frame; err = ioctl_try_fmt(arg, cam); if(err != 0) return err; /* Ensure that only this process can change the format. */ err = v4l2_prio_change(&cam->prio, &fh->prio, V4L2_PRIORITY_RECORD); if(err != 0) { return err; } cam->pixelformat = f->fmt.pix.pixelformat; /* NOTE: This should be set to 1 for MJPEG, but some apps don't handle * the missing Huffman table properly. */ cam->params.compression.inhibit_htables = 0; /*f->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG;*/ /* we set the video window to something smaller or equal to what * is requested by the user??? */ DBG("Requested width = %d, height = %d\n", f->fmt.pix.width, f->fmt.pix.height); if (f->fmt.pix.width != cam->vw.width || f->fmt.pix.height != cam->vw.height) { cam->vw.width = f->fmt.pix.width; cam->vw.height = f->fmt.pix.height; cam->params.roi.width = f->fmt.pix.width; cam->params.roi.height = f->fmt.pix.height; cpia2_set_format(cam); } for (frame = 0; frame < cam->num_frames; ++frame) { if (cam->buffers[frame].status == FRAME_READING) if ((err = sync(cam, frame)) < 0) return err; cam->buffers[frame].status = FRAME_EMPTY; } return 0;}/****************************************************************************** * * ioctl_get_fmt * * V4L2 format get * *****************************************************************************/static int ioctl_get_fmt(void *arg,struct camera_data *cam){ struct v4l2_format *f = arg; if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; f->fmt.pix.width = cam->vw.width; f->fmt.pix.height = cam->vw.height; f->fmt.pix.pixelformat = cam->pixelformat; f->fmt.pix.field = V4L2_FIELD_NONE; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = cam->frame_size; f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; f->fmt.pix.priv = 0; return 0;}/****************************************************************************** * * ioctl_cropcap * * V4L2 query cropping capabilities * NOTE: cropping is currently disabled * *****************************************************************************/static int ioctl_cropcap(void *arg,struct camera_data *cam){ 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 = cam->vw.width; c->bounds.height = cam->vw.height; c->defrect.left = 0; c->defrect.top = 0; c->defrect.width = cam->vw.width; c->defrect.height = cam->vw.height; c->pixelaspect.numerator = 1; c->pixelaspect.denominator = 1; return 0;}/****************************************************************************** * * ioctl_queryctrl * * V4L2 query possible control variables * *****************************************************************************/static int ioctl_queryctrl(void *arg,struct camera_data *cam){ struct v4l2_queryctrl *c = arg; int i; for(i=0; i<NUM_CONTROLS; ++i) { if(c->id == controls[i].id) { memcpy(c, controls+i, sizeof(*c)); break; } } if(i == NUM_CONTROLS) return -EINVAL; /* Some devices have additional limitations */ switch(c->id) { case V4L2_CID_BRIGHTNESS: /*** * Don't let the register be set to zero - bug in VP4 * flash of full brightness ***/ if (cam->params.pnp_id.device_type == DEVICE_STV_672) c->minimum = 1; break; case V4L2_CID_VFLIP: // VP5 Only if(cam->params.pnp_id.device_type == DEVICE_STV_672) c->flags |= V4L2_CTRL_FLAG_DISABLED; break; case CPIA2_CID_FRAMERATE: if(cam->params.pnp_id.device_type == DEVICE_STV_672 && cam->params.version.sensor_flags==CPIA2_VP_SENSOR_FLAGS_500){ // Maximum 15fps int i; for(i=0; i<c->maximum; ++i) { if(framerate_controls[i].value == CPIA2_VP_FRAMERATE_15) { c->maximum = i; c->default_value = i; } } } break; case CPIA2_CID_FLICKER_MODE: // Flicker control only valid for 672. if(cam->params.pnp_id.device_type != DEVICE_STV_672)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -