📄 usbvision-video.c
字号:
}/* * usbvision_ioctl() * * This is part of Video 4 Linux API. The procedure handles ioctl() calls. * */#ifdef CONFIG_VIDEO_ADV_DEBUGstatic int vidioc_g_register (struct file *file, void *priv, struct v4l2_register *reg){ struct usb_usbvision *usbvision = video_drvdata(file); int errCode; if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; /* NT100x has a 8-bit register space */ errCode = usbvision_read_reg(usbvision, reg->reg&0xff); if (errCode < 0) { err("%s: VIDIOC_DBG_G_REGISTER failed: error %d", __func__, errCode); return errCode; } reg->val = errCode; return 0;}static int vidioc_s_register (struct file *file, void *priv, struct v4l2_register *reg){ struct usb_usbvision *usbvision = video_drvdata(file); int errCode; if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; /* NT100x has a 8-bit register space */ errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); if (errCode < 0) { err("%s: VIDIOC_DBG_S_REGISTER failed: error %d", __func__, errCode); return errCode; } return 0;}#endifstatic int vidioc_querycap (struct file *file, void *priv, struct v4l2_capability *vc){ struct usb_usbvision *usbvision = video_drvdata(file); strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString, sizeof(vc->card)); strlcpy(vc->bus_info, usbvision->dev->dev.bus_id, sizeof(vc->bus_info)); vc->version = USBVISION_DRIVER_VERSION; vc->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | (usbvision->have_tuner ? V4L2_CAP_TUNER : 0); return 0;}static int vidioc_enum_input (struct file *file, void *priv, struct v4l2_input *vi){ struct usb_usbvision *usbvision = video_drvdata(file); int chan; if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) ) return -EINVAL; if (usbvision->have_tuner) { chan = vi->index; } else { chan = vi->index + 1; /*skip Television string*/ } /* Determine the requested input characteristics specific for each usbvision card model */ switch(chan) { case 0: if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { strcpy(vi->name, "White Video Input"); } else { strcpy(vi->name, "Television"); vi->type = V4L2_INPUT_TYPE_TUNER; vi->audioset = 1; vi->tuner = chan; vi->std = USBVISION_NORMS; } break; case 1: vi->type = V4L2_INPUT_TYPE_CAMERA; if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { strcpy(vi->name, "Green Video Input"); } else { strcpy(vi->name, "Composite Video Input"); } vi->std = V4L2_STD_PAL; break; case 2: vi->type = V4L2_INPUT_TYPE_CAMERA; if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { strcpy(vi->name, "Yellow Video Input"); } else { strcpy(vi->name, "S-Video Input"); } vi->std = V4L2_STD_PAL; break; case 3: vi->type = V4L2_INPUT_TYPE_CAMERA; strcpy(vi->name, "Red Video Input"); vi->std = V4L2_STD_PAL; break; } return 0;}static int vidioc_g_input (struct file *file, void *priv, unsigned int *input){ struct usb_usbvision *usbvision = video_drvdata(file); *input = usbvision->ctl_input; return 0;}static int vidioc_s_input (struct file *file, void *priv, unsigned int input){ struct usb_usbvision *usbvision = video_drvdata(file); if ((input >= usbvision->video_inputs) || (input < 0) ) return -EINVAL; mutex_lock(&usbvision->lock); usbvision_muxsel(usbvision, input); usbvision_set_input(usbvision); usbvision_set_output(usbvision, usbvision->curwidth, usbvision->curheight); mutex_unlock(&usbvision->lock); return 0;}static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id){ struct usb_usbvision *usbvision = video_drvdata(file); usbvision->tvnormId=*id; mutex_lock(&usbvision->lock); call_i2c_clients(usbvision, VIDIOC_S_STD, &usbvision->tvnormId); mutex_unlock(&usbvision->lock); /* propagate the change to the decoder */ usbvision_muxsel(usbvision, usbvision->ctl_input); return 0;}static int vidioc_g_tuner (struct file *file, void *priv, struct v4l2_tuner *vt){ struct usb_usbvision *usbvision = video_drvdata(file); if (!usbvision->have_tuner || vt->index) // Only tuner 0 return -EINVAL; if(usbvision->radio) { strcpy(vt->name, "Radio"); vt->type = V4L2_TUNER_RADIO; } else { strcpy(vt->name, "Television"); } /* Let clients fill in the remainder of this struct */ call_i2c_clients(usbvision,VIDIOC_G_TUNER,vt); return 0;}static int vidioc_s_tuner (struct file *file, void *priv, struct v4l2_tuner *vt){ struct usb_usbvision *usbvision = video_drvdata(file); // Only no or one tuner for now if (!usbvision->have_tuner || vt->index) return -EINVAL; /* let clients handle this */ call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt); return 0;}static int vidioc_g_frequency (struct file *file, void *priv, struct v4l2_frequency *freq){ struct usb_usbvision *usbvision = video_drvdata(file); freq->tuner = 0; // Only one tuner if(usbvision->radio) { freq->type = V4L2_TUNER_RADIO; } else { freq->type = V4L2_TUNER_ANALOG_TV; } freq->frequency = usbvision->freq; return 0;}static int vidioc_s_frequency (struct file *file, void *priv, struct v4l2_frequency *freq){ struct usb_usbvision *usbvision = video_drvdata(file); // Only no or one tuner for now if (!usbvision->have_tuner || freq->tuner) return -EINVAL; usbvision->freq = freq->frequency; call_i2c_clients(usbvision, VIDIOC_S_FREQUENCY, freq); return 0;}static int vidioc_g_audio (struct file *file, void *priv, struct v4l2_audio *a){ struct usb_usbvision *usbvision = video_drvdata(file); memset(a,0,sizeof(*a)); if(usbvision->radio) { strcpy(a->name,"Radio"); } else { strcpy(a->name, "TV"); } return 0;}static int vidioc_s_audio (struct file *file, void *fh, struct v4l2_audio *a){ if(a->index) { return -EINVAL; } return 0;}static int vidioc_queryctrl (struct file *file, void *priv, struct v4l2_queryctrl *ctrl){ struct usb_usbvision *usbvision = video_drvdata(file); int id=ctrl->id; memset(ctrl,0,sizeof(*ctrl)); ctrl->id=id; call_i2c_clients(usbvision, VIDIOC_QUERYCTRL, ctrl); if (!ctrl->type) return -EINVAL; return 0;}static int vidioc_g_ctrl (struct file *file, void *priv, struct v4l2_control *ctrl){ struct usb_usbvision *usbvision = video_drvdata(file); call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); return 0;}static int vidioc_s_ctrl (struct file *file, void *priv, struct v4l2_control *ctrl){ struct usb_usbvision *usbvision = video_drvdata(file); call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); return 0;}static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *vr){ struct usb_usbvision *usbvision = video_drvdata(file); int ret; RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES); /* Check input validity: the user must do a VIDEO CAPTURE and MMAP method. */ if((vr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) || (vr->memory != V4L2_MEMORY_MMAP)) return -EINVAL; if(usbvision->streaming == Stream_On) { if ((ret = usbvision_stream_interrupt(usbvision))) return ret; } usbvision_frames_free(usbvision); usbvision_empty_framequeues(usbvision); vr->count = usbvision_frames_alloc(usbvision,vr->count); usbvision->curFrame = NULL; return 0;}static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *vb){ struct usb_usbvision *usbvision = video_drvdata(file); struct usbvision_frame *frame; /* FIXME : must control that buffers are mapped (VIDIOC_REQBUFS has been called) */ if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { return -EINVAL; } if(vb->index>=usbvision->num_frames) { return -EINVAL; } /* Updating the corresponding frame state */ vb->flags = 0; frame = &usbvision->frame[vb->index]; if(frame->grabstate >= FrameState_Ready) vb->flags |= V4L2_BUF_FLAG_QUEUED; if(frame->grabstate >= FrameState_Done) vb->flags |= V4L2_BUF_FLAG_DONE; if(frame->grabstate == FrameState_Unused) vb->flags |= V4L2_BUF_FLAG_MAPPED; vb->memory = V4L2_MEMORY_MMAP; vb->m.offset = vb->index*PAGE_ALIGN(usbvision->max_frame_size); vb->memory = V4L2_MEMORY_MMAP; vb->field = V4L2_FIELD_NONE; vb->length = usbvision->curwidth* usbvision->curheight* usbvision->palette.bytes_per_pixel; vb->timestamp = usbvision->frame[vb->index].timestamp; vb->sequence = usbvision->frame[vb->index].sequence; return 0;}static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb){ struct usb_usbvision *usbvision = video_drvdata(file); struct usbvision_frame *frame; unsigned long lock_flags; /* FIXME : works only on VIDEO_CAPTURE MODE, MMAP. */ if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { return -EINVAL; } if(vb->index>=usbvision->num_frames) { return -EINVAL; } frame = &usbvision->frame[vb->index]; if (frame->grabstate != FrameState_Unused) { return -EAGAIN; } /* Mark it as ready and enqueue frame */ frame->grabstate = FrameState_Ready; frame->scanstate = ScanState_Scanning; frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */ vb->flags &= ~V4L2_BUF_FLAG_DONE; /* set v4l2_format index */ frame->v4l2_format = usbvision->palette; spin_lock_irqsave(&usbvision->queue_lock, lock_flags); list_add_tail(&usbvision->frame[vb->index].frame, &usbvision->inqueue); spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); return 0;}static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb){ struct usb_usbvision *usbvision = video_drvdata(file); int ret; struct usbvision_frame *f; unsigned long lock_flags; if (vb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; if (list_empty(&(usbvision->outqueue))) { if (usbvision->streaming == Stream_Idle) return -EINVAL; ret = wait_event_interruptible (usbvision->wait_frame, !list_empty(&(usbvision->outqueue))); if (ret) return ret; } spin_lock_irqsave(&usbvision->queue_lock, lock_flags); f = list_entry(usbvision->outqueue.next, struct usbvision_frame, frame); list_del(usbvision->outqueue.next); spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); f->grabstate = FrameState_Unused; vb->memory = V4L2_MEMORY_MMAP; vb->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE; vb->index = f->index; vb->sequence = f->sequence; vb->timestamp = f->timestamp; vb->field = V4L2_FIELD_NONE; vb->bytesused = f->scanlength; return 0;}static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i){ struct usb_usbvision *usbvision = video_drvdata(file); int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; usbvision->streaming = Stream_On; call_i2c_clients(usbvision,VIDIOC_STREAMON , &b); return 0;}static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type type){ struct usb_usbvision *usbvision = video_drvdata(file); int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; if(usbvision->streaming == Stream_On) { usbvision_stream_interrupt(usbvision); /* Stop all video streamings */ call_i2c_clients(usbvision,VIDIOC_STREAMOFF , &b); } usbvision_empty_framequeues(usbvision); return 0;}static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, struct v4l2_fmtdesc *vfd){ if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) { return -EINVAL; } vfd->flags = 0; vfd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -