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 + -
显示快捷键?