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

📄 stv680.c

📁 h内核
💻 C
📖 第 1 页 / 共 3 页
字号:
	struct video_device *vdev = to_video_device(class_dev);		\	struct usb_stv *stv = video_get_drvdata(vdev);			\	return sprintf(buf, field, stv->variable);			\}									\static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);stv680_file(model, camera_name, "%s\n");stv680_file(in_use, user, "%d\n");stv680_file(streaming, streaming, "%d\n");stv680_file(palette, palette, "%i\n");stv680_file(frames_total, readcount, "%d\n");stv680_file(frames_read, framecount, "%d\n");stv680_file(packets_dropped, dropped, "%d\n");stv680_file(decoding_errors, error, "%d\n");static void stv680_create_sysfs_files(struct video_device *vdev){	video_device_create_file(vdev, &class_device_attr_model);	video_device_create_file(vdev, &class_device_attr_in_use);	video_device_create_file(vdev, &class_device_attr_streaming);	video_device_create_file(vdev, &class_device_attr_palette);	video_device_create_file(vdev, &class_device_attr_frames_total);	video_device_create_file(vdev, &class_device_attr_frames_read);	video_device_create_file(vdev, &class_device_attr_packets_dropped);	video_device_create_file(vdev, &class_device_attr_decoding_errors);}static void stv680_remove_sysfs_files(struct video_device *vdev){	video_device_remove_file(vdev, &class_device_attr_model);	video_device_remove_file(vdev, &class_device_attr_in_use);	video_device_remove_file(vdev, &class_device_attr_streaming);	video_device_remove_file(vdev, &class_device_attr_palette);	video_device_remove_file(vdev, &class_device_attr_frames_total);	video_device_remove_file(vdev, &class_device_attr_frames_read);	video_device_remove_file(vdev, &class_device_attr_packets_dropped);	video_device_remove_file(vdev, &class_device_attr_decoding_errors);}/******************************************************************** * Camera control *******************************************************************/static int stv680_get_pict (struct usb_stv *stv680, struct video_picture *p){	/* This sets values for v4l interface. max/min = 65535/0  */	p->brightness = stv680->brightness;	p->whiteness = stv680->whiteness;	/* greyscale */	p->colour = stv680->colour;	p->contrast = stv680->contrast;	p->hue = stv680->hue;	p->palette = stv680->palette;	p->depth = stv680->depth;	return 0;}static int stv680_set_pict (struct usb_stv *stv680, struct video_picture *p){	/* See above stv680_get_pict  */	if (p->palette != STV_VIDEO_PALETTE) {		PDEBUG (2, "STV(e): Palette set error in _set_pic");		return 1;	}	if (stv680->brightness != p->brightness) {		stv680->chgbright = 1;		stv680->brightness = p->brightness;	} 	stv680->whiteness = p->whiteness;	/* greyscale */	stv680->colour = p->colour;	stv680->contrast = p->contrast;	stv680->hue = p->hue;	stv680->palette = p->palette;	stv680->depth = p->depth;	return 0;}static void stv680_video_irq (struct urb *urb, struct pt_regs *regs){	struct usb_stv *stv680 = urb->context;	int length = urb->actual_length;	if (length < stv680->rawbufsize)		PDEBUG (2, "STV(i): Lost data in transfer: exp %li, got %i", stv680->rawbufsize, length);	/* ohoh... */	if (!stv680->streaming)		return;	if (!stv680->udev) {		PDEBUG (0, "STV(e): device vapourished in video_irq");		return;	}	/* 0 sized packets happen if we are to fast, but sometimes the camera	   keeps sending them forever...	 */	if (length && !urb->status) {		stv680->nullpackets = 0;		switch (stv680->scratch[stv680->scratch_next].state) {		case BUFFER_READY:		case BUFFER_BUSY:			stv680->dropped++;			break;		case BUFFER_UNUSED:			memcpy (stv680->scratch[stv680->scratch_next].data,			        (unsigned char *) urb->transfer_buffer, length);			stv680->scratch[stv680->scratch_next].state = BUFFER_READY;			stv680->scratch[stv680->scratch_next].length = length;			if (waitqueue_active (&stv680->wq)) {				wake_up_interruptible (&stv680->wq);			}			stv680->scratch_overflow = 0;			stv680->scratch_next++;			if (stv680->scratch_next >= STV680_NUMSCRATCH)				stv680->scratch_next = 0;			break;		}		/* switch  */	} else {		stv680->nullpackets++;		if (stv680->nullpackets > STV680_MAX_NULLPACKETS) {			if (waitqueue_active (&stv680->wq)) {				wake_up_interruptible (&stv680->wq);			}		}	}			/*  if - else */	/* Resubmit urb for new data */	urb->status = 0;	urb->dev = stv680->udev;	if (usb_submit_urb (urb, GFP_ATOMIC))		PDEBUG (0, "STV(e): urb burned down in video irq");	return;}				/*  _video_irq  */static int stv680_start_stream (struct usb_stv *stv680){	struct urb *urb;	int err = 0, i;	stv680->streaming = 1;	/* Do some memory allocation */	for (i = 0; i < STV680_NUMFRAMES; i++) {		stv680->frame[i].data = stv680->fbuf + i * stv680->maxframesize;		stv680->frame[i].curpix = 0;	}	/* packet size = 4096  */	for (i = 0; i < STV680_NUMSBUF; i++) {		stv680->sbuf[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL);		if (stv680->sbuf[i].data == NULL) {			PDEBUG (0, "STV(e): Could not kmalloc raw data buffer %i", i);			return -1;		}	}	stv680->scratch_next = 0;	stv680->scratch_use = 0;	stv680->scratch_overflow = 0;	for (i = 0; i < STV680_NUMSCRATCH; i++) {		stv680->scratch[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL);		if (stv680->scratch[i].data == NULL) {			PDEBUG (0, "STV(e): Could not kmalloc raw scratch buffer %i", i);			return -1;		}		stv680->scratch[i].state = BUFFER_UNUSED;	}	for (i = 0; i < STV680_NUMSBUF; i++) {		urb = usb_alloc_urb (0, GFP_KERNEL);		if (!urb)			return -ENOMEM;		/* sbuf is urb->transfer_buffer, later gets memcpyed to scratch */		usb_fill_bulk_urb (urb, stv680->udev,				   usb_rcvbulkpipe (stv680->udev, stv680->bulk_in_endpointAddr),				   stv680->sbuf[i].data, stv680->rawbufsize,				   stv680_video_irq, stv680);		stv680->urb[i] = urb;		err = usb_submit_urb (stv680->urb[i], GFP_KERNEL);		if (err)			PDEBUG (0, "STV(e): urb burned down in start stream");	}			/* i STV680_NUMSBUF */	stv680->framecount = 0;	return 0;}static int stv680_stop_stream (struct usb_stv *stv680){	int i;	if (!stv680->streaming || !stv680->udev)		return 1;	stv680->streaming = 0;	for (i = 0; i < STV680_NUMSBUF; i++)		if (stv680->urb[i]) {			usb_kill_urb (stv680->urb[i]);			usb_free_urb (stv680->urb[i]);			stv680->urb[i] = NULL;			kfree (stv680->sbuf[i].data);		}	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) && (stv680->QVGA == 1)) {		width = 160;		height = 120;	} else if ((width >= 172) && (width <= 180) && (stv680->CIF == 1)) {		width = 176;		height = 144;	} else if ((width >= 318) && (width <= 350) && (stv680->QVGA == 1)) {		width = 320;		height = 240;	} else if ((width >= 350) && (width <= 358) && (stv680->CIF == 1)) {		width = 352;		height = 288;	} else {		PDEBUG (1, "STV(e): request for non-supported size: request: v.width = %i, v.height = %i  actual: stv.width = %i, stv.height = %i", width, height, stv680->vwidth, stv680->vheight);		return 1;	}		/* 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;

⌨️ 快捷键说明

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