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

📄 ov511.c

📁 Usb1.1驱动c语言源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	*pOut++     = LIMIT(g + y00);	*(pOut+w*3) = LIMIT(b + y10);	*pOut++     = LIMIT(b + y00);	*(pOut+w*3) = LIMIT(r + y11);	*pOut++     = LIMIT(r + y01);	*(pOut+w*3) = LIMIT(g + y11);	*pOut++     = LIMIT(g + y01);	*(pOut+w*3) = LIMIT(b + y11);	*pOut++     = LIMIT(b + y01);}/***************************************************************For a 640x480 YUV4:2:0 images, data shows up in 1200 384 byte segments.  Thefirst 64 bytes of each segment are V, the next 64 are U.  The V andU are arranged as follows:  0  1 ...  7  8  9 ... 15       ...    56 57 ... 63The next 256 bytes are Y data and represent 4 squares of 8x8 pixels asfollows:  0  1 ...  7    64  65 ...  71   ...  192 193 ... 199  8  9 ... 15    72  73 ...  79        200 201 ... 207       ...              ...                    ... 56 57 ... 63   120 121     127        248 249 ... 255If OV511_DUMPPIX is defined, _parse_data just dumps theincoming segments, verbatim, in order, into the frame.When used with vidcat -f ppm -s 640x480 this puts the dataon the standard output and can be analyzed with the parseppm.cutility I wrote.  That's a much faster way for figuring out howthis data is scrambled.****************************************************************/ #define HDIV 8#define WDIV (256/HDIV)static void ov511_parse_data(unsigned char * pIn0,			     unsigned char * pOut0,			     int iWidth,			     int iSegment)			    {#ifndef OV511_DUMPPIX    int k, l, m;    unsigned char * pIn;    unsigned char * pOut, * pOut1;    int iHalf = (iSegment / (iWidth / 32)) & 1;    int iY     = iSegment / (iWidth / WDIV);    int jY     = iSegment - iY * (iWidth / WDIV);    int iOutY  = (iY*HDIV*iWidth + jY*WDIV) * 3;    int iUV    = iSegment / (iWidth / WDIV * 2);    int jUV    = iSegment - iUV * (iWidth / WDIV * 2);    int iOutUV = (iUV*HDIV*2*iWidth + jUV*WDIV/2) * 3;    /* Just copy the Y's if in the first stripe */    if (!iHalf) {	pIn = pIn0 + 128;	pOut = pOut0 + iOutY;	for(k=0; k<4; k++) {	    pOut1 = pOut;	    for(l=0; l<8; l++) {	      for(m=0; m<8; m++) {		*pOut1 = *pIn++;		pOut1 += 3;	      }	      pOut1 += (iWidth - 8) * 3;	    }	    pOut += 8 * 3;	}    }    /* Use the first half of VUs to calculate value */    pIn = pIn0;    pOut = pOut0 + iOutUV;    for(l=0; l<4; l++) {	for(m=0; m<8; m++) {	    int y00 = *(pOut);	    int y01 = *(pOut+3);	    int y10 = *(pOut+iWidth*3);	    int y11 = *(pOut+iWidth*3+3);	    int u   = *(pIn+64) - 128;	    int v   = *pIn++ - 128;	    ov511_move_420_block(y00, y01, y10, y11, u, v, iWidth, pOut);	    pOut += 6;	}	pOut += (iWidth*2 - 16) * 3;    }    /* Just copy the other UV rows */    for(l=0; l<4; l++) {	for(m=0; m<8; m++) {	  *pOut++ = *(pIn + 64);	  *pOut = *pIn++;	  pOut += 5;	}	pOut += (iWidth*2 - 16) * 3;    }    /* Calculate values if it's the second half */    if (iHalf) {	pIn = pIn0 + 128;	pOut = pOut0 + iOutY;	for(k=0; k<4; k++) {	    pOut1 = pOut;	    for(l=0; l<4; l++) {	      for(m=0; m<4; m++) {		int y10 = *(pIn+8);		int y00 = *pIn++;		int y11 = *(pIn+8);		int y01 = *pIn++;		int u   = *pOut1 - 128;		int v   = *(pOut1+1) - 128;		ov511_move_420_block(y00, y01, y10, y11, u, v, iWidth, pOut1);		pOut1 += 6;	      }	      pOut1 += (iWidth*2 - 8) * 3;	      pIn += 8;	    }	    pOut += 8 * 3;	}    }#else	/* Just dump pix data straight out for debug */	int i;	pOut0 += iSegment * 384;	for(i=0; i<384; i++) {	  *pOut0++ = *pIn0++;	}#endif}static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb){	unsigned char *cdata;	int i, totlen = 0;	int aPackNum[10];	struct ov511_frame *frame;	if (ov511->curframe == -1) {	  return 0;	}	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;		if (!n) continue;		aPackNum[i] = n ? cdata[992] : -1;		if (st){ 			// Macro - must be in braces!			PDEBUG("data error: [%d] len=%d, status=%d\n",				i, n, st);		}		frame = &ov511->frame[ov511->curframe];				/* Can we find a frame end */		if ((cdata[0] | cdata[1] | cdata[2] | cdata[3] | 		     cdata[4] | cdata[5] | cdata[6] | cdata[7]) == 0 &&		    (cdata[8] & 8) && (cdata[8] & 0x80)) {#if 0		    PDEBUG("Found Frame End!, packnum = %d\n", (int)(cdata[992]));		    PDEBUG("Current frame = %d\n", ov511->curframe);#endif		    if (frame->scanstate == STATE_LINES) {		        if (waitqueue_active(&frame->wq)) {#if 0			  PDEBUG("About to wake up waiting processes\n");#endif			  frame->grabstate = FRAME_DONE;			  ov511->curframe = -1;			  wake_up_interruptible(&frame->wq);			}		    }		}		/* Can we find a frame start */		else if ((cdata[0] | cdata[1] | cdata[2] | cdata[3] | 			  cdata[4] | cdata[5] | cdata[6] | cdata[7]) == 0 &&			 (cdata[8] & 8)) {#if 0			PDEBUG("ov511: Found Frame Start!, packnum = %d\n", (int)(cdata[992]));			PDEBUG("ov511: Frame Header Byte = 0x%x\n", (int)(cdata[8]));#endif		    frame->scanstate = STATE_LINES;			frame->segment = 0;		}		/* Are we in a frame? */		if (frame->scanstate == STATE_LINES) {			unsigned char * pData;			int iPix;			/* Deal with leftover from last segment, if any */			if (frame->segment) {			  pData = ov511->scratch;			  iPix = - ov511->scratchlen;			  memmove(pData + ov511->scratchlen, cdata, iPix+384);		  } else {			  pData = &cdata[iPix = 9];		  }			/* Parse the segments */			while(iPix <= 992 - 384 &&			      frame->segment < frame->width * frame->height / 256) {			  ov511_parse_data(pData, frame->data,					   frame->width,					   frame->segment);			  frame->segment++;			  iPix += 384;			  pData = &cdata[iPix];		}			/* Save extra data for next time */			if (frame->segment < frame->width * frame->height / 256) {			  memmove(ov511->scratch, pData, 992 - iPix);			  ov511->scratchlen = 992 - iPix;			}		}	}#if 0	PDEBUG("pn: %d %d %d %d %d %d %d %d %d %d\n",	       aPackNum[0], aPackNum[1], aPackNum[2], aPackNum[3], aPackNum[4],	       aPackNum[5],aPackNum[6], aPackNum[7], aPackNum[8], aPackNum[9]);#endif	return totlen;}static void ov511_isoc_irq(struct urb *urb){	int len;	struct usb_ov511 *ov511 = urb->context;	struct ov511_sbuf *sbuf;	int i;	if (!ov511->streaming) {		PDEBUG("hmmm... not streaming, but got interrupt\n");		return;	}		sbuf = &ov511->sbuf[ov511->cursbuf];	/* Copy the data received into our scratch buffer */	if (ov511->curframe >= 0) {	  len = ov511_move_data(ov511, urb);	}	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 */	ov511->cursbuf = (ov511->cursbuf + 1) % OV511_NUMSBUF;	return;}static int ov511_init_isoc(struct usb_ov511 *ov511){	struct usb_device *dev = ov511->dev;	urb_t *urb;	int fx, err;		ov511->compress = 0;	ov511->curframe = -1;	ov511->cursbuf = 0;	ov511->scratchlen = 0;	ov511_set_packet_size(ov511, 993);	/* We double buffer the Iso lists */	urb = usb_alloc_urb(FRAMES_PER_DESC);		if (!urb) {		printk(KERN_ERR "ov511_init_isoc: usb_alloc_urb ret. NULL\n");		return -ENOMEM;	}	ov511->sbuf[0].urb = urb;	urb->dev = dev;	urb->context = ov511;	urb->pipe = usb_rcvisocpipe(dev, OV511_ENDPOINT_ADDRESS);	urb->transfer_flags = USB_ISO_ASAP;	urb->transfer_buffer = ov511->sbuf[0].data; 	urb->complete = ov511_isoc_irq; 	urb->number_of_packets = FRAMES_PER_DESC; 	urb->transfer_buffer_length = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC; 	for (fx = 0; fx < FRAMES_PER_DESC; fx++) { 		urb->iso_frame_desc[fx].offset = FRAME_SIZE_PER_DESC * fx;		urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC;	}	urb = usb_alloc_urb(FRAMES_PER_DESC);	if (!urb) {		printk(KERN_ERR "ov511_init_isoc: usb_alloc_urb ret. NULL\n");		return -ENOMEM;	}	ov511->sbuf[1].urb = urb;	urb->dev = dev;	urb->context = ov511;	urb->pipe = usb_rcvisocpipe(dev, OV511_ENDPOINT_ADDRESS);	urb->transfer_flags = USB_ISO_ASAP;	urb->transfer_buffer = ov511->sbuf[1].data; 	urb->complete = ov511_isoc_irq; 	urb->number_of_packets = FRAMES_PER_DESC; 	urb->transfer_buffer_length = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC; 	for (fx = 0; fx < FRAMES_PER_DESC; fx++) { 		urb->iso_frame_desc[fx].offset = FRAME_SIZE_PER_DESC * fx;		urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC;	}	ov511->sbuf[1].urb->next = ov511->sbuf[0].urb;	ov511->sbuf[0].urb->next = ov511->sbuf[1].urb;	err = usb_submit_urb(ov511->sbuf[0].urb);	if (err)		printk(KERN_ERR "ov511_init_isoc: usb_run_isoc(0) ret %d\n",			err);	err = usb_submit_urb(ov511->sbuf[1].urb);	if (err)		printk(KERN_ERR "ov511_init_isoc: usb_run_isoc(1) ret %d\n",			err);	ov511->streaming = 1;	return 0;}static void ov511_stop_isoc(struct usb_ov511 *ov511){	if (!ov511->streaming)		return;	ov511_set_packet_size(ov511, 0);		/* Unschedule all of the iso td's */	usb_unlink_urb(ov511->sbuf[1].urb);	usb_unlink_urb(ov511->sbuf[0].urb);	ov511->streaming = 0;	/* Delete them all */	usb_free_urb(ov511->sbuf[1].urb);	usb_free_urb(ov511->sbuf[0].urb);}static int ov511_new_frame(struct usb_ov511 *ov511, int framenum){	struct ov511_frame *frame;	int width, height;	/* If we're not grabbing a frame right now and the other frame is */	/*  ready to be grabbed into, then use it instead */	if (ov511->curframe == -1) {		if (ov511->frame[(framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES].grabstate == FRAME_READY)			framenum = (framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES;	} else		return 0;	frame = &ov511->frame[framenum];	width = frame->width;	height = frame->height;	frame->grabstate = FRAME_GRABBING;	frame->scanstate = STATE_SCANNING;	frame->scanlength = 0;		/* accumulated in ov511_parse_data() */	ov511->curframe = framenum;	/* Make sure it's not too big */	if (width > DEFAULT_WIDTH)		width = DEFAULT_WIDTH;	width = (width / 8) * 8;	/* Multiple of 8 */	if (height > DEFAULT_HEIGHT)		height = DEFAULT_HEIGHT;	height = (height / 4) * 4;	/* Multiple of 4 */	//	/* We want a fresh frame every 30 we get *///	ov511->compress = (ov511->compress + 1) % 30;	return 0;}/* Video 4 Linux API */static int ov511_open(struct video_device *dev, int flags){	int err = -EBUSY;	struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;	PDEBUG("ov511_open\n");		down(&ov511->lock);	if (ov511->user)		goto out_unlock;			ov511->frame[0].grabstate = FRAME_UNUSED;	ov511->frame[1].grabstate = FRAME_UNUSED;	err = -ENOMEM;		/* Allocate memory for the frame buffers */					ov511->fbuf = rvmalloc(2 * MAX_FRAME_SIZE);	if (!ov511->fbuf)		goto open_err_ret;	ov511->frame[0].data = ov511->fbuf;	ov511->frame[1].data = ov511->fbuf + MAX_FRAME_SIZE;	PDEBUG("frame [0] @ %p\n", ov511->frame[0].data);	PDEBUG("frame [1] @ %p\n", ov511->frame[1].data);	ov511->sbuf[0].data = kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL);	if (!ov511->sbuf[0].data)		goto open_err_on0;	ov511->sbuf[1].data = kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL);	if (!ov511->sbuf[1].data)		goto open_err_on1;			PDEBUG("sbuf[0] @ %p\n", ov511->sbuf[0].data);	PDEBUG("sbuf[1] @ %p\n", ov511->sbuf[1].data);	err = ov511_init_isoc(ov511);	if (err)		goto open_err_on2;	ov511->user++;	up(&ov511->lock);	MOD_INC_USE_COUNT;	return 0;open_err_on2:	kfree (ov511->sbuf[1].data);open_err_on1:	kfree (ov511->sbuf[0].data);open_err_on0:	rvfree(ov511->fbuf, 2 * MAX_FRAME_SIZE);open_err_ret:	return err;out_unlock:	up(&ov511->lock);	return err;}static void ov511_close(struct video_device *dev){	struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;	PDEBUG("ov511_close\n");		down(&ov511->lock);		ov511->user--;	MOD_DEC_USE_COUNT;	ov511_stop_isoc(ov511);	rvfree(ov511->fbuf, 2 * MAX_FRAME_SIZE);	kfree(ov511->sbuf[1].data);	kfree(ov511->sbuf[0].data);	up(&ov511->lock);}static int ov511_init_done(struct video_device *dev){	return 0;}static long ov511_write(struct video_device *dev, const char *buf, unsigned long count, int noblock){	return -EINVAL;}// FIXME - Needs much work!!!static int ov511_ioctl(struct video_device *dev, unsigned int cmd, void *arg){	struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;#if 0		PDEBUG("IOCtl: 0x%X\n", cmd);#endif		switch (cmd) {		case VIDIOCGCAP:		{			struct video_capability b;			strcpy(b.name, "OV511 USB Camera");			b.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE;			b.channels = 1;			b.audios = 0;			b.maxwidth = DEFAULT_WIDTH;			b.maxheight = DEFAULT_HEIGHT;			b.minwidth = 8;			b.minheight = 4;			if (copy_to_user(arg, &b, sizeof(b)))				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, "Camera");			if (copy_to_user(arg, &v, sizeof(v)))				return -EFAULT;							return 0;		}		case VIDIOCSCHAN:		{			int v;			if (copy_from_user(&v, arg, sizeof(v)))				return -EFAULT;			if (v != 0)				return -EINVAL;			return 0;		}		case VIDIOCGPICT:		{			struct video_picture p;

⌨️ 快捷键说明

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