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

📄 pwc-ctrl.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
		return ret;	*flicker = !!buf;	return 0;}int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise){	unsigned char buf;	if (noise < 0)		noise = 0;	if (noise > 3)		noise = 3;	buf = noise;	return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);}int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise){	int ret;	unsigned char buf;	ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);	if (ret < 0)		return ret;	*noise = buf;	return 0;}static int _pwc_mpt_reset(struct pwc_device *pdev, int flags){	unsigned char buf;	buf = flags & 0x03; // only lower two bits are currently used	return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1);}int pwc_mpt_reset(struct pwc_device *pdev, int flags){	int ret;	ret = _pwc_mpt_reset(pdev, flags);	if (ret >= 0) {		pdev->pan_angle = 0;		pdev->tilt_angle = 0;	}	return ret;}static int _pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt){	unsigned char buf[4];	/* set new relative angle; angles are expressed in degrees * 100,	   but cam as .5 degree resolution, hence divide by 200. Also	   the angle must be multiplied by 64 before it's send to	   the cam (??)	 */	pan  =  64 * pan  / 100;	tilt = -64 * tilt / 100; /* positive tilt is down, which is not what the user would expect */	buf[0] = pan & 0xFF;	buf[1] = (pan >> 8) & 0xFF;	buf[2] = tilt & 0xFF;	buf[3] = (tilt >> 8) & 0xFF;	return SendControlMsg(SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, 4);}int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt){	int ret;	/* check absolute ranges */	if (pan  < pdev->angle_range.pan_min  ||	    pan  > pdev->angle_range.pan_max  ||	    tilt < pdev->angle_range.tilt_min ||	    tilt > pdev->angle_range.tilt_max)		return -ERANGE;	/* go to relative range, check again */	pan  -= pdev->pan_angle;	tilt -= pdev->tilt_angle;	/* angles are specified in degrees * 100, thus the limit = 36000 */	if (pan < -36000 || pan > 36000 || tilt < -36000 || tilt > 36000)		return -ERANGE;	ret = _pwc_mpt_set_angle(pdev, pan, tilt);	if (ret >= 0) {		pdev->pan_angle  += pan;		pdev->tilt_angle += tilt;	}	if (ret == -EPIPE) /* stall -> out of range */		ret = -ERANGE;	return ret;}static int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status){	int ret;	unsigned char buf[5];	ret = RecvControlMsg(GET_MPT_CTL, PT_STATUS_FORMATTER, 5);	if (ret < 0)		return ret;	status->status = buf[0] & 0x7; // 3 bits are used for reporting	status->time_pan = (buf[1] << 8) + buf[2];	status->time_tilt = (buf[3] << 8) + buf[4];	return 0;}int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor){	unsigned char buf;	int ret = -1, request;	if (pdev->type < 675)		request = SENSOR_TYPE_FORMATTER1;	else if (pdev->type < 730)		return -1; /* The Vesta series doesn't have this call */	else		request = SENSOR_TYPE_FORMATTER2;	ret = RecvControlMsg(GET_STATUS_CTL, request, 1);	if (ret < 0)		return ret;	if (pdev->type < 675)		*sensor = buf | 0x100;	else		*sensor = buf;	return 0;} /* End of Add-Ons                                    */ /* ************************************************* *//* Linux 2.5.something and 2.6 pass direct pointers to arguments of   ioctl() calls. With 2.4, you have to do tedious copy_from_user()   and copy_to_user() calls. With these macros we circumvent this,   and let me maintain only one source file. The functionality is   exactly the same otherwise. *//* define local variable for arg */#define ARG_DEF(ARG_type, ARG_name)\	ARG_type *ARG_name = arg;/* copy arg to local variable */#define ARG_IN(ARG_name) /* nothing *//* argument itself (referenced) */#define ARGR(ARG_name) (*ARG_name)/* argument address */#define ARGA(ARG_name) ARG_name/* copy local variable to arg */#define ARG_OUT(ARG_name) /* nothing */int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg){	int ret = 0;	switch(cmd) {	case VIDIOCPWCRUSER:	{		if (pwc_restore_user(pdev))			ret = -EINVAL;		break;	}	case VIDIOCPWCSUSER:	{		if (pwc_save_user(pdev))			ret = -EINVAL;		break;	}	case VIDIOCPWCFACTORY:	{		if (pwc_restore_factory(pdev))			ret = -EINVAL;		break;	}	case VIDIOCPWCSCQUAL:	{		ARG_DEF(int, qual)		ARG_IN(qual)		if (ARGR(qual) < 0 || ARGR(qual) > 3)			ret = -EINVAL;		else			ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot);		if (ret >= 0)			pdev->vcompression = ARGR(qual);		break;	}	case VIDIOCPWCGCQUAL:	{		ARG_DEF(int, qual)		ARGR(qual) = pdev->vcompression;		ARG_OUT(qual)		break;	}	case VIDIOCPWCPROBE:	{		ARG_DEF(struct pwc_probe, probe)		strcpy(ARGR(probe).name, pdev->vdev->name);		ARGR(probe).type = pdev->type;		ARG_OUT(probe)		break;	}	case VIDIOCPWCGSERIAL:	{		ARG_DEF(struct pwc_serial, serial)		strcpy(ARGR(serial).serial, pdev->serial);		ARG_OUT(serial)		break;	}	case VIDIOCPWCSAGC:	{		ARG_DEF(int, agc)		ARG_IN(agc)		if (pwc_set_agc(pdev, ARGR(agc) < 0 ? 1 : 0, ARGR(agc)))			ret = -EINVAL;		break;	}	case VIDIOCPWCGAGC:	{		ARG_DEF(int, agc)		if (pwc_get_agc(pdev, ARGA(agc)))			ret = -EINVAL;		ARG_OUT(agc)		break;	}	case VIDIOCPWCSSHUTTER:	{		ARG_DEF(int, shutter_speed)		ARG_IN(shutter_speed)		ret = pwc_set_shutter_speed(pdev, ARGR(shutter_speed) < 0 ? 1 : 0, ARGR(shutter_speed));		break;	}	case VIDIOCPWCSAWB:	{		ARG_DEF(struct pwc_whitebalance, wb)		ARG_IN(wb)		ret = pwc_set_awb(pdev, ARGR(wb).mode);		if (ret >= 0 && ARGR(wb).mode == PWC_WB_MANUAL) {			pwc_set_red_gain(pdev, ARGR(wb).manual_red);			pwc_set_blue_gain(pdev, ARGR(wb).manual_blue);		}		break;	}	case VIDIOCPWCGAWB:	{		ARG_DEF(struct pwc_whitebalance, wb)		memset(ARGA(wb), 0, sizeof(struct pwc_whitebalance));		ARGR(wb).mode = pwc_get_awb(pdev);		if (ARGR(wb).mode < 0)			ret = -EINVAL;		else {			if (ARGR(wb).mode == PWC_WB_MANUAL) {				ret = pwc_get_red_gain(pdev, &ARGR(wb).manual_red);				if (ret < 0)					break;				ret = pwc_get_blue_gain(pdev, &ARGR(wb).manual_blue);				if (ret < 0)					break;			}			if (ARGR(wb).mode == PWC_WB_AUTO) {				ret = pwc_read_red_gain(pdev, &ARGR(wb).read_red);				if (ret < 0)					break;				ret = pwc_read_blue_gain(pdev, &ARGR(wb).read_blue);				if (ret < 0)					break;			}		}		ARG_OUT(wb)		break;	}	case VIDIOCPWCSAWBSPEED:	{		ARG_DEF(struct pwc_wb_speed, wbs)		if (ARGR(wbs).control_speed > 0) {			ret = pwc_set_wb_speed(pdev, ARGR(wbs).control_speed);		}		if (ARGR(wbs).control_delay > 0) {			ret = pwc_set_wb_delay(pdev, ARGR(wbs).control_delay);		}		break;	}	case VIDIOCPWCGAWBSPEED:	{		ARG_DEF(struct pwc_wb_speed, wbs)		ret = pwc_get_wb_speed(pdev, &ARGR(wbs).control_speed);		if (ret < 0)			break;		ret = pwc_get_wb_delay(pdev, &ARGR(wbs).control_delay);		if (ret < 0)			break;		ARG_OUT(wbs)		break;	}	case VIDIOCPWCSLED:	{		ARG_DEF(struct pwc_leds, leds)		ARG_IN(leds)		ret = pwc_set_leds(pdev, ARGR(leds).led_on, ARGR(leds).led_off);		break;	}	case VIDIOCPWCGLED:	{		ARG_DEF(struct pwc_leds, leds)		ret = pwc_get_leds(pdev, &ARGR(leds).led_on, &ARGR(leds).led_off);		ARG_OUT(leds)		break;	}	case VIDIOCPWCSCONTOUR:	{		ARG_DEF(int, contour)		ARG_IN(contour)		ret = pwc_set_contour(pdev, ARGR(contour));		break;	}	case VIDIOCPWCGCONTOUR:	{		ARG_DEF(int, contour)		ret = pwc_get_contour(pdev, ARGA(contour));		ARG_OUT(contour)		break;	}	case VIDIOCPWCSBACKLIGHT:	{		ARG_DEF(int, backlight)		ARG_IN(backlight)		ret = pwc_set_backlight(pdev, ARGR(backlight));		break;	}	case VIDIOCPWCGBACKLIGHT:	{		ARG_DEF(int, backlight)		ret = pwc_get_backlight(pdev, ARGA(backlight));		ARG_OUT(backlight)		break;	}	case VIDIOCPWCSFLICKER:	{		ARG_DEF(int, flicker)		ARG_IN(flicker)		ret = pwc_set_flicker(pdev, ARGR(flicker));		break;	}	case VIDIOCPWCGFLICKER:	{		ARG_DEF(int, flicker)		ret = pwc_get_flicker(pdev, ARGA(flicker));		ARG_OUT(flicker)		break;	}	case VIDIOCPWCSDYNNOISE:	{		ARG_DEF(int, dynnoise)		ARG_IN(dynnoise)		ret = pwc_set_dynamic_noise(pdev, ARGR(dynnoise));		break;	}	case VIDIOCPWCGDYNNOISE:	{		ARG_DEF(int, dynnoise)		ret = pwc_get_dynamic_noise(pdev, ARGA(dynnoise));		ARG_OUT(dynnoise);		break;	}	case VIDIOCPWCGREALSIZE:	{		ARG_DEF(struct pwc_imagesize, size)		ARGR(size).width = pdev->image.x;		ARGR(size).height = pdev->image.y;		ARG_OUT(size)		break;	}	case VIDIOCPWCMPTRESET:	{		if (pdev->features & FEATURE_MOTOR_PANTILT)		{			ARG_DEF(int, flags)			ARG_IN(flags)			ret = pwc_mpt_reset(pdev, ARGR(flags));		}		else		{			ret = -ENXIO;		}		break;	}	case VIDIOCPWCMPTGRANGE:	{		if (pdev->features & FEATURE_MOTOR_PANTILT)		{			ARG_DEF(struct pwc_mpt_range, range)			ARGR(range) = pdev->angle_range;			ARG_OUT(range)		}		else		{			ret = -ENXIO;		}		break;	}	case VIDIOCPWCMPTSANGLE:	{		int new_pan, new_tilt;		if (pdev->features & FEATURE_MOTOR_PANTILT)		{			ARG_DEF(struct pwc_mpt_angles, angles)			ARG_IN(angles)			/* The camera can only set relative angles, so			   do some calculations when getting an absolute angle .			 */			if (ARGR(angles).absolute)			{				new_pan  = ARGR(angles).pan;				new_tilt = ARGR(angles).tilt;			}			else			{				new_pan  = pdev->pan_angle  + ARGR(angles).pan;				new_tilt = pdev->tilt_angle + ARGR(angles).tilt;			}			ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt);		}		else		{			ret = -ENXIO;		}		break;	}	case VIDIOCPWCMPTGANGLE:	{		if (pdev->features & FEATURE_MOTOR_PANTILT)		{			ARG_DEF(struct pwc_mpt_angles, angles)			ARGR(angles).absolute = 1;			ARGR(angles).pan  = pdev->pan_angle;			ARGR(angles).tilt = pdev->tilt_angle;			ARG_OUT(angles)		}		else		{			ret = -ENXIO;		}		break;	}	case VIDIOCPWCMPTSTATUS:	{		if (pdev->features & FEATURE_MOTOR_PANTILT)		{			ARG_DEF(struct pwc_mpt_status, status)			ret = pwc_mpt_get_status(pdev, ARGA(status));			ARG_OUT(status)		}		else		{			ret = -ENXIO;		}		break;	}	case VIDIOCPWCGVIDCMD:	{		ARG_DEF(struct pwc_video_command, vcmd);		ARGR(vcmd).type = pdev->type;		ARGR(vcmd).release = pdev->release;		ARGR(vcmd).command_len = pdev->cmd_len;		memcpy(&ARGR(vcmd).command_buf, pdev->cmd_buf, pdev->cmd_len);		ARGR(vcmd).bandlength = pdev->vbandlength;		ARGR(vcmd).frame_size = pdev->frame_size;		ARG_OUT(vcmd)		break;	}	/*	case VIDIOCPWCGVIDTABLE:	{		ARG_DEF(struct pwc_table_init_buffer, table);		ARGR(table).len = pdev->cmd_len;		memcpy(&ARGR(table).buffer, pdev->decompress_data, pdev->decompressor->table_size);		ARG_OUT(table)		break;	}	*/	default:		ret = -ENOIOCTLCMD;		break;	}	if (ret > 0)		return 0;	return ret;}/* vim: set cinoptions= formatoptions=croql cindent shiftwidth=8 tabstop=8: */

⌨️ 快捷键说明

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