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

📄 cpia_pp.c

📁 cpia usb摄像头的驱动程序源码。需要video4linux和i2c-core支持
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* We don't want to be interrupted every character. */	parport_pc_disable_irq (port);	/* set nErrIntrEn and serviceIntr */	frob_econtrol (port, (1<<4) | (1<<2), (1<<4) | (1<<2));		/* Reverse mode. */	parport_pc_data_reverse (port); /* Must be in PS2 mode */	while (left) {		int i;		char *ptr;#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))		long expire = jiffies + port->physport->cad->timeout;#else		unsigned long expire = jiffies + port->physport->cad->timeout;#endif			DBG ("start of while %i left\n", left);			        count = left;				if (count > maxlen)			count = maxlen;				dmaflag = claim_dma_lock();		disable_dma(port->dma);		clear_dma_ff(port->dma);		set_dma_mode(port->dma, DMA_MODE_READ);		set_dma_addr(port->dma, dma_addr);		set_dma_count(port->dma, count);				/* Set DMA mode */		frob_econtrol (port, 1<<3, 1<<3);				/* Clear serviceIntr */		frob_econtrol (port, 1<<2, 0);				enable_dma(port->dma);		release_dma_lock(dmaflag);				/* Wait for interrupt. */		DBG ("about to wait\n");	false_alarm:		if (0 > parport_wait_event (port, HZ))			break;		if (!time_before (jiffies, expire)) {			/* Timed out. */			DBG("DMA read timed out\n");			break;		}		/* Is serviceIntr set? */		if (!(inb (ECONTROL (port)) & (1<<2))) {#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))			if (current->need_resched)				schedule ();#else			cond_resched();#endif						goto false_alarm;		}				dmaflag = claim_dma_lock();		disable_dma(port->dma);		clear_dma_ff(port->dma);		count -= get_dma_residue(port->dma);		release_dma_lock(dmaflag);#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))				if (current->need_resched)			/* Can't yield the port. */			schedule ();#else		cond_resched(); /* Can't yield the port. */#endif				/* update for possible DMA residue ! */		DBG ("read %i in loop\n", count);				if (dma_handle) 			dma_addr += count;		else 			memcpy(buf, priv->dma_buf, count);		buf  += count;		left -= count;		/* (cpia specific): test the last 4 bytes of data for EOI */		endseen = 1;		ptr = buf;		for (i = 0; i < 4; i++) {			ptr--;			if(((unsigned char) *ptr ) != EOI) {				endseen = 0;				break;			}		}		if(endseen) 			break;	}		/* Maybe got here through break, so adjust for DMA residue! */        if (left && !endseen) {		DBG("exited on break\n");		dmaflag = claim_dma_lock();		disable_dma(port->dma);		clear_dma_ff(port->dma);		count -= get_dma_residue(port->dma);		release_dma_lock(dmaflag);				if (!dma_handle)			memcpy(buf, priv->dma_buf, count);		left -= count;	}		frob_econtrol (port, 1<<2, 1<<2);	/* Turn off DMA mode */	frob_econtrol (port, 1<<3, 0);		if (dma_handle)		pci_unmap_single(priv->dev, dma_handle, length, PCI_DMA_TODEVICE);	 out_no_data:		if (change_mode (port, ECR_PS2)) /* ECP FIFO */ 		printk (KERN_DEBUG "%s: Warning change_mode ECR_PS2 failed\n", 			port->name);		/* Go to forward idle mode to shut the peripheral up (event 47). */	parport_frob_control (port, PARPORT_CONTROL_INIT | PARPORT_CONTROL_AUTOFD, 			      PARPORT_CONTROL_INIT | PARPORT_CONTROL_AUTOFD);		/* event 49: PError goes high */	if( (r = parport_wait_peripheral (port,					  PARPORT_STATUS_PAPEROUT,					  PARPORT_STATUS_PAPEROUT)) ) {		printk (KERN_DEBUG			"%s: PE timeout FWDIDLE (%d) in ecp_read_block_dma\n",			port->name, r);	} else {		parport_data_forward (port);        		port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;	}	DBG ("returning %i bytes read, endseen = %d\n", length - left, endseen);	return length - left;}#endif /*CPIA_PARPORT_DMA */static ssize_t cpia_parport_read (struct parport *port, void *buffer, size_t len, int stream){        int mode = port->physport->ieee1284.mode;        size_t (*fn) (struct parport *, void *, size_t, int);        /* Ignore the device-ID-request bit and the address bit. */        mode &= ~(IEEE1284_DEVICEID | IEEE1284_ADDR);        switch (mode) {        case IEEE1284_MODE_NIBBLE:                if(stream){			DBG("%s: Using cpia nibble stream mode\n", port->name);			fn = cpia_read_nibble_stream;		} else {			DBG("%s: Using cpia nibble mode\n", port->name);			fn = cpia_read_nibble;		}		return (*fn) (port, buffer, len, 0);		break;        case IEEE1284_MODE_ECP:#ifdef CPIA_PARPORT_DMA		if (stream && port->dma != PARPORT_DMA_NONE){			fn = cpia_ecp_read_block_dma;			return (*fn) (port, buffer, len, 0);			break;		}#endif	default:		return parport_read(port, buffer, len);		break;	}}/**************************************************************************** * *  EndTransferMode * ***************************************************************************/static void EndTransferMode(struct pp_cam_entry *cam){	parport_negotiate(cam->port, IEEE1284_MODE_COMPAT);}/**************************************************************************** * *  ForwardSetup * ***************************************************************************/static int ForwardSetup(struct pp_cam_entry *cam){	int retry;		/* The CPiA uses ECP protocol for Downloads from the Host to the camera. 	 * This will be software-emulated if ECP hardware is not present	 */	/* the usual camera maximum response time is 10ms, but after receiving	 * some commands, it needs up to 40ms. (Data Sheet p. 32)*/	for(retry = 0; retry < 4; ++retry) {		if(!parport_negotiate(cam->port, IEEE1284_MODE_ECP)) {			break;		}		mdelay(10);	}	if(retry == 4) {		DBG("Unable to negotiate IEEE1284 ECP Download mode\n");		return -1;	}	return 0;}/**************************************************************************** * *  ReverseSetup * ***************************************************************************/static int ReverseSetup(struct pp_cam_entry *cam, int extensibility){	int retry, mode;	int transfer_mode = NIBBLE_TRANSFER;	/* The CPiA uses either ECP protocol or non-standard variants of	 * Nibble protocol for Uploads from the camera to the Host. 	 * ECP protocol will be software-emulated if ECP hardware is not present.	 * Private CPiA-specific susbstitutes for port->ops->nibble_read_data()	 * are provided here.	 */	switch (cam->upload_mode) {	case IEEE1284_MODE_ECPSWE:	case IEEE1284_MODE_ECP:		transfer_mode = ECP_TRANSFER;	case IEEE1284_MODE_NIBBLE:   /* for non-ECP non-TRISTATE ports */		if(!extensibility)			mode = cam->upload_mode; 		else 			mode = UPLOAD_FLAG|transfer_mode|IEEE1284_EXT_LINK;				/* the usual camera maximum response time is 10ms, but after 		 * receiving some commands, it needs up to 40ms. */				for(retry = 0; retry < 4; ++retry) {			if(!parport_negotiate(cam->port, mode)) {				break;			}			mdelay(10);		}		if(retry == 4) {			if(extensibility)				DBG("Unable to negotiate IEEE1284 extensibility mode\n");			else				DBG("Unable to negotiate IEEE1284 Upload mode\n");			return -1;		}		if(extensibility) 			cam->port->ieee1284.mode = cam->upload_mode;		return 0;		break;	default:		return -1;		break;	}}/**************************************************************************** * *  WritePacket * ***************************************************************************/static int WritePacket(struct pp_cam_entry *cam, const u8 *packet, size_t size){	int retval=0;	int size_written;	if (packet == NULL) {		return -EINVAL;	}	if (ForwardSetup(cam)) {		DBG("Write failed in setup\n");		return -EIO;	}	size_written = parport_write(cam->port, packet, size);	if(size_written != size) {		DBG("Write failed, wrote %d/%d\n", size_written, size);		retval = -EIO;	}	EndTransferMode(cam);	return retval;}/**************************************************************************** * *  ReadPacket * ***************************************************************************/static int ReadPacket(struct pp_cam_entry *cam, u8 *packet, size_t size){	int retval = 0, size_read;	if (packet == NULL) {		return -EINVAL;	}	if (ReverseSetup(cam, 0)) {		DBG("Read failed in setup\n");		return -EIO;	}	if((size_read = cpia_parport_read(cam->port, packet, size, 0)) != size) {		DBG("Read failed, read %d/%d\n", size_read, size);		retval = -EIO;	}	EndTransferMode(cam);	return retval;}/**************************************************************************** * *  cpia_pp_streamStart * ***************************************************************************/static int cpia_pp_streamStart(void *privdata){	struct pp_cam_entry *cam = privdata;	DBG("\n");	cam->streaming=1;	cam->image_ready=0;        //if (ReverseSetup(cam,1)) return -EIO; 	if(cam->stream_irq)		cpia_parport_enable_irq(cam->port);	return 0;	}/**************************************************************************** * *  cpia_pp_streamStop * ***************************************************************************/static int cpia_pp_streamStop(void *privdata){	struct pp_cam_entry *cam = privdata;	DBG("\n");	cam->streaming=0;	cpia_parport_disable_irq(cam->port);	//EndTransferMode(cam);	return 0;}/**************************************************************************** * *  cpia_pp_streamRead * ***************************************************************************/static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock){	struct pp_cam_entry *cam = privdata;	int read_bytes = 0,  endseen = 0, chunks = 0;	size_t chunksize = CPIA_UPLOAD_CHUNKSIZE;	u8 *buf = buffer, *buf_end = buffer + CPIA_MAX_IMAGE_SIZE;	if(cam == NULL) {		DBG("Internal driver error: cam is NULL\n");		return -EINVAL;	}	if(buffer == NULL) {		DBG("Internal driver error: buffer is NULL\n");		return -EINVAL;	}	//if(cam->streaming) DBG("%d / %d\n", cam->image_ready, noblock);	if( cam->stream_irq ) {		DBG("%d\n", cam->image_ready);		cam->image_ready--;	}	cam->image_complete=0;	if (0/*cam->streaming*/) {		if(!cam->image_ready) {			if(noblock) return -EWOULDBLOCK;			interruptible_sleep_on(&cam->wq_stream);			if( signal_pending(current) ) return -EINTR;			DBG("%d\n", cam->image_ready);		}	} else {		if (ReverseSetup(cam, 1)) {			DBG("unable to ReverseSetup\n");			return -EIO;		}	}	if (cam->upload_mode == IEEE1284_MODE_ECP) {		chunksize = CPIA_FIFO_UPLOAD_CHUNKSIZE;#ifdef CPIA_PARPORT_DMA		if(cam->port->dma != PARPORT_DMA_NONE) 			chunksize = CPIA_MAX_IMAGE_SIZE;#endif	}	     	/*  If we are using "Nibble Stream" or Software-Emulated ECP 	 *  protocols to upload data byte-by-byte through the parport.	 *  we must read the image in small chunks and call schedule	 *  to avoid eating up all the cpu resources.	 */	while (read_bytes < CPIA_MAX_IMAGE_SIZE && endseen < 4) {		size_t datasize, bufsize;		int i;		u8 *pos;		/* be nice to other processes ! */#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))				if (current->need_resched)			schedule();#else		cond_resched(); #endif				bufsize = chunksize;		if(bufsize > (size_t)(buf_end - buf)) 			bufsize = (size_t)(buf_end - buf);		datasize = cpia_parport_read(cam->port, buf, bufsize,1); 		chunks++;		buf += datasize;		read_bytes += (int) datasize;		/* test the last 4 bytes of data for EOI */		if (read_bytes >= 4) {			endseen = 1;			pos = buf;			for (i = 0; i < 4; i++) {				pos--;				if( *pos != EOI) {					endseen = 0;					break;				}			}		}		if (endseen) {			cam->image_complete = 1 ;			break;		}	}	EndTransferMode(cam);	DBG("read %d bytes in %d chunks of size <= %d, endseen = %d\n", 	    read_bytes, chunks, chunksize, endseen);		if( endseen ) 		DBG("EOI at  %d bytes \n", read_bytes);	else		DBG("EOI not seen, read  %d bytes\n", read_bytes);	return cam->image_complete ? read_bytes : -EIO;	}/**************************************************************************** * *  cpia_pp_transferCmd * ***************************************************************************/static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data){	int err;	int retval=0;	int databytes;	struct pp_cam_entry *cam = privdata;	if(cam == NULL) {		DBG("Internal driver error: cam is NULL\n");		return -EINVAL;	}	if(command == NULL) {		DBG("Internal driver error: command is NULL\n");		return -EINVAL;	}	databytes = (((int)command[7])<<8) | command[6];

⌨️ 快捷键说明

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