📄 spca_core.c
字号:
#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 + -