📄 spca5xx.c
字号:
/* reset iso context */ spca50x->compress = compress; spca50x->curframe = 0; spca50x->cursbuf = 0; spca50x->frame[0].seq = -1; spca50x->lastFrameRead = -1; spca50x_set_packet_size(spca50x, spca50x->pipe_size); PDEBUG(2, "setpacketsize %d", spca50x->pipe_size); for (n = 0; n < SPCA50X_NUMSBUF; n++) { urb = usb_alloc_urb(FRAMES_PER_DESC); if (!urb) { err("init isoc: usb_alloc_urb ret. NULL"); return -ENOMEM; } spca50x->sbuf[n].urb = urb; urb->dev = spca50x->dev; urb->context = spca50x; if (spca50x->bridge == BRIDGE_PAC207) { urb->pipe = usb_rcvisocpipe(spca50x->dev, PAC207_ENDPOINT_ADDRESS); } else { urb->pipe = usb_rcvisocpipe(spca50x->dev, SPCA50X_ENDPOINT_ADDRESS); } urb->transfer_flags = USB_ISO_ASAP; 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); if (spca50x->bridge == BRIDGE_SONIX) { intpipe = usb_rcvintpipe(spca50x->dev, 3); usb_clear_halt(spca50x->dev, intpipe); } 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; err = usb_submit_urb(spca50x->sbuf[n].urb); 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 void spca5xx_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) { usb_unlink_urb(spca50x->sbuf[n].urb); usb_free_urb(spca50x->sbuf[n].urb); spca50x->sbuf[n].urb = NULL; } } PDEBUG(3, "*** Isoc killed ***");}static void spca50x_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); if (spca50x->bridge == BRIDGE_CX11646) cx11646_stop(spca50x); PDEBUG(3, "*** Capture stopped ***");}/*********************************************************************** spca50x_find_mode_index* Function finds the mode index in the modes table***********************************************************************/static inline intspca50x_find_mode_index(int width, int height, __u16 ext_modes[][6]){ int i = 0; int j = 0; /* search through the mode list until we hit one which has * a smaller or equal resolution, or we run out of modes. */ for (i = 0; ext_modes[i][0] && (ext_modes[i][0] >= width && ext_modes[i][1] >= height); i++) { if (((ext_modes[i][2] & 0xF0) >> 4) == 0) j = (i & 0x0F) << 4; } /* search to found the first hardware available mode */ i--; /* FIXME */ PDEBUG(2, "find Hardware mode %d soft mode %d", j >> 4, i); /* check whether we found the requested mode, or ran out of * modes in the list. */ if (!ext_modes[i][0] || ext_modes[i][0] != width || ext_modes[i][1] != height) { PDEBUG(3, "Failed to find mode %d x %d", width, height); return -EINVAL; } i = (i & 0x0F) | j; PDEBUG(2, "Pass Hardware mode %d soft mode %d", (i >> 4), (i & 0x0F)); /* return the index of the requested mode */ return i;}/*********************************************************************** 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;}static inline intspca50x_smallest_mode_index(__u16 ext_modes[][6], int *cols, int *rows, int *pipe){ int i; int width = INT_MAX; int height = INT_MAX; int intpipe = 1023; int index = -EINVAL; /* search through the mode list until we run out of modes */ /* and take the smallest hardware mode and pipe size */ for (i = 0; ext_modes[i][0]; i++) { if (ext_modes[i][0] < width || ext_modes[i][1] < height) { if (!(ext_modes[i][2] & 0xF0)) { width = ext_modes[i][0]; height = ext_modes[i][1]; intpipe = ext_modes[i][5]; index = i; } } } /* return the index of the smallest mode */ if (index != -EINVAL) { *pipe = intpipe; if (cols != NULL) *cols = width; if (rows != NULL) *rows = height; } return i;}/*********************************************************************** 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;}static inline intspca50x_set_mode(struct usb_spca50x *spca50x, int index, __u16 ext_modes[][6]){ struct usb_device *dev = spca50x->dev; int i; int mode = 0; int method = 0; int crop = 0, cropx1 = 0, cropx2 = 0, cropy1 = 0, cropy2 = 0, x = 0, y = 0; if (spca50x->bridge == BRIDGE_ETOMS) { spca50x->mode = (ext_modes[index][2] & 0x0f); } else if (spca50x->bridge == BRIDGE_TV8532) { mode = (ext_modes[index][2]) & 0x0F; method = (ext_modes[index][2] & 0xF0) >> 4; spca50x->mode = mode; } else if (spca50x->bridge == BRIDGE_CX11646) { mode = (ext_modes[index][2]) & 0x0F; method = (ext_modes[index][2] & 0xF0) >> 4; spca50x->mode = mode; } else if (spca50x->bridge == BRIDGE_SPCA506) { spca506_Setsize(spca50x, ext_modes[index][2], ext_modes[index][3], ext_modes[index][4]); } else if (spca50x->bridge == BRIDGE_SPCA505) { spca50x_reg_write(dev, SPCA50X_REG_COMPRESS, 0x0, ext_modes[index][2]); spca50x_reg_write(dev, SPCA50X_REG_COMPRESS, 0x6, ext_modes[index][3]); spca50x_reg_write(dev, SPCA50X_REG_COMPRESS, 0x7, ext_modes[index][4]); } else if (spca50x->bridge == BRIDGE_SPCA501) { mode = (ext_modes[index][2]) & 0x0F; method = (ext_modes[index][2] & 0xF0) >> 4; spca50x_reg_write(dev, SPCA50X_REG_USB, 0x6, ext_modes[index][3]); spca50x_reg_write(dev, SPCA50X_REG_USB, 0x7, ext_modes[index][4]); } else if (spca50x->bridge == BRIDGE_SPCA508) { spca50x_reg_write(dev, 0, 0x8500, ext_modes[index][2]); // mode
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -