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

📄 spca_core.c

📁 通用的摄像头驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#endif      urb->transfer_buffer = spca50x->sbuf[n].data;      urb->complete = spca50x_isoc_irq;      urb->number_of_packets = FRAMES_PER_DESC;      urb->transfer_buffer_length = spca50x->packet_size * FRAMES_PER_DESC;      for (fx = 0; fx < FRAMES_PER_DESC; fx++)	{	  urb->iso_frame_desc[fx].offset = spca50x->packet_size * fx;	  urb->iso_frame_desc[fx].length = spca50x->packet_size;	}    }#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,41)  spca50x->sbuf[SPCA50X_NUMSBUF - 1].urb->next = spca50x->sbuf[0].urb;  for (n = 0; n < SPCA50X_NUMSBUF - 1; n++)    spca50x->sbuf[n].urb->next = spca50x->sbuf[n + 1].urb;#endif  spcaCameraStart (spca50x);  PDEBUG (5, "init isoc int %d altsetting %d", spca50x->iface, spca50x->alt);  for (n = 0; n < SPCA50X_NUMSBUF; n++)    {      spca50x->sbuf[n].urb->dev = spca50x->dev;#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41)      err = usb_submit_urb (spca50x->sbuf[n].urb, GFP_KERNEL);#else      err = usb_submit_urb (spca50x->sbuf[n].urb);#endif      if (err){	err ("init isoc: usb_submit_urb(%d) ret %d", n, err);	return err;	}    }  for (n = 0; n < SPCA50X_NUMFRAMES; n++)    {      spca50x->frame[n].grabstate = FRAME_UNUSED;      spca50x->frame[n].scanstate = STATE_SCANNING;    }  spca50x->streaming = 1;  return 0;}/*********************************************************************** spca50x_stop_isoc* Function stops the USB ISO pipe by stopping the chip ISO machine* and stopping USB transfer***********************************************************************/static voidspca5xx_kill_isoc (struct usb_spca50x *spca50x){  int n;  if (!spca50x)    return;  PDEBUG (3, "*** killing capture ***");  spca50x->streaming = 0;  /* Unschedule all of the iso td's */  for (n = SPCA50X_NUMSBUF - 1; n >= 0; n--)    {      if (spca50x->sbuf[n].urb)	{#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)	  usb_kill_urb (spca50x->sbuf[n].urb);#else	  usb_unlink_urb (spca50x->sbuf[n].urb);#endif	  usb_free_urb (spca50x->sbuf[n].urb);	  spca50x->sbuf[n].urb = NULL;	}    }  PDEBUG (3, "*** Isoc killed ***");}static voidspca50x_stop_isoc (struct usb_spca50x *spca50x){  if (!spca50x->streaming || !spca50x->dev)    return;  PDEBUG (3, "*** Stopping capture ***");  spcaCameraStop (spca50x);  spca5xx_kill_isoc(spca50x);  spca50x_set_packet_size (spca50x, 0);  PDEBUG (3, "*** Capture stopped ***");}/*********************************************************************** spca50x_smallest_mode_index* Function finds the mode index in the modes table of the smallest* available mode.***********************************************************************/static int spca5xx_getDefaultMode(struct usb_spca50x *spca50x){  int i;  for (i = QCIF;i < TOTMODE; i++){  if(spca50x->mode_cam[i].method == 0 && spca50x->mode_cam[i].width){		spca50x->width = spca50x->mode_cam[i].width;		spca50x->height = spca50x->mode_cam[i].height;		spca50x->method = 0;		spca50x->pipe_size = spca50x->mode_cam[i].pipe ;		spca50x->mode = spca50x->mode_cam[i].mode;		return 0;		}  }return -EINVAL;}/*********************************************************************** spca50x_set_mode* Function sets up the resolution directly. * Attention!!! index, the index in modes array is NOT checked. ***********************************************************************/static int spca5xx_getcapability(struct usb_spca50x *spca50x ){		int maxw,maxh,minw,minh;	int i;	minw = minh = 255*255;	maxw = maxh = 0;	for (i = QCIF; i < TOTMODE; i++){	if( spca50x->mode_cam[i].width){	  if (maxw < spca50x->mode_cam[i].width || maxh < spca50x->mode_cam[i].height){	    maxw = spca50x->mode_cam[i].width;	    maxh = spca50x->mode_cam[i].height;	  }	  if (minw > spca50x->mode_cam[i].width || minh > spca50x->mode_cam[i].height){	    minw = spca50x->mode_cam[i].width;	    minh = spca50x->mode_cam[i].height;	  }	 }	}	spca50x->maxwidth = maxw;	spca50x->maxheight = maxh;	spca50x->minwidth = minw;	spca50x->minheight = minh;	PDEBUG(0,"maxw %d maxh %d minw %d minh %d",maxw,maxh,minw,minh);	return 0;}static inline int v4l_to_spca5xx(int format){switch(format){    case VIDEO_PALETTE_RGB565: return P_RGB16;    case VIDEO_PALETTE_RGB24: return P_RGB24;    case VIDEO_PALETTE_RGB32: return P_RGB32;    case VIDEO_PALETTE_YUV422P: return P_YUV422;    case VIDEO_PALETTE_YUV420P: return P_YUV420;    case VIDEO_PALETTE_RAW_JPEG: return P_RAW;    case VIDEO_PALETTE_JPEG: return P_JPEG;    default: return -EINVAL;   }} static inline int spca5xx_setMode(struct usb_spca50x *spca50x,int width,int height,int format){  int i,j;  int formatIn;  int crop = 0, cropx1 = 0, cropx2 = 0, cropy1 = 0, cropy2 = 0, x = 0, y = 0;   /* Avoid changing to already selected mode */   /* convert V4l format to our internal format */   PDEBUG(2,"Set mode asked w %d h %d p %d",width,height,format);    if ((formatIn = v4l_to_spca5xx(format)) < 0)     return -EINVAL;  for (i = QCIF; i< TOTMODE; i++){    if((spca50x->mode_cam[i].width == width) &&     (spca50x->mode_cam[i].height == height) &&     (spca50x->mode_cam[i].t_palette & formatIn)){        spca50x->width = spca50x->mode_cam[i].width;        spca50x->height = spca50x->mode_cam[i].height;        spca50x->pipe_size = spca50x->mode_cam[i].pipe ;        spca50x->mode = spca50x->mode_cam[i].mode;	spca50x->method = spca50x->mode_cam[i].method;	spca50x->format = format; //palette in use     if(spca50x->method){     if (spca50x->method == 1){      for (j = i; j < TOTMODE ; j++){       if(spca50x->mode_cam[j].method == 0 && spca50x->mode_cam[j].width){        spca50x->hdrwidth = spca50x->mode_cam[j].width;        spca50x->hdrheight = spca50x->mode_cam[j].height;	spca50x->mode = spca50x->mode_cam[j].mode; // overwrite by the hardware mode        break;       }      } // end match hardware mode      if (!spca50x->hdrwidth && !spca50x->hdrheight)          return -EINVAL;       }      }    /* match found */    break;    }   } // end match mode  /* initialize the hdrwidth and hdrheight for the first init_source */  /* precompute the crop x y value for each frame */  if (!spca50x->method)    {      /* nothing todo hardware found stream */      cropx1 = cropx2 = cropy1 = cropy2 = x = y = 0;      spca50x->hdrwidth = spca50x->width;      spca50x->hdrheight = spca50x->height;    }  if (spca50x->method & 0x01)    {      /* cropping method */      if (spca50x->hdrwidth > spca50x->width)	{	  crop = (spca50x->hdrwidth - spca50x->width);	  if (spca50x->cameratype == JPEG || spca50x->cameratype == JPGH || spca50x->cameratype == JPGS)	    crop = crop >> 4;	  cropx1 = crop >> 1;	  cropx2 = cropx1 + (crop % 2);	}      else	{	  cropx1 = cropx2 = 0;	}      if (spca50x->hdrheight > spca50x->height)	{	  crop = (spca50x->hdrheight - spca50x->height);	  if (spca50x->cameratype == JPEG)	    crop = crop >> 4;	  if (spca50x->cameratype == JPGH || spca50x->cameratype == JPGS)	    crop = crop >> 3;	  cropy1 = crop >> 1;	  cropy2 = cropy1 + (crop % 2);	}      else	{	  cropy1 = cropy2 = 0;	}    }  if (spca50x->method & 0x02)    {      /* what can put here for div method */    }  if (spca50x->method & 0x04)    {      /* and here for mult */    }  PDEBUG (2, "Found code %d method %d", spca50x->mode, spca50x->method);  PDEBUG (2, "Soft Win width height %d x %d", spca50x->width,	  spca50x->height);  PDEBUG (2, "Hard Win width height %d x %d", spca50x->hdrwidth,	  spca50x->hdrheight);  for (i = 0; i < SPCA50X_NUMFRAMES; i++)    {      spca50x->frame[i].method = spca50x->method;      spca50x->frame[i].cameratype = spca50x->cameratype;      spca50x->frame[i].cropx1 = cropx1;      spca50x->frame[i].cropx2 = cropx2;      spca50x->frame[i].cropy1 = cropy1;      spca50x->frame[i].cropy2 = cropy2;      spca50x->frame[i].x = x;      spca50x->frame[i].y = y;      spca50x->frame[i].hdrwidth = spca50x->hdrwidth;      spca50x->frame[i].hdrheight = spca50x->hdrheight;      spca50x->frame[i].width = spca50x->width;      spca50x->frame[i].height = spca50x->height;       spca50x->frame[i].format = spca50x->format;      spca50x->frame[i].scanlength = spca50x->width * spca50x->height * 3 / 2;      // ?? assumes 4:2:0 data    }  return 0;  }/*********************************************************************** spca50x_mode_init_regs* Function sets up the resolution with checking if it's necessary ***********************************************************************/static int spca5xx_restartMode (struct usb_spca50x *spca50x, int width, int height, int format){ int was_streaming; int r; /* Avoid changing to already selected mode */  if (spca50x->width == width && spca50x->height == height)    return 0;PDEBUG (1, "Mode changing to %d,%d", width, height);  was_streaming = spca50x->streaming;  if (was_streaming)    	spca50x_stop_isoc (spca50x);      r = spca5xx_setMode(spca50x,width,height,format);  if (r < 0)       goto out;  if (was_streaming)	  r = spca50x_init_isoc (spca50x);out:      return r;}/*********************************************************************** spca50x_get_brightness* Function reads the brightness from the camera* Receives the pointer to the description structure* returns the value of brightness**********************************************************************/static inline __u16spca50x_get_brightness (struct usb_spca50x *spca50x){  __u16 brightness = 0;		// value of the brightness        switch (spca50x->bridge)	{	case BRIDGE_SN9CXXX:	  brightness = sn9cxxx_getbrightness (spca50x);	  break;	case BRIDGE_ZC3XX:	  brightness = zc3xx_getbrightness (spca50x);	  break;	case BRIDGE_SPCA536:	case BRIDGE_SPCA533:	case BRIDGE_SPCA504:	case BRIDGE_SPCA504B:	case BRIDGE_SPCA504C:	 brightness = sp5xxfw2_getbrightness (spca50x);	break;	default:	  {	    brightness = 0;	    break;	  }	}      return brightness;}/*********************************************************************** spca50x_set_brightness* Function sets the brightness to the camera* Receives the pointer to the description structure * and brightness value**********************************************************************/static inline voidspca50x_set_brightness (struct usb_spca50x *spca50x, __u8 brightness){      switch (spca50x->bridge)	{	case BRIDGE_SN9CXXX:	spca50x->brightness = brightness << 8;	  sn9cxxx_setbrightness (spca50x);	break;	case BRIDGE_ZC3XX:	  spca50x->brightness = brightness << 8;	  zc3xx_setbrightness (spca50x);	  break;	case BRIDGE_SPCA536:	case BRIDGE_SPCA533:	case BRIDGE_SPCA504:	case BRIDGE_SPCA504B:	case BRIDGE_SPCA504C:	  {	  spca50x->brightness = brightness << 8;	  sp5xxfw2_setbrightness (spca50x);	   	    break;	  }	default:	  {	    break;	  }	}    }/********************************************************************** * * SPCA50X data transfer, IRQ handler * **********************************************************************/static struct spca50x_frame *spca50x_next_frame (struct usb_spca50x *spca50x, unsigned char *cdata){  int iFrameNext;  struct spca50x_frame *frame = NULL;  /* Cycle through the frame buffer looking for a free frame to overwrite */  iFrameNext = (spca50x->curframe + 1) % SPCA50X_NUMFRAMES;  while (frame == NULL && iFrameNext != (spca50x->curframe))    {      if (spca50x->frame[iFrameNext].grabstate == FRAME_READY ||	  spca50x->frame[iFrameNext].grabstate == FRAME_UNUSED ||	  spca50x->frame[iFrameNext].grabstate == FRAME_ERROR)	{	  spca50x->curframe = iFrameNext;	  frame = &spca50x->frame[iFrameNext];	  break;	}      else	{	  iFrameNext = (iFrameNext + 1) % SPCA50X_NUMFRAMES;	}    }  if (frame == NULL)    {      PDEBUG (3, "Can't find a free frame to grab into...using next. "	      "This is caused by the application not reading fast enough.");      spca50x->curframe = (spca50x->curframe + 1) % SPCA50X_NUMFRAMES;      frame = &spca50x->frame[spca50x->curframe];    }  frame->grabstate = FRAME_GRABBING;  /* Record the frame sequence number the camera has told us */  if (cdata)    {      switch (spca50x->bridge)	{	case BRIDGE_SPCA504:	  frame->seq = cdata[SPCA50X_OFFSET_FRAMSEQ];	  break;	case BRIDGE_SPCA504C:	  frame->seq = cdata[SPCA50X_OFFSET_FRAMSEQ];	  break;	case BRIDGE_SPCA504B:	  frame->seq = cdata[SPCA50X_OFFSET_FRAMSEQ];	  break;	case BRIDGE_SPCA533:	  frame->seq = cdata[SPCA533_OFFSET_FRAMSEQ];	  break;	case BRIDGE_SPCA536:	  frame->seq = cdata[SPCA536_OFFSET_FRAMSEQ];	  break;	case BRIDGE_ZC3XX: 	case BRIDGE_SN9CXXX:	 frame->seq=00;	 break;	}    }  /* Reset some per-frame variables */  frame->highwater = frame->data;  frame->scanstate = STATE_LINES;  frame->scanlength = 0;  frame->last_packet = -1;  frame->totlength = 0;  spca50x->packet = 0;  return frame;}/* Tasklet function to decode */voidoutpict_do_tasklet (unsigned long ptr){  int err;  struct spca50x_frame *taskletframe = (struct spca50x_frame *) ptr;  taskletframe->scanlength = taskletframe->highwater - taskletframe->data;  PDEBUG (2, "Tasklet ask spcadecoder hdrwidth %d hdrheight %d method %d",	  taskletframe->hdrwidth, taskletframe->hdrheight,	  taskletframe->method);  err = spca50x_outpicture (taskletframe);  if (err != 0)    {      PDEBUG (2, "frame decoder failed (%d)", err);      taskletframe->grabstate = FRAME_ERROR;    }  else    {      taskletframe->grabstate = FRAME_DONE;

⌨️ 快捷键说明

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