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

📄 ibmcam.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
		/*		 * The purpose of creating the pixel here, in one,		 * dedicated place is that we may need to make the		 * pixel wider and taller than it actually is. This		 * may be used if camera generates small frames for		 * sake of frame rate (or any other reason.)		 *		 * The output data consists of B, G, R bytes		 * (in this order).		 */#if USES_IBMCAM_PUTPIXEL		IBMCAM_PUTPIXEL(frame, i, frame->curline, rv, gv, bv);#else		*f++ = bv;		*f++ = gv;		*f++ = rv;#endif		/*		 * Typically we do not decide within a legitimate frame		 * that we want to end the frame. However debugging code		 * may detect marker of new frame within the data. Then		 * this condition activates. The 'data' pointer is already		 * pointing at the new marker, so we'd better leave it as is.		 */		if (frame_done)			break;	/* End scanning of lines */	}	/*	 * Account for number of bytes that we wrote into output V4L frame.	 * We do it here, after we are done with the scanline, because we	 * may fill more than one output scanline if we do vertical	 * enlargement.	 */	frame->curline++;	*pcopylen += v4l_linesize;	usb_ibmcam_align_scratch(ibmcam, data);	if (frame_done || (frame->curline >= frame->frmheight))		return scan_NextFrame;	else		return scan_Continue;}/* * usb_ibmcam_model2_parse_lines() * * This procedure deals with a weird RGB format that is produced by IBM * camera model 2 in modes 320x240 and above; 'x' below is 159 or 175, * depending on horizontal size of the picture: * * <--- 160 or 176 pairs of RA,RB bytes -----> * *-----------------------------------------* \ * | RA0 | RB0 | RA1 | RB1 | ... | RAx | RBx |  \ * |-----+-----+-----+-----+ ... +-----+-----|   *- This is pair of horizontal lines, * | B0  | G0  | B1  | G1  | ... | Bx  | Gx  |  /   total 240 or 288 lines (120 or 144 * |=====+=====+=====+=====+ ... +=====+=====| /    such pairs). * * Each group of FOUR bytes (RAi, RBi, Bi, Gi) where i=0..frame_width/2-1 * defines ONE pixel. Therefore this format yields 176x144 "decoded" * resolution at best. I do not know why camera sends such format - the * previous model just used I420 and everyone was happy. * * I do not know what is the difference between RAi and RBi bytes. Both * seemingly represent R component, but slightly vary in value (so that * the picture looks a bit colored if one or another is used). I use * them both as R component in attempt to at least partially recover the * lost resolution. */static scan_state_t usb_ibmcam_model2_parse_lines(struct usb_ibmcam *ibmcam, long *pcopylen){	struct ibmcam_frame *frame;	unsigned char *data, *f, *la, *lb;	unsigned int len;	const int v4l_linesize = imgwidth * V4L_BYTES_PER_PIXEL;	/* V4L line offset */	int i, j, frame_done=0, color_corr;	color_corr = (ibmcam->vpic.colour) >> 8; /* 0..+255 */	data = ibmcam->scratch;	frame = &ibmcam->frame[ibmcam->curframe];	/* Here we deal with pairs of horizontal lines */	len = frame->frmwidth * 2; /* 2 lines */	/*printk(KERN_DEBUG "len=%d. left=%d.\n",len,scratch_left(data));*/	/* Make sure there's enough data for the entire line */	if (scratch_left(data) < (len+32)) {		/*printk(KERN_DEBUG "out of data, need %u.\n", len);*/		return scan_Out;	}	/*	 * Make sure that our writing into output buffer	 * will not exceed the buffer. Mind that we may write	 * not into current output scanline but in several after	 * it as well (if we enlarge image vertically.)	 */	if ((frame->curline + 1) >= V4L_FRAME_HEIGHT)		return scan_NextFrame;	if ((frame->curline & 1) == 0) {		la = data;		lb = data + frame->frmwidth;	} else {		la = data + frame->frmwidth;		lb = data;	}	/*	 * Now we are sure that entire line (representing all 'frame->frmwidth'	 * pixels from the camera) is available in the scratch buffer. We	 * start copying the line left-aligned to the V4L buffer (which	 * might be larger - not smaller, hopefully). If the camera	 * line is shorter then we should pad the V4L buffer with something	 * (black in this case) to complete the line.	 */	f = frame->data + (v4l_linesize * frame->curline);	/* Fill the 2-line strip */	for (i = 0; i < frame->frmwidth; i++) {		int y, rv, gv, bv;	/* RGB components */		j = i & (~1);		/* Check for various visual debugging hints (colorized pixels) */		if ((flags & FLAGS_DISPLAY_HINTS) && (ibmcam->has_hdr)) {			if (ibmcam->has_hdr == 1) {				bv = 0; /* Yellow marker */				gv = 0xFF;				rv = 0xFF;			} else {				bv = 0xFF; /* Cyan marker */				gv = 0xFF;				rv = 0;			}			ibmcam->has_hdr = 0;			goto make_pixel;		}		/*		 * Here I use RA and RB components, one per physical pixel.		 * This causes fine vertical grid on the picture but may improve		 * horizontal resolution. If you prefer replicating, use this:		 *   rv = la[j + 0];   ... or ... rv = la[j + 1];		 * then the pixel will be replicated.		 */		rv = la[i];		gv = lb[j + 1];		bv = lb[j + 0];		y = (rv + gv + bv) / 3; /* Brightness (badly calculated) */		if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */			rv = gv = bv = y;		else if (color_corr != 128) {			/* Calculate difference between color and brightness */			rv -= y;			gv -= y;			bv -= y;			/* Scale differences */			rv = (rv * color_corr) / 128;			gv = (gv * color_corr) / 128;			bv = (bv * color_corr) / 128;			/* Reapply brightness */			rv += y;			gv += y;			bv += y;			/* Watch for overflows */			RESTRICT_TO_RANGE(rv, 0, 255);			RESTRICT_TO_RANGE(gv, 0, 255);			RESTRICT_TO_RANGE(bv, 0, 255);		}	make_pixel:		IBMCAM_PUTPIXEL(frame, i, frame->curline, rv, gv, bv);		IBMCAM_PUTPIXEL(frame, i, frame->curline+1, rv, gv, bv);	}	/*	 * Account for number of bytes that we wrote into output V4L frame.	 * We do it here, after we are done with the scanline, because we	 * may fill more than one output scanline if we do vertical	 * enlargement.	 */	frame->curline += 2;	*pcopylen += v4l_linesize * 2;	data += frame->frmwidth * 2;	usb_ibmcam_align_scratch(ibmcam, data);	if (frame_done || (frame->curline >= frame->frmheight))		return scan_NextFrame;	else		return scan_Continue;}/* * ibmcam_parse_data() * * Generic routine to parse the scratch buffer. It employs either * usb_ibmcam_find_header() or usb_ibmcam_parse_lines() to do most * of work. * * History: * 1/21/00  Created. */static void ibmcam_parse_data(struct usb_ibmcam *ibmcam){	struct ibmcam_frame *frame;	unsigned char *data = ibmcam->scratch;	scan_state_t newstate;	long copylen = 0;	/* Grab the current frame and the previous frame */	frame = &ibmcam->frame[ibmcam->curframe];	/* printk(KERN_DEBUG "parsing %u.\n", ibmcam->scratchlen); */	while (1) {		newstate = scan_Out;		if (scratch_left(data)) {			if (frame->scanstate == STATE_SCANNING)				newstate = usb_ibmcam_find_header(ibmcam);			else if (frame->scanstate == STATE_LINES) {				if ((ibmcam->camera_model == IBMCAM_MODEL_2) &&				    (videosize >= VIDEOSIZE_352x288)) {					newstate = usb_ibmcam_model2_parse_lines(ibmcam, &copylen);				}				else {					newstate = usb_ibmcam_parse_lines(ibmcam, &copylen);				}			}		}		if (newstate == scan_Continue)			continue;		else if ((newstate == scan_NextFrame) || (newstate == scan_Out))			break;		else			return; /* scan_EndParse */	}	if (newstate == scan_NextFrame) {		frame->grabstate = FRAME_DONE;		ibmcam->curframe = -1;		ibmcam->frame_num++;		/* Optionally display statistics on the screen */		if (flags & FLAGS_OVERLAY_STATS)			usb_ibmcam_overlaystats(ibmcam, frame);		/* This will cause the process to request another frame. */		if (waitqueue_active(&frame->wq))			wake_up_interruptible(&frame->wq);	}	/* Update the frame's uncompressed length. */	frame->scanlength += copylen;}/* * Make all of the blocks of data contiguous */static int ibmcam_compress_isochronous(struct usb_ibmcam *ibmcam, urb_t *urb){	unsigned char *cdata, *data, *data0;	int i, totlen = 0;	data = data0 = ibmcam->scratch + ibmcam->scratchlen;	for (i = 0; i < urb->number_of_packets; i++) {		int n = urb->iso_frame_desc[i].actual_length;		int st = urb->iso_frame_desc[i].status;				cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;		/* Detect and ignore errored packets */		if (st < 0) {			if (debug >= 1) {				printk(KERN_ERR "ibmcam data error: [%d] len=%d, status=%X\n",				       i, n, st);			}			ibmcam->iso_err_count++;			continue;		}		/* Detect and ignore empty packets */		if (n <= 0) {			ibmcam->iso_skip_count++;			continue;		}		/*		 * If camera continues to feed us with data but there is no		 * consumption (if, for example, V4L client fell asleep) we		 * may overflow the buffer. We have to move old data over to		 * free room for new data. This is bad for old data. If we		 * just drop new data then it's bad for new data... choose		 * your favorite evil here.		 */		if ((ibmcam->scratchlen + n) > scratchbufsize) {#if 0			ibmcam->scratch_ovf_count++;			if (debug >= 3)				printk(KERN_ERR "ibmcam: scratch buf overflow! "				       "scr_len: %d, n: %d\n", ibmcam->scratchlen, n );			return totlen;#else			int mv;			ibmcam->scratch_ovf_count++;			if (debug >= 3) {				printk(KERN_ERR "ibmcam: scratch buf overflow! "				       "scr_len: %d, n: %d\n", ibmcam->scratchlen, n );			}			mv  = (ibmcam->scratchlen + n) - scratchbufsize;			if (ibmcam->scratchlen >= mv) {				int newslen = ibmcam->scratchlen - mv;				memmove(ibmcam->scratch, ibmcam->scratch + mv, newslen);				ibmcam->scratchlen = newslen;				data = data0 = ibmcam->scratch + ibmcam->scratchlen;			} else {				printk(KERN_ERR "ibmcam: scratch buf too small\n");				return totlen;			}#endif		}		/* Now we know that there is enough room in scratch buffer */		memmove(data, cdata, n);		data += n;		totlen += n;		ibmcam->scratchlen += n;	}#if 0	if (totlen > 0) {		static int foo=0;		if (foo < 1) {			printk(KERN_DEBUG "+%d.\n", totlen);			ibmcam_hexdump(data0, (totlen > 64) ? 64:totlen);			++foo;		}	}#endif	return totlen;}static void ibmcam_isoc_irq(struct urb *urb){	int len;	struct usb_ibmcam *ibmcam = urb->context;	struct ibmcam_sbuf *sbuf;	int i;	/* We don't want to do anything if we are about to be removed! */	if (!IBMCAM_IS_OPERATIONAL(ibmcam))		return;#if 0	if (urb->actual_length > 0) {		printk(KERN_DEBUG "ibmcam_isoc_irq: %p status %d, "		       " errcount = %d, length = %d\n", urb, urb->status,		       urb->error_count, urb->actual_length);	} else {		static int c = 0;		if (c++ % 100 == 0)			printk(KERN_DEBUG "ibmcam_isoc_irq: no data\n");	}#endif	if (!ibmcam->streaming) {		if (debug >= 1)			printk(KERN_DEBUG "ibmcam: oops, not streaming, but interrupt\n");		return;	}		sbuf = &ibmcam->sbuf[ibmcam->cursbuf];	/* Copy the data received into our scratch buffer */	len = ibmcam_compress_isochronous(ibmcam, urb);	ibmcam->urb_count++;	ibmcam->urb_length = len;	ibmcam->data_count += len;#if 0   /* This code prints few initial bytes of ISO data: used to decode markers */	if (ibmcam->urb_count % 64 == 1) {		if (ibmcam->urb_count == 1) {			ibmcam_hexdump(ibmcam->scratch,				       (ibmcam->scratchlen > 32) ? 32 : ibmcam->scratchlen);		}	}#endif	/* If we collected enough data let's parse! */	if (ibmcam->scratchlen) {		/* If we don't have a frame we're current working on, complain */		if (ibmcam->curframe >= 0)			ibmcam_parse_data(ibmcam);		else {			if (debug >= 1)				printk(KERN_DEBUG "ibmcam: received data, but no frame available\n");		}	}	for (i = 0; i < FRAMES_PER_DESC; i++) {		sbuf->urb->iso_frame_desc[i].status = 0;		sbuf->urb->iso_frame_desc[i].actual_length = 0;	}	/* Move to the next sbuf */	ibmcam->cursbuf = (ibmcam->cursbuf + 1) % IBMCAM_NUMSBUF;	return;}/* * usb_ibmcam_veio() * * History: * 1/27/00  Added check for dev == NULL; this happens if camera is unplugged. */static int usb_ibmcam_veio(	struct usb_ibmcam *ibmcam,	unsigned char req,	unsigned short value,	unsigned short index){	static const char proc[] = "usb_ibmcam_veio";

⌨️ 快捷键说明

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