📄 gspca_core.c
字号:
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 intwxh_to_size(int width, int height){ switch (width) { case 640: if (height == 480) return VGA; break; case 384: if (height == 288) return PAL; break; case 352: if (height == 288) return SIF; break; case 320: if (height == 240) return CIF; break; case 192: if (height == 144) return QPAL; break; case 176: if (height == 144) return QSIF; break; case 160: if (height == 120) return QCIF; break; } return -EINVAL;}static intv4l_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 intspca5xx_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(3, "spca5xx 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 || spca50x->cameratype == PJPG) 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 || spca50x->cameratype == PJPG) 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 intspca5xx_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;/* FIXME spca500 bridge is there a way to find an init like Clicksmart310 ? */ if (was_streaming) { if ((spca50x->bridge != BRIDGE_SPCA500) || (spca50x->desc == LogitechClickSmart310)) spca50x_stop_isoc(spca50x); } r = spca5xx_setMode(spca50x, width, height, format); if (r < 0) goto out; if (was_streaming) { if ((spca50x->bridge != BRIDGE_SPCA500) || (spca50x->desc == LogitechClickSmart310)) { r = gspca_init_transfert(spca50x); } else { spca50x->funct.start(spca50x); } } out: return r;}#if 0/************************************************************************ 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; PDEBUG(2, "Frame %d State %d", spca50x->curframe, spca50x->frame[spca50x->curframe].grabstate); if (spca50x->frame[spca50x->curframe].grabstate == FRAME_ERROR) { PDEBUG(2, "Frame %d errdrop", spca50x->curframe); frame = &spca50x->frame[spca50x->curframe]; goto dropframe; }/* 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]; }dropframe: frame->grabstate = FRAME_GRABBING; if (spca50x->pictsetting.change) { memcpy(&frame->pictsetting, &spca50x->pictsetting, sizeof (struct pictparam));/* reset flag change */ spca50x->pictsetting.change = 0; PDEBUG(2, "Picture setting change Pass to decoding "); }/* 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;out: return frame;}#endif/************************************************************************ SPCA50X data transfer, IRQ handler***********************************************************************/static struct spca50x_frame *spca50x_next_frame(struct usb_spca50x *spca50x, unsigned char *cdata){ struct spca50x_frame *frame = NULL; PDEBUG(2, "Frame %d State %d", spca50x->curframe, spca50x->frame[spca50x->curframe].grabstate); if (spca50x->frame[spca50x->curframe].grabstate != FRAME_ERROR) spca50x->curframe = (spca50x->curframe + 1) % SPCA50X_NUMFRAMES; frame = &spca50x->frame[spca50x->curframe]; if (spca50x->pictsetting.change) { memcpy(&frame->pictsetting, &spca50x->pictsetting, sizeof (struct pictparam));/* reset flag change */ spca50x->pictsetting.change = 0; PDEBUG(2, "Picture setting change Pass to decoding "); }/* Reset some per-frame variables */ frame->grabstate = FRAME_GRABBING; frame->scanstate = STATE_LINES; frame->highwater = frame->data; 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); if ((err = spca50x_outpicture(taskletframe)) < 0) { PDEBUG(2, "frame decoder failed (%d)", err); taskletframe->grabstate = FRAME_ERROR; } else { taskletframe->grabstate = FRAME_DONE; PDEBUG(2, "Decode framestate return %d", taskletframe->grabstate); } if (waitqueue_active(&taskletframe->wq)) wake_up_interruptible(&taskletframe->wq); atomic_set(&taskletframe->spca50x_dev->in_use,0);}/*********************************************************************time Helper function**********************************************************************/static inline unsigned longspca5xx_gettimes(void){ u64 times_now; times_now = get_jiffies_64(); return jiffies_to_msecs(times_now);}/* ******************************************************************* 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; 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; unsigned long ms_times_now; unsigned long ms_times_before; struct spca50x_frame *frame; //Pointer to frame data int sequenceNumber; int sof; int iPix; //Offset of pixel data in the ISO packet if (st) { PDEBUG(0, "ISOC data error: [%d] len=%d, status=%d \n", i, datalength, st); continue; } 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) { spca50x->synchro = 0; continue; } PDEBUG(5, "Packet data [%d,%d,%d] Status: %d", datalength, st, urb->iso_frame_desc[i].offset, st); frame = &spca50x->frame[spca50x->curframe]; if (frame->last_packet == -1) {/*initialize a new frame */ sequenceNumber = 0; } else { sequenceNumber = frame->last_packet; }/* check frame start */ if ((sof = spca50x->funct.sof_detect(spca50x, frame, cdata, &iPix, sequenceNumber, &datalength)) < 0) continue; sequenceNumber = sof; PDEBUG(3, "spca50x: Packet seqnum = 0x%02x. curframe=%2d", sequenceNumber, spca50x->curframe); pData = cdata;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -