pvrusb2-v4l2.c
来自「trident tm5600的linux驱动」· C语言 代码 · 共 1,371 行 · 第 1/3 页
C
1,371 行
if (ret != 0) break; pvr2_ctrl_get_value( pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT), &cur_input); if (cur_input == PVR2_CVAL_INPUT_RADIO) { vf->type = V4L2_TUNER_RADIO; } else { vf->type = V4L2_TUNER_ANALOG_TV; } if (vt.capability & V4L2_TUNER_CAP_LOW) { val = (val * 2) / 125; } else { val /= 62500; } vf->frequency = val; break; } case VIDIOC_ENUM_FMT: { struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg; /* Only one format is supported : mpeg.*/ if (fd->index != 0) break; memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc)); ret = 0; break; } case VIDIOC_G_FMT: { struct v4l2_format *vf = (struct v4l2_format *)arg; int val; switch(vf->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: memcpy(vf, &pvr_format[PVR_FORMAT_PIX], sizeof(struct v4l2_format)); val = 0; pvr2_ctrl_get_value( pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES), &val); vf->fmt.pix.width = val; val = 0; pvr2_ctrl_get_value( pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES), &val); vf->fmt.pix.height = val; ret = 0; break; case V4L2_BUF_TYPE_VBI_CAPTURE: // ????? Still need to figure out to do VBI correctly ret = -EINVAL; break; default: ret = -EINVAL; break; } break; } case VIDIOC_TRY_FMT: case VIDIOC_S_FMT: { struct v4l2_format *vf = (struct v4l2_format *)arg; ret = 0; switch(vf->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: { int lmin,lmax,ldef; struct pvr2_ctrl *hcp,*vcp; int h = vf->fmt.pix.height; int w = vf->fmt.pix.width; hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES); vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES); lmin = pvr2_ctrl_get_min(hcp); lmax = pvr2_ctrl_get_max(hcp); pvr2_ctrl_get_def(hcp, &ldef); if (w == -1) { w = ldef; } else if (w < lmin) { w = lmin; } else if (w > lmax) { w = lmax; } lmin = pvr2_ctrl_get_min(vcp); lmax = pvr2_ctrl_get_max(vcp); pvr2_ctrl_get_def(vcp, &ldef); if (h == -1) { h = ldef; } else if (h < lmin) { h = lmin; } else if (h > lmax) { h = lmax; } memcpy(vf, &pvr_format[PVR_FORMAT_PIX], sizeof(struct v4l2_format)); vf->fmt.pix.width = w; vf->fmt.pix.height = h; if (cmd == VIDIOC_S_FMT) { pvr2_ctrl_set_value(hcp,vf->fmt.pix.width); pvr2_ctrl_set_value(vcp,vf->fmt.pix.height); } } break; case V4L2_BUF_TYPE_VBI_CAPTURE: // ????? Still need to figure out to do VBI correctly ret = -EINVAL; break; default: ret = -EINVAL; break; } break; } case VIDIOC_STREAMON: { if (!fh->dev_info->stream) { /* No stream defined for this node. This means that we're not currently allowed to stream from this node. */ ret = -EPERM; break; } ret = pvr2_hdw_set_stream_type(hdw,dev_info->config); if (ret < 0) return ret; ret = pvr2_hdw_set_streaming(hdw,!0); break; } case VIDIOC_STREAMOFF: { if (!fh->dev_info->stream) { /* No stream defined for this node. This means that we're not currently allowed to stream from this node. */ ret = -EPERM; break; } ret = pvr2_hdw_set_streaming(hdw,0); break; } case VIDIOC_QUERYCTRL: { struct pvr2_ctrl *cptr; int val; struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg; ret = 0; if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) { cptr = pvr2_hdw_get_ctrl_nextv4l( hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL)); if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr); } else { cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id); } if (!cptr) { pvr2_trace(PVR2_TRACE_V4LIOCTL, "QUERYCTRL id=0x%x not implemented here", vc->id); ret = -EINVAL; break; } pvr2_trace(PVR2_TRACE_V4LIOCTL, "QUERYCTRL id=0x%x mapping name=%s (%s)", vc->id,pvr2_ctrl_get_name(cptr), pvr2_ctrl_get_desc(cptr)); strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name)); vc->flags = pvr2_ctrl_get_v4lflags(cptr); pvr2_ctrl_get_def(cptr, &val); vc->default_value = val; switch (pvr2_ctrl_get_type(cptr)) { case pvr2_ctl_enum: vc->type = V4L2_CTRL_TYPE_MENU; vc->minimum = 0; vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1; vc->step = 1; break; case pvr2_ctl_bool: vc->type = V4L2_CTRL_TYPE_BOOLEAN; vc->minimum = 0; vc->maximum = 1; vc->step = 1; break; case pvr2_ctl_int: vc->type = V4L2_CTRL_TYPE_INTEGER; vc->minimum = pvr2_ctrl_get_min(cptr); vc->maximum = pvr2_ctrl_get_max(cptr); vc->step = 1; break; default: pvr2_trace(PVR2_TRACE_V4LIOCTL, "QUERYCTRL id=0x%x name=%s not mappable", vc->id,pvr2_ctrl_get_name(cptr)); ret = -EINVAL; break; } break; } case VIDIOC_QUERYMENU: { struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg; unsigned int cnt = 0; ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id), vm->index, vm->name,sizeof(vm->name)-1, &cnt); vm->name[cnt] = 0; break; } case VIDIOC_G_CTRL: { struct v4l2_control *vc = (struct v4l2_control *)arg; int val = 0; ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id), &val); vc->value = val; break; } case VIDIOC_S_CTRL: { struct v4l2_control *vc = (struct v4l2_control *)arg; ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id), vc->value); break; } case VIDIOC_G_EXT_CTRLS: { struct v4l2_ext_controls *ctls = (struct v4l2_ext_controls *)arg; struct v4l2_ext_control *ctrl; unsigned int idx; int val; ret = 0; for (idx = 0; idx < ctls->count; idx++) { ctrl = ctls->controls + idx; ret = pvr2_ctrl_get_value( pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val); if (ret) { ctls->error_idx = idx; break; } /* Ensure that if read as a 64 bit value, the user will still get a hopefully sane value */ ctrl->value64 = 0; ctrl->value = val; } break; } case VIDIOC_S_EXT_CTRLS: { struct v4l2_ext_controls *ctls = (struct v4l2_ext_controls *)arg; struct v4l2_ext_control *ctrl; unsigned int idx; ret = 0; for (idx = 0; idx < ctls->count; idx++) { ctrl = ctls->controls + idx; ret = pvr2_ctrl_set_value( pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id), ctrl->value); if (ret) { ctls->error_idx = idx; break; } } break; } case VIDIOC_TRY_EXT_CTRLS: { struct v4l2_ext_controls *ctls = (struct v4l2_ext_controls *)arg; struct v4l2_ext_control *ctrl; struct pvr2_ctrl *pctl; unsigned int idx; /* For the moment just validate that the requested control actually exists. */ ret = 0; for (idx = 0; idx < ctls->count; idx++) { ctrl = ctls->controls + idx; pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id); if (!pctl) { ret = -EINVAL; ctls->error_idx = idx; break; } } break; } case VIDIOC_CROPCAP: { struct v4l2_cropcap *cap = (struct v4l2_cropcap *)arg; if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { ret = -EINVAL; break; } ret = pvr2_hdw_get_cropcap(hdw, cap); cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */ break; } case VIDIOC_G_CROP: { struct v4l2_crop *crop = (struct v4l2_crop *)arg; int val = 0; if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { ret = -EINVAL; break; } ret = pvr2_ctrl_get_value( pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val); if (ret != 0) { ret = -EINVAL; break; } crop->c.left = val; ret = pvr2_ctrl_get_value( pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val); if (ret != 0) { ret = -EINVAL; break; } crop->c.top = val; ret = pvr2_ctrl_get_value( pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val); if (ret != 0) { ret = -EINVAL; break; } crop->c.width = val; ret = pvr2_ctrl_get_value( pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val); if (ret != 0) { ret = -EINVAL; break; } crop->c.height = val; } case VIDIOC_S_CROP: { struct v4l2_crop *crop = (struct v4l2_crop *)arg; struct v4l2_cropcap cap; if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { ret = -EINVAL; break; } cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ret = pvr2_ctrl_set_value( pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), crop->c.left); if (ret != 0) { ret = -EINVAL; break; } ret = pvr2_ctrl_set_value( pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), crop->c.top); if (ret != 0) { ret = -EINVAL; break; } ret = pvr2_ctrl_set_value( pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), crop->c.width); if (ret != 0) { ret = -EINVAL; break; } ret = pvr2_ctrl_set_value( pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), crop->c.height); if (ret != 0) { ret = -EINVAL; break; } } case VIDIOC_LOG_STATUS: { pvr2_hdw_trigger_module_log(hdw); ret = 0; break; }#ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_DBG_S_REGISTER: case VIDIOC_DBG_G_REGISTER: { u64 val; struct v4l2_register *req = (struct v4l2_register *)arg; if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val; ret = pvr2_hdw_register_access( hdw,req->match_type,req->match_chip,req->reg, cmd == VIDIOC_DBG_S_REGISTER,&val); if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val; break; }#endif default : ret = v4l_compat_translate_ioctl(file, cmd, arg, __pvr2_v4l2_do_ioctl); } pvr2_hdw_commit_ctl(hdw); if (ret < 0) { if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) { pvr2_trace(PVR2_TRACE_V4LIOCTL, "pvr2_v4l2_do_ioctl failure, ret=%d",ret); } else { if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) { pvr2_trace(PVR2_TRACE_V4LIOCTL, "pvr2_v4l2_do_ioctl failure, ret=%d" " command was:",ret); v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw), cmd); } } } else { pvr2_trace(PVR2_TRACE_V4LIOCTL, "pvr2_v4l2_do_ioctl complete, ret=%d (0x%x)", ret,ret); } return ret;}static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg){ return __pvr2_v4l2_do_ioctl(file, cmd, arg);}static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip){ int num = dip->devbase.num; struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw; enum pvr2_config cfg = dip->config; int v4l_type = dip->v4l_type; pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1); /* Paranoia */ dip->v4lp = NULL; dip->stream = NULL; /* Actual deallocation happens later when all internal references are gone. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?