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

📄 cpia_pp.c

📁 cpia usb摄像头的驱动程序源码。需要video4linux和i2c-core支持
💻 C
📖 第 1 页 / 共 3 页
字号:
	if ((err = WritePacket(cam, command, PACKET_LENGTH)) < 0) {		DBG("Error writing command\n");		return err;	}	if(command[0] == DATA_IN) {		u8 buffer[8];		if(data == NULL) {			DBG("Internal driver error: data is NULL\n");			return -EINVAL;		}		if((err = ReadPacket(cam, buffer, 8)) < 0) {			DBG("Error reading command result\n");			return err;		}		memcpy(data, buffer, databytes);	} else if(command[0] == DATA_OUT) {		if(databytes > 0) {			if(data == NULL) {				DBG("Internal driver error: data is NULL\n");				retval = -EINVAL;			} else {				if((err=WritePacket(cam, data, databytes)) < 0){					DBG("Error writing command data\n");					return err;				}			}		}	} else {		DBG("Unexpected first byte of command: %x\n", command[0]);		retval = -EINVAL;	}	return retval;}/**************************************************************************** * *  cpia_pp_upload_mode * ***************************************************************************/static int cpia_pp_upload_mode(void *privdata ){	struct pp_cam_entry *cam = (struct pp_cam_entry *)privdata;	switch (cam->upload_mode) {	case IEEE1284_MODE_ECP:		return 3;		break;	case IEEE1284_MODE_ECPSWE:		return 2;		break;	case IEEE1284_MODE_NIBBLE:		return 1;		break;	}	return 0;}/**************************************************************************** * *  cpia_pp_open * ***************************************************************************/static int cpia_pp_open(void *privdata , int alt ){	struct pp_cam_entry *cam = (struct pp_cam_entry *)privdata;		/* alt has no meaning for parport cameras */	if (cam == NULL)		return -EINVAL;		if(cam->open_count == 0) {		if (parport_claim(cam->pdev)) {			LOG("cpia_pp: failed to claim parport%d\n",			    cam->port->portnum);			return -EBUSY;		}		DBG("cpia_pp: claim parport%d\n",cam->port->portnum);		parport_negotiate(cam->port, IEEE1284_MODE_COMPAT);		parport_data_forward(cam->port);		parport_write_control(cam->port, PARPORT_CONTROL_SELECT);		udelay(50);		parport_write_control(cam->port,		                      PARPORT_CONTROL_SELECT		                      | PARPORT_CONTROL_INIT);	} else		return -EBUSY;		++cam->open_count;		return 0;}/**************************************************************************** * *  cpia_pp_registerCallback * ***************************************************************************/static int cpia_pp_registerCallback(void *privdata, void (*cb)(void *cbdata), void *cbdata){	struct pp_cam_entry *cam = privdata;	int retval = 0;		if(cam->port->irq != PARPORT_IRQ_NONE) {#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))				cam->cb_task.routine = cb;		cam->cb_task.data = cbdata;#else		INIT_WORK(&cam->cb_task, cb, cbdata);#endif	} else {		retval = -1;	}	return retval;}/**************************************************************************** * *  cpia_pp_close * ***************************************************************************/static int cpia_pp_close(void *privdata){	struct pp_cam_entry *cam = privdata;	if (--cam->open_count == 0) {		/* delay to allow parport status lines to reset: 		 * seems to fix problems when lp is also registered on port(?)*/		if(cam->port->ops->read_status(cam->port) != 80)				mdelay(40);		DBG("cpia_pp: releasing parport%d\n",cam->port->portnum,status);		parport_release(cam->pdev);	}	return 0;}/**************************************************************************** * *  cpia_pp_register * ***************************************************************************/static int cpia_pp_register(struct parport *port){	struct pardevice *pdev = NULL;	struct pp_cam_entry *cam;	struct cam_data *cpia;	if (!(port->modes & PARPORT_MODE_PCSPP)) {		printk ("Unsupported (non-IEEE1284) Parallel Port.\n");		return -ENODEV;	}	cam = kmalloc(sizeof(struct pp_cam_entry), GFP_KERNEL);	if (cam == NULL) {		LOG("failed to allocate camera structure\n");		return -ENOMEM;	}	memset(cam,0,sizeof(struct pp_cam_entry));		pdev = parport_register_device(port, "cpia_pp", NULL, NULL,	                               NULL, 0, cam);	if (!pdev) {		LOG("failed to parport_register_device\n");		kfree(cam);		return -ENXIO;	}		cam->pdev = pdev;	cam->port = port;	init_waitqueue_head(&cam->wq_stream);	cam->streaming = 0;	cam->stream_irq = 0;	cam->upload_mode = IEEE1284_MODE_NIBBLE;	if (port->modes & PARPORT_MODE_TRISTATE)		cam->upload_mode = IEEE1284_MODE_ECPSWE;	if (port->modes & PARPORT_MODE_ECP) 		cam->upload_mode = IEEE1284_MODE_ECP;	if((cpia = cpia_register_camera(&cpia_pp_ops, cam)) == NULL) {		LOG("failed to cpia_register_camera\n");		parport_unregister_device(pdev);		kfree(cam);		return -ENXIO;	}	/* (for testing:) 	 * if cam->upload_mode = IEEE1284_MODE_ECPSWE or IEEE1284_NIBBLE	 * is set here, even if "better" modes are detected, this mode will	 * be used for uploads from the camera.  	 */	//cam->upload_mode = IEEE1284_MODE_NIBBLE;	//cam->upload_mode = IEEE1284_MODE_ECPSWE;	switch(cam->upload_mode) {	case IEEE1284_MODE_ECP:		if(port->modes & PARPORT_MODE_DMA) {#ifdef CPIA_PARPORT_DMA			printk("ECP Parallel Port with DMA detected: "#else			printk("ECP Parallel Port (DMA not enabled in cpia_pp): "#endif		       "image stream should be fast\n");		} else {			printk("ECP Parallel Port without DMA detected: "		       "image stream should be fast\n");		}		break;	case IEEE1284_MODE_ECPSWE: 		printk("Bidirectional Parallel Port will emulate ECP mode: "		       "image stream may be slow\n");		break;	case IEEE1284_MODE_NIBBLE: 	default:       		printk("Non-bidirectional Parallel Port will use"		       " \"nibble\" mode: image stream will be slow\n");	}	spin_lock( &cam_list_lock_pp );	list_add( &cpia->cam_data_list, &cam_list );	spin_unlock( &cam_list_lock_pp );	return 0;}static void cpia_pp_detach (struct parport *port){	struct list_head *tmp;	struct cam_data *cpia = NULL;	struct pp_cam_entry *cam;	spin_lock( &cam_list_lock_pp );	list_for_each (tmp, &cam_list) {		cpia = list_entry(tmp, struct cam_data, cam_data_list);		cam = (struct pp_cam_entry *) cpia->lowlevel_data;		if (cam && cam->port->number == port->number) {			list_del(&cpia->cam_data_list);			break;		}		cpia = NULL;	}	spin_unlock( &cam_list_lock_pp );				if (!cpia) {		DBG("cpia_pp_detach failed to find cam_data in cam_list\n");		return;	}		cam = (struct pp_cam_entry *) cpia->lowlevel_data;		cpia_unregister_camera(cpia);	if(cam->open_count > 0) 		cpia_pp_close(cam);	parport_unregister_device(cam->pdev);	cpia->lowlevel_data = NULL;		kfree(cam);}static void cpia_pp_attach (struct parport *port){	unsigned int i;	switch (parport_nr[0])	{	case PPCPIA_PARPORT_UNSPEC:	case PPCPIA_PARPORT_AUTO:		if (port->probe_info[0].class != PARPORT_CLASS_MEDIA ||		    port->probe_info[0].cmdset == NULL ||		    strncmp(port->probe_info[0].cmdset, "CPIA_1", 6) != 0)			return;		cpia_pp_register(port);		break;	default:		for (i = 0; i < PARPORT_MAX; ++i) {			if (port->number == parport_nr[i]) {				cpia_pp_register(port);				break;			}		}		break;	}}static struct parport_driver cpia_pp_driver = {	"cpia_pp",	cpia_pp_attach,	cpia_pp_detach,	NULL};int cpia_pp_init(void){	printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT, 	       CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER);	if(parport_nr[0] == PPCPIA_PARPORT_OFF) {		printk("  disabled\n");		return 0;	}		spin_lock_init( &cam_list_lock_pp );	if (parport_register_driver (&cpia_pp_driver)) {		LOG ("unable to register with parport\n");		return -EIO;	}	return 0;}#ifdef MODULEint init_module(void){	if (parport[0]) {		/* The user gave some parameters.  Let's see what they were. */		if (!strncmp(parport[0], "auto", 4)) {			parport_nr[0] = PPCPIA_PARPORT_AUTO;		} else {			int n;			for (n = 0; n < PARPORT_MAX && parport[n]; n++) {				if (!strncmp(parport[n], "none", 4)) {					parport_nr[n] = PPCPIA_PARPORT_NONE;				} else {					char *ep;					unsigned long r = simple_strtoul(parport[n], &ep, 0);					if (ep != parport[n]) {						parport_nr[n] = r;					} else {						LOG("bad port specifier `%s'\n", parport[n]);						return -ENODEV;					}				}			}		}	}#if defined(CONFIG_KMOD) && defined(CONFIG_PNP_PARPORT_MODULE)	if(parport_enumerate() && !parport_enumerate()->probe_info.model) {		request_module("parport_probe");	}#endif	return cpia_pp_init();}void cleanup_module(void){	parport_unregister_driver (&cpia_pp_driver);	return;}#else /* !MODULE */static int __init cpia_pp_setup(char *str){	if (!strncmp(str, "parport", 7)) {		int n = simple_strtoul(str + 7, NULL, 10);		if (parport_ptr < PARPORT_MAX) {			parport_nr[parport_ptr++] = n;		} else {			LOG("too many ports, %s ignored.\n", str);		}	} else if (!strcmp(str, "auto")) {		parport_nr[0] = PPCPIA_PARPORT_AUTO;	} else if (!strcmp(str, "none")) {		parport_nr[parport_ptr++] = PPCPIA_PARPORT_NONE;	}	return 0;}__setup("cpia_pp=", cpia_pp_setup);#endif /* !MODULE */#ifdef CPIA_PARPORT_DMA/*-----------------------------------------------------------------------*//* stuff below is static stuff  * copied from parport_pc.c (should be made public) */#define DPRINTK(fmt,args...) do {} while(0)/* ECR modes */#define ECR_SPP 00#define ECR_PS2 01#define ECR_PPF 02#define ECR_ECP 03#define ECR_EPP 04#define ECR_VND 05#define ECR_TST 06#define ECR_CNF 07#define ECR_MODE_MASK 0xe0#define ECR_WRITE(p,v) frob_econtrol((p),0xff,(v))#define ECONTROL(p) ((p)->base_hi + 0x2)/* frob_control, but for ECR */static void frob_econtrol (struct parport *pb, unsigned char m,			   unsigned char v){	unsigned char ectr = 0;	if (m != 0xff)		ectr = inb (ECONTROL (pb));	DPRINTK (KERN_DEBUG "frob_econtrol(%02x,%02x): %02x -> %02x\n",		m, v, ectr, (ectr & ~m) ^ v);	outb ((ectr & ~m) ^ v, ECONTROL (pb));}/* Safely change the mode bits in the ECR    Returns:	    0    : Success	   -EBUSY: Could not drain FIFO in some finite amount of time,		   mode not changed! */static int change_mode(struct parport *p, int m){	const struct parport_pc_private *priv = p->physport->private_data;	unsigned char oecr;	int mode;	DPRINTK(KERN_INFO "parport change_mode ECP-ISA to mode 0x%02x\n",m);	if (!priv->ecr) {		printk (KERN_DEBUG "change_mode: but there's no ECR!\n");		return 0;	}	/* Bits <7:5> contain the mode. */	oecr = inb (ECONTROL (p));	mode = (oecr >> 5) & 0x7;	if (mode == m) return 0;	if (mode >= 2 && !(priv->ctr & 0x20)) {		/* This mode resets the FIFO, so we may		 * have to wait for it to drain first. */#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))		long expire = jiffies + p->physport->cad->timeout;#else		unsigned long expire = jiffies + p->physport->cad->timeout;#endif		int counter;		switch (mode) {		case ECR_PPF: /* Parallel Port FIFO mode */		case ECR_ECP: /* ECP Parallel Port mode */			/* Busy wait for 200us */			for (counter = 0; counter < 40; counter++) {				if (inb (ECONTROL (p)) & 0x01)					break;				if (signal_pending (current)) break;				udelay (5);			}			/* Poll slowly. */			while (!(inb (ECONTROL (p)) & 0x01)) {				if (time_after_eq (jiffies, expire))					/* The FIFO is stuck. */					return -EBUSY;				__set_current_state (TASK_INTERRUPTIBLE);				schedule_timeout ((HZ + 99) / 100);				if (signal_pending (current))					break;			}		}	}	if (mode >= 2 && m >= 2) {		/* We have to go through mode 001 */		oecr &= ~(7 << 5);		oecr |= ECR_PS2 << 5;		ECR_WRITE (p, oecr);	}	/* Set the mode. */	oecr &= ~(7 << 5);	oecr |= m << 5;	ECR_WRITE (p, oecr);	return 0;}#endif /* CPIA_PARPORT_DMA */

⌨️ 快捷键说明

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