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

📄 spca_core.c

📁 通用的摄像头驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    }  if (waitqueue_active (&taskletframe->wq))    wake_up_interruptible (&taskletframe->wq);}/* ******************************************************************* spca50x_move_data* Function serves for moving data from USB transfer buffers* to internal driver frame buffers.******************************************************************* */static intspca50x_move_data (struct usb_spca50x *spca50x, struct urb *urb){  unsigned char *cdata;		//Pointer to buffer where we do store next packet  unsigned char *pData;		//Pointer to buffer where we do store next packet  int i;  struct spca50x_frame *frame;	//Pointer to frame data  int iPix;			//Offset of pixel data in the ISO packet  int totlen = 0;  int tv8532 = 0;  for (i = 0; i < urb->number_of_packets; i++)    {      int datalength = urb->iso_frame_desc[i].actual_length;      int st = urb->iso_frame_desc[i].status;      int sequenceNumber;      int sof;      /* PDEBUG(5,"Packet data [%d,%d,%d]", datalength, st,         urb->iso_frame_desc[i].offset); */      urb->iso_frame_desc[i].actual_length = 0;      urb->iso_frame_desc[i].status = 0;      cdata = ((unsigned char *) urb->transfer_buffer) +	urb->iso_frame_desc[i].offset;      /* Check for zero length block or no selected frame buffer */      if (!datalength || spca50x->curframe == -1)	{	  tv8532 = 0;	  continue;	}      PDEBUG (5, "Packet data [%d,%d,%d] Status: %d", datalength, st,	      urb->iso_frame_desc[i].offset, st);      if (st)	PDEBUG (2, "data error: [%d] len=%d, status=%d", i, datalength, st);      frame = &spca50x->frame[spca50x->curframe];      totlen = frame->totlength;      /* read the sequence number */      if (spca50x->bridge == BRIDGE_ZC3XX ||	  spca50x->bridge == BRIDGE_SN9CXXX )	{	  if (frame->last_packet == -1)	    {	      /*initialize a new frame */	      sequenceNumber = 0;	    }	  else	    {	      sequenceNumber = frame->last_packet;	    }	}      else	{	  sequenceNumber = cdata[SPCA50X_OFFSET_SEQUENCE];	  PDEBUG (4, "Packet start  %x %x %x %x %x", cdata[0], cdata[1],		  cdata[2], cdata[3], cdata[4]);	}      /* check frame start */      switch (spca50x->bridge)	{	case BRIDGE_SN9CXXX:		iPix = 0;		sof = datalength - 64;		if (sof < 0)			sequenceNumber++;		else if(cdata[sof] == 0xff && cdata[sof +1] == 0xd9){			 sequenceNumber = 0; //start of frame			 // copy the end of data frame	  		memcpy (frame->highwater, cdata, sof+2);      			frame->highwater += (sof+2);      			totlen += (sof+2);#if 0			spin_lock(&spca50x->v4l_lock);			spca50x->avg_lum = (cdata[sof+24] + cdata[sof+26]) >> 1 ;			spin_unlock(&spca50x->v4l_lock);			PDEBUG (5,"mean luma %d",spca50x->avg_lum );#endif			PDEBUG (5,			"Sonix header packet found datalength %d totlength %d!!",			  datalength, totlen);			  PDEBUG(5,"%03d %03d %03d %03d %03d %03d %03d %03d",cdata[sof+24], cdata[sof+25],			  cdata[sof+26] , cdata[sof+27], cdata[sof+28], cdata[sof+29],			  cdata[sof+30], cdata[sof+31]);				// setting to skip the rest of the packet			spca50x->header_len = datalength;			} else				sequenceNumber++;	break;	case BRIDGE_ZC3XX:	  {	    iPix = 0;	    if (cdata[0] == 0xFF && cdata[1] == 0xD8)	      {		sequenceNumber = 0;		spca50x->header_len = 2;	//18 remove 0xff 0xd8;		PDEBUG (5,			"Zc301 header packet found datalength %d totlength %d!!",			datalength, totlen);	      }	    else	      {		sequenceNumber++;	      }	  }	  break;	case BRIDGE_SPCA533:	  {	    iPix = 1;	    if (sequenceNumber == SPCA50X_SEQUENCE_DROP)	      {		if (cdata[1] == 0x01)		  {		    sequenceNumber = 0;		  }		else		  {		    /* drop packet */		    PDEBUG (5, "Dropped packet (expected seq 0x%02x)",			    frame->last_packet + 1);		    continue;		  }	      }	    else	      {		sequenceNumber++;	      }	  }	  break;	case BRIDGE_SPCA536:	  {	    iPix = 2;	    if (sequenceNumber == SPCA50X_SEQUENCE_DROP)	      {		sequenceNumber = 0;	      }	    else	      {		sequenceNumber++;	      }	  }	  break;	case BRIDGE_SPCA504:	case BRIDGE_SPCA504B:	case BRIDGE_SPCA504C:	  {	    iPix = 1;	    switch (sequenceNumber)	      {	      case 0xfe:		sequenceNumber = 0;		break;	      case SPCA50X_SEQUENCE_DROP:		/* drop packet */		PDEBUG (5, "Dropped packet (expected seq 0x%02x)",			frame->last_packet + 1);		continue;	      default:		sequenceNumber++;		break;	      }	  }	  break;	default:	  {	    iPix = 1;	    /* check if this is a drop packet */	    if (sequenceNumber == SPCA50X_SEQUENCE_DROP)	      {		PDEBUG (3, "Dropped packet (expected seq 0x%02x)",			frame->last_packet + 1);		continue;	      }	  }	  break;	}      PDEBUG (3, "spca50x: Packet seqnum = 0x%02x.  curframe=%2d",	      sequenceNumber, spca50x->curframe);      pData = cdata;      /* Can we find a frame start */      if (sequenceNumber == 0)	{	  totlen = 0;	  iPix = spca50x->header_len;	  PDEBUG (3, "spca50x: Found Frame Start!, framenum = %d",		  spca50x->curframe);	  // Start of frame is implicit end of previous frame	  // Check for a previous frame and finish it off if one exists	  if (frame->scanstate == STATE_LINES){	      if (frame->format != VIDEO_PALETTE_RAW_JPEG)		{		  /* Decode the frame */		 		tasklet_init (&spca50x->spca5xx_tasklet, outpict_do_tasklet,				(unsigned long) frame);		tasklet_schedule (&spca50x->spca5xx_tasklet);		}	      else		{		  /* RAW DATA stream */		  frame->grabstate = FRAME_DONE;		  if (waitqueue_active (&frame->wq))		    wake_up_interruptible (&frame->wq);		}	      // If someone decided to wait for ANY frame - wake him up 	      if (waitqueue_active (&spca50x->wq))		wake_up_interruptible (&spca50x->wq);	      frame = spca50x_next_frame (spca50x, cdata);	    }	  else	    frame->scanstate = STATE_LINES;	}      /* Are we in a frame? */      if (frame == NULL || frame->scanstate != STATE_LINES)	continue;      if (sequenceNumber != frame->last_packet + 1 &&	  frame->last_packet != -1)	{	  /* Note, may get one of these for the first packet after opening */	  PDEBUG (2, "Out of order packet, last = %d, this = %d",		  frame->last_packet, sequenceNumber);	}      frame->last_packet = sequenceNumber;      /* This is the real conversion of the raw camera data to BGR for V4L */      datalength -= iPix;	// correct length for packet header      pData = cdata + iPix;	// Skip packet header (1 or 10 bytes)      // Consume data      PDEBUG (5, "Processing packet seq  %d,length %d,totlength %d",	      frame->last_packet, datalength, frame->totlength);      /* this copy consume input data from the isoc stream */      if ((datalength > 0) && (datalength <= 0x3ff)){      memcpy (frame->highwater, pData, datalength);      frame->highwater += datalength;      totlen += datalength;      }      	      frame->totlength = totlen;#ifdef SPCA50X_ENABLE_EXP_BRIGHTNESS      /* autoadjust is set to 1 to so now autobrightness will be         calculated frome this frame. autoadjust will be set to 0 when         autobrightness has been corrected if needed. */      autoadjust = 1;#endif /* SPCA50X_ENABLE_EXP_BRIGHTNESS */    }  return totlen;}/**************************************************************************** * * Buffer management * ***************************************************************************/static intspca50x_alloc (struct usb_spca50x *spca50x){  int i;  PDEBUG (4, "entered");  down (&spca50x->buf_lock);  spca50x->tmpBuffer = rvmalloc (MAX_FRAME_SIZE);  if (spca50x->buf_state == BUF_ALLOCATED)    goto out;  spca50x->fbuf = rvmalloc (SPCA50X_NUMFRAMES * MAX_DATA_SIZE);  if (!spca50x->fbuf)    goto error;  for (i = 0; i < SPCA50X_NUMFRAMES; i++)    {      spca50x->frame[i].tmpbuffer = spca50x->tmpBuffer;      spca50x->frame[i].decoder = &spca50x->maindecode; //connect each frame to the main data decoding       spca50x->frame[i].grabstate = FRAME_UNUSED;      spca50x->frame[i].scanstate = STATE_SCANNING;      spca50x->frame[i].data = spca50x->fbuf + i * MAX_DATA_SIZE;      spca50x->frame[i].highwater = spca50x->frame[i].data;      PDEBUG (4, "frame[%d] @ %p", i, spca50x->frame[i].data);    }  for (i = 0; i < SPCA50X_NUMSBUF; i++)    {      spca50x->sbuf[i].data = kmalloc (FRAMES_PER_DESC *				       MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL);      if (!spca50x->sbuf[i].data)	goto error;      PDEBUG (4, "sbuf[%d] @ %p", i, spca50x->sbuf[i].data);    }  spca50x->buf_state = BUF_ALLOCATED;out:  up (&spca50x->buf_lock);  PDEBUG (4, "leaving");  return 0;error:  /* FIXME: IMHO, it's better to move error deallocation code here. */  for (i = 0; i < SPCA50X_NUMSBUF; i++)    {      if (spca50x->sbuf[i].data)	{	  kfree (spca50x->sbuf[i].data);	  spca50x->sbuf[i].data = NULL;	}    }  if (spca50x->fbuf)    {      rvfree (spca50x->fbuf, SPCA50X_NUMFRAMES * MAX_DATA_SIZE);      spca50x->fbuf = NULL;    }  if (spca50x->tmpBuffer)    {      rvfree (spca50x->tmpBuffer, MAX_FRAME_SIZE);      spca50x->tmpBuffer = NULL;    }  spca50x->buf_state = BUF_NOT_ALLOCATED;  up (&spca50x->buf_lock);  PDEBUG (1, "errored");  return -ENOMEM;}static voidspca5xx_dealloc (struct usb_spca50x *spca50x ){  int i;  PDEBUG (2, "entered dealloc");  down (&spca50x->buf_lock);  if (spca50x->fbuf)    {      rvfree (spca50x->fbuf, SPCA50X_NUMFRAMES * MAX_DATA_SIZE);      spca50x->fbuf = NULL;      for (i = 0; i < SPCA50X_NUMFRAMES; i++)	spca50x->frame[i].data = NULL;    }  if (spca50x->tmpBuffer)    {      rvfree (spca50x->tmpBuffer, MAX_FRAME_SIZE);      spca50x->tmpBuffer = NULL;    }  for (i = 0; i < SPCA50X_NUMSBUF; i++)    {      if (spca50x->sbuf[i].data)	{	  kfree (spca50x->sbuf[i].data);	  spca50x->sbuf[i].data = NULL;	}    }  PDEBUG (2, "buffer memory deallocated");  spca50x->buf_state = BUF_NOT_ALLOCATED;  up (&spca50x->buf_lock);  PDEBUG (2, "leaving dealloc");}/** * Reset the camera and send the correct initialization sequence for the * currently selected source */static intspca50x_init_source (struct usb_spca50x *spca50x){  int err_code;  switch (spca50x->bridge)    {    case BRIDGE_SN9CXXX:      err_code = sn9cxxx_init (spca50x);      PDEBUG (2, "Initializing Sonix finished %d",err_code);      if (err_code < 0) return err_code;      break;    case BRIDGE_ZC3XX:      err_code = zc3xx_init (spca50x);      break;    case BRIDGE_SPCA504:    case BRIDGE_SPCA504C:    case BRIDGE_SPCA536:    case BRIDGE_SPCA533:    case BRIDGE_SPCA504B:      {	PDEBUG (2, "Opening SPCA5xx FW2");	sp5xxfw2_init (spca50x);	break;      }    default:      {	err ("Unimplemented bridge type");	return -EINVAL;      }    }  spca50x->norme = 0;  spca50x->channel = 0;     err_code =spca5xx_setMode(spca50x,spca50x->width,spca50x->height,VIDEO_PALETTE_JPEG);     PDEBUG(2,"set Mode return %d ", err_code);     if (err_code < 0) return -EINVAL;  return 0;}/**************************************************************************** * * V4L API * ***************************************************************************/static inline void spca5xx_setFrameDecoder(struct usb_spca50x *spca50x){ int i;  /* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used   * (using read() instead). */  for (i = 0; i < SPCA50X_NUMFRAMES; i++)    {      spca50x->frame[i].width = spca50x->width;      spca50x->frame[i].height = spca50x->height;      spca50x->frame[i].cameratype = spca50x->cameratype;      spca50x->frame[i].scanlength = 0;      spca50x->frame[i].depth = 8;      spca50x->frame[i].format = VIDEO_PALETTE_JPEG;    }}static inline void spca5xx_initDecoder(struct usb_spca50x *spca50x){  if (spca50x->cameratype == JPEG)    init_jpeg_decoder (spca50x,2);  if (spca50x->cameratype == JPGH      || spca50x->cameratype == JPGC     || spca50x->cameratype == JPGS)    init_jpeg_decoder (spca50x,1);  if (spca50x->cameratype == JPGM)    init_jpeg_decoder (spca50x,0);}#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22)static intspca5xx_open (struct inode *inode, struct file *file){  struct video_device *vdev = video_devdata (file);#elsestatic intspca5xx_open(struct video_device *vdev, int flags){#endif  struct usb_spca50x *spca50x = video_get_drvdata (vdev);  int err;  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)  MOD_INC_USE_COUNT;#endif  PDEBUG (2, "opening");  down (&spca50x->lock);  /* sanity check disconnect, in use, no memory available */  err = -ENODEV;

⌨️ 快捷键说明

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