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

📄 mdc800.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
		mdc800_usb_download_notify,		mdc800	);	mdc800->state=READY;	up (&mdc800->io_lock);		usb_set_intfdata(intf, mdc800);	return 0;}/* * Disconnect USB device (maybe the MDC800) */static void mdc800_usb_disconnect (struct usb_interface *intf){	struct mdc800_data* mdc800 = usb_get_intfdata(intf);	dbg ("(mdc800_usb_disconnect) called");	if (mdc800) {		if (mdc800->state == NOT_CONNECTED)			return;		usb_deregister_dev(intf, &mdc800_class);		mdc800->state=NOT_CONNECTED;		usb_kill_urb(mdc800->irq_urb);		usb_kill_urb(mdc800->write_urb);		usb_kill_urb(mdc800->download_urb);		mdc800->dev = NULL;		usb_set_intfdata(intf, NULL);	}	info ("Mustek MDC800 disconnected from USB.");}/***************************************************************************	The Misc device Part (file_operations)****************************************************************************//* * This Function calc the Answersize for a command. */static int mdc800_getAnswerSize (char command){	switch ((unsigned char) command)	{		case 0x2a:		case 0x49:		case 0x51:		case 0x0d:		case 0x20:		case 0x07:		case 0x01:		case 0x25:		case 0x00:			return 8;		case 0x05:		case 0x3e:			return mdc800->pic_len;		case 0x09:			return 4096;		default:			return 0;	}}/* * Init the device: (1) alloc mem (2) Increase MOD Count .. */static int mdc800_device_open (struct inode* inode, struct file *file){	int retval=0;	int errn=0;	down (&mdc800->io_lock);		if (mdc800->state == NOT_CONNECTED)	{		errn=-EBUSY;		goto error_out;	}	if (mdc800->open)	{		errn=-EBUSY;		goto error_out;	}	mdc800->in_count=0;	mdc800->out_count=0;	mdc800->out_ptr=0;	mdc800->pic_index=0;	mdc800->pic_len=-1;	mdc800->download_left=0;	mdc800->camera_busy=0;	mdc800->camera_request_ready=0;	retval=0;	mdc800->irq_urb->dev = mdc800->dev;	if (usb_submit_urb (mdc800->irq_urb, GFP_KERNEL))	{		err ("request USB irq fails (submit_retval=%i urb_status=%i).",retval, mdc800->irq_urb->status);		errn = -EIO;		goto error_out;	}	mdc800->open=1;	dbg ("Mustek MDC800 device opened.");error_out:	up (&mdc800->io_lock);	return errn;}/* * Close the Camera and release Memory */static int mdc800_device_release (struct inode* inode, struct file *file){	int retval=0;	dbg ("Mustek MDC800 device closed.");	down (&mdc800->io_lock);	if (mdc800->open && (mdc800->state != NOT_CONNECTED))	{		usb_kill_urb(mdc800->irq_urb);		usb_kill_urb(mdc800->write_urb);		usb_kill_urb(mdc800->download_urb);		mdc800->open=0;	}	else	{		retval=-EIO;	}	up(&mdc800->io_lock);	return retval;}/* * The Device read callback Function */static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t len, loff_t *pos){	size_t left=len, sts=len; /* single transfer size */	char __user *ptr = buf;	down (&mdc800->io_lock);	if (mdc800->state == NOT_CONNECTED)	{		up (&mdc800->io_lock);		return -EBUSY;	}	if (mdc800->state == WORKING)	{		warn ("Illegal State \"working\" reached during read ?!");		up (&mdc800->io_lock);		return -EBUSY;	}	if (!mdc800->open)	{		up (&mdc800->io_lock);		return -EBUSY;	}	while (left)	{		if (signal_pending (current)) 		{			up (&mdc800->io_lock);			return -EINTR;		}		sts=left > (mdc800->out_count-mdc800->out_ptr)?mdc800->out_count-mdc800->out_ptr:left;		if (sts <= 0)		{			/* Too less Data in buffer */			if (mdc800->state == DOWNLOAD)			{				mdc800->out_count=0;				mdc800->out_ptr=0;				/* Download -> Request new bytes */				mdc800->download_urb->dev = mdc800->dev;				if (usb_submit_urb (mdc800->download_urb, GFP_KERNEL))				{					err ("Can't submit download urb (status=%i)",mdc800->download_urb->status);					up (&mdc800->io_lock);					return len-left;				}				wait_event_timeout(mdc800->download_wait, mdc800->downloaded,										TO_DOWNLOAD_GET_READY*HZ/1000);				mdc800->downloaded = 0;				if (mdc800->download_urb->status != 0)				{					err ("request download-bytes fails (status=%i)",mdc800->download_urb->status);					up (&mdc800->io_lock);					return len-left;				}			}			else			{				/* No more bytes -> that's an error*/				up (&mdc800->io_lock);				return -EIO;			}		}		else		{			/* Copy Bytes */			if (copy_to_user(ptr, &mdc800->out [mdc800->out_ptr],						sts)) {				up(&mdc800->io_lock);				return -EFAULT;			}			ptr+=sts;			left-=sts;			mdc800->out_ptr+=sts;		}	}	up (&mdc800->io_lock);	return len-left;}/* * The Device write callback Function * If a 8Byte Command is received, it will be send to the camera. * After this the driver initiates the request for the answer or * just waits until the camera becomes ready. */static ssize_t mdc800_device_write (struct file *file, const char __user *buf, size_t len, loff_t *pos){	size_t i=0;	down (&mdc800->io_lock);	if (mdc800->state != READY)	{		up (&mdc800->io_lock);		return -EBUSY;	}	if (!mdc800->open )	{		up (&mdc800->io_lock);		return -EBUSY;	}	while (i<len)	{		unsigned char c;		if (signal_pending (current)) 		{			up (&mdc800->io_lock);			return -EINTR;		}				if(get_user(c, buf+i))		{			up(&mdc800->io_lock);			return -EFAULT;		}		/* check for command start */		if (c == 0x55)		{			mdc800->in_count=0;			mdc800->out_count=0;			mdc800->out_ptr=0;			mdc800->download_left=0;		}		/* save command byte */		if (mdc800->in_count < 8)		{			mdc800->in[mdc800->in_count] = c;			mdc800->in_count++;		}		else		{			up (&mdc800->io_lock);			return -EIO;		}		/* Command Buffer full ? -> send it to camera */		if (mdc800->in_count == 8)		{			int answersize;			if (mdc800_usb_waitForIRQ (0,TO_GET_READY))			{				err ("Camera didn't get ready.\n");				up (&mdc800->io_lock);				return -EIO;			}			answersize=mdc800_getAnswerSize (mdc800->in[1]);			mdc800->state=WORKING;			memcpy (mdc800->write_urb->transfer_buffer, mdc800->in,8);			mdc800->write_urb->dev = mdc800->dev;			if (usb_submit_urb (mdc800->write_urb, GFP_KERNEL))			{				err ("submitting write urb fails (status=%i)", mdc800->write_urb->status);				up (&mdc800->io_lock);				return -EIO;			}			wait_event_timeout(mdc800->write_wait, mdc800->written, TO_WRITE_GET_READY*HZ/1000);			mdc800->written = 0;			if (mdc800->state == WORKING)			{				usb_kill_urb(mdc800->write_urb);				up (&mdc800->io_lock);				return -EIO;			}			switch ((unsigned char) mdc800->in[1])			{				case 0x05: /* Download Image */				case 0x3e: /* Take shot in Fine Mode (WCam Mode) */					if (mdc800->pic_len < 0)					{						err ("call 0x07 before 0x05,0x3e");						mdc800->state=READY;						up (&mdc800->io_lock);						return -EIO;					}					mdc800->pic_len=-1;				case 0x09: /* Download Thumbnail */					mdc800->download_left=answersize+64;					mdc800->state=DOWNLOAD;					mdc800_usb_waitForIRQ (0,TO_DOWNLOAD_GET_BUSY);					break;				default:					if (answersize)					{						if (mdc800_usb_waitForIRQ (1,TO_READ_FROM_IRQ))						{							err ("requesting answer from irq fails");							up (&mdc800->io_lock);							return -EIO;						}						/* Write dummy data, (this is ugly but part of the USB Protocol */						/* if you use endpoint 1 as bulk and not as irq) */						memcpy (mdc800->out, mdc800->camera_response,8);						/* This is the interpreted answer */						memcpy (&mdc800->out[8], mdc800->camera_response,8);						mdc800->out_ptr=0;						mdc800->out_count=16;						/* Cache the Imagesize, if command was getImageSize */						if (mdc800->in [1] == (char) 0x07)						{							mdc800->pic_len=(int) 65536*(unsigned char) mdc800->camera_response[0]+256*(unsigned char) mdc800->camera_response[1]+(unsigned char) mdc800->camera_response[2];							dbg ("cached imagesize = %i",mdc800->pic_len);						}					}					else					{						if (mdc800_usb_waitForIRQ (0,TO_DEFAULT_COMMAND))						{							err ("Command Timeout.");							up (&mdc800->io_lock);							return -EIO;						}					}					mdc800->state=READY;					break;			}		}		i++;	}	up (&mdc800->io_lock);	return i;}/***************************************************************************	Init and Cleanup this driver (Structs and types)****************************************************************************//* File Operations of this drivers */static struct file_operations mdc800_device_ops ={	.owner =	THIS_MODULE,	.read =		mdc800_device_read,	.write =	mdc800_device_write,	.open =		mdc800_device_open,	.release =	mdc800_device_release,};static struct usb_device_id mdc800_table [] = {	{ USB_DEVICE(MDC800_VENDOR_ID, MDC800_PRODUCT_ID) },	{ }						/* Terminating entry */};MODULE_DEVICE_TABLE (usb, mdc800_table);/* * USB Driver Struct for this device */static struct usb_driver mdc800_usb_driver ={	.owner =	THIS_MODULE,	.name =		"mdc800",	.probe =	mdc800_usb_probe,	.disconnect =	mdc800_usb_disconnect,	.id_table =	mdc800_table};/************************************************************************	Init and Cleanup this driver (Main Functions)*************************************************************************/static int __init usb_mdc800_init (void){	int retval = -ENODEV;	/* Allocate Memory */	mdc800=kmalloc (sizeof (struct mdc800_data), GFP_KERNEL);	if (!mdc800)		goto cleanup_on_fail;	memset(mdc800, 0, sizeof(struct mdc800_data));	mdc800->dev = NULL;	mdc800->open=0;	mdc800->state=NOT_CONNECTED;	init_MUTEX (&mdc800->io_lock);	init_waitqueue_head (&mdc800->irq_wait);	init_waitqueue_head (&mdc800->write_wait);	init_waitqueue_head (&mdc800->download_wait);	mdc800->irq_woken = 0;	mdc800->downloaded = 0;	mdc800->written = 0;	mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL);	if (!mdc800->irq_urb_buffer)		goto cleanup_on_fail;	mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL);	if (!mdc800->write_urb_buffer)		goto cleanup_on_fail;	mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL);	if (!mdc800->download_urb_buffer)		goto cleanup_on_fail;	mdc800->irq_urb=usb_alloc_urb (0, GFP_KERNEL);	if (!mdc800->irq_urb)		goto cleanup_on_fail;	mdc800->download_urb=usb_alloc_urb (0, GFP_KERNEL);	if (!mdc800->download_urb)		goto cleanup_on_fail;	mdc800->write_urb=usb_alloc_urb (0, GFP_KERNEL);	if (!mdc800->write_urb)		goto cleanup_on_fail;	/* Register the driver */	retval = usb_register(&mdc800_usb_driver);	if (retval)		goto cleanup_on_fail;	info (DRIVER_VERSION ":" DRIVER_DESC);	return 0;	/* Clean driver up, when something fails */cleanup_on_fail:	if (mdc800 != NULL)	{		err ("can't alloc memory!");		kfree(mdc800->download_urb_buffer);		kfree(mdc800->write_urb_buffer);		kfree(mdc800->irq_urb_buffer);		usb_free_urb(mdc800->write_urb);		usb_free_urb(mdc800->download_urb);		usb_free_urb(mdc800->irq_urb);		kfree (mdc800);	}	mdc800 = NULL;	return retval;}static void __exit usb_mdc800_cleanup (void){	usb_deregister (&mdc800_usb_driver);	usb_free_urb (mdc800->irq_urb);	usb_free_urb (mdc800->download_urb);	usb_free_urb (mdc800->write_urb);	kfree (mdc800->irq_urb_buffer);	kfree (mdc800->write_urb_buffer);	kfree (mdc800->download_urb_buffer);	kfree (mdc800);	mdc800 = NULL;}module_init (usb_mdc800_init);module_exit (usb_mdc800_cleanup);MODULE_AUTHOR( DRIVER_AUTHOR );MODULE_DESCRIPTION( DRIVER_DESC );MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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