⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ivtv-ioctl.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 4 页
字号:
		fmt->fmt.vbi.sampling_rate = 27000000;		fmt->fmt.vbi.offset = 248;		fmt->fmt.vbi.samples_per_line = itv->vbi.raw_decoder_line_size - 4;		fmt->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;		fmt->fmt.vbi.start[0] = itv->vbi.start[0];		fmt->fmt.vbi.start[1] = itv->vbi.start[1];		fmt->fmt.vbi.count[0] = fmt->fmt.vbi.count[1] = itv->vbi.count;		break;	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:	{		struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;		if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))			return -EINVAL;		vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;		memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved));		memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines));		if (itv->is_60hz) {			vbifmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525;			vbifmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525;		} else {			vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625;			vbifmt->service_lines[0][16] = V4L2_SLICED_VPS;		}		vbifmt->service_set = get_service_set(vbifmt);		break;	}	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:	{		struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;		vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;		memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved));		memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines));		if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) {			vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 :						 V4L2_SLICED_VBI_525;			expand_service_set(vbifmt, itv->is_50hz);			break;		}		itv->video_dec_func(itv, VIDIOC_G_FMT, fmt);		vbifmt->service_set = get_service_set(vbifmt);		break;	}	case V4L2_BUF_TYPE_VBI_OUTPUT:	case V4L2_BUF_TYPE_VIDEO_OVERLAY:	default:		return -EINVAL;	}	return 0;}static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype,		struct v4l2_format *fmt, int set_fmt){	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;	u16 set;	if (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {		struct v4l2_rect r;		int field;		if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))			return -EINVAL;		field = fmt->fmt.pix.field;		r.top = 0;		r.left = 0;		r.width = fmt->fmt.pix.width;		r.height = fmt->fmt.pix.height;		ivtv_get_fmt(itv, streamtype, fmt);		if (itv->output_mode != OUT_UDMA_YUV) {			/* TODO: would setting the rect also be valid for this mode? */			fmt->fmt.pix.width = r.width;			fmt->fmt.pix.height = r.height;		}		if (itv->output_mode == OUT_UDMA_YUV) {			/* TODO: add checks for validity */			fmt->fmt.pix.field = field;		}		if (set_fmt) {			if (itv->output_mode == OUT_UDMA_YUV) {				switch (field) {				case V4L2_FIELD_NONE:					itv->yuv_info.lace_mode = IVTV_YUV_MODE_PROGRESSIVE;					break;				case V4L2_FIELD_ANY:					itv->yuv_info.lace_mode = IVTV_YUV_MODE_AUTO;					break;				case V4L2_FIELD_INTERLACED_BT:					itv->yuv_info.lace_mode =						IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD;					break;				case V4L2_FIELD_INTERLACED_TB:				default:					itv->yuv_info.lace_mode = IVTV_YUV_MODE_INTERLACED;					break;				}				itv->yuv_info.lace_sync_field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1;				/* Force update of yuv registers */				itv->yuv_info.yuv_forced_update = 1;				return 0;			}		}		return 0;	}	if (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) {		if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))			return -EINVAL;		if (set_fmt) {			itv->osd_chroma_key = fmt->fmt.win.chromakey;			itv->osd_global_alpha = fmt->fmt.win.global_alpha;			ivtv_set_osd_alpha(itv);		}		return 0;	}	/* set window size */	if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {		struct cx2341x_mpeg_params *p = &itv->params;		int w = fmt->fmt.pix.width;		int h = fmt->fmt.pix.height;		if (w > 720) w = 720;		else if (w < 1) w = 1;		if (h > (itv->is_50hz ? 576 : 480)) h = (itv->is_50hz ? 576 : 480);		else if (h < 2) h = 2;		ivtv_get_fmt(itv, streamtype, fmt);		fmt->fmt.pix.width = w;		fmt->fmt.pix.height = h;		if (!set_fmt || (p->width == w && p->height == h))			return 0;		if (atomic_read(&itv->capturing) > 0)			return -EBUSY;		p->width = w;		p->height = h;		if (w != 720 || h != (itv->is_50hz ? 576 : 480))			p->video_temporal_filter = 0;		else			p->video_temporal_filter = 8;		if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)			fmt->fmt.pix.width /= 2;		itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);		return ivtv_get_fmt(itv, streamtype, fmt);	}	/* set raw VBI format */	if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {		if (set_fmt && atomic_read(&itv->capturing) > 0) {			return -EBUSY;		}		if (set_fmt) {			itv->vbi.sliced_in->service_set = 0;			itv->video_dec_func(itv, VIDIOC_S_FMT, &itv->vbi.in);		}		return ivtv_get_fmt(itv, streamtype, fmt);	}	/* set sliced VBI output	   In principle the user could request that only certain	   VBI types are output and that the others are ignored.	   I.e., suppress CC in the even fields or only output	   WSS and no VPS. Currently though there is no choice. */	if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT)		return ivtv_get_fmt(itv, streamtype, fmt);	/* any else but sliced VBI capture is an error */	if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)		return -EINVAL;	if (streamtype == IVTV_DEC_STREAM_TYPE_VBI)		return ivtv_get_fmt(itv, streamtype, fmt);	/* set sliced VBI capture format */	vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;	memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved));	if (vbifmt->service_set)		expand_service_set(vbifmt, itv->is_50hz);	set = check_service_set(vbifmt, itv->is_50hz);	vbifmt->service_set = get_service_set(vbifmt);	if (!set_fmt)		return 0;	if (set == 0)		return -EINVAL;	if (atomic_read(&itv->capturing) > 0) {		return -EBUSY;	}	itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);	memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in));	return 0;}static int ivtv_debug_ioctls(struct file *filp, unsigned int cmd, void *arg){	struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;	struct ivtv *itv = id->itv;	struct v4l2_register *reg = arg;	switch (cmd) {	/* ioctls to allow direct access to the encoder registers for testing */	case VIDIOC_DBG_G_REGISTER:		if (v4l2_chip_match_host(reg->match_type, reg->match_chip))			return ivtv_itvc(itv, cmd, arg);		if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)			return ivtv_i2c_id(itv, reg->match_chip, cmd, arg);		return ivtv_call_i2c_client(itv, reg->match_chip, cmd, arg);	case VIDIOC_DBG_S_REGISTER:		if (v4l2_chip_match_host(reg->match_type, reg->match_chip))			return ivtv_itvc(itv, cmd, arg);		if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)			return ivtv_i2c_id(itv, reg->match_chip, cmd, arg);		return ivtv_call_i2c_client(itv, reg->match_chip, cmd, arg);	case VIDIOC_G_CHIP_IDENT: {		struct v4l2_chip_ident *chip = arg;		chip->ident = V4L2_IDENT_NONE;		chip->revision = 0;		if (reg->match_type == V4L2_CHIP_MATCH_HOST) {			if (v4l2_chip_match_host(reg->match_type, reg->match_chip)) {				struct v4l2_chip_ident *chip = arg;				chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416;			}			return 0;		}		if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)			return ivtv_i2c_id(itv, reg->match_chip, cmd, arg);		if (reg->match_type == V4L2_CHIP_MATCH_I2C_ADDR)			return ivtv_call_i2c_client(itv, reg->match_chip, cmd, arg);		return -EINVAL;	}	case VIDIOC_INT_S_AUDIO_ROUTING: {		struct v4l2_routing *route = arg;		ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, route);		break;	}	case VIDIOC_INT_RESET: {		u32 val = *(u32 *)arg;		if ((val == 0 && itv->options.newi2c) || (val & 0x01)) {			ivtv_reset_ir_gpio(itv);		}		if (val & 0x02) {			itv->video_dec_func(itv, cmd, 0);		}		break;	}	default:		return -EINVAL;	}	return 0;}int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg){	struct ivtv_open_id *id = NULL;	u32 data[CX2341X_MBOX_MAX_DATA];	if (filp) id = (struct ivtv_open_id *)filp->private_data;	switch (cmd) {	case VIDIOC_G_PRIORITY:	{		enum v4l2_priority *p = arg;		*p = v4l2_prio_max(&itv->prio);		break;	}	case VIDIOC_S_PRIORITY:	{		enum v4l2_priority *prio = arg;		return v4l2_prio_change(&itv->prio, &id->prio, *prio);	}	case VIDIOC_QUERYCAP:{		struct v4l2_capability *vcap = arg;		memset(vcap, 0, sizeof(*vcap));		strcpy(vcap->driver, IVTV_DRIVER_NAME);     /* driver name */		strncpy(vcap->card, itv->card_name,				sizeof(vcap->card)-1); 	    /* card type */		strcpy(vcap->bus_info, pci_name(itv->dev)); /* bus info... */		vcap->version = IVTV_DRIVER_VERSION; 	    /* version */		vcap->capabilities = itv->v4l2_cap; 	    /* capabilities */		/* reserved.. must set to 0! */		vcap->reserved[0] = vcap->reserved[1] =			vcap->reserved[2] = vcap->reserved[3] = 0;		break;	}	case VIDIOC_ENUMAUDIO:{		struct v4l2_audio *vin = arg;		return ivtv_get_audio_input(itv, vin->index, vin);	}	case VIDIOC_G_AUDIO:{		struct v4l2_audio *vin = arg;		vin->index = itv->audio_input;		return ivtv_get_audio_input(itv, vin->index, vin);	}	case VIDIOC_S_AUDIO:{		struct v4l2_audio *vout = arg;		if (vout->index >= itv->nof_audio_inputs)			return -EINVAL;		itv->audio_input = vout->index;		ivtv_audio_set_io(itv);		break;	}	case VIDIOC_ENUMAUDOUT:{		struct v4l2_audioout *vin = arg;		/* set it to defaults from our table */		return ivtv_get_audio_output(itv, vin->index, vin);	}	case VIDIOC_G_AUDOUT:{		struct v4l2_audioout *vin = arg;		vin->index = 0;		return ivtv_get_audio_output(itv, vin->index, vin);	}	case VIDIOC_S_AUDOUT:{		struct v4l2_audioout *vout = arg;		return ivtv_get_audio_output(itv, vout->index, vout);	}	case VIDIOC_ENUMINPUT:{		struct v4l2_input *vin = arg;		/* set it to defaults from our table */		return ivtv_get_input(itv, vin->index, vin);	}	case VIDIOC_ENUMOUTPUT:{		struct v4l2_output *vout = arg;		return ivtv_get_output(itv, vout->index, vout);	}	case VIDIOC_TRY_FMT:	case VIDIOC_S_FMT: {		struct v4l2_format *fmt = arg;		return ivtv_try_or_set_fmt(itv, id->type, fmt, cmd == VIDIOC_S_FMT);	}	case VIDIOC_G_FMT: {		struct v4l2_format *fmt = arg;		int type = fmt->type;		memset(fmt, 0, sizeof(*fmt));		fmt->type = type;		return ivtv_get_fmt(itv, id->type, fmt);	}	case VIDIOC_CROPCAP: {		struct v4l2_cropcap *cropcap = arg;		if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&		    cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)			return -EINVAL;		cropcap->bounds.top = cropcap->bounds.left = 0;		cropcap->bounds.width = 720;		if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {			cropcap->bounds.height = itv->is_50hz ? 576 : 480;			cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;			cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;		} else {			cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;			cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;			cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;		}		cropcap->defrect = cropcap->bounds;		return 0;	}	case VIDIOC_S_CROP: {		struct v4l2_crop *crop = arg;		if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&		    (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {			if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,				 crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {				itv->main_rect = crop->c;				return 0;			}			return -EINVAL;		}		if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)			return -EINVAL;		return itv->video_dec_func(itv, VIDIOC_S_CROP, arg);	}	case VIDIOC_G_CROP: {		struct v4l2_crop *crop = arg;		if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&		    (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {			crop->c = itv->main_rect;			return 0;		}		if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)			return -EINVAL;		return itv->video_dec_func(itv, VIDIOC_G_CROP, arg);	}	case VIDIOC_ENUM_FMT: {		static struct v4l2_fmtdesc formats[] = {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -