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

📄 stv680.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	for (i = 0; i < STV680_NUMSCRATCH; i++) {		kfree (stv680->scratch[i].data);		stv680->scratch[i].data = NULL;	}	return 0;}static int stv680_set_size (struct usb_stv *stv680, int width, int height){	int wasstreaming = stv680->streaming;	/* Check to see if we need to change */	if ((stv680->vwidth == width) && (stv680->vheight == height))		return 0;	PDEBUG (1, "STV(i): size request for %i x %i", width, height);	/* Check for a valid mode */	if ((!width || !height) || ((width & 1) || (height & 1))) {		PDEBUG (1, "STV(e): set_size error: request: v.width = %i, v.height = %i  actual: stv.width = %i, stv.height = %i", width, height, stv680->vwidth, stv680->vheight);		return 1;	}	if ((width < (stv680->maxwidth / 2)) || (height < (stv680->maxheight / 2))) {		width = stv680->maxwidth / 2;		height = stv680->maxheight / 2;	} else if ((width >= 158) && (width <= 166)) {		width = 160;		height = 120;	} else if ((width >= 172) && (width <= 180)) {		width = 176;		height = 144;	} else if ((width >= 318) && (width <= 350)) {		width = 320;		height = 240;	} else if ((width >= 350) && (width <= 358)) {		width = 352;		height = 288;	}	/* Stop a current stream and start it again at the new size */	if (wasstreaming)		stv680_stop_stream (stv680);	stv680->vwidth = width;	stv680->vheight = height;	PDEBUG (1, "STV(i): size set to %i x %i", stv680->vwidth, stv680->vheight);	if (wasstreaming)		stv680_start_stream (stv680);	return 0;}/********************************************************************** * Video Decoding **********************************************************************//*******  routines from the pencam program; hey, they work!  ********//* * STV0680 Vision Camera Chipset Driver * Copyright (C) 2000 Adam Harrison <adam@antispin.org> */#define RED 0#define GREEN 1#define BLUE 2#define AD(x, y, w) (((y)*(w)+(x))*3)static void bayer_unshuffle (struct usb_stv *stv680, struct stv680_scratch *buffer){	int x, y, i;	int w = stv680->cwidth;	int vw = stv680->cwidth, vh = stv680->cheight;	unsigned int p = 0;	int colour = 0, bayer = 0;	unsigned char *raw = buffer->data;	struct stv680_frame *frame = &stv680->frame[stv680->curframe];	unsigned char *output = frame->data;	unsigned char *temp = frame->data;	int offset = buffer->offset;	if (frame->curpix == 0) {		if (frame->grabstate == FRAME_READY) {			frame->grabstate = FRAME_GRABBING;		}	}	if (offset != frame->curpix) {	/* Regard frame as lost :( */		frame->curpix = 0;		stv680->error++;		return;	}	if ((stv680->vwidth == 320) || (stv680->vwidth == 160)) {		vw = 320;		vh = 240;	}	if ((stv680->vwidth == 352) || (stv680->vwidth == 176)) {		vw = 352;		vh = 288;	}	memset (output, 0, 3 * vw * vh);	/* clear output matrix. */	for (y = 0; y < vh; y++) {		for (x = 0; x < vw; x++) {			if (x & 1)				p = *(raw + y * w + (x >> 1));			else				p = *(raw + y * w + (x >> 1) + (w >> 1));			if (y & 1)				bayer = 2;			else				bayer = 0;			if (x & 1)				bayer++;			switch (bayer) {			case 0:			case 3:				colour = 1;				break;			case 1:				colour = 0;				break;			case 2:				colour = 2;				break;			}			i = (y * vw + x) * 3;				*(output + i + colour) = (unsigned char) p;		}		/* for x */	}			/* for y */	/****** gamma correction plus hardcoded white balance */	/* Thanks to Alexander Schwartx <alexander.schwartx@gmx.net> for this code.	   Correction values red[], green[], blue[], are generated by 	   (pow(i/256.0, GAMMA)*255.0)*white balanceRGB where GAMMA=0.55, 1<i<255. 	   White balance (RGB)= 1.0, 1.17, 1.48. Values are calculated as double float and 	   converted to unsigned char. Values are in stv680.h  */	for (y = 0; y < vh; y++) {		for (x = 0; x < vw; x++) {			i = (y * vw + x) * 3;			*(output + i) = red[*(output + i)];			*(output + i + 1) = green[*(output + i + 1)];			*(output + i + 2) = blue[*(output + i + 2)];		}	}	/******  bayer demosaic  ******/	for (y = 1; y < (vh - 1); y++) {		for (x = 1; x < (vw - 1); x++) {	/* work out pixel type */			if (y & 1)				bayer = 0;			else				bayer = 2;			if (!(x & 1))				bayer++;			switch (bayer) {			case 0:	/* green. blue lr, red tb */				*(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x - 1, y, vw) + BLUE) + (int) *(output + AD (x + 1, y, vw) + BLUE)) >> 1;				*(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x, y - 1, vw) + RED) + (int) *(output + AD (x, y + 1, vw) + RED)) >> 1;				break;			case 1:	/* blue. green lrtb, red diagonals */				*(output + AD (x, y, vw) + GREEN) = ((int) *(output + AD (x - 1, y, vw) + GREEN) + (int) *(output + AD (x + 1, y, vw) + GREEN) + (int) *(output + AD (x, y - 1, vw) + GREEN) + (int) *(output + AD (x, y + 1, vw) + GREEN)) >> 2;				*(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x - 1, y - 1, vw) + RED) + (int) *(output + AD (x - 1, y + 1, vw) + RED) + (int) *(output + AD (x + 1, y - 1, vw) + RED) + (int) *(output + AD (x + 1, y + 1, vw) + RED)) >> 2;				break;			case 2:	/* red. green lrtb, blue diagonals */				*(output + AD (x, y, vw) + GREEN) = ((int) *(output + AD (x - 1, y, vw) + GREEN) + (int) *(output + AD (x + 1, y, vw) + GREEN) + (int) *(output + AD (x, y - 1, vw) + GREEN) + (int) *(output + AD (x, y + 1, vw) + GREEN)) >> 2;				*(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x - 1, y - 1, vw) + BLUE) + (int) *(output + AD (x + 1, y - 1, vw) + BLUE) + (int) *(output + AD (x - 1, y + 1, vw) + BLUE) + (int) *(output + AD (x + 1, y + 1, vw) + BLUE)) >> 2;				break;			case 3:	/* green. red lr, blue tb */				*(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x - 1, y, vw) + RED) + (int) *(output + AD (x + 1, y, vw) + RED)) >> 1;				*(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x, y - 1, vw) + BLUE) + (int) *(output + AD (x, y + 1, vw) + BLUE)) >> 1;				break;			}	/* switch */		}		/* for x */	}			/* for y  - end demosaic  */	/* fix top and bottom row, left and right side */	i = vw * 3;	memcpy (output, (output + i), i);	memcpy ((output + (vh * i)), (output + ((vh - 1) * i)), i);	for (y = 0; y < vh; y++) {		i = y * vw * 3;		memcpy ((output + i), (output + i + 3), 3);		memcpy ((output + i + (vw * 3)), (output + i + (vw - 1) * 3), 3);	}	/*  process all raw data, then trim to size if necessary */	if ((stv680->vwidth == 160) || (stv680->vwidth == 176))  {		i = 0;		for (y = 0; y < vh; y++) {			if (!(y & 1)) {				for (x = 0; x < vw; x++) {					p = (y * vw + x) * 3;					if (!(x & 1)) {						*(output + i) = *(output + p);						*(output + i + 1) = *(output + p + 1);						*(output + i + 2) = *(output + p + 2);						i += 3;					}				}  /* for x */			}		}  /* for y */	}	/* reset to proper width */	if ((stv680->vwidth == 160)) {		vw = 160;		vh = 120;	}	if ((stv680->vwidth == 176)) {		vw = 176;		vh = 144;	}	/* output is RGB; some programs want BGR  */	/* swapRGB_on=0 -> program decides;  swapRGB_on=1, always swap */	/* swapRGB_on=-1, never swap */	if (((swapRGB == 1) && (swapRGB_on != -1)) || (swapRGB_on == 1)) {		for (y = 0; y < vh; y++) {			for (x = 0; x < vw; x++) {				i = (y * vw + x) * 3;				*(temp) = *(output + i);				*(output + i) = *(output + i + 2);				*(output + i + 2) = *(temp);			}		}	}	/* brightness */	if (stv680->chgbright == 1) {		if (stv680->brightness >= 32767) {			p = (stv680->brightness - 32767) / 256;			for (x = 0; x < (vw * vh * 3); x++) {				if ((*(output + x) + (unsigned char) p) > 255)					*(output + x) = 255;				else					*(output + x) += (unsigned char) p;			}	/* for */		} else {			p = (32767 - stv680->brightness) / 256;			for (x = 0; x < (vw * vh * 3); x++) {				if ((unsigned char) p > *(output + x))					*(output + x) = 0;				else					*(output + x) -= (unsigned char) p;			}	/* for */		}		/* else */	}	/* if */	frame->curpix = 0;	frame->curlinepix = 0;	frame->grabstate = FRAME_DONE;	stv680->framecount++;	stv680->readcount++;	if (stv680->frame[(stv680->curframe + 1) & (STV680_NUMFRAMES - 1)].grabstate == FRAME_READY) {		stv680->curframe = (stv680->curframe + 1) & (STV680_NUMFRAMES - 1);	}}				/* bayer_unshuffle *//*******  end routines from the pencam program  *********/static int stv680_newframe (struct usb_stv *stv680, int framenr){	int errors = 0;	while (stv680->streaming && (stv680->frame[framenr].grabstate == FRAME_READY || stv680->frame[framenr].grabstate == FRAME_GRABBING)) {		if (!stv680->frame[framenr].curpix) {			errors++;		}		wait_event_interruptible (stv680->wq, (stv680->scratch[stv680->scratch_use].state == BUFFER_READY));		if (stv680->nullpackets > STV680_MAX_NULLPACKETS) {			stv680->nullpackets = 0;			PDEBUG (2, "STV(i): too many null length packets, restarting capture");			stv680_stop_stream (stv680);			stv680_start_stream (stv680);		} else {			if (stv680->scratch[stv680->scratch_use].state != BUFFER_READY) {				stv680->frame[framenr].grabstate = FRAME_ERROR;				PDEBUG (2, "STV(e): FRAME_ERROR in _newframe");				return -EIO;			}			stv680->scratch[stv680->scratch_use].state = BUFFER_BUSY;			bayer_unshuffle (stv680, &stv680->scratch[stv680->scratch_use]);			stv680->scratch[stv680->scratch_use].state = BUFFER_UNUSED;			stv680->scratch_use++;			if (stv680->scratch_use >= STV680_NUMSCRATCH)				stv680->scratch_use = 0;			if (errors > STV680_MAX_ERRORS) {				errors = 0;				PDEBUG (2, "STV(i): too many errors, restarting capture");				stv680_stop_stream (stv680);				stv680_start_stream (stv680);			}		}		/* else */	}			/* while */	return 0;}/********************************************************************* * Video4Linux *********************************************************************/static int stv_open (struct video_device *dev, int flags){	struct usb_stv *stv680 = (struct usb_stv *) dev;	int err = 0;	/* we are called with the BKL held */	MOD_INC_USE_COUNT;	stv680->user = 1;	err = stv_init (stv680);	/* main initialization routine for camera */	if (err >= 0) {		stv680->fbuf = rvmalloc (stv680->maxframesize * STV680_NUMFRAMES);		if (!stv680->fbuf) {			PDEBUG (0, "STV(e): Could not rvmalloc frame bufer");			err = -ENOMEM;		}	}	if (err) {		MOD_DEC_USE_COUNT;		stv680->user = 0;	}	return err;}static void stv_close (struct video_device *dev){	/* called with BKL held */	struct usb_stv *stv680 = (struct usb_stv *) dev;	int i;	for (i = 0; i < STV680_NUMFRAMES; i++)		stv680->frame[i].grabstate = FRAME_UNUSED;	if (stv680->streaming)		stv680_stop_stream (stv680);	if ((i = stv_stop_video (stv680)) < 0)		PDEBUG (1, "STV(e): stop_video failed in stv_close");	rvfree (stv680->fbuf, stv680->maxframesize * STV680_NUMFRAMES);	stv680->user = 0;	if (stv680->removed) {		video_unregister_device (&stv680->vdev);		kfree (stv680);		stv680 = NULL;		PDEBUG (0, "STV(i): device unregistered");	}	MOD_DEC_USE_COUNT;}static long stv680_write (struct video_device *dev, const char *buf, unsigned long count, int noblock){	return -EINVAL;}static int stv680_ioctl (struct video_device *vdev, unsigned int cmd, void *arg){	struct usb_stv *stv680 = (struct usb_stv *) vdev;	if (!stv680->udev)		return -EIO;	switch (cmd) {	case VIDIOCGCAP:{			struct video_capability b;			strcpy (b.name, stv680->camera_name);			b.type = VID_TYPE_CAPTURE;			b.channels = 1;			b.audios = 0;			b.maxwidth = stv680->maxwidth;			b.maxheight = stv680->maxheight;			b.minwidth = stv680->maxwidth / 2;			b.minheight = stv680->maxheight / 2;			if (copy_to_user (arg, &b, sizeof (b))) {				PDEBUG (2, "STV(e): VIDIOCGGAP failed");				return -EFAULT;			}			return 0;		}	case VIDIOCGCHAN:{			struct video_channel v;			if (copy_from_user (&v, arg, sizeof (v)))				return -EFAULT;			if (v.channel != 0)				return -EINVAL;			v.flags = 0;			v.tuners = 0;			v.type = VIDEO_TYPE_CAMERA;			strcpy (v.name, "STV Camera");			if (copy_to_user (arg, &v, sizeof (v))) {				PDEBUG (2, "STV(e): VIDIOCGCHAN failed");				return -EFAULT;			}			return 0;		}	case VIDIOCSCHAN:{			int v;			if (copy_from_user (&v, arg, sizeof (v))) {				PDEBUG (2, "STV(e): VIDIOCSCHAN failed");

⌨️ 快捷键说明

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