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

📄 pwc-ctrl.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),		GET_CHROM_CTL,		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1,		pdev->vcinterface,		&buf, 1, HZ / 2);	if (ret < 0)		return ret;	return 32768 + buf * 327;}int pwc_set_saturation(struct pwc_device *pdev, int value){	char buf;	if (pdev->type < 675)		return -EINVAL;	if (value < 0)		value = 0;	if (value > 0xffff)		value = 0xffff;	/* saturation ranges from -100 to +100 */	buf = (value - 32768) / 327;	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),		SET_CHROM_CTL,		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1,		pdev->vcinterface,		&buf, 1, HZ / 2);}/* AGC */static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value){	char buf;	int ret;		if (mode)		buf = 0x0; /* auto */	else		buf = 0xff; /* fixed */	ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),		SET_LUM_CTL,		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		AGC_MODE_FORMATTER,		pdev->vcinterface,		&buf, 1, HZ / 2);		if (!mode && ret >= 0) {		if (value < 0)			value = 0;		if (value > 0xffff)			value = 0xffff;		buf = (value >> 10) & 0x3F;		ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),			SET_LUM_CTL,			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,			PRESET_AGC_FORMATTER,			pdev->vcinterface,			&buf, 1, HZ / 2);	}	if (ret < 0)		return ret;	return 0;}static inline int pwc_get_agc(struct pwc_device *pdev, int *value){	unsigned char buf;	int ret;		ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),		GET_LUM_CTL,		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		AGC_MODE_FORMATTER,		pdev->vcinterface,		&buf, 1, HZ / 2);	if (ret < 0)		return ret;	if (buf != 0) { /* fixed */		ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),			GET_LUM_CTL,			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,			PRESET_AGC_FORMATTER,			pdev->vcinterface,			&buf, 1, HZ / 2);		if (ret < 0)			return ret;		if (buf > 0x3F)			buf = 0x3F;		*value = (buf << 10);			}	else { /* auto */		ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),			GET_STATUS_CTL,			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,			READ_AGC_FORMATTER,			pdev->vcinterface,			&buf, 1, HZ / 2);		if (ret < 0)			return ret;		/* Gah... this value ranges from 0x00 ... 0x9F */		if (buf > 0x9F)			buf = 0x9F;		*value = -(48 + buf * 409);	}	return 0;}static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value){	char buf[2];	int speed, ret;	if (mode)		buf[0] = 0x0;	/* auto */	else		buf[0] = 0xff; /* fixed */		ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),		SET_LUM_CTL,		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		SHUTTER_MODE_FORMATTER,		pdev->vcinterface,		buf, 1, HZ / 2);	if (!mode && ret >= 0) {		if (value < 0)			value = 0;		if (value > 0xffff)			value = 0xffff;		switch(pdev->type) {		case 675:		case 680:		case 690:			/* speed ranges from 0x0 to 0x290 (656) */			speed = (value / 100);			buf[1] = speed >> 8;			buf[0] = speed & 0xff;			break;		case 730:		case 740:		case 750:			/* speed seems to range from 0x0 to 0xff */			buf[1] = 0;			buf[0] = value >> 8;			break;		}		ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),			SET_LUM_CTL,			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,			PRESET_SHUTTER_FORMATTER,			pdev->vcinterface,			&buf, 2, HZ / 2);	}	return ret;}	/* POWER */int pwc_camera_power(struct pwc_device *pdev, int power){	char buf;	if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))		return 0;	/* Not supported by Nala or Timon < release 6 */	if (power)		buf = 0x00; /* active */	else		buf = 0xFF; /* power save */	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),		SET_STATUS_CTL,		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		SET_POWER_SAVE_MODE_FORMATTER,		pdev->vcinterface,		&buf, 1, HZ / 2);}/* private calls */static inline int pwc_restore_user(struct pwc_device *pdev){	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),		SET_STATUS_CTL,		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		RESTORE_USER_DEFAULTS_FORMATTER,		pdev->vcinterface,		NULL, 0, HZ / 2);}static inline int pwc_save_user(struct pwc_device *pdev){	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),		SET_STATUS_CTL,		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		SAVE_USER_DEFAULTS_FORMATTER,		pdev->vcinterface,		NULL, 0, HZ / 2);}static inline int pwc_restore_factory(struct pwc_device *pdev){	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),		SET_STATUS_CTL,		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		RESTORE_FACTORY_DEFAULTS_FORMATTER,		pdev->vcinterface,		NULL, 0, HZ / 2);} /* ************************************************* */ /* Patch by Alvarado: (not in the original version   */ /*  * the camera recognizes modes from 0 to 4:  *  * 00: indoor (incandescant lighting)  * 01: outdoor (sunlight)  * 02: fluorescent lighting  * 03: manual  * 04: auto  */ static inline int pwc_set_awb(struct pwc_device *pdev, int mode){	char buf;	int ret;		if (mode < 0)	    mode = 0;		if (mode > 4)	    mode = 4;		buf = mode & 0x07; /* just the lowest three bits */		ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),		SET_CHROM_CTL,		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		WB_MODE_FORMATTER,		pdev->vcinterface,		&buf, 1, HZ / 2);		if (ret < 0)		return ret;	return 0;}static inline int pwc_get_awb(struct pwc_device *pdev){	unsigned char buf;	int ret;		ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),		GET_CHROM_CTL,		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		WB_MODE_FORMATTER,		pdev->vcinterface,		&buf, 1, HZ / 2);	if (ret < 0) 		return ret;	return buf;}static inline int pwc_set_red_gain(struct pwc_device *pdev, int value){        unsigned char buf;	if (value < 0)		value = 0;	if (value > 0xffff)		value = 0xffff;	/* only the msb are considered */	buf = value >> 8;	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),		SET_CHROM_CTL,		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		PRESET_MANUAL_RED_GAIN_FORMATTER,		pdev->vcinterface,		&buf, 1, HZ / 2);}static inline int pwc_get_red_gain(struct pwc_device *pdev){	unsigned char buf;	int ret;		ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 	        GET_STATUS_CTL, 		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,	        PRESET_MANUAL_RED_GAIN_FORMATTER,		pdev->vcinterface,		&buf, 1, HZ / 2);	if (ret < 0)	    return ret;		return (buf << 8);}static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value){	unsigned char buf;	if (value < 0)		value = 0;	if (value > 0xffff)		value = 0xffff;	/* linear mapping of 0..0xffff to -0x80..0x7f */	buf = (value >> 8);	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),		SET_CHROM_CTL,		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		PRESET_MANUAL_BLUE_GAIN_FORMATTER,		pdev->vcinterface,		&buf, 1, HZ / 2);}static inline int pwc_get_blue_gain(struct pwc_device *pdev){	unsigned char buf;	int ret;		ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),   	        GET_STATUS_CTL,		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		PRESET_MANUAL_BLUE_GAIN_FORMATTER,		pdev->vcinterface,		&buf, 1, HZ / 2);	if (ret < 0)	    return ret;		return (buf << 8);}/* The following two functions are different, since they only read the   internal red/blue gains, which may be different from the manual    gains set or read above. */   static inline int pwc_read_red_gain(struct pwc_device *pdev){	unsigned char buf;	int ret;		ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 	        GET_STATUS_CTL, 		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,	        READ_RED_GAIN_FORMATTER,		pdev->vcinterface,		&buf, 1, HZ / 2);	if (ret < 0)	    return ret;		return (buf << 8);}static inline int pwc_read_blue_gain(struct pwc_device *pdev){	unsigned char buf;	int ret;		ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),   	        GET_STATUS_CTL,		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		READ_BLUE_GAIN_FORMATTER,		pdev->vcinterface,		&buf, 1, HZ / 2);	if (ret < 0)	    return ret;		return (buf << 8);}int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value){	unsigned char buf[2];	if (pdev->type < 730)		return 0;	on_value /= 100;	off_value /= 100;	if (on_value < 0)		on_value = 0;	if (on_value > 0xff)		on_value = 0xff;	if (off_value < 0)		off_value = 0;	if (off_value > 0xff)		off_value = 0xff;	buf[0] = on_value;	buf[1] = off_value;	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),		SET_STATUS_CTL,		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		LED_FORMATTER,		pdev->vcinterface,		&buf, 2, HZ / 2);}int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value){	unsigned char buf[2];	int ret;		if (pdev->type < 730) {		*on_value = -1;		*off_value = -1;		return 0;	}	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),   	        GET_STATUS_CTL,		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		LED_FORMATTER,		pdev->vcinterface,		&buf, 2, HZ / 2);	if (ret < 0)		return ret;	*on_value = buf[0] * 100;	*off_value = buf[1] * 100;	return 0;} /* End of Add-Ons                                    */ /* ************************************************* */int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg){	switch(cmd) {	case VIDIOCPWCRUSER:	{		if (pwc_restore_user(pdev))			return -EINVAL;		break;	}		case VIDIOCPWCSUSER:	{		if (pwc_save_user(pdev))			return -EINVAL;		break;	}			case VIDIOCPWCFACTORY:	{		if (pwc_restore_factory(pdev))			return -EINVAL;		break;	}		case VIDIOCPWCSCQUAL:	{			int qual, ret;		if (copy_from_user(&qual, arg, sizeof(int)))			return -EFAULT;					if (qual < 0 || qual > 3)			return -EINVAL;		ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, qual, pdev->vsnapshot);		if (ret < 0)			return ret;		pdev->vcompression = qual;		break;	}		case VIDIOCPWCGCQUAL:	{		if (copy_to_user(arg, &pdev->vcompression, sizeof(int)))			return -EFAULT;		break;	}	case VIDIOCPWCSAGC:	{		int agc;				if (copy_from_user(&agc, arg, sizeof(agc)))			return -EFAULT;			else {			if (pwc_set_agc(pdev, agc < 0 ? 1 : 0, agc))				return -EINVAL;		}		break;	}		case VIDIOCPWCGAGC:	{		int agc;				if (pwc_get_agc(pdev, &agc))			return -EINVAL;		if (copy_to_user(arg, &agc, sizeof(agc)))			return -EFAULT;		break;	}		case VIDIOCPWCSSHUTTER:	{		int shutter_speed, ret;		if (copy_from_user(&shutter_speed, arg, sizeof(shutter_speed)))			return -EFAULT;		else {			ret = pwc_set_shutter_speed(pdev, shutter_speed < 0 ? 1 : 0, shutter_speed);			if (ret < 0)				return ret;		}		break;	}	 /* ************************************************* */ /* Begin of Add-Ons for color compensation           */        case VIDIOCPWCSAWB:	{		struct pwc_whitebalance wb;		int ret;				if (copy_from_user(&wb, arg, sizeof(wb)))			return -EFAULT;			ret = pwc_set_awb(pdev, wb.mode);		if (ret >= 0 && wb.mode == PWC_WB_MANUAL) {			pwc_set_red_gain(pdev, wb.manual_red);			pwc_set_blue_gain(pdev, wb.manual_blue);		}		break;	}	case VIDIOCPWCGAWB:	{		struct pwc_whitebalance wb;				memset(&wb, 0, sizeof(wb));		wb.mode = pwc_get_awb(pdev);		if (wb.mode < 0)			return -EINVAL;		wb.manual_red = pwc_get_red_gain(pdev);		wb.manual_blue = pwc_get_blue_gain(pdev);		if (wb.mode == PWC_WB_AUTO) {			wb.read_red = pwc_read_red_gain(pdev);			wb.read_blue = pwc_read_blue_gain(pdev);		}		if (copy_to_user(arg, &wb, sizeof(wb)))			return -EFAULT;		break;	}        case VIDIOCPWCSLED:	{		int ret;		struct pwc_leds leds;		if (copy_from_user(&leds, arg, sizeof(leds)))			return -EFAULT;		ret = pwc_set_leds(pdev, leds.led_on, leds.led_off);		if (ret<0)		    return ret;	    break;	}	case VIDIOCPWCGLED:	{		int led;		struct pwc_leds leds;				led = pwc_get_leds(pdev, &leds.led_on, &leds.led_off); 		if (led < 0)			return -EINVAL;		if (copy_to_user(arg, &leds, sizeof(leds)))			return -EFAULT;		break;	} /* End of Add-Ons                                    */ /* ************************************************* */	default:		return -ENOIOCTLCMD;		break;	}	return 0;}

⌨️ 快捷键说明

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