📄 cpia2_v4l.c
字号:
c->flags |= V4L2_CTRL_FLAG_DISABLED; break; case CPIA2_CID_LIGHTS: // Light control only valid for the QX5 Microscope. if(cam->params.pnp_id.product != 0x151) c->flags |= V4L2_CTRL_FLAG_DISABLED; break; default: break; } return 0;}/****************************************************************************** * * ioctl_querymenu * * V4L2 query possible control variables * *****************************************************************************/static int ioctl_querymenu(void *arg,struct camera_data *cam){ struct v4l2_querymenu *m = arg; memset(m->name, 0, sizeof(m->name)); m->reserved = 0; switch(m->id) { case CPIA2_CID_FLICKER_MODE: if(m->index < 0 || m->index >= NUM_FLICKER_CONTROLS) return -EINVAL; strcpy(m->name, flicker_controls[m->index].name); break; case CPIA2_CID_FRAMERATE: { int maximum = NUM_FRAMERATE_CONTROLS - 1; 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<maximum; ++i) { if(framerate_controls[i].value == CPIA2_VP_FRAMERATE_15) maximum = i; } } if(m->index < 0 || m->index > maximum) return -EINVAL; strcpy(m->name, framerate_controls[m->index].name); break; } case CPIA2_CID_LIGHTS: if(m->index < 0 || m->index >= NUM_LIGHTS_CONTROLS) return -EINVAL; strcpy(m->name, lights_controls[m->index].name); break; default: return -EINVAL; } return 0;}/****************************************************************************** * * ioctl_g_ctrl * * V4L2 get the value of a control variable * *****************************************************************************/static int ioctl_g_ctrl(void *arg,struct camera_data *cam){ struct v4l2_control *c = arg; switch(c->id) { case V4L2_CID_BRIGHTNESS: cpia2_do_command(cam, CPIA2_CMD_GET_VP_BRIGHTNESS, TRANSFER_READ, 0); c->value = cam->params.color_params.brightness; break; case V4L2_CID_CONTRAST: cpia2_do_command(cam, CPIA2_CMD_GET_CONTRAST, TRANSFER_READ, 0); c->value = cam->params.color_params.contrast; break; case V4L2_CID_SATURATION: cpia2_do_command(cam, CPIA2_CMD_GET_VP_SATURATION, TRANSFER_READ, 0); c->value = cam->params.color_params.saturation; break; case V4L2_CID_HFLIP: cpia2_do_command(cam, CPIA2_CMD_GET_USER_EFFECTS, TRANSFER_READ, 0); c->value = (cam->params.vp_params.user_effects & CPIA2_VP_USER_EFFECTS_MIRROR) != 0; break; case V4L2_CID_VFLIP: cpia2_do_command(cam, CPIA2_CMD_GET_USER_EFFECTS, TRANSFER_READ, 0); c->value = (cam->params.vp_params.user_effects & CPIA2_VP_USER_EFFECTS_FLIP) != 0; break; case CPIA2_CID_TARGET_KB: c->value = cam->params.vc_params.target_kb; break; case CPIA2_CID_GPIO: cpia2_do_command(cam, CPIA2_CMD_GET_VP_GPIO_DATA, TRANSFER_READ, 0); c->value = cam->params.vp_params.gpio_data; break; case CPIA2_CID_FLICKER_MODE: { int i, mode; cpia2_do_command(cam, CPIA2_CMD_GET_FLICKER_MODES, TRANSFER_READ, 0); if(cam->params.flicker_control.cam_register & CPIA2_VP_FLICKER_MODES_NEVER_FLICKER) { mode = NEVER_FLICKER; } else { if(cam->params.flicker_control.cam_register & CPIA2_VP_FLICKER_MODES_50HZ) { mode = FLICKER_50; } else { mode = FLICKER_60; } } for(i=0; i<NUM_FLICKER_CONTROLS; i++) { if(flicker_controls[i].value == mode) { c->value = i; break; } } if(i == NUM_FLICKER_CONTROLS) return -EINVAL; break; } case CPIA2_CID_FRAMERATE: { int maximum = NUM_FRAMERATE_CONTROLS - 1; int i; for(i=0; i<= maximum; i++) { if(cam->params.vp_params.frame_rate == framerate_controls[i].value) break; } if(i > maximum) return -EINVAL; c->value = i; break; } case CPIA2_CID_USB_ALT: c->value = cam->params.camera_state.stream_mode; break; case CPIA2_CID_LIGHTS: { int i; cpia2_do_command(cam, CPIA2_CMD_GET_VP_GPIO_DATA, TRANSFER_READ, 0); for(i=0; i<NUM_LIGHTS_CONTROLS; i++) { if((cam->params.vp_params.gpio_data&GPIO_LIGHTS_MASK) == lights_controls[i].value) { break; } } if(i == NUM_LIGHTS_CONTROLS) return -EINVAL; c->value = i; break; } case CPIA2_CID_RESET_CAMERA: return -EINVAL; default: return -EINVAL; } DBG("Get control id:%d, value:%d\n", c->id, c->value); return 0;}/****************************************************************************** * * ioctl_s_ctrl * * V4L2 set the value of a control variable * *****************************************************************************/static int ioctl_s_ctrl(void *arg,struct camera_data *cam){ struct v4l2_control *c = arg; int i; int retval = 0; DBG("Set control id:%d, value:%d\n", c->id, c->value); /* Check that the value is in range */ for(i=0; i<NUM_CONTROLS; i++) { if(c->id == controls[i].id) { if(c->value < controls[i].minimum || c->value > controls[i].maximum) { return -EINVAL; } break; } } if(i == NUM_CONTROLS) return -EINVAL; switch(c->id) { case V4L2_CID_BRIGHTNESS: cpia2_set_brightness(cam, c->value); break; case V4L2_CID_CONTRAST: cpia2_set_contrast(cam, c->value); break; case V4L2_CID_SATURATION: cpia2_set_saturation(cam, c->value); break; case V4L2_CID_HFLIP: cpia2_set_property_mirror(cam, c->value); break; case V4L2_CID_VFLIP: cpia2_set_property_flip(cam, c->value); break; case CPIA2_CID_TARGET_KB: retval = cpia2_set_target_kb(cam, c->value); break; case CPIA2_CID_GPIO: retval = cpia2_set_gpio(cam, c->value); break; case CPIA2_CID_FLICKER_MODE: retval = cpia2_set_flicker_mode(cam, flicker_controls[c->value].value); break; case CPIA2_CID_FRAMERATE: retval = cpia2_set_fps(cam, framerate_controls[c->value].value); break; case CPIA2_CID_USB_ALT: retval = cpia2_usb_change_streaming_alternate(cam, c->value); break; case CPIA2_CID_LIGHTS: retval = cpia2_set_gpio(cam, lights_controls[c->value].value); break; case CPIA2_CID_RESET_CAMERA: cpia2_usb_stream_pause(cam); cpia2_reset_camera(cam); cpia2_usb_stream_resume(cam); break; default: retval = -EINVAL; } return retval;}/****************************************************************************** * * ioctl_g_jpegcomp * * V4L2 get the JPEG compression parameters * *****************************************************************************/static int ioctl_g_jpegcomp(void *arg,struct camera_data *cam){ struct v4l2_jpegcompression *parms = arg; memset(parms, 0, sizeof(*parms)); parms->quality = 80; // TODO: Can this be made meaningful? parms->jpeg_markers = V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI; if(!cam->params.compression.inhibit_htables) { parms->jpeg_markers |= V4L2_JPEG_MARKER_DHT; } parms->APPn = cam->APPn; parms->APP_len = cam->APP_len; if(cam->APP_len > 0) { memcpy(parms->APP_data, cam->APP_data, cam->APP_len); parms->jpeg_markers |= V4L2_JPEG_MARKER_APP; } parms->COM_len = cam->COM_len; if(cam->COM_len > 0) { memcpy(parms->COM_data, cam->COM_data, cam->COM_len); parms->jpeg_markers |= JPEG_MARKER_COM; } DBG("G_JPEGCOMP APP_len:%d COM_len:%d\n", parms->APP_len, parms->COM_len); return 0;}/****************************************************************************** * * ioctl_s_jpegcomp * * V4L2 set the JPEG compression parameters * NOTE: quality and some jpeg_markers are ignored. * *****************************************************************************/static int ioctl_s_jpegcomp(void *arg,struct camera_data *cam){ struct v4l2_jpegcompression *parms = arg; DBG("S_JPEGCOMP APP_len:%d COM_len:%d\n", parms->APP_len, parms->COM_len); cam->params.compression.inhibit_htables = !(parms->jpeg_markers & V4L2_JPEG_MARKER_DHT); if(parms->APP_len != 0) { if(parms->APP_len > 0 && parms->APP_len <= sizeof(cam->APP_data) && parms->APPn >= 0 && parms->APPn <= 15) { cam->APPn = parms->APPn; cam->APP_len = parms->APP_len; memcpy(cam->APP_data, parms->APP_data, parms->APP_len); } else { LOG("Bad APPn Params n=%d len=%d\n", parms->APPn, parms->APP_len); return -EINVAL; } } else { cam->APP_len = 0; } if(parms->COM_len != 0) { if(parms->COM_len > 0 && parms->COM_len <= sizeof(cam->COM_data)) { cam->COM_len = parms->COM_len; memcpy(cam->COM_data, parms->COM_data, parms->COM_len); } else { LOG("Bad COM_len=%d\n", parms->COM_len); return -EINVAL; } } return 0;}/****************************************************************************** * * ioctl_reqbufs * * V4L2 Initiate memory mapping. * NOTE: The user's request is ignored. For now the buffers are fixed. * *****************************************************************************/static int ioctl_reqbufs(void *arg,struct camera_data *cam){ struct v4l2_requestbuffers *req = arg; if(req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || req->memory != V4L2_MEMORY_MMAP) return -EINVAL; DBG("REQBUFS requested:%d returning:%d\n", req->count, cam->num_frames); req->count = cam->num_frames; memset(&req->reserved, 0, sizeof(req->reserved)); return 0;}/****************************************************************************** * * ioctl_querybuf * * V4L2 Query memory buffer status. * *****************************************************************************/static int ioctl_querybuf(void *arg,struct camera_data *cam){ struct v4l2_buffer *buf = arg; if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || buf->index > cam->num_frames) return -EINVAL; buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer; buf->length = cam->frame_size; buf->memory = V4L2_MEMORY_MMAP; if(cam->mmapped) buf->flags = V4L2_BUF_FLAG_MAPPED; else buf->flags = 0; switch (cam->buffers[buf->index].status) { case FRAME_EMPTY: case FRAME_ERROR: case FRAME_READING: buf->bytesused = 0; buf->flags = V4L2_BUF_FLAG_QUEUED; break; case FRAME_READY: buf->bytesused = cam->buffers[buf->index].length; buf->timestamp = cam->buffers[buf->index].timestamp; buf->sequence = cam->buffers[buf->index].seq; buf->flags = V4L2_BUF_FLAG_DONE; break; } DBG("QUERYBUF index:%d offset:%d flags:%d seq:%d bytesused:%d\n", buf->index, buf->m.offset, buf->flags, buf->sequence, buf->bytesused); return 0;}/****************************************************************************** * * ioctl_qbuf * * V4L2 User is freeing buffer * *****************************************************************************/static int ioctl_qbuf(void *arg,struct camera_data *cam){ struct v4l2_buffer *buf = arg; if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || buf->memory != V4L2_MEMORY_MMAP || buf->index > cam->num_frames) return -EINVAL; DBG("QBUF #%d\n", buf->index); if(cam->buffers[buf->index].status == FRAME_READY) cam->buffers[buf->index].status = FRAME_EMPTY; return 0;}/****************************************************************************** * * find_earliest_filled_buffer * * Helper for ioctl_dqbuf. Find the next ready buffer. * *****************************************************************************/static int find_earliest_filled_buffer(struct camera_data *cam){ int i; int found = -1; for (i=0; i<cam->num_frames; i++) { if(cam->buffers[i].status == FRAME_READY) { if(found < 0) { found = i; } else { /* find which buffer is earlier */ struct timeval *tv1, *tv2; tv1 = &cam->buffers[i].timestamp; tv2 = &cam->buffers[found].timestamp; if(tv1->tv_sec < tv2->tv_sec || (tv1->tv_sec == tv2->tv_sec && tv1->tv_usec < tv2->tv_usec)) found = i; } } } return found;}/****************************************************************************** * * ioctl_dqbuf * * V4L2 User is asking for a filled buffer. * *****************************************************************************/static int ioctl_dqbuf(void *arg,struct camera_data *cam, struct file *file){ struct v4l2_buffer *buf = arg; int frame; if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || buf->memory != V4L2_MEMORY_MMAP) return -EINVAL; frame = find_earliest_filled_buffer(cam); if(frame < 0 && file->f_flags&O_NONBLOCK) return -EAGAIN; if(frame < 0) { /* Wait for a frame to become available */ struct framebuf *cb=cam->curbuff; mutex_unlock(&cam->busy_lock); wait_event_interruptible(cam->wq_stream, !cam->present || (cb=cam->curbuff)->status == FRAME_READY); mutex_lock(&cam->busy_lock); if (signal_pending(current)) return -ERESTARTSYS; if(!cam->present) return -ENOTTY; frame = cb->num; } buf->index = frame; buf->bytesused = cam->buffers[buf->index].length; buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE; buf->field = V4L2_FIELD_NONE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -