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

📄 scanner.c

📁 linux qt的图形设计实际例子
💻 C
📖 第 1 页 / 共 3 页
字号:

	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 int
close_scanner(struct inode * inode, struct file * file)
{
	struct scn_usb_data *scn;

	int 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_t
write_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;

	int 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_t
read_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;

	int 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 != -EREMOTEIO)) {
			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 int
ioctl_scanner(struct inode *inode, struct file *file,
	      unsigned int cmd, unsigned long arg)
{
	struct usb_device *dev;

	int 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 */
 	case SCANNER_IOCTL_CTRLMSG:
 	{
 		struct ctrlmsg_ioctl {
 			struct usb_ctrlrequest	req;
 			void			*data;
 		} cmsg;
 		int pipe, nb, ret;
 		unsigned char buf[64];
 
 		if (copy_from_user(&cmsg, (void *)arg, sizeof(cmsg)))
 			return -EFAULT;

⌨️ 快捷键说明

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