usbvision-core.c

来自「linux 内核源代码」· C语言 代码 · 共 2,307 行 · 第 1/5 页

C
2,307
字号
		usbvision->isocDataCount += packet_len;		usbvision->isocPacketCount++;	}#if ENABLE_HEXDUMP	if (totlen > 0) {		static int foo = 0;		if (foo < 1) {			printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen);			usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen);			++foo;		}	}#endif return totlen;}static void usbvision_isocIrq(struct urb *urb){	int errCode = 0;	int len;	struct usb_usbvision *usbvision = urb->context;	int i;	unsigned long startTime = jiffies;	struct usbvision_frame **f;	/* We don't want to do anything if we are about to be removed! */	if (!USBVISION_IS_OPERATIONAL(usbvision))		return;	/* any urb with wrong status is ignored without acknowledgement */	if (urb->status == -ENOENT) {		return;	}	f = &usbvision->curFrame;	/* Manage streaming interruption */	if (usbvision->streaming == Stream_Interrupt) {		usbvision->streaming = Stream_Idle;		if ((*f)) {			(*f)->grabstate = FrameState_Ready;			(*f)->scanstate = ScanState_Scanning;		}		PDEBUG(DBG_IRQ, "stream interrupted");		wake_up_interruptible(&usbvision->wait_stream);	}	/* Copy the data received into our scratch buffer */	len = usbvision_compress_isochronous(usbvision, urb);	usbvision->isocUrbCount++;	usbvision->urb_length = len;	if (usbvision->streaming == Stream_On) {		/* If we collected enough data let's parse! */		if ((scratch_len(usbvision) > USBVISION_HEADER_LENGTH) &&		    (!list_empty(&(usbvision->inqueue))) ) {			if (!(*f)) {				(*f) = list_entry(usbvision->inqueue.next,						  struct usbvision_frame,						  frame);			}			usbvision_parse_data(usbvision);		}		else {			/*If we don't have a frame			  we're current working on, complain */			PDEBUG(DBG_IRQ,			       "received data, but no one needs it");			scratch_reset(usbvision);		}	}	else {		PDEBUG(DBG_IRQ, "received data, but no one needs it");		scratch_reset(usbvision);	}	usbvision->timeInIrq += jiffies - startTime;	for (i = 0; i < USBVISION_URB_FRAMES; i++) {		urb->iso_frame_desc[i].status = 0;		urb->iso_frame_desc[i].actual_length = 0;	}	urb->status = 0;	urb->dev = usbvision->dev;	errCode = usb_submit_urb (urb, GFP_ATOMIC);	if(errCode) {		err("%s: usb_submit_urb failed: error %d",		    __FUNCTION__, errCode);	}	return;}/*************************************//* Low level usbvision access functions *//*************************************//* * usbvision_read_reg() * * return  < 0 -> Error *        >= 0 -> Data */int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg){	int errCode = 0;	unsigned char buffer[1];	if (!USBVISION_IS_OPERATIONAL(usbvision))		return -1;	errCode = usb_control_msg(usbvision->dev, usb_rcvctrlpipe(usbvision->dev, 1),				USBVISION_OP_CODE,				USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,				0, (__u16) reg, buffer, 1, HZ);	if (errCode < 0) {		err("%s: failed: error %d", __FUNCTION__, errCode);		return errCode;	}	return buffer[0];}/* * usbvision_write_reg() * * return 1 -> Reg written *        0 -> usbvision is not yet ready *       -1 -> Something went wrong */int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg,			    unsigned char value){	int errCode = 0;	if (!USBVISION_IS_OPERATIONAL(usbvision))		return 0;	errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),				USBVISION_OP_CODE,				USB_DIR_OUT | USB_TYPE_VENDOR |				USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ);	if (errCode < 0) {		err("%s: failed: error %d", __FUNCTION__, errCode);	}	return errCode;}static void usbvision_ctrlUrb_complete(struct urb *urb){	struct usb_usbvision *usbvision = (struct usb_usbvision *)urb->context;	PDEBUG(DBG_IRQ, "");	usbvision->ctrlUrbBusy = 0;	if (waitqueue_active(&usbvision->ctrlUrb_wq)) {		wake_up_interruptible(&usbvision->ctrlUrb_wq);	}}static int usbvision_write_reg_irq(struct usb_usbvision *usbvision,int address,									unsigned char *data, int len){	int errCode = 0;	PDEBUG(DBG_IRQ, "");	if (len > 8) {		return -EFAULT;	}//	down(&usbvision->ctrlUrbLock);	if (usbvision->ctrlUrbBusy) {//		up(&usbvision->ctrlUrbLock);		return -EBUSY;	}	usbvision->ctrlUrbBusy = 1;//	up(&usbvision->ctrlUrbLock);	usbvision->ctrlUrbSetup.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;	usbvision->ctrlUrbSetup.bRequest     = USBVISION_OP_CODE;	usbvision->ctrlUrbSetup.wValue       = 0;	usbvision->ctrlUrbSetup.wIndex       = cpu_to_le16(address);	usbvision->ctrlUrbSetup.wLength      = cpu_to_le16(len);	usb_fill_control_urb (usbvision->ctrlUrb, usbvision->dev,							usb_sndctrlpipe(usbvision->dev, 1),							(unsigned char *)&usbvision->ctrlUrbSetup,							(void *)usbvision->ctrlUrbBuffer, len,							usbvision_ctrlUrb_complete,							(void *)usbvision);	memcpy(usbvision->ctrlUrbBuffer, data, len);	errCode = usb_submit_urb(usbvision->ctrlUrb, GFP_ATOMIC);	if (errCode < 0) {		// error in usb_submit_urb()		usbvision->ctrlUrbBusy = 0;	}	PDEBUG(DBG_IRQ, "submit %d byte: error %d", len, errCode);	return errCode;}static int usbvision_init_compression(struct usb_usbvision *usbvision){	int errCode = 0;	usbvision->lastIsocFrameNum = -1;	usbvision->isocDataCount = 0;	usbvision->isocPacketCount = 0;	usbvision->isocSkipCount = 0;	usbvision->comprLevel = 50;	usbvision->lastComprLevel = -1;	usbvision->isocUrbCount = 0;	usbvision->requestIntra = 1;	usbvision->isocMeasureBandwidthCount = 0;	return errCode;}/* this function measures the used bandwidth since last call * return:    0 : no error * sets usedBandwidth to 1-100 : 1-100% of full bandwidth resp. to isocPacketSize */static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision){	int errCode = 0;	if (usbvision->isocMeasureBandwidthCount < 2) { // this gives an average bandwidth of 3 frames		usbvision->isocMeasureBandwidthCount++;		return errCode;	}	if ((usbvision->isocPacketSize > 0) && (usbvision->isocPacketCount > 0)) {		usbvision->usedBandwidth = usbvision->isocDataCount /					(usbvision->isocPacketCount + usbvision->isocSkipCount) *					100 / usbvision->isocPacketSize;	}	usbvision->isocMeasureBandwidthCount = 0;	usbvision->isocDataCount = 0;	usbvision->isocPacketCount = 0;	usbvision->isocSkipCount = 0;	return errCode;}static int usbvision_adjust_compression (struct usb_usbvision *usbvision){	int errCode = 0;	unsigned char buffer[6];	PDEBUG(DBG_IRQ, "");	if ((adjustCompression) && (usbvision->usedBandwidth > 0)) {		usbvision->comprLevel += (usbvision->usedBandwidth - 90) / 2;		RESTRICT_TO_RANGE(usbvision->comprLevel, 0, 100);		if (usbvision->comprLevel != usbvision->lastComprLevel) {			int distorsion;			if (usbvision->bridgeType == BRIDGE_NT1004 || usbvision->bridgeType == BRIDGE_NT1005) {				buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100);	// PCM Threshold 1				buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100);	// PCM Threshold 2				distorsion = 7 + 248 * usbvision->comprLevel / 100;				buffer[2] = (unsigned char)(distorsion & 0xFF);				// Average distorsion Threshold (inter)				buffer[3] = (unsigned char)(distorsion & 0xFF);				// Average distorsion Threshold (intra)				distorsion = 1 + 42 * usbvision->comprLevel / 100;				buffer[4] = (unsigned char)(distorsion & 0xFF);				// Maximum distorsion Threshold (inter)				buffer[5] = (unsigned char)(distorsion & 0xFF);				// Maximum distorsion Threshold (intra)			}			else { //BRIDGE_NT1003				buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100);	// PCM threshold 1				buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100);	// PCM threshold 2				distorsion = 2 + 253 * usbvision->comprLevel / 100;				buffer[2] = (unsigned char)(distorsion & 0xFF);				// distorsion threshold bit0-7				buffer[3] = 0; 	//(unsigned char)((distorsion >> 8) & 0x0F);		// distorsion threshold bit 8-11				distorsion = 0 + 43 * usbvision->comprLevel / 100;				buffer[4] = (unsigned char)(distorsion & 0xFF);				// maximum distorsion bit0-7				buffer[5] = 0; //(unsigned char)((distorsion >> 8) & 0x01);		// maximum distorsion bit 8			}			errCode = usbvision_write_reg_irq(usbvision, USBVISION_PCM_THR1, buffer, 6);			if (errCode == 0){				PDEBUG(DBG_IRQ, "new compr params %#02x %#02x %#02x %#02x %#02x %#02x", buffer[0],								buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]);				usbvision->lastComprLevel = usbvision->comprLevel;			}		}	}	return errCode;}static int usbvision_request_intra (struct usb_usbvision *usbvision){	int errCode = 0;	unsigned char buffer[1];	PDEBUG(DBG_IRQ, "");	usbvision->requestIntra = 1;	buffer[0] = 1;	usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1);	return errCode;}static int usbvision_unrequest_intra (struct usb_usbvision *usbvision){	int errCode = 0;	unsigned char buffer[1];	PDEBUG(DBG_IRQ, "");	usbvision->requestIntra = 0;	buffer[0] = 0;	usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1);	return errCode;}/******************************* * usbvision utility functions *******************************/int usbvision_power_off(struct usb_usbvision *usbvision){	int errCode = 0;	PDEBUG(DBG_FUNC, "");	errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN);	if (errCode == 1) {		usbvision->power = 0;	}	PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode!=1)?"ERROR":"power is off", errCode);	return errCode;}/* * usbvision_set_video_format() * */static int usbvision_set_video_format(struct usb_usbvision *usbvision, int format){	static const char proc[] = "usbvision_set_video_format";	int rc;	unsigned char value[2];	if (!USBVISION_IS_OPERATIONAL(usbvision))		return 0;	PDEBUG(DBG_FUNC, "isocMode %#02x", format);	if ((format != ISOC_MODE_YUV422)	    && (format != ISOC_MODE_YUV420)	    && (format != ISOC_MODE_COMPRESS)) {		printk(KERN_ERR "usbvision: unknown video format %02x, using default YUV420",		       format);		format = ISOC_MODE_YUV420;	}	value[0] = 0x0A;  //TODO: See the effect of the filter	value[1] = format; // Sets the VO_MODE register which follows FILT_CONT	rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),			     USBVISION_OP_CODE,			     USB_DIR_OUT | USB_TYPE_VENDOR |			     USB_RECIP_ENDPOINT, 0,			     (__u16) USBVISION_FILT_CONT, value, 2, HZ);	if (rc < 0) {		printk(KERN_ERR "%s: ERROR=%d. USBVISION stopped - "		       "reconnect or reload driver.\n", proc, rc);	}	usbvision->isocMode = format;	return rc;}/* * usbvision_set_output() * */int usbvision_set_output(struct usb_usbvision *usbvision, int width,			 int height){	int errCode = 0;	int UsbWidth, UsbHeight;	unsigned int frameRate=0, frameDrop=0;	unsigned char value[4];	if (!USBVISION_IS_OPERATIONAL(usbvision)) {		return 0;	}	if (width > MAX_USB_WIDTH) {		UsbWidth = width / 2;		usbvision->stretch_width = 2;	}	else {		UsbWidth = width;		usbvision->stretch_width = 1;	}	if (height > MAX_USB_HEIGHT) {		UsbHeight = height / 2;		usbvision->stretch_height = 2;	}	else {		UsbHeight = height;		usbvision->stretch_height = 1;	}	RESTRICT_TO_RANGE(UsbWidth, MIN_FRAME_WIDTH, MAX_USB_WIDTH);	UsbWidth &= ~(MIN_FRAME_WIDTH-1);	RESTRICT_TO_RANGE(UsbHeight, MIN_FRAME_HEIGHT, MAX_USB_HEIGHT);	UsbHeight &= ~(1);	PDEBUG(DBG_FUNC, "usb %dx%d; screen %dx%d; stretch %dx%d",						UsbWidth, UsbHeight, width, height,						usbvision->stretch_width, usbvision->stretch_height);	/* I'll not rewrite the same values */	if ((UsbWidth != usbvision->curwidth) || (UsbHeight != usbvision->curheight)) {		value[0] = UsbWidth & 0xff;		//LSB		value[1] = (UsbWidth >> 8) & 0x03;	//MSB		value[2] = UsbHeight & 0xff;		//LSB		value[3] = (UsbHeight >> 8) & 0x03;	//MSB		errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),			     USBVISION_OP_CODE,			     USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,				 0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ);		if (errCode < 0) {			err("%s failed: error %d", __FUNCTION__, errCode);			return errCode;		}		usbvision->curwidth = usbvision->stretch_width * UsbWidth;		usbvision->curheight = usbvision->stretch_height * UsbHeight;	}	if (usbvision->isocMode == ISOC_MODE_YUV422) {		frameRate = (usbvision->isocPacketSize * 1000) / (UsbWidth * UsbHeight * 2);	}	else if (usbvision->isocMode == ISOC_MODE_YUV420) {		frameRate = (usbvision->isocPacketSize * 1000) / ((UsbWidth * UsbHeight * 12) / 8);	}	else {		frameRate = FRAMERATE_MAX;	}	if (usbvision->tvnormId & V4L2_STD_625_50) {		frameDrop = frameRate * 32 / 25 - 1;	}	else if (usbvision->tvnormId & V4L2_STD_525_60) {		frameDrop = frameRate * 32 / 30 - 1;	}	RESTRICT_TO_RANGE(frameDrop, FRAMERATE_MIN, FRAMERATE_MAX);	PDEBUG(DBG_FUNC, "frameRate %d fps, frameDrop %d", frameRate, frameDrop);	frameDrop = FRAMERATE_MAX; 	// We can allow the maximum here, because dropping is controlled	/* frameDrop = 7; => framePhase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ...		=> frameSkip = 4;		=> frameRate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25;

⌨️ 快捷键说明

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