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

📄 scanner.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	down(&scn_mutex);	scn_minor = USB_SCN_MINOR(inode);	dbg("open_scanner: scn_minor:%d", scn_minor);	if (!p_scn_table[scn_minor]) {		up(&scn_mutex);		MOD_DEC_USE_COUNT;		err("open_scanner(%d): Unable to access minor data", scn_minor);		return -ENODEV;	}	scn = p_scn_table[scn_minor];	dev = scn->scn_dev;	down(&(scn->sem));	/* Now protect the scn_usb_data structure */ 	up(&scn_mutex); /* Now handled by the above */	if (!dev) {		err("open_scanner(%d): Scanner device not present", scn_minor);		err = -ENODEV;		goto out_error;	}	if (!scn->present) {		err("open_scanner(%d): Scanner is not present", scn_minor);		err = -ENODEV;		goto out_error;	}	if (scn->isopen) {		err("open_scanner(%d): Scanner device is already open", scn_minor);		err = -EBUSY;		goto out_error;	}	init_waitqueue_head(&scn->rd_wait_q);	scn->isopen = 1;	file->private_data = scn; /* Used by the read and write methods */out_error:	up(&(scn->sem)); /* Wake up any possible contending processes */	if (err)		MOD_DEC_USE_COUNT;	return err;}static intclose_scanner(struct inode * inode, struct file * file){	struct scn_usb_data *scn;	kdev_t scn_minor;	scn_minor = USB_SCN_MINOR (inode);	dbg("close_scanner: scn_minor:%d", scn_minor);	if (!p_scn_table[scn_minor]) {		err("close_scanner(%d): invalid scn_minor", scn_minor);		return -ENODEV;	}	down(&scn_mutex);	scn = p_scn_table[scn_minor];	down(&(scn->sem));	scn->isopen = 0;	file->private_data = NULL;	up(&scn_mutex);	up(&(scn->sem));	MOD_DEC_USE_COUNT;	return 0;}static ssize_twrite_scanner(struct file * file, const char * buffer,              size_t count, loff_t *ppos){	struct scn_usb_data *scn;	struct usb_device *dev;	ssize_t bytes_written = 0; /* Overall count of bytes written */	ssize_t ret = 0;	kdev_t scn_minor;	int this_write;		/* Number of bytes to write */	int partial;		/* Number of bytes successfully written */	int result = 0;	char *obuf;	scn = file->private_data;	down(&(scn->sem));	scn_minor = scn->scn_minor;	obuf = scn->obuf;	dev = scn->scn_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(scn->obuf, buffer, this_write)) {			ret = -EFAULT;			break;		}		result = usb_bulk_msg(dev,usb_sndbulkpipe(dev, scn->bulk_out_ep), obuf, this_write, &partial, 60*HZ);		dbg("write stats(%d): result:%d this_write:%d partial:%d", scn_minor, result, this_write, partial);		if (result == -ETIMEDOUT) {	/* NAK -- shouldn't happen */			warn("write_scanner: NAK received.");			ret = result;			break;		} else if (result < 0) { /* We should not get any I/O errors */			warn("write_scanner(%d): funky result: %d. Consult Documentataion/usb/scanner.txt.", scn_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): ", scn_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(&(scn->sem));	mdelay(5);		/* This seems to help with SANE queries */	return ret ? ret : bytes_written;}static ssize_tread_scanner(struct file * file, char * buffer,             size_t count, loff_t *ppos){	struct scn_usb_data *scn;	struct usb_device *dev;	ssize_t bytes_read;	/* Overall count of bytes_read */	ssize_t ret;	kdev_t scn_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;	scn = file->private_data;	down(&(scn->sem));	scn_minor = scn->scn_minor;	ibuf = scn->ibuf;	dev = scn->scn_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, scn->bulk_in_ep), ibuf, this_read, &partial, scn->rd_nak_timeout);		dbg("read stats(%d): result:%d this_read:%d partial:%d count:%d", scn_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 scanner 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_scanner(%d): excessive NAK's received", scn_minor);					ret = result;					break;				} else { /* Keep trying to read data */					interruptible_sleep_on_timeout(&scn->rd_wait_q, scn->rd_nak_timeout);					continue;				}			} else { /* Timeout w/ some data */				goto data_recvd;			}		}				if (result == -EPIPE) { /* No hope */			if(usb_clear_halt(dev, scn->bulk_in_ep)) {				err("read_scanner(%d): Failure to clear endpoint halt condition (%Zd).", scn_minor, ret);			}			ret = result;			break;		} else if ((result < 0) && (result != USB_ST_DATAUNDERRUN)) {			warn("read_scanner(%d): funky result:%d. Consult Documentation/usb/scanner.txt.", scn_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): ", scn_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 {			ret = 0;			break;		}	}	up(&(scn->sem));	return ret ? ret : bytes_read;}static intioctl_scanner(struct inode *inode, struct file *file,	      unsigned int cmd, unsigned long arg){	struct usb_device *dev;	kdev_t scn_minor;	scn_minor = USB_SCN_MINOR(inode);	if (!p_scn_table[scn_minor]) {		err("ioctl_scanner(%d): invalid scn_minor", scn_minor);		return -ENODEV;	}	dev = p_scn_table[scn_minor]->scn_dev;	switch (cmd)	{	case SCANNER_IOCTL_VENDOR :		return (put_user(dev->descriptor.idVendor, (unsigned int *) arg));	case SCANNER_IOCTL_PRODUCT :		return (put_user(dev->descriptor.idProduct, (unsigned int *) arg));#ifdef PV8630	case PV8630_IOCTL_INREQUEST :	{		int result;		struct {			__u8  data;			__u8  request;			__u16 value;			__u16 index;		} args;		if (copy_from_user(&args, (void *)arg, sizeof(args)))			return -EFAULT;		result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),					 args.request, USB_TYPE_VENDOR|					 USB_RECIP_DEVICE|USB_DIR_IN,					 args.value, args.index, &args.data,					 1, HZ*5);		dbg("ioctl_scanner(%d): inreq: args.data:%x args.value:%x args.index:%x args.request:%x\n", scn_minor, args.data, args.value, args.index, args.request);		if (copy_to_user((void *)arg, &args, sizeof(args)))			return -EFAULT;		dbg("ioctl_scanner(%d): inreq: result:%d\n", scn_minor, result);		return result;	}	case PV8630_IOCTL_OUTREQUEST :	{		int result;		struct {			__u8  request;			__u16 value;			__u16 index;		} args;		if (copy_from_user(&args, (void *)arg, sizeof(args)))			return -EFAULT;		dbg("ioctl_scanner(%d): outreq: args.value:%x args.index:%x args.request:%x\n", scn_minor, args.value, args.index, args.request);		result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),					 args.request, USB_TYPE_VENDOR|					 USB_RECIP_DEVICE|USB_DIR_OUT,					 args.value, args.index, NULL,					 0, HZ*5);		dbg("ioctl_scanner(%d): outreq: result:%d\n", scn_minor, result);		return result;	}#endif /* PV8630 */

⌨️ 快捷键说明

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