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

📄 spca5xx.c

📁 linux摄像头驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
#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 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) {#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 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);    spcaCameraStop2(spca50x);    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 int wxh_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 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(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)		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 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 = spca50x_init_isoc(spca50x);	} else {	    spcaCameraStart(spca50x);	}    }  out:    return r;}/********************************************************************** * * 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;    return frame;}/* Tasklet function to decode */void outpict_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);}/*********************************************************************	time Helper function**********************************************************************/static inline

⌨️ 快捷键说明

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