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

📄 gspca_core.c

📁 Linux下面摄像头最新源代码:支持200多中摄像头
💻 C
📖 第 1 页 / 共 5 页
字号:
/*Let's include the initialization data for each camera type*/#include "utils/spcausb.h"#include "Sunplus/spca501_init.h"#include "Sunplus/spca505_init.h"#include "Sunplus/spca506.h"#include "Sunplus/spca508_init.h"#include "Sunplus/spca561.h"#include "Sunplus-jpeg/jpeg_qtables.h"#include "Sunplus-jpeg/spca500_init.h"#include "Sunplus-jpeg/sp5xxfw2.h"#include "Sonix/sonix.h"#include "Vimicro/zc3xx.h"#include "Conexant/cx11646.h"#include "Transvision/tv8532.h"#include "Etoms/et61xx51.h"#include "Mars-Semi/mr97311.h"#include "Pixart/pac207.h"#include "Pixart/pac7311.h"#include "Vimicro/vc032x.h"/* function for the tasklet */void outpict_do_tasklet(unsigned long ptr);/************************************************************************ Memory management**********************************************************************/static inline unsigned longkvirt_to_pa(unsigned long adr){	unsigned long kva, ret;	kva = (unsigned long) page_address(vmalloc_to_page((void *) adr));	kva |= adr & (PAGE_SIZE - 1);	ret = __pa(kva);	return ret;}static void *rvmalloc(unsigned long size){	void *mem;	unsigned long adr;	size = PAGE_ALIGN(size);	mem = vmalloc_32(size);	if (!mem)		return NULL;	memset(mem, 0, size);	/* Clear the ram out, no junk to the user */	adr = (unsigned long) mem;	while ((long) size > 0) {		SetPageReserved(vmalloc_to_page((void *) adr));		adr += PAGE_SIZE;		size -= PAGE_SIZE;	}	return mem;}static voidrvfree(void *mem, unsigned long size){	unsigned long adr;	if (!mem)		return;	adr = (unsigned long) mem;	while ((long) size > 0) {		ClearPageReserved(vmalloc_to_page((void *) adr));		adr += PAGE_SIZE;		size -= PAGE_SIZE;	}	vfree(mem);}/* ------------------------------------------------------------------------ *//*** Endpoint management we assume one isoc endpoint per device* that is not true some Zoran 0x0572:0x0001 have two* assume ep adresse is static know * FIXME as I don't know how to set the bandwith budget* we allow the maximum**/static struct usb_host_endpoint *gspca_set_isoc_ep(struct usb_spca50x *spca50x, int nbalt){	int i, j;	struct usb_interface *intf;	struct usb_host_endpoint *ep;	struct usb_device *dev = spca50x->dev;	struct usb_host_interface *altsetting = NULL;	int error = 0;	PDEBUG(3, "enter get iso ep ");	intf = usb_ifnum_to_if(dev, spca50x->iface);	/* bandwith budget can be set here */	for (i = nbalt; i; i--) {		altsetting = &intf->altsetting[i];		for (j = 0; j < altsetting->desc.bNumEndpoints; ++j) {			ep = &altsetting->endpoint[j];			PDEBUG(3, "test ISO EndPoint  %d",ep->desc.bEndpointAddress);			if ((ep->desc.bEndpointAddress ==			     (spca50x->epadr | USB_DIR_IN))			    &&			    ((ep->desc.			      bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==			     USB_ENDPOINT_XFER_ISOC)) {				PDEBUG(0, "ISO EndPoint found 0x%02X AlternateSet %d",				       ep->desc.bEndpointAddress,i);				if ((error =				     usb_set_interface(dev, spca50x->iface,						       i)) < 0) {					PDEBUG(0, "Set interface err %d",					       error);					return NULL;				}				spca50x->alt = i;				return ep;			}		}	}	PDEBUG(0, "FATAL ISO EndPoint not found ");	return NULL;}static intgspca_set_alt0(struct usb_spca50x *spca50x){	int error = 0;	if ((error = usb_set_interface(spca50x->dev, spca50x->iface, 0)) < 0) {		PDEBUG(0, "Set interface err %d", error);	}	spca50x->alt = 0;	return  error;}static intgspca_kill_transfert(struct usb_spca50x *spca50x){	struct urb *urb;	unsigned int i;	spca50x->streaming = 0;	for (i = 0; i <  SPCA50X_NUMSBUF; ++i) {		if ((urb = spca50x->sbuf[i].urb) == NULL)			continue;		usb_kill_urb(urb);		/* urb->transfer_buffer_length is not touched by USB core, so		 * we can use it here as the buffer length.		 */		if (spca50x->sbuf[i].data) {			// kfree(gspca_dev->sbuf[i].data);					usb_buffer_free(spca50x->dev,				urb->transfer_buffer_length,				spca50x->sbuf[i].data, urb->transfer_dma);					spca50x->sbuf[i].data = NULL;		}		usb_free_urb(urb);		spca50x->sbuf[i].urb = NULL;	}	return 0;} static intgspca_init_transfert(struct usb_spca50x *spca50x){	struct usb_host_endpoint *ep;	struct usb_interface *intf;	struct urb *urb;	__u16 psize;	int n,fx;	struct usb_device *dev = spca50x->dev;//	struct usb_host_interface *altsetting = NULL;	int error = -ENOSPC;	int nbalt = 0;		if (spca50x->streaming)		return -EBUSY;	intf = usb_ifnum_to_if(dev, spca50x->iface);	nbalt = intf->num_altsetting - 1;	/* Damned Sunplus fault */	if(spca50x->bridge == BRIDGE_SPCA561) 		nbalt =7;	PDEBUG(3, "get iso nbalt %d",nbalt);	spca50x->curframe = 0;	while (nbalt && (error == -ENOSPC)) {		if ((ep = gspca_set_isoc_ep(spca50x,nbalt--)) == NULL)			return -EIO;		psize = le16_to_cpu(ep->desc.wMaxPacketSize);		psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));		PDEBUG(3, "packet size %d", psize);		for (n = 0; n < SPCA50X_NUMSBUF; n++) {			urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);			if (!urb) {				err("init isoc: usb_alloc_urb ret. NULL");				return -ENOMEM;			}						spca50x->sbuf[n].data = usb_buffer_alloc(spca50x->dev,					psize * FRAMES_PER_DESC,					GFP_KERNEL, &urb->transfer_dma);						//gspca_dev->sbuf[n].data = kmalloc((psize+1)* FRAMES_PER_DESC,GFP_KERNEL);						if(spca50x->sbuf[n].data == NULL){				usb_free_urb(urb);				gspca_kill_transfert(spca50x);				return -ENOMEM;			}			spca50x->sbuf[n].urb = urb;			urb->dev = spca50x->dev;			urb->context = spca50x;			urb->pipe =			    usb_rcvisocpipe(spca50x->dev,					    ep->desc.bEndpointAddress);			urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;			urb->interval = ep->desc.bInterval;			urb->transfer_buffer = spca50x->sbuf[n].data;			urb->complete = spca50x_isoc_irq;			urb->number_of_packets = FRAMES_PER_DESC;			urb->transfer_buffer_length = psize * FRAMES_PER_DESC;			for (fx = 0; fx < FRAMES_PER_DESC; fx++) {				urb->iso_frame_desc[fx].offset = psize * fx;				urb->iso_frame_desc[fx].length = psize;			}		}				/* mark all frame unused */	for (n = 0; n <  SPCA50X_NUMFRAMES; n++) {		spca50x->frame[n].grabstate = FRAME_UNUSED;		spca50x->frame[n].scanstate = STATE_SCANNING;	}	/* start the cam and initialize the tasklet lock */	spca50x->funct.start(spca50x);	spca50x->streaming = 1;	atomic_set(&spca50x->in_use,0);	PDEBUG(3, "Submit URB Now");	/* Submit the URBs. */	for (n = 0; n < SPCA50X_NUMSBUF; ++n) {		if ((error = usb_submit_urb(spca50x->sbuf[n].urb, GFP_KERNEL)) < 0) {			err("init isoc: usb_submit_urb(%d) ret %d", n, error);			gspca_kill_transfert(spca50x);			break;			}		}	}	return error;}/* Returns number of bits per pixel (regardless of where they are located; planar or* not), or zero for unsupported format.*/static intspca5xx_get_depth(struct usb_spca50x *spca50x, int palette){	switch (palette) {//      case VIDEO_PALETTE_GREY:     return 8;	case VIDEO_PALETTE_RGB565:		return 16;	case VIDEO_PALETTE_RGB24:		return 24;//      case VIDEO_PALETTE_YUV422:   return 16;//      case VIDEO_PALETTE_YUYV:// return 16;//      case VIDEO_PALETTE_YUV420:   return 24;	case VIDEO_PALETTE_YUV420P:		return 12;	/* strange need 12 this break the read method for this planar mode (6*8/4) *///      case VIDEO_PALETTE_YUV422P:  return 24; /* Planar */	case VIDEO_PALETTE_RGB32:		return 32;	case VIDEO_PALETTE_RAW_JPEG:		return 24;	/* raw jpeg. what should we return ?? */	case VIDEO_PALETTE_JPEG:		if (spca50x->cameratype == JPEG ||		    spca50x->cameratype == JPGH ||		    spca50x->cameratype == JPGC ||		    spca50x->cameratype == JPGS ||  		    spca50x->cameratype == JPGM ||  		    spca50x->cameratype == PJPG) {			return 8;		} else			return 0;	default:		return 0;	/* Invalid format */	}}/*********************************************************************** spca50x_isoc_irq* Function processes the finish of the USB transfer by calling * spca50x_move_data function to move data from USB buffer to internal* driver structures ***********************************************************************/#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)static voidspca50x_isoc_irq(struct urb *urb, struct pt_regs *regs)#elsestatic voidspca50x_isoc_irq(struct urb *urb)#endif{	int i;	struct usb_spca50x *spca50x = (struct usb_spca50x *) urb->context;	int len;	switch (urb->status) {	case 0:		break;	default:		PDEBUG(0, "Non-zero status (%d) in isoc "		       "completion handler.", urb->status);	case -ENOENT:		/* usb_kill_urb() called. */	case -ECONNRESET:	/* usb_unlink_urb() called. */	case -ESHUTDOWN:	/* The endpoint is being disabled. */		return;	}	if (!spca50x->dev) {		PDEBUG(4, "no device ");		return;	}	if (!spca50x->user) {		PDEBUG(4, "device not open");		return;	}	if (!spca50x->streaming) {/* Always get some of these after close but before packet engine stops */		PDEBUG(4, "hmmm... not streaming, but got interrupt");		return;	}	if (!spca50x->present) {/*  */		PDEBUG(4, "device disconnected ..., but got interrupt !!");		return;	}/* Copy the data received into our scratch buffer */	if (spca50x->curframe >= 0) {		len = spca50x_move_data(spca50x, urb);	} else if (waitqueue_active(&spca50x->wq)) {		wake_up_interruptible(&spca50x->wq);	}/* Move to the next sbuf */	urb->dev = spca50x->dev;	urb->status = 0;	if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0)		err("usb_submit_urb() ret %d", i);	return;}static voidspca50x_stop_isoc(struct usb_spca50x *spca50x){	if (!spca50x->streaming || !spca50x->dev)		return;	PDEBUG(3, "*** Stopping capture ***");	spca50x->funct.stopN(spca50x);	gspca_kill_transfert(spca50x);	gspca_set_alt0(spca50x);	spca50x->funct.stop0(spca50x);	PDEBUG(3, "*** Capture stopped ***");}/*********************************************************************** spca50x_smallest_mode_index* Function finds the mode index in the modes table of the smallest* available mode.***********************************************************************/static intspca5xx_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 intspca5xx_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;			}

⌨️ 快捷键说明

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