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

📄 vivi_usb_drv.c

📁 可以写s3c2410 USB device的PC端USB驱动和程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- linux-c -*- *//*  * Driver for USB of VIVI (linux-2.4.20-8) * * Copyright (C) 2006, thisway.diy@163.com * *  * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Originally based upon scanner.c (David E. Nelson) * * History * *  0.1  05/13/2006 * *    change from usb driver scanner.c, to support s3c2410's bootloader vivi * */#include "vivi_usb_drv.h"static intopen_vivi_s3c2410(struct inode * inode, struct file * file){	struct vivi_usb_data *vivi;	struct usb_device *dev;	kdev_t vivi_minor;	int err=0;	MOD_INC_USE_COUNT;	down(&vivi_mutex);	vivi_minor = USB_VIVI_MINOR(inode);	dbg("open_vivi_s3c2410: vivi_minor:%d", vivi_minor);	if (!p_vivi_table[vivi_minor]) {		up(&vivi_mutex);		MOD_DEC_USE_COUNT;		err("open_vivi_s3c2410(%d): Unable to access minor data", vivi_minor);		return -ENODEV;	}	vivi = p_vivi_table[vivi_minor];	dev = vivi->vivi_dev;	down(&(vivi->sem));	/* Now protect the vivi_usb_data structure */ 	up(&vivi_mutex); /* Now handled by the above */	if (!dev) {		err("open_vivi_s3c2410(%d): Scanner device not present", vivi_minor);		err = -ENODEV;		goto out_error;	}	if (!vivi->present) {		err("open_vivi_s3c2410(%d): Scanner is not present", vivi_minor);		err = -ENODEV;		goto out_error;	}	if (vivi->isopen) {		err("open_vivi_s3c2410(%d): Scanner device is already open", vivi_minor);		err = -EBUSY;		goto out_error;	}	init_waitqueue_head(&vivi->rd_wait_q);	vivi->isopen = 1;	file->private_data = vivi; /* Used by the read and write methods */out_error:	up(&(vivi->sem)); /* Wake up any possible contending processes */	if (err)		MOD_DEC_USE_COUNT;	return err;}static intclose_vivi_s3c2410(struct inode * inode, struct file * file){	struct vivi_usb_data *vivi;	kdev_t vivi_minor;	vivi_minor = USB_VIVI_MINOR (inode);	dbg("close_vivi_s3c2410: vivi_minor:%d", vivi_minor);	if (!p_vivi_table[vivi_minor]) {		err("close_vivi_s3c2410(%d): invalid vivi_minor", vivi_minor);		return -ENODEV;	}	down(&vivi_mutex);	vivi = p_vivi_table[vivi_minor];	down(&(vivi->sem));	vivi->isopen = 0;	file->private_data = NULL;	up(&vivi_mutex);	up(&(vivi->sem));	MOD_DEC_USE_COUNT;	return 0;}static ssize_twrite_vivi_s3c2410(struct file * file, const char * buffer,              size_t count, loff_t *ppos){	struct vivi_usb_data *vivi;	struct usb_device *dev;	ssize_t bytes_written = 0; /* Overall count of bytes written */	ssize_t ret = 0;	kdev_t vivi_minor;	int this_write;		/* Number of bytes to write */	int partial;		/* Number of bytes successfully written */	int result = 0;	char *obuf;	vivi = file->private_data;	down(&(vivi->sem));	vivi_minor = vivi->vivi_minor;	obuf = vivi->obuf;	dev = vivi->vivi_dev;	file->f_dentry->d_inode->i_atime = CURRENT_TIME;	while (count > 0) {		if (signal_pending(current)) {			ret = -ERESTARTSYS;			break;		}		this_write = (count >= OBUF_SIZE) ? OBUF_SIZE : count;		if (copy_from_user(vivi->obuf, buffer, this_write)) {			ret = -EFAULT;			break;		}		result = usb_bulk_msg(dev,usb_sndbulkpipe(dev, vivi->bulk_out_ep), obuf, this_write, &partial, 60*HZ);		dbg("write stats(%d): result:%d this_write:%d partial:%d", vivi_minor, result, this_write, partial);		if (result == -ETIMEDOUT) {	/* NAK -- shouldn't happen */			warn("write_vivi_s3c2410: NAK received.");			ret = result;			break;		} else if (result < 0) { /* We should not get any I/O errors */			warn("write_vivi_s3c2410(%d): funky result: %d. Consult Documentataion/usb/vivi_s3c2410.txt.", vivi_minor, result);			ret = -EIO;			break;		}#ifdef WR_DATA_DUMP		if (partial) {			unsigned char cnt, cnt_max;			cnt_max = (partial > 24) ? 24 : partial;			printk(KERN_DEBUG "dump(%d): ", vivi_minor);			for (cnt=0; cnt < cnt_max; cnt++) {				printk("%X ", obuf[cnt]);			}			printk("\n");		}#endif		if (partial != this_write) { /* Unable to write all contents of obuf */			ret = -EIO;			break;		}		if (partial) { /* Data written */			buffer += partial;			count -= partial;			bytes_written += partial;		} else { /* No data written */			ret = 0;			break;		}	}	up(&(vivi->sem));	mdelay(5);		/* This seems to help with SANE queries */	return ret ? ret : bytes_written;}static ssize_tread_vivi_s3c2410(struct file * file, char * buffer,             size_t count, loff_t *ppos){	struct vivi_usb_data *vivi;	struct usb_device *dev;	ssize_t bytes_read;	/* Overall count of bytes_read */	ssize_t ret;	kdev_t vivi_minor;	int partial;		/* Number of bytes successfully read */	int this_read;		/* Max number of bytes to read */	int result;	int rd_expire = RD_EXPIRE;	char *ibuf;	vivi = file->private_data;	down(&(vivi->sem));	vivi_minor = vivi->vivi_minor;	ibuf = vivi->ibuf;	dev = vivi->vivi_dev;	bytes_read = 0;	ret = 0;	file->f_dentry->d_inode->i_atime = CURRENT_TIME; /* Update the                                                            atime of                                                            the device                                                            node */	while (count > 0) {		if (signal_pending(current)) {			ret = -ERESTARTSYS;			break;		}		this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;		result = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, vivi->bulk_in_ep), ibuf, this_read, &partial, vivi->rd_nak_timeout);		dbg("read stats(%d): result:%d this_read:%d partial:%d count:%d", vivi_minor, result, this_read, partial, count);/* * Scanners are sometimes inheriently slow since they are mechanical * in nature.  USB bulk reads tend to timeout while the vivi_s3c2410 is * positioning, resetting, warming up the lamp, etc if the timeout is * set too low.  A very long timeout parameter for bulk reads was used * to overcome this limitation, but this sometimes resulted in folks * having to wait for the timeout to expire after pressing Ctrl-C from * an application. The user was sometimes left with the impression * that something had hung or crashed when in fact the USB read was * just waiting on data.  So, the below code retains the same long * timeout period, but splits it up into smaller parts so that * Ctrl-C's are acted upon in a reasonable amount of time. */		if (result == -ETIMEDOUT) { /* NAK */			if (!partial) { /* No data */				if (--rd_expire <= 0) {	/* Give it up */					warn("read_vivi_s3c2410(%d): excessive NAK's received", vivi_minor);					ret = result;					break;				} else { /* Keep trying to read data */					interruptible_sleep_on_timeout(&vivi->rd_wait_q, vivi->rd_nak_timeout);					continue;				}			} else { /* Timeout w/ some data */				goto data_recvd;			}		}				if (result == -EPIPE) { /* No hope */			if(usb_clear_halt(dev, vivi->bulk_in_ep)) {				err("read_vivi_s3c2410(%d): Failure to clear endpoint halt condition (%Zd).", vivi_minor, ret);			}			ret = result;			break;		} else if ((result < 0) && (result != USB_ST_DATAUNDERRUN)) {			warn("read_vivi_s3c2410(%d): funky result:%d. Consult Documentation/usb/vivi_s3c2410.txt.", vivi_minor, (int)result);			ret = -EIO;			break;		}	data_recvd:#ifdef RD_DATA_DUMP		if (partial) {			unsigned char cnt, cnt_max;			cnt_max = (partial > 24) ? 24 : partial;			printk(KERN_DEBUG "dump(%d): ", vivi_minor);			for (cnt=0; cnt < cnt_max; cnt++) {				printk("%X ", ibuf[cnt]);			}			printk("\n");		}#endif		if (partial) { /* Data returned */			if (copy_to_user(buffer, ibuf, partial)) {				ret = -EFAULT;				break;			}			count -= this_read; /* Compensate for short reads */			bytes_read += partial; /* Keep tally of what actually was read */			buffer += partial;		} else {

⌨️ 快捷键说明

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