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

📄 scanner.c

📁 Linux2.6系统下USB2.0gadget扫描仪驱动器
💻 C
📖 第 1 页 / 共 3 页
字号:
		DBG(dev, "printer_read trying to read %d bytes\n", (int)len);	spin_lock (&dev->lock_printer_io);	spin_lock_irqsave (&dev->lock, flags);	/* Check if a printer reset happens while we have interrupts on */	dev->reset_printer = 0;		while (likely (!list_empty (&dev->rx_reqs))) {		int error;		req = container_of (dev->rx_reqs.next,				struct usb_request, list);		list_del_init (&req->list);				req->length = USB_BUFSIZE;		req->complete = rx_complete;		error = usb_ep_queue (dev->out_ep, req, GFP_ATOMIC);		if (error) {			DBG(dev, "rx submit --> %d\n", error);			list_add (&req->list, &dev->rx_reqs);			break;		} else {			list_add (&req->list, &dev->rx_reqs_active);		}	}		bytes_copied = 0;	current_rx_req = dev->current_rx_req;	current_rx_bytes = dev->current_rx_bytes;	current_rx_buf = dev->current_rx_buf;	dev->current_rx_req = NULL;	dev->current_rx_bytes = 0;	dev->current_rx_buf = NULL;	/* Check if there is any data in the read buffers */	if ((current_rx_bytes == 0) &&			(likely (list_empty (&dev->rx_buffers))))	{		/* Turn interrupts back on before sleeping. */		spin_unlock_irqrestore (&dev->lock, flags);		/*		 * If no data is available check if this is a NON-Blocking		 * call or not.		 */		if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {			spin_unlock (&dev->lock_printer_io);			return -EAGAIN;		}		/* Sleep until data is available */		wait_event_interruptible(dev->rx_wait,				(likely (!list_empty (&dev->rx_buffers))));		spin_lock_irqsave (&dev->lock, flags);	}				while ((current_rx_bytes || likely (!list_empty (&dev->rx_buffers)))			&& len)	{		if (current_rx_bytes == 0) {			req = container_of (dev->rx_buffers.next,					struct usb_request, list);			list_del_init (&req->list);						if (req->actual && req->buf) {				current_rx_req = req;				current_rx_bytes = req->actual;				current_rx_buf = req->buf;			} else {				list_add (&req->list, &dev->rx_reqs);				continue;			}		}		/* Don't leave irqs off while doing memory copies */		spin_unlock_irqrestore (&dev->lock, flags);			if (len > current_rx_bytes)			size = current_rx_bytes;		else			size = len;		size -= copy_to_user (buf, current_rx_buf, size);		bytes_copied += size;		len -= size;		buf += size;		spin_lock_irqsave (&dev->lock, flags);		/* We've disconnected or reset free the req and buffer */		if (dev->reset_printer) {			printer_req_free (dev->out_ep, current_rx_req);			spin_unlock_irqrestore (&dev->lock, flags);			spin_unlock (&dev->lock_printer_io);			return -EAGAIN;		}		if (size <  current_rx_bytes) {			current_rx_bytes -= size;			current_rx_buf += size;		} else {			list_add (&current_rx_req->list, &dev->rx_reqs);			current_rx_bytes = 0;			current_rx_buf = NULL;			current_rx_req = NULL;		}	}		dev->current_rx_req = current_rx_req;	dev->current_rx_bytes = current_rx_bytes;	dev->current_rx_buf = current_rx_buf;	spin_unlock_irqrestore (&dev->lock, flags);	spin_unlock (&dev->lock_printer_io);	DBG(dev, "printer_read returned %d bytes\n", (int)bytes_copied);	if (bytes_copied) {		return bytes_copied;	} else {		return -EAGAIN;	}}static ssize_tprinter_write (struct file *fd, const char __user *buf, size_t len,		loff_t *ptr){	struct printer_dev	*dev = fd->private_data;	unsigned long		flags;	size_t			size;	size_t			bytes_copied = 0;	struct usb_request	*req;	if (dev == NULL) {		printk(KERN_ERR "printer_write: NULL device pointer\n");		return -EIO;	}	DBG(dev, "printer_write trying to send %d bytes\n", (int)len);	if (len == 0)		return -EINVAL;	spin_lock (&dev->lock_printer_io);	spin_lock_irqsave (&dev->lock, flags);		/* Check if a printer reset happens while we have interrupts on */	dev->reset_printer = 0;	/* Check if there is any available write buffers */	if (likely (list_empty (&dev->tx_reqs))) {		/* Turn interrupts back on before sleeping. */		spin_unlock_irqrestore (&dev->lock, flags);		/*		 * If write buffers are available check if this is		 * a NON-Blocking call or not.		 */		if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {			spin_unlock (&dev->lock_printer_io);			return -EAGAIN;		}		/* Sleep until a write buffer is available */		wait_event_interruptible(dev->tx_wait,				(likely (!list_empty (&dev->tx_reqs))));		spin_lock_irqsave (&dev->lock, flags);	}	while (likely (!list_empty (&dev->tx_reqs)) && len) {		/* Some hardware doesn't like to write zlps. Hopefully the		 * extra data byte won't cause any problems.		 */		if (len < USB_BUFSIZE && !dev->zlp &&				(len % dev->in_ep->maxpacket) == 0) {			len++;		}		if (len > USB_BUFSIZE)			size = USB_BUFSIZE;		else			size = len;		req = container_of (dev->tx_reqs.next, struct usb_request,				list);		list_del_init (&req->list);			req->complete = tx_complete;		req->length = size;		if (len > size)			req->zero = 0;		else			req->zero = ((len % dev->in_ep->maxpacket) == 0);		/* Don't leave irqs off while doing memory copies */		spin_unlock_irqrestore (&dev->lock, flags);			if (copy_from_user (req->buf, buf, size)) {			list_add (&req->list, &dev->tx_reqs);			spin_unlock_irqrestore (&dev->lock, flags);			spin_unlock (&dev->lock_printer_io);			return bytes_copied;		}		bytes_copied += size;		len -= size;		buf += size;		spin_lock_irqsave (&dev->lock, flags);		/* We've disconnected or reset so free the req and buffer */		if (dev->reset_printer) {			printer_req_free (dev->in_ep, req);			spin_unlock_irqrestore (&dev->lock, flags);			spin_unlock (&dev->lock_printer_io);			return -EAGAIN;		}		if (usb_ep_queue (dev->in_ep, req, GFP_ATOMIC)) {			list_add (&req->list, &dev->tx_reqs);			spin_unlock_irqrestore (&dev->lock, flags);			spin_unlock (&dev->lock_printer_io);			return -EAGAIN;		}		list_add (&req->list, &dev->tx_reqs_active);	}	spin_unlock_irqrestore (&dev->lock, flags);	spin_unlock (&dev->lock_printer_io);	DBG(dev, "printer_write sent %d bytes\n", (int)bytes_copied);	if (bytes_copied) {		return bytes_copied;	} else {		return -EAGAIN;	}}static intprinter_fsync (struct file *fd, struct dentry *dentry, int datasync){	struct printer_dev	*dev = fd->private_data;	unsigned long		flags;	int			tx_list_empty;	if (dev == NULL) {		printk(KERN_ERR "printer_fsync: NULL device pointer\n");		return -EIO;	}	spin_lock_irqsave (&dev->lock, flags);	tx_list_empty = (likely (list_empty (&dev->tx_reqs)));	spin_unlock_irqrestore (&dev->lock, flags);	if (!tx_list_empty) {		/* Sleep until all data has been sent */		wait_event_interruptible(dev->tx_flush_wait,				(likely (list_empty (&dev->tx_reqs_active))));	}	return 0;}static unsigned intprinter_poll (struct file *fd, poll_table *wait){	struct printer_dev	*dev = fd->private_data;	unsigned long		flags;	int			status = 0;	if (dev == NULL) {		printk(KERN_ERR "printer_poll: NULL device pointer\n");		return -EIO;	}	poll_wait(fd, &dev->rx_wait, wait);	poll_wait(fd, &dev->tx_wait, wait);	spin_lock_irqsave (&dev->lock, flags);	if (likely (!list_empty (&dev->tx_reqs))) {		status |= POLLOUT | POLLWRNORM;	}	if (likely (!list_empty (&dev->rx_buffers))) {		status |= POLLIN | POLLRDNORM;	}	spin_unlock_irqrestore (&dev->lock, flags);	return status;}static intprinter_ioctl (struct inode *inode, struct file *fd, unsigned int code,		unsigned long arg){	struct printer_dev	*dev = fd->private_data;	unsigned long		flags;	int			status = 0;	if (dev == NULL) {		printk(KERN_ERR "printer_ioctl: NULL device pointer\n");		return -EIO;	}	printk(KERN_INFO "printer_ioctl: cmd=0x%4.4x, arg=%lu\n", code, arg);	/* handle ioctls */	spin_lock_irqsave (&dev->lock, flags);	switch (code) {	case GADGET_GET_PRINTER_STATUS:		status = (int)dev->printer_status;		break;	case GADGET_SET_PRINTER_STATUS:		dev->printer_status = (u8)arg;		break;	default:		/* could not handle ioctl */		printk(KERN_ERR "printer_ioctl: ERROR cmd=0x%4.4x"				"is not supported\n", code);		status = -ENOIOCTLCMD;	}			 	spin_unlock_irqrestore (&dev->lock, flags);	return status;}/* used after endpoint configuration */static struct file_operations printer_io_operations = {	.owner =	THIS_MODULE,	.open =		printer_open,	.read =		printer_read,	.write =	printer_write,	.fsync =	printer_fsync,	.poll =		printer_poll,	.ioctl =	printer_ioctl,	.release =	printer_close};/*-------------------------------------------------------------------------*/static intset_printer_interface (struct printer_dev *dev){	int			result = 0;	dev->in = ep_desc (dev->gadget, &hs_ep_in_desc, &fs_ep_in_desc);	dev->in_ep->driver_data = dev;	dev->out = ep_desc (dev->gadget, &hs_ep_out_desc, &fs_ep_out_desc);	dev->out_ep->driver_data = dev;	result = usb_ep_enable (dev->in_ep, dev->in);	if (result != 0) {		DBG(dev, "enable %s --> %d\n", 			dev->in_ep->name, result);		goto done;	}	result = usb_ep_enable (dev->out_ep, dev->out);	if (result != 0) {		DBG(dev, "enable %s --> %d\n", 			dev->in_ep->name, result);		goto done;	}done:	/* on error, disable any endpoints  */	if (result != 0) {		(void) usb_ep_disable (dev->in_ep);		(void) usb_ep_disable (dev->out_ep);		dev->in = NULL;		dev->out = NULL;	}	/* caller is responsible for cleanup on error */	return result;}static void printer_reset_interface (struct printer_dev *dev){	if (dev->interface < 0)		return;	DBG(dev, "%s\n", __FUNCTION__);	if (dev->in)		usb_ep_disable (dev->in_ep);			if (dev->out)		usb_ep_disable (dev->out_ep);	dev->interface = -1;}/* change our operational config.  must agree with the code * that returns config descriptors, and altsetting code. */static intprinter_set_config (struct printer_dev *dev, unsigned number){	int			result = 0;	struct usb_gadget	*gadget = dev->gadget;	if (gadget_is_sa1100 (gadget)			&& dev->config) {		/* tx fifo is full, but we can't clear it...*/		INFO (dev, "can't change configurations\n");		return -ESPIPE;	}	switch (number) {	case DEV_CONFIG_VALUE:		result = 0;		break;	default:		result = -EINVAL;		/* FALL THROUGH */	case 0:		break;	}	if (result) {		usb_gadget_vbus_draw(dev->gadget,				dev->gadget->is_otg ? 8 : 100);	} else {		char *speed;		unsigned power;		power = 2 * config_desc.bMaxPower;		usb_gadget_vbus_draw(dev->gadget, power);		switch (gadget->speed) {		case USB_SPEED_FULL:	speed = "full"; break;#ifdef CONFIG_USB_GADGET_DUALSPEED		case USB_SPEED_HIGH:	speed = "high"; break;#endif		default: 		speed = "?"; break;		}		dev->config = number;		INFO (dev, "%s speed config #%d: %d mA, %s\n",				speed, number, power, driver_desc);	}	return result;}static intconfig_buf (enum usb_device_speed speed,	u8 *buf, u8 type,	unsigned index, int is_otg){	int					len;	const struct usb_descriptor_header	**function;#ifdef CONFIG_USB_GADGET_DUALSPEED	int				hs = (speed == USB_SPEED_HIGH);	if (type == USB_DT_OTHER_SPEED_CONFIG)		hs = !hs;	if (hs) {		function = hs_printer_function;	} else {		function = fs_printer_function;	}#else	function = fs_printer_function;#endif	if (index >= device_desc.bNumConfigurations)		return -EINVAL;	/* for now, don't advertise srp-only devices */	if (!is_otg)		function++;	len = usb_gadget_config_buf (&config_desc, buf, USB_DESC_BUFSIZE,			function);	if (len < 0)		return len;	((struct usb_config_descriptor *) buf)->bDescriptorType = type;	return len;}/* Change our operational Interface. */static intset_interface (struct printer_dev *dev, unsigned number){	int			result = 0;	if (gadget_is_sa1100 (dev->gadget)			&& dev->interface < 0) {		/* tx fifo is full, but we can't clear it...*/		INFO (dev, "can't change interfaces\n");		return -ESPIPE;	}	/* Free the current interface */	switch (dev->interface) {	case PRINTER_INTERFACE:		printer_reset_interface (dev);		break;	}	switch (number) {	case PRINTER_INTERFACE:		result = set_printer_interface (dev);		if (result) {			printer_reset_interface (dev);		} else {			dev->interface = PRINTER_INTERFACE;		}		break;	default:		result = -EINVAL;		/* FALL THROUGH */	}	if (!result)		INFO (dev, "Using interface %x\n", number);	return result;}static void printer_setup_complete (struct usb_ep *ep,		struct usb_request *req){	if (req->status || req->actual != req->length)		DBG((struct printer_dev *) ep->driver_data,				"setup complete --> %d, %d/%d\n",				req->status, req->actual, req->length);}static void printer_soft_reset (struct printer_dev *dev){	struct usb_request	*req;	INFO (dev, "Received Printer Reset Request\n");	if (usb_ep_disable (dev->in_ep))		DBG(dev, "Failed to disable USB in_ep\n");	if (usb_ep_disable (dev->out_ep))		DBG(dev, "Failed to disable USB out_ep\n");	if (dev->current_rx_req != NULL) {		list_add (&dev->current_rx_req->list, &dev->rx_reqs);		dev->current_rx_req = NULL;	}	dev->current_rx_bytes = 0;	dev->current_rx_buf = NULL;	dev->reset_printer = 1;	while (likely (!(list_empty (&dev->rx_buffers)))) {		req = container_of (dev->rx_buffers.next, struct usb_request,				list);		list_del_init (&req->list);		list_add (&req->list, &dev->rx_reqs);	}		while (likely (!(list_empty (&dev->rx_reqs_active)))) {		req = container_of (dev->rx_buffers.next, struct usb_request,				list);		if (usb_ep_dequeue (dev->in_ep, req))

⌨️ 快捷键说明

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